fastcgi++
transceiver.hpp
Go to the documentation of this file.
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