fastcgi++
|
00001 00002 /*************************************************************************** 00003 * Copyright (C) 2007 Eddie Carle [eddie@erctech.org] * 00004 * * 00005 * This file is part of fastcgi++. * 00006 * * 00007 * fastcgi++ is free software: you can redistribute it and/or modify it * 00008 * under the terms of the GNU Lesser General Public License as published * 00009 * by the Free Software Foundation, either version 3 of the License, or (at * 00010 * your option) any later version. * 00011 * * 00012 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT * 00013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 00014 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * 00015 * License for more details. * 00016 * * 00017 * You should have received a copy of the GNU Lesser General Public License * 00018 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. * 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