00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <fastcgi++/transceiver.hpp>
00023
00024 int Fastcgipp::Transceiver::transmit()
00025 {
00026 while(1)
00027 {{
00028 Buffer::SendBlock sendBlock(buffer.requestRead());
00029 if(sendBlock.size)
00030 {
00031 ssize_t sent = write(sendBlock.fd, sendBlock.data, sendBlock.size);
00032 if(sent<0)
00033 {
00034 if(errno==EPIPE)
00035 {
00036 epoll_ctl(epollFd, EPOLL_CTL_DEL, sendBlock.fd, NULL);
00037 sent=sendBlock.size;
00038 }
00039 else if(errno!=EAGAIN) throw Exceptions::FastcgiException("Error writing to file descriptor");
00040 }
00041
00042 buffer.freeRead(sent);
00043 if(sent!=sendBlock.size)
00044 break;
00045 }
00046 else
00047 break;
00048 }}
00049
00050 return buffer.empty();
00051 }
00052
00053 void Fastcgipp::Transceiver::Buffer::secureWrite(size_t size, Protocol::FullId id, bool kill)
00054 {
00055 writeIt->end+=size;
00056 if(minBlockSize>(writeIt->data.get()+Chunk::size-writeIt->end) && ++writeIt==chunks.end())
00057 {
00058 chunks.push_back(Chunk());
00059 --writeIt;
00060 }
00061 frames.push(Frame(size, kill, id));
00062 }
00063
00064 bool Fastcgipp::Transceiver::handler()
00065 {
00066 using namespace std;
00067 using namespace Protocol;
00068
00069 bool transmitEmpty=transmit();
00070
00071 epoll_event event;
00072 int retVal=epoll_wait(epollFd, &event, 1, 0);
00073 if(retVal==0)
00074 {
00075 if(transmitEmpty) return true;
00076 else return false;
00077 }
00078 if(retVal<0) throw Exceptions::FastcgiException("Epoll Error");
00079
00080 if(event.events&EPOLLHUP)
00081 {
00082 epoll_ctl(epollFd, EPOLL_CTL_DEL, event.data.fd, NULL);
00083 return false;
00084 }
00085
00086 int& fd=event.data.fd;
00087 if(fd==socket)
00088 {
00089 sockaddr_un addr;
00090 socklen_t addrlen=sizeof(sockaddr_un);
00091 fd=accept(fd, (sockaddr*)&addr, &addrlen);
00092 fcntl(fd, F_SETFL, (fcntl(fd, F_GETFL)|O_NONBLOCK)^O_NONBLOCK);
00093 event.events=EPOLLIN;
00094 epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &event);
00095 Message& messageBuffer=fdBuffers[fd].messageBuffer;
00096 messageBuffer.size=0;
00097 messageBuffer.type=0;
00098 }
00099 Message& messageBuffer=fdBuffers[fd].messageBuffer;
00100 Header& headerBuffer=fdBuffers[fd].headerBuffer;
00101
00102 ssize_t actual;
00103
00104 if(!messageBuffer.data)
00105 {
00106
00107 actual=read(fd, (char*)&headerBuffer+messageBuffer.size, sizeof(Header)-messageBuffer.size);
00108 if(actual<0 && errno!=EAGAIN) throw Exceptions::FastcgiException("Error readin from file descriptor");
00109 if(actual>0) messageBuffer.size+=actual;
00110 if(messageBuffer.size!=sizeof(Header))
00111 {
00112 if(transmitEmpty) return true;
00113 else return false;
00114 }
00115
00116 messageBuffer.data.reset(new char[sizeof(Header)+headerBuffer.getContentLength()+headerBuffer.getPaddingLength()]);
00117 memcpy(static_cast<void*>(messageBuffer.data.get()), static_cast<const void*>(&headerBuffer), sizeof(Header));
00118 }
00119
00120 const Header& header=*(const Header*)messageBuffer.data.get();
00121 size_t needed=header.getContentLength()+header.getPaddingLength()+sizeof(Header)-messageBuffer.size;
00122 actual=read(fd, messageBuffer.data.get()+messageBuffer.size, needed);
00123 if(actual<0 && errno!=EAGAIN) throw Exceptions::FastcgiException("Error readin from file descriptor");
00124 if(actual>0) messageBuffer.size+=actual;
00125
00126
00127 if(actual==needed)
00128 {
00129 sendMessage(FullId(headerBuffer.getRequestId(), fd), messageBuffer);
00130 messageBuffer.size=0;
00131 messageBuffer.data.reset();
00132 return false;
00133 }
00134 if(transmitEmpty) return true;
00135 else return false;
00136 }
00137
00138 void Fastcgipp::Transceiver::Buffer::freeRead(size_t size)
00139 {
00140 pRead+=size;
00141 if(pRead>=chunks.begin()->end)
00142 {
00143 if(writeIt==chunks.begin())
00144 {
00145 pRead=writeIt->data.get();
00146 writeIt->end=pRead;
00147 }
00148 else
00149 {
00150 if(writeIt==--chunks.end())
00151 {
00152 chunks.begin()->end=chunks.begin()->data.get();
00153 chunks.splice(chunks.end(), chunks, chunks.begin());
00154 }
00155 else
00156 chunks.pop_front();
00157 pRead=chunks.begin()->data.get();
00158 }
00159 }
00160 if((frames.front().size-=size)==0)
00161 {
00162 if(frames.front().closeFd)
00163 {
00164 epoll_ctl(epollFd, EPOLL_CTL_DEL, frames.front().id.fd, NULL);
00165 close(frames.front().id.fd);
00166 fdBuffers.erase(frames.front().id.fd);
00167 }
00168 frames.pop();
00169 }
00170
00171 }
00172
00173 void Fastcgipp::Transceiver::sleep()
00174 {
00175 sigset_t sigSet;
00176 sigemptyset(&sigSet);
00177 sigprocmask(SIG_BLOCK, NULL, &sigSet);
00178 sigdelset(&sigSet, SIGUSR2);
00179 epoll_event event;
00180 epoll_pwait(epollFd, &event, 1, -1, &sigSet);
00181 }
00182
00183 Fastcgipp::Transceiver::Transceiver(int fd_, boost::function<void(Protocol::FullId, Message)> sendMessage_): socket(fd_), sendMessage(sendMessage_), epollFd(epoll_create(16)), buffer(epollFd, fdBuffers)
00184 {
00185 fcntl(socket, F_SETFL, (fcntl(socket, F_GETFL)|O_NONBLOCK)^O_NONBLOCK);
00186 epoll_event event;
00187 event.events=EPOLLIN;
00188 event.data.fd=socket;
00189 epoll_ctl(epollFd, EPOLL_CTL_ADD, socket, &event);
00190 }