fastcgi++
transceiver.hpp
Go to the documentation of this file.
1 
2 /***************************************************************************
3 * Copyright (C) 2007 Eddie Carle [eddie@erctech.org] *
4 * *
5 * This file is part of fastcgi++. *
6 * *
7 * fastcgi++ is free software: you can redistribute it and/or modify it *
8 * under the terms of the GNU Lesser General Public License as published *
9 * by the Free Software Foundation, either version 3 of the License, or (at *
10 * your option) any later version. *
11 * *
12 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT *
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
15 * License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public License *
18 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. *
19 ****************************************************************************/
20 
21 
22 #ifndef TRANSCEIVER_HPP
23 #define TRANSCEIVER_HPP
24 
25 #include <map>
26 #include <list>
27 #include <queue>
28 #include <algorithm>
29 #include <map>
30 #include <vector>
31 #include <functional>
32 
33 #include <boost/function.hpp>
34 #include <boost/bind.hpp>
35 #include <boost/shared_array.hpp>
36 
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <poll.h>
41 #include <sys/socket.h>
42 #include <sys/un.h>
43 #include <signal.h>
44 
45 #include <fastcgi++/protocol.hpp>
46 #include <fastcgi++/exceptions.hpp>
47 
49 namespace Fastcgipp
50 {
52 
56  struct Block
57  {
59 
63  Block(char* data_, size_t size_): data(data_), size(size_) { }
65  Block(const Block& block): data(block.data), size(block.size) { }
67  const Block& operator=(const Block& block) { data=block.data; size=block.size; return *this; }
69  char* data;
71  size_t size;
72  };
73 
75 
80  {
81  public:
83 
90  bool handler();
91 
93  Block requestWrite(size_t size) { return buffer.requestWrite(size); }
95  void secureWrite(size_t size, Protocol::FullId id, bool kill) { buffer.secureWrite(size, id, kill); transmit(); }
97 
104  Transceiver(int fd_, boost::function<void(Protocol::FullId, Message)> sendMessage_);
106  void sleep()
107  {
108  poll(&pollFds.front(), pollFds.size(), -1);
109  }
110 
112  void wake();
113 
114  private:
116  struct fdBuffer
117  {
122  };
123 
125 
135  class Buffer
136  {
138  struct Frame
139  {
141 
146  Frame(size_t size_, bool closeFd_, Protocol::FullId id_): size(size_), closeFd(closeFd_), id(id_) { }
148  size_t size;
150  bool closeFd;
153  };
155  std::queue<Frame> frames;
157  const static unsigned int minBlockSize = 256;
159  struct Chunk
160  {
162  const static unsigned int size = 131072;
164  boost::shared_array<char> data;
166  char* end;
168  Chunk(): data(new char[size]), end(data.get()) { }
169  ~Chunk() { }
171  Chunk(const Chunk& chunk): data(chunk.data), end(data.get()) { }
172  };
173 
175  std::list<Chunk> chunks;
177  std::list<Chunk>::iterator writeIt;
178 
180  char* pRead;
181 
183  std::vector<pollfd>& pollFds;
185  std::map<int, fdBuffer>& fdBuffers;
188  public:
190 
194  Buffer(std::vector<pollfd>& pollFds_, std::map<int, fdBuffer>& fdBuffers_): chunks(1), writeIt(chunks.begin()), pRead(chunks.begin()->data.get()), pollFds(pollFds_), fdBuffers(fdBuffers_) { }
195 
197 
201  Block requestWrite(size_t size)
202  {
203  return Block(writeIt->end, std::min(size, (size_t)(writeIt->data.get()+Chunk::size-writeIt->end)));
204  }
206 
211  void secureWrite(size_t size, Protocol::FullId id, bool kill);
212 
214  struct SendBlock
215  {
217 
222  SendBlock(const char* data_, size_t size_, int fd_): data(data_), size(size_), fd(fd_) { }
224  SendBlock(const SendBlock& sendBlock): data(sendBlock.data), size(sendBlock.size), fd(sendBlock.fd) { }
226  const char* data;
228  size_t size;
230  int fd;
231  };
232 
234 
238  {
239  return SendBlock(pRead, frames.empty()?0:frames.front().size, frames.empty()?-1:frames.front().id.fd);
240  }
242 
245  void freeRead(size_t size);
246 
248 
251  bool empty()
252  {
253  return pRead==writeIt->end;
254  }
255  };
256 
260  boost::function<void(Protocol::FullId, Message)> sendMessage;
261 
263  std::vector<pollfd> pollFds;
265  int socket;
270 
272  std::map<int, fdBuffer> fdBuffers;
273 
275  int transmit();
276 
277  public:
279 
289  static void freeFd(int fd, std::vector<pollfd>& pollFds, std::map<int, fdBuffer>& fdBuffers);
290 
292  void freeFd(int fd_) { freeFd(fd_, pollFds, fdBuffers); }
293  };
294 
296  struct equalsFd : public std::unary_function<pollfd, bool>
297  {
298  int fd;
299  explicit equalsFd(int fd_): fd(fd_) {}
300  bool operator()(const pollfd& x) const { return x.fd==fd; };
301  };
302 
304  inline bool reventsZero(const pollfd& x)
305  {
306  return x.revents;
307  }
308 
309  namespace Exceptions
310  {
312  struct Socket: public CodedException
313  {
315 
319  Socket(const int& fd_, const int& erno_): CodedException(0, erno_), fd(fd_) { }
321  const int fd;
322  };
323 
325  struct SocketWrite: public Socket
326  {
328 
332  SocketWrite(int fd_, int erno_);
333  };
334 
336  struct SocketRead: public Socket
337  {
339 
343  SocketRead(int fd_, int erno_);
344  };
345 
347  struct SocketPoll: public CodedException
348  {
350 
353  SocketPoll(int erno_);
354  };
355  }
356 }
357 
358 #endif