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; }
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;
00186 public:
00188
00192 Buffer(std::vector<pollfd>& pollFds, std::map<int, fdBuffer>& fdBuffers_): pollFds(pollFds), fdBuffers(fdBuffers_), chunks(1), pRead(chunks.begin()->data.get()), writeIt(chunks.begin()) { }
00193
00195
00199 Block requestWrite(size_t size)
00200 {
00201 return Block(writeIt->end, std::min(size, (size_t)(writeIt->data.get()+Chunk::size-writeIt->end)));
00202 }
00204
00209 void secureWrite(size_t size, Protocol::FullId id, bool kill);
00210
00212 struct SendBlock
00213 {
00215
00220 SendBlock(const char* data_, size_t size_, int fd_): data(data_), size(size_), fd(fd_) { }
00222 SendBlock(const SendBlock& sendBlock): data(sendBlock.data), size(sendBlock.size), fd(sendBlock.fd) { }
00224 const char* data;
00226 size_t size;
00228 int fd;
00229 };
00230
00232
00235 SendBlock requestRead()
00236 {
00237 return SendBlock(pRead, frames.empty()?0:frames.front().size, frames.empty()?-1:frames.front().id.fd);
00238 }
00240
00243 void freeRead(size_t size);
00244
00246
00249 bool empty()
00250 {
00251 return pRead==writeIt->end;
00252 }
00253 };
00254
00256 Buffer buffer;
00258 boost::function<void(Protocol::FullId, Message)> sendMessage;
00259
00261 std::vector<pollfd> pollFds;
00263 int socket;
00265 int wakeUpFdIn;
00267 int wakeUpFdOut;
00268
00270 std::map<int, fdBuffer> fdBuffers;
00271
00273 int transmit();
00274 };
00275
00277 struct equalsFd : public std::unary_function<pollfd, bool>
00278 {
00279 int fd;
00280 explicit equalsFd(int fd_): fd(fd_) {}
00281 bool operator()(const pollfd& x) const { return x.fd==fd; };
00282 };
00283
00285 inline bool reventsZero(const pollfd& x)
00286 {
00287 return x.revents;
00288 }
00289 }
00290
00291 #endif