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:
180 
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  bool isUpgrade() const;
259 
260  void setUpgrade();
261 
262  // Returns a properly formatted current time-string, as needed in http.
263  // The buffer must have at least 30 bytes.
264  static char* htdateCurrent(char* buffer);
265 
266  private:
268  char* eptr()
269  { return _rawdata + _endOffset; }
270 
271  private:
272  static const unsigned MaxHeaderSize = 4096;
273  char _rawdata[MaxHeaderSize]; // key_1\0value_1\0key_2\0value_2\0...key_n\0value_n\0\0
274  std::size_t _endOffset;
275  unsigned _httpVersionMajor;
276  unsigned _httpVersionMinor;
277 };
278 
282 {
283  private:
285  enum Result
286  {
287  InProgress = 1,
288  Header = 2,
289  Body = 4,
290  Finished = 8,
291  Trailer = 16, // NOTE: questionable if we need this
292  };
293 
294  public:
298  : _result(InProgress)
299  {}
300 
303  bool header() const
304  { return (_result & Header) == Header; }
305 
308  bool body() const
309  { return (_result & Body) == Body; }
310 
311  bool trailer() const
312  { return (_result & Trailer) == Trailer; }
313 
316  bool finished() const
317  { return (_result & Finished) == Finished; }
318 
320  void setFinished()
321  { _result |= Finished ; }
322 
324  void setHeader()
325  { _result |= Header; }
326 
328  void setBody()
329  { _result |= Body; }
330 
332  void setTrailer()
333  { _result |= Trailer; }
334 
336  unsigned long mask() const
337  { return _result; }
338 
339  private:
340  unsigned long _result;
341 };
342 
346 class MessageBuffer : public std::streambuf
347 {
348  public:
350  MessageBuffer();
351 
353  ~MessageBuffer();
354 
356  void discard()
357  {
358  this->setp(_buffer, _buffer + _bufferSize);
359  this->setg(0,0,0);
360  }
361 
363  std::size_t size() const
364  { return pptr() - pbase(); }
365 
367  const char* data() const
368  { return _buffer; }
369 
370  protected:
371  // @internal
372  virtual int_type overflow(int_type ch);
373 
374  // @internal
375  virtual int_type underflow();
376 
377  private:
378  static const unsigned int BufferSize = 512;
379  char* _buffer;
380  std::size_t _bufferSize;
381 };
382 
385 class PT_HTTP_API Message
386 {
387  friend class Connection;
388 
389  public:
391  explicit Message(Http::Connection& conn);
392 
395  { return *_conn; }
396 
399  { return _header; }
400 
402  const MessageHeader& header() const
403  { return _header; }
404 
406  std::iostream& body()
407  { return _ios; }
408 
410  std::size_t available() const;
411 
413  std::size_t pending() const;
414 
416  void discard();
417 
419  bool isSending() const
420  { return _isSending; }
421 
423  bool isReceiving() const
424  { return _isReceiving; }
425 
427  bool isFinished() const
428  { return _finished; }
429 
431  MessageBuffer& buffer()
432  { return _buf; }
433 
434  protected:
436  void setBuffer(std::streambuf& sb)
437  { _ios.rdbuf(&sb); }
438 
440  void setSending(bool b)
441  { _isSending = b; }
442 
444  void setReceiving(bool b)
445  { _isReceiving = b; }
446 
448  void setFinished(bool b)
449  { _finished = b; }
450 
451  private:
452  Http::Connection* _conn;
453  MessageHeader _header;
454  MessageBuffer _buf;
455  std::iostream _ios;
456  bool _isSending;
457  bool _isReceiving;
458  bool _finished;
459 };
460 
461 } // namespace Http
462 
463 } // namespace Pt
464 
465 #endif // Pt_Http_Message_h
const Field * operator->() const
Returns the header field.
Definition: Message.h:147
Core module.
Definition: pt-gfx-images.dox:14
const char * name() const
Returns the field name.
Definition: Message.h:72
MessageHeader()
Default constructor.
bool header() const
Returns true if the header was processed.
Definition: Message.h:303
void remove(const char *key)
Removes a header field.
const char * value() const
Returns the field value.
Definition: Message.h:82
void clear()
Clears all content.
std::size_t pending() const
Returns the number of bytes pending to be written.
bool isKeepAlive() const
Returns true if HTTP keep-alive is set.
ConstIterator & operator++()
Advance the iterator.
Definition: Message.h:125
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
HTTP message with header and body.
Definition: Message.h:386
bool isSet(const char *key, const char *value) const
Returns true if the field is set to the value.
void setVersion(unsigned major, unsigned minor)
Sets the HTTP version number.
Definition: Message.h:236
const Field & operator*() const
Returns the header field.
Definition: Message.h:142
void discard()
Discards the message body.
ConstIterator end() const
Returns the end of the header fields.
Definition: Message.h:221
ConstIterator operator++(int)
Advance the iterator.
Definition: Message.h:133
bool body() const
Returns true if the body was processed.
Definition: Message.h:308
std::iostream & body()
Returns the body of the message.
Definition: Message.h:406
MessageProgress()
Default Constructor.
Definition: Message.h:297
bool isChunked() const
Returns true if chunked encoding is set.
HTTP message header.
Definition: Message.h:49
Field()
Default constructor.
Definition: Message.h:58
const MessageHeader & header() const
Returns the header of the message.
Definition: Message.h:402
HTTP message progress.
Definition: Message.h:282
bool finished() const
Returns true if message is complete.
Definition: Message.h:316
unsigned versionMinor() const
Returns the minor HTTP version number.
Definition: Message.h:231
Connection & connection()
Returns the used connection.
Definition: Message.h:394
Message(Http::Connection &conn)
Constructs with connection to use.
void setValue(const char *value)
Sets the field name.
Definition: Message.h:87
ConstIterator()
Default constructor.
Definition: Message.h:104
Field of a HTTP header.
Definition: Message.h:54
void setName(const char *name)
Sets the field name.
Definition: Message.h:77
void add(const char *key, const char *value)
Adds a header field.
void set(const char *key, const char *value)
Sets a header field.
std::size_t available() const
Returns the number of bytes available to read.
Protects derived classes from being copied.
Definition: NonCopyable.h:54
~MessageHeader()
Denstructor.
Field(const char *f, const char *s)
Construct with field name and value.
Definition: Message.h:65
HTTP header field iterator.
Definition: Message.h:98
void setKeepAlive()
Sets the HTTP keep-alive header.
bool has(const char *key) const
Returns true if the field is present.
Definition: Message.h:207
MessageHeader & header()
Returns the header of the message.
Definition: Message.h:398
std::size_t contentLength() const
Returns the content length.
Represents a connection between a Signal/Delegate and a slot.
Definition: Connection.h:91
const char * get(const char *key) const
Returns a field value.