00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef TRANSCEIVER_HPP
00023 #define TRANSCEIVER_HPP
00024
00025 #include <map>
00026 #include <list>
00027 #include <queue>
00028 #include <algorithm>
00029 #include <map>
00030 #include <vector>
00031 #include <functional>
00032
00033 #include <boost/function.hpp>
00034 #include <boost/bind.hpp>
00035 #include <boost/shared_array.hpp>
00036
00037 #include <unistd.h>
00038 #include <fcntl.h>
00039 #include <errno.h>
00040 #include <poll.h>
00041 #include <sys/socket.h>
00042 #include <sys/un.h>
00043 #include <signal.h>
00044
00045 #include <fastcgi++/protocol.hpp>
00046 #include <fastcgi++/exceptions.hpp>
00047
00049 namespace Fastcgipp
00050 {
00052
00056 struct Block
00057 {
00059
00063 Block(char* data_, size_t size_): data(data_), size(size_) { }
00065 Block(const Block& block): data(block.data), size(block.size) { }
00067 const Block& operator=(const Block& block) { data=block.data; size=block.size; return *this; }
00069 char* data;
00071 size_t size;
00072 };
00073
00075
00079 class Transceiver
00080 {
00081 public:
00083
00090 bool handler();
00091
00093 Block requestWrite(size_t size) { return buffer.requestWrite(size); }
00095 void secureWrite(size_t size, Protocol::FullId id, bool kill) { buffer.secureWrite(size, id, kill); transmit(); }
00097
00104 Transceiver(int fd_, boost::function<void(Protocol::FullId, Message)> sendMessage_);
00106 void sleep()
00107 {
00108 poll(&pollFds.front(), pollFds.size(), -1);
00109 }
00110
00112 void wake();
00113
00114 private:
00116 struct fdBuffer
00117 {
00119 Protocol::Header headerBuffer;
00121 Message messageBuffer;
00122 };
00123
00125
00135 class Buffer
00136 {
00138 struct Frame
00139 {
00141
00146 Frame(size_t size_, bool closeFd_, Protocol::FullId id_): size(size_), closeFd(closeFd_), id(id_) { }
00148 size_t size;
00150 bool closeFd;
00152 Protocol::FullId id;
00153 };
00155 std::queue<Frame> frames;
00157 const static unsigned int minBlockSize = 256;
00159 struct Chunk
00160 {
00162 const static unsigned int size = 131072;
00164 boost::shared_array<char> data;
00166 char* end;
00168 Chunk(): data(new char[size]), end(data.get()) { }
00169 ~Chunk() { }
00171 Chunk(const Chunk& chunk): data(chunk.data), end(data.get()) { }
00172 };
00173
00175 std::list<Chunk> chunks;
00177 std::list<Chunk>::iterator writeIt;
00178
00180 char* pRead;
00181
00183 std::vector<pollfd>& pollFds;
00185 std::map<int, fdBuffer>& fdBuffers;
00187 void freeFd(int fd_) { Fastcgipp::Transceiver::freeFd(fd_, pollFds, fdBuffers); }
00188 public:
00190
00194 Buffer(std::vector<pollfd>& pollFds_, std::map<int, fdBuffer>& fdBuffers_): chunks(1), writeIt(chunks.begin()), pRead(chunks.begin()->data.get()), pollFds(pollFds_), fdBuffers(fdBuffers_) { }
00195
00197
00201 Block requestWrite(size_t size)
00202 {
00203 return Block(writeIt->end, std::min(size, (size_t)(writeIt->data.get()+Chunk::size-writeIt->end)));
00204 }
00206
00211 void secureWrite(size_t size, Protocol::FullId id, bool kill);
00212
00214 struct SendBlock
00215 {
00217
00222 SendBlock(const char* data_, size_t size_, int fd_): data(data_), size(size_), fd(fd_) { }
00224 SendBlock(const SendBlock& sendBlock): data(sendBlock.data), size(sendBlock.size), fd(sendBlock.fd) { }
00226 const char* data;
00228 size_t size;
00230 int fd;
00231 };
00232
00234
00237 SendBlock requestRead()
00238 {
00239 return SendBlock(pRead, frames.empty()?0:frames.front().size, frames.empty()?-1:frames.front().id.fd);
00240 }
00242
00245 void freeRead(size_t size);
00246
00248
00251 bool empty()
00252 {
00253 return pRead==writeIt->end;
00254 }
00255 };
00256
00258 Buffer buffer;
00260 boost::function<void(Protocol::FullId, Message)> sendMessage;
00261
00263 std::vector<pollfd> pollFds;
00265 int socket;
00267 int wakeUpFdIn;
00269 int wakeUpFdOut;
00270
00272 std::map<int, fdBuffer> fdBuffers;
00273
00275 int transmit();
00276
00277 public:
00279
00289 static void freeFd(int fd, std::vector<pollfd>& pollFds, std::map<int, fdBuffer>& fdBuffers);
00290
00292 void freeFd(int fd_) { freeFd(fd_, pollFds, fdBuffers); }
00293 };
00294
00296 struct equalsFd : public std::unary_function<pollfd, bool>
00297 {
00298 int fd;
00299 explicit equalsFd(int fd_): fd(fd_) {}
00300 bool operator()(const pollfd& x) const { return x.fd==fd; };
00301 };
00302
00304 inline bool reventsZero(const pollfd& x)
00305 {
00306 return x.revents;
00307 }
00308
00309 namespace Exceptions
00310 {
00312 struct Socket: public CodedException
00313 {
00315
00319 Socket(const int& fd_, const int& erno_): CodedException(0, erno_), fd(fd_) { }
00321 const int fd;
00322 };
00323
00325 struct SocketWrite: public Socket
00326 {
00328
00332 SocketWrite(int fd_, int erno_);
00333 };
00334
00336 struct SocketRead: public Socket
00337 {
00339
00343 SocketRead(int fd_, int erno_);
00344 };
00345
00347 struct SocketPoll: public CodedException
00348 {
00350
00353 SocketPoll(int erno_);
00354 };
00355 }
00356 }
00357
00358 #endif