3 * Copyright 2004--2005, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 // Copyright 2005 Google Inc. All Rights Reserved.
32 #ifndef TALK_BASE_HTTPBASE_H__
33 #define TALK_BASE_HTTPBASE_H__
35 #include "talk/base/httpcommon.h"
39 class StreamInterface;
41 ///////////////////////////////////////////////////////////////////////////////
42 // HttpParser - Parses an HTTP stream provided via Process and end_of_input, and
43 // generates events for:
44 // Structural Elements: Leader, Headers, Document Data
45 // Events: End of Headers, End of Document, Errors
46 ///////////////////////////////////////////////////////////////////////////////
50 enum ProcessResult { PR_CONTINUE, PR_BLOCK, PR_COMPLETE };
52 virtual ~HttpParser();
55 ProcessResult Process(const char* buffer, size_t len, size_t* processed,
57 bool is_valid_end_of_input() const;
58 void complete(HttpError err);
60 size_t GetDataRemaining() const { return data_size_; }
63 ProcessResult ProcessLine(const char* line, size_t len, HttpError* error);
65 // HttpParser Interface
66 virtual ProcessResult ProcessLeader(const char* line, size_t len,
67 HttpError* error) = 0;
68 virtual ProcessResult ProcessHeader(const char* name, size_t nlen,
69 const char* value, size_t vlen,
70 HttpError* error) = 0;
71 virtual ProcessResult ProcessHeaderComplete(bool chunked, size_t& data_size,
72 HttpError* error) = 0;
73 virtual ProcessResult ProcessData(const char* data, size_t len, size_t& read,
74 HttpError* error) = 0;
75 virtual void OnComplete(HttpError err) = 0;
79 ST_LEADER, ST_HEADERS,
80 ST_CHUNKSIZE, ST_CHUNKTERM, ST_TRAILERS,
87 ///////////////////////////////////////////////////////////////////////////////
89 ///////////////////////////////////////////////////////////////////////////////
91 enum HttpMode { HM_NONE, HM_CONNECT, HM_RECV, HM_SEND };
95 virtual ~IHttpNotify() {}
96 virtual HttpError onHttpHeaderComplete(bool chunked, size_t& data_size) = 0;
97 virtual void onHttpComplete(HttpMode mode, HttpError err) = 0;
98 virtual void onHttpClosed(HttpError err) = 0;
101 ///////////////////////////////////////////////////////////////////////////////
102 // HttpBase - Provides a state machine for implementing HTTP-based components.
103 // Attach HttpBase to a StreamInterface which represents a bidirectional HTTP
104 // stream, and then call send() or recv() to initiate sending or receiving one
105 // side of an HTTP transaction. By default, HttpBase operates as an I/O pump,
106 // moving data from the HTTP stream to the HttpData object and vice versa.
107 // However, it can also operate in stream mode, in which case the user of the
108 // stream interface drives I/O via calls to Read().
109 ///////////////////////////////////////////////////////////////////////////////
112 : private HttpParser,
113 public sigslot::has_slots<>
119 void notify(IHttpNotify* notify) { notify_ = notify; }
120 bool attach(StreamInterface* stream);
121 StreamInterface* stream() { return http_stream_; }
122 StreamInterface* detach();
123 bool isConnected() const;
125 void send(HttpData* data);
126 void recv(HttpData* data);
127 void abort(HttpError err);
129 HttpMode mode() const { return mode_; }
131 void set_ignore_data(bool ignore) { ignore_data_ = ignore; }
132 bool ignore_data() const { return ignore_data_; }
134 // Obtaining this stream puts HttpBase into stream mode until the stream
135 // is closed. HttpBase can only expose one open stream interface at a time.
136 // Further calls will return NULL.
137 StreamInterface* GetDocumentStream();
140 // Do cleanup when the http stream closes (error may be 0 for a clean
141 // shutdown), and return the error code to signal.
142 HttpError HandleStreamClose(int error);
144 // DoReceiveLoop acts as a data pump, pulling data from the http stream,
145 // pushing it through the HttpParser, and then populating the HttpData object
146 // based on the callbacks from the parser. One of the most interesting
147 // callbacks is ProcessData, which provides the actual http document body.
148 // This data is then written to the HttpData::document. As a result, data
149 // flows from the network to the document, with some incidental protocol
150 // parsing in between.
151 // Ideally, we would pass in the document* to DoReceiveLoop, to more easily
152 // support GetDocumentStream(). However, since the HttpParser is callback
153 // driven, we are forced to store the pointer somewhere until the callback
155 // Returns true if the received document has finished, and
156 // HttpParser::complete should be called.
157 bool DoReceiveLoop(HttpError* err);
159 void read_and_process_data();
161 bool queue_headers();
162 void do_complete(HttpError err = HE_NONE);
164 void OnHttpStreamEvent(StreamInterface* stream, int events, int error);
165 void OnDocumentEvent(StreamInterface* stream, int events, int error);
167 // HttpParser Interface
168 virtual ProcessResult ProcessLeader(const char* line, size_t len,
170 virtual ProcessResult ProcessHeader(const char* name, size_t nlen,
171 const char* value, size_t vlen,
173 virtual ProcessResult ProcessHeaderComplete(bool chunked, size_t& data_size,
175 virtual ProcessResult ProcessData(const char* data, size_t len, size_t& read,
177 virtual void OnComplete(HttpError err);
180 class DocumentStream;
181 friend class DocumentStream;
183 enum { kBufferSize = 32 * 1024 };
187 IHttpNotify* notify_;
188 StreamInterface* http_stream_;
189 DocumentStream* doc_stream_;
190 char buffer_[kBufferSize];
193 bool ignore_data_, chunk_data_;
194 HttpData::const_iterator header_;
197 ///////////////////////////////////////////////////////////////////////////////
199 } // namespace talk_base
201 #endif // TALK_BASE_HTTPBASE_H__