blob: 97527eb24654bcef3bd84001a68e6835c610f880 [file] [log] [blame]
henrike@webrtc.org0e118e72013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004--2005, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
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.
15 *
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.
26 */
27
28// Copyright 2005 Google Inc. All Rights Reserved.
29//
30
31
32#ifndef TALK_BASE_HTTPBASE_H__
33#define TALK_BASE_HTTPBASE_H__
34
35#include "talk/base/httpcommon.h"
36
37namespace talk_base {
38
39class StreamInterface;
40
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///////////////////////////////////////////////////////////////////////////////
47
48class HttpParser {
49public:
50 enum ProcessResult { PR_CONTINUE, PR_BLOCK, PR_COMPLETE };
51 HttpParser();
52 virtual ~HttpParser();
53
54 void reset();
55 ProcessResult Process(const char* buffer, size_t len, size_t* processed,
56 HttpError* error);
57 bool is_valid_end_of_input() const;
58 void complete(HttpError err);
59
60 size_t GetDataRemaining() const { return data_size_; }
61
62protected:
63 ProcessResult ProcessLine(const char* line, size_t len, HttpError* error);
64
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;
76
77private:
78 enum State {
79 ST_LEADER, ST_HEADERS,
80 ST_CHUNKSIZE, ST_CHUNKTERM, ST_TRAILERS,
81 ST_DATA, ST_COMPLETE
82 } state_;
83 bool chunked_;
84 size_t data_size_;
85};
86
87///////////////////////////////////////////////////////////////////////////////
88// IHttpNotify
89///////////////////////////////////////////////////////////////////////////////
90
91enum HttpMode { HM_NONE, HM_CONNECT, HM_RECV, HM_SEND };
92
93class IHttpNotify {
94public:
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;
99};
100
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///////////////////////////////////////////////////////////////////////////////
110
111class HttpBase
112: private HttpParser,
113 public sigslot::has_slots<>
114{
115public:
116 HttpBase();
117 virtual ~HttpBase();
118
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;
124
125 void send(HttpData* data);
126 void recv(HttpData* data);
127 void abort(HttpError err);
128
129 HttpMode mode() const { return mode_; }
130
131 void set_ignore_data(bool ignore) { ignore_data_ = ignore; }
132 bool ignore_data() const { return ignore_data_; }
133
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();
138
139protected:
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);
143
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
154 // is triggered.
155 // Returns true if the received document has finished, and
156 // HttpParser::complete should be called.
157 bool DoReceiveLoop(HttpError* err);
158
159 void read_and_process_data();
160 void flush_data();
161 bool queue_headers();
162 void do_complete(HttpError err = HE_NONE);
163
164 void OnHttpStreamEvent(StreamInterface* stream, int events, int error);
165 void OnDocumentEvent(StreamInterface* stream, int events, int error);
166
167 // HttpParser Interface
168 virtual ProcessResult ProcessLeader(const char* line, size_t len,
169 HttpError* error);
170 virtual ProcessResult ProcessHeader(const char* name, size_t nlen,
171 const char* value, size_t vlen,
172 HttpError* error);
173 virtual ProcessResult ProcessHeaderComplete(bool chunked, size_t& data_size,
174 HttpError* error);
175 virtual ProcessResult ProcessData(const char* data, size_t len, size_t& read,
176 HttpError* error);
177 virtual void OnComplete(HttpError err);
178
179private:
180 class DocumentStream;
181 friend class DocumentStream;
182
183 enum { kBufferSize = 32 * 1024 };
184
185 HttpMode mode_;
186 HttpData* data_;
187 IHttpNotify* notify_;
188 StreamInterface* http_stream_;
189 DocumentStream* doc_stream_;
190 char buffer_[kBufferSize];
191 size_t len_;
192
193 bool ignore_data_, chunk_data_;
194 HttpData::const_iterator header_;
195};
196
197///////////////////////////////////////////////////////////////////////////////
198
199} // namespace talk_base
200
201#endif // TALK_BASE_HTTPBASE_H__