Message.h
1 /*
2  * Copyright (C) 2012 by Marc Boris Duerner
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 
29 #ifndef Pt_Http_Message_h
30 #define Pt_Http_Message_h
31 
32 #include <Pt/Http/Api.h>
33 #include <Pt/NonCopyable.h>
34 #include <iostream>
35 #include <streambuf>
36 #include <string>
37 #include <cstring>
38 #include <cstddef>
39 
40 namespace Pt {
41 
42 namespace Http {
43 
44 class Connection;
45 
48 class PT_HTTP_API MessageHeader : private Pt::NonCopyable
49 {
50  public:
53  class Field
54  {
55  public:
59  : _name(0)
60  , _value(0)
61  {}
62 
65  Field(const char* f, const char* s)
66  : _name(f)
67  , _value(s)
68  {}
69 
72  const char* name() const
73  { return _name; }
74 
77  void setName(const char* name)
78  { _name = name; }
79 
82  const char* value() const
83  { return _value; }
84 
87  void setValue(const char* value)
88  { _value = value; }
89 
90  private:
91  const char* _name;
92  const char* _value;
93  };
94 
98  {
99  friend class MessageHeader;
100 
101  public:
105  { }
107  explicit ConstIterator(const char* p)
108  : current(p, p)
109  {
110  fixup();
111  }
112 
115  bool operator== (const ConstIterator& it) const
116  { return current.name() == it.current.name(); }
117 
120  bool operator!= (const ConstIterator& it) const
121  { return current.name() != it.current.name(); }
122 
126  {
127  moveForward();
128  return *this;
129  }
130 
134  {
135  ConstIterator ret = *this;
136  moveForward();
137  return ret;
138  }
139 
142  const Field& operator*() const
143  { return current; }
144 
147  const Field* operator->() const
148  { return &current; }
149 
150  private:
152  void fixup()
153  {
154  if( *current.name() )
155  {
156  current.setValue( current.name() + std::strlen(current.name()) + 1 );
157  }
158  else
159  {
160  current.setName(0);
161  current.setValue(0);
162  }
163  }
164 
166  void moveForward()
167  {
168  current.setName( current.value() + std::strlen(current.value()) + 1 );
169  fixup();
170  }
171 
172  private:
173  Field current;
174  };
175 
176  public:
179  MessageHeader();
180 
183  ~MessageHeader();
184 
187  void clear();
188 
191  void set(const char* key, const char* value);
192 
195  void add(const char* key, const char* value);
196 
199  void remove(const char* key);
200 
203  const char* get(const char* key) const;
204 
207  bool has(const char* key) const
208  { return get(key) != 0; }
209 
212  bool isSet(const char* key, const char* value) const;
213 
217  { return ConstIterator(_rawdata); }
218 
222  { return ConstIterator(); }
223 
226  unsigned versionMajor() const
227  { return _httpVersionMajor; }
228 
231  unsigned versionMinor() const
232  { return _httpVersionMinor; }
233 
236  void setVersion(unsigned major, unsigned minor)
237  {
238  _httpVersionMajor = major;
239  _httpVersionMinor = minor;
240  }
241 
244  bool isChunked() const;
245 
248  std::size_t contentLength() const;
249 
252  bool isKeepAlive() const;
253 
256  void setKeepAlive();
257 
258  // Returns a properly formatted current time-string, as needed in http.
259  // The buffer must have at least 30 bytes.
260  static char* htdateCurrent(char* buffer);
261 
262  private:
264  char* eptr()
265  { return _rawdata + _endOffset; }
266 
267  private:
268  static const unsigned MaxHeaderSize = 4096;
269  char _rawdata[MaxHeaderSize]; // key_1\0value_1\0key_2\0value_2\0...key_n\0value_n\0\0
270  std::size_t _endOffset;
271  unsigned _httpVersionMajor;
272  unsigned _httpVersionMinor;
273 };
274 
278 {
279  private:
281  enum Result
282  {
283  InProgress = 1,
284  Header = 2,
285  Body = 4,
286  Finished = 8,
287  Trailer = 16, // NOTE: questionable if we need this
288  };
289 
290  public:
294  : _result(InProgress)
295  {}
296 
299  bool header() const
300  { return (_result & Header) == Header; }
301 
304  bool body() const
305  { return (_result & Body) == Body; }
306 
307  bool trailer() const
308  { return (_result & Trailer) == Trailer; }
309 
312  bool finished() const
313  { return (_result & Finished) == Finished; }
314 
316  void setFinished()
317  { _result |= Finished ; }
318 
320  void setHeader()
321  { _result |= Header; }
322 
324  void setBody()
325  { _result |= Body; }
326 
328  void setTrailer()
329  { _result |= Trailer; }
330 
332  unsigned long mask() const
333  { return _result; }
334 
335  private:
336  unsigned long _result;
337 };
338 
342 class MessageBuffer : public std::streambuf
343 {
344  public:
346  MessageBuffer();
347 
349  ~MessageBuffer();
350 
352  void discard()
353  {
354  this->setp(_buffer, _buffer + _bufferSize);
355  this->setg(0,0,0);
356  }
357 
359  std::size_t size() const
360  { return pptr() - pbase(); }
361 
363  const char* data() const
364  { return _buffer; }
365 
366  protected:
367  // @internal
368  virtual int_type overflow(int_type ch);
369 
370  // @internal
371  virtual int_type underflow();
372 
373  private:
374  static const unsigned int BufferSize = 512;
375  char* _buffer;
376  std::size_t _bufferSize;
377 };
378 
381 class PT_HTTP_API Message
382 {
383  friend class Connection;
384 
385  public:
387  explicit Message(Http::Connection& conn);
388 
389  Connection& connection()
390  { return *_conn; }
391 
394  { return _header; }
395 
397  const MessageHeader& header() const
398  { return _header; }
399 
401  std::iostream& body()
402  { return _ios; }
403 
405  bool isSending() const
406  { return _isSending; }
407 
409  bool isReceiving() const
410  { return _isReceiving; }
411 
413  bool isFinished() const
414  { return _finished; }
415 
417  void discard();
418 
420  MessageBuffer& buffer()
421  { return _buf; }
422 
423  protected:
425  void setBuffer(std::streambuf& sb)
426  { _ios.rdbuf(&sb); }
427 
429  void setSending(bool b)
430  { _isSending = b; }
431 
433  void setReceiving(bool b)
434  { _isReceiving = b; }
435 
437  void setFinished(bool b)
438  { _finished = b; }
439 
440  private:
441  Http::Connection* _conn;
442  MessageHeader _header;
443  MessageBuffer _buf;
444  std::iostream _ios;
445  bool _isSending;
446  bool _isReceiving;
447  bool _finished;
448 };
449 
450 } // namespace Http
451 
452 } // namespace Pt
453 
454 #endif // Pt_Http_Message_h
Field(const char *f, const char *s)
Construct with field name and value.
Definition: Message.h:65
HTTP message progress.
Definition: Message.h:277
bool header() const
Returns true if the header was processed.
Definition: Message.h:299
const Field & operator*() const
Returns the header field.
Definition: Message.h:142
ConstIterator & operator++()
Advance the iterator.
Definition: Message.h:125
Protects derived classes from being copied.
Definition: NonCopyable.h:54
ConstIterator operator++(int)
Advance the iterator.
Definition: Message.h:133
const MessageHeader & header() const
Returns the header of the message.
Definition: Message.h:397
ConstIterator()
Default constructor.
Definition: Message.h:104
const Field * operator->() const
Returns the header field.
Definition: Message.h:147
bool has(const char *key) const
Returns true if the field is present.
Definition: Message.h:207
HTTP message with header and body.
Definition: Message.h:381
HTTP header field iterator.
Definition: Message.h:97
void setName(const char *name)
Sets the field name.
Definition: Message.h:77
const char * name() const
Returns the field name.
Definition: Message.h:72
bool body() const
Returns true if the body was processed.
Definition: Message.h:304
MessageProgress()
Default Constructor.
Definition: Message.h:293
HTTP message header.
Definition: Message.h:48
Represents a connection between a Signal/Delegate and a slot.
Definition: Connection.h:90
std::iostream & body()
Returns the body of the message.
Definition: Message.h:401
MessageHeader & header()
Returns the header of the message.
Definition: Message.h:393
unsigned versionMinor() const
Returns the minor HTTP version number.
Definition: Message.h:231
ConstIterator end() const
Returns the end of the header fields.
Definition: Message.h:221
unsigned versionMajor() const
Returns the major HTTP version number.
Definition: Message.h:226
ConstIterator begin() const
Returns the begin of the header fields.
Definition: Message.h:216
void setVersion(unsigned major, unsigned minor)
Sets the HTTP version number.
Definition: Message.h:236
Field of a HTTP header.
Definition: Message.h:53
bool finished() const
Returns true if message is complete.
Definition: Message.h:312
const char * value() const
Returns the field value.
Definition: Message.h:82
void setValue(const char *value)
Sets the field name.
Definition: Message.h:87
Field()
Default constructor.
Definition: Message.h:58