VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/include/HappyHttp.h@ 4436

Last change on this file since 4436 was 4436, checked in by vboxsync, 17 years ago

export

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 9.0 KB
Line 
1/*
2 * HappyHTTP - a simple HTTP library
3 * Version 0.1
4 *
5 * Copyright (c) 2006 Ben Campbell
6 *
7 * This software is provided 'as-is', without any express or implied
8 * warranty. In no event will the authors be held liable for any damages
9 * arising from the use of this software.
10 *
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions:
14 *
15 * 1. The origin of this software must not be misrepresented; you must not
16 * claim that you wrote the original software. If you use this software in a
17 * product, an acknowledgment in the product documentation would be
18 * appreciated but is not required.
19 *
20 * 2. Altered source versions must be plainly marked as such, and must not
21 * be misrepresented as being the original software.
22 *
23 * 3. This notice may not be removed or altered from any source distribution.
24 *
25 */
26
27
28#ifndef HAPPYHTTP_H
29#define HAPPYHTTP_H
30
31
32#include <string>
33#include <map>
34#include <vector>
35#include <deque>
36
37
38
39
40// forward decl
41struct in_addr;
42
43namespace happyhttp
44{
45
46
47class Response;
48
49// Helper Functions
50void BailOnSocketError( const char* context );
51struct in_addr *atoaddr( const char* address);
52
53
54typedef void (*ResponseBegin_CB)( const Response* r, void* userdata );
55typedef void (*ResponseData_CB)( const Response* r, void* userdata, const unsigned char* data, int numbytes );
56typedef void (*ResponseComplete_CB)( const Response* r, void* userdata );
57
58
59// HTTP status codes
60enum {
61 // 1xx informational
62 CONTINUE = 100,
63 SWITCHING_PROTOCOLS = 101,
64 PROCESSING = 102,
65
66 // 2xx successful
67 OK = 200,
68 CREATED = 201,
69 ACCEPTED = 202,
70 NON_AUTHORITATIVE_INFORMATION = 203,
71 NO_CONTENT = 204,
72 RESET_CONTENT = 205,
73 PARTIAL_CONTENT = 206,
74 MULTI_STATUS = 207,
75 IM_USED = 226,
76
77 // 3xx redirection
78 MULTIPLE_CHOICES = 300,
79 MOVED_PERMANENTLY = 301,
80 FOUND = 302,
81 SEE_OTHER = 303,
82 NOT_MODIFIED = 304,
83 USE_PROXY = 305,
84 TEMPORARY_REDIRECT = 307,
85
86 // 4xx client error
87 BAD_REQUEST = 400,
88 UNAUTHORIZED = 401,
89 PAYMENT_REQUIRED = 402,
90 FORBIDDEN = 403,
91 NOT_FOUND = 404,
92 METHOD_NOT_ALLOWED = 405,
93 NOT_ACCEPTABLE = 406,
94 PROXY_AUTHENTICATION_REQUIRED = 407,
95 REQUEST_TIMEOUT = 408,
96 CONFLICT = 409,
97 GONE = 410,
98 LENGTH_REQUIRED = 411,
99 PRECONDITION_FAILED = 412,
100 REQUEST_ENTITY_TOO_LARGE = 413,
101 REQUEST_URI_TOO_LONG = 414,
102 UNSUPPORTED_MEDIA_TYPE = 415,
103 REQUESTED_RANGE_NOT_SATISFIABLE = 416,
104 EXPECTATION_FAILED = 417,
105 UNPROCESSABLE_ENTITY = 422,
106 LOCKED = 423,
107 FAILED_DEPENDENCY = 424,
108 UPGRADE_REQUIRED = 426,
109
110 // 5xx server error
111 INTERNAL_SERVER_ERROR = 500,
112 NOT_IMPLEMENTED = 501,
113 BAD_GATEWAY = 502,
114 SERVICE_UNAVAILABLE = 503,
115 GATEWAY_TIMEOUT = 504,
116 HTTP_VERSION_NOT_SUPPORTED = 505,
117 INSUFFICIENT_STORAGE = 507,
118 NOT_EXTENDED = 510,
119};
120
121
122
123// Exception class
124
125class Wobbly
126{
127public:
128 Wobbly( const char* fmt, ... );
129 const char* what() const
130 { return m_Message; }
131protected:
132 enum { MAXLEN=256 };
133 char m_Message[ MAXLEN ];
134};
135
136
137
138//-------------------------------------------------
139// Connection
140//
141// Handles the socket connection, issuing of requests and managing
142// responses.
143// ------------------------------------------------
144
145class Connection
146{
147 friend class Response;
148public:
149 // doesn't connect immediately
150 Connection( const char* host, int port );
151 ~Connection();
152
153 // Set up the response handling callbacks. These will be invoked during
154 // calls to pump().
155 // begincb - called when the responses headers have been received
156 // datacb - called repeatedly to handle body data
157 // completecb - response is completed
158 // userdata is passed as a param to all callbacks.
159 void setcallbacks(
160 ResponseBegin_CB begincb,
161 ResponseData_CB datacb,
162 ResponseComplete_CB completecb,
163 void* userdata );
164
165 // Don't need to call connect() explicitly as issuing a request will
166 // call it automatically if needed.
167 // But it could block (for name lookup etc), so you might prefer to
168 // call it in advance.
169 void connect();
170
171 // close connection, discarding any pending requests.
172 void close();
173
174 // Update the connection (non-blocking)
175 // Just keep calling this regularly to service outstanding requests.
176 void pump();
177
178 // any requests still outstanding?
179 bool outstanding() const
180 { return !m_Outstanding.empty(); }
181
182 // ---------------------------
183 // high-level request interface
184 // ---------------------------
185
186 // method is "GET", "POST" etc...
187 // url is only path part: eg "/index.html"
188 // headers is array of name/value pairs, terminated by a null-ptr
189 // body & bodysize specify body data of request (eg values for a form)
190 void request( const char* method, const char* url, const char* headers[]=0,
191 const unsigned char* body=0, int bodysize=0 );
192
193 // ---------------------------
194 // low-level request interface
195 // ---------------------------
196
197 // begin request
198 // method is "GET", "POST" etc...
199 // url is only path part: eg "/index.html"
200 void putrequest( const char* method, const char* url );
201
202 // Add a header to the request (call after putrequest() )
203 void putheader( const char* header, const char* value );
204 void putheader( const char* header, int numericvalue ); // alternate version
205
206 // Finished adding headers, issue the request.
207 void endheaders();
208
209 // send body data if any.
210 // To be called after endheaders()
211 void send( const unsigned char* buf, int numbytes );
212
213protected:
214 // some bits of implementation exposed to Response class
215
216 // callbacks
217 ResponseBegin_CB m_ResponseBeginCB;
218 ResponseData_CB m_ResponseDataCB;
219 ResponseComplete_CB m_ResponseCompleteCB;
220 void* m_UserData;
221
222private:
223 enum { IDLE, REQ_STARTED, REQ_SENT } m_State;
224 std::string m_Host;
225 int m_Port;
226 int m_Sock;
227 std::vector< std::string > m_Buffer; // lines of request
228
229 std::deque< Response* > m_Outstanding; // responses for outstanding requests
230};
231
232
233
234
235
236
237//-------------------------------------------------
238// Response
239//
240// Handles parsing of response data.
241// ------------------------------------------------
242
243
244class Response
245{
246 friend class Connection;
247public:
248
249 // retrieve a header (returns 0 if not present)
250 const char* getheader( const char* name ) const;
251
252 bool completed() const
253 { return m_State == COMPLETE; }
254
255
256 // get the HTTP status code
257 int getstatus() const;
258
259 // get the HTTP response reason string
260 const char* getreason() const;
261
262 // true if connection is expected to close after this response.
263 bool willclose() const
264 { return m_WillClose; }
265protected:
266 // interface used by Connection
267
268 // only Connection creates Responses.
269 Response( const char* method, Connection& conn );
270
271 // pump some data in for processing.
272 // Returns the number of bytes used.
273 // Will always return 0 when response is complete.
274 int pump( const unsigned char* data, int datasize );
275
276 // tell response that connection has closed
277 void notifyconnectionclosed();
278
279private:
280 enum {
281 STATUSLINE, // start here. status line is first line of response.
282 HEADERS, // reading in header lines
283 BODY, // waiting for some body data (all or a chunk)
284 CHUNKLEN, // expecting a chunk length indicator (in hex)
285 CHUNKEND, // got the chunk, now expecting a trailing blank line
286 TRAILERS, // reading trailers after body.
287 COMPLETE, // response is complete!
288 } m_State;
289
290 Connection& m_Connection; // to access callback ptrs
291 std::string m_Method; // req method: "GET", "POST" etc...
292
293 // status line
294 std::string m_VersionString; // HTTP-Version
295 int m_Version; // 10: HTTP/1.0 11: HTTP/1.x (where x>=1)
296 int m_Status; // Status-Code
297 std::string m_Reason; // Reason-Phrase
298
299 // header/value pairs
300 std::map<std::string,std::string> m_Headers;
301
302 int m_BytesRead; // body bytes read so far
303 bool m_Chunked; // response is chunked?
304 int m_ChunkLeft; // bytes left in current chunk
305 int m_Length; // -1 if unknown
306 bool m_WillClose; // connection will close at response end?
307
308 std::string m_LineBuf; // line accumulation for states that want it
309 std::string m_HeaderAccum; // accumulation buffer for headers
310
311
312 void FlushHeader();
313 void ProcessStatusLine( std::string const& line );
314 void ProcessHeaderLine( std::string const& line );
315 void ProcessTrailerLine( std::string const& line );
316 void ProcessChunkLenLine( std::string const& line );
317
318 int ProcessDataChunked( const unsigned char* data, int count );
319 int ProcessDataNonChunked( const unsigned char* data, int count );
320
321 void BeginBody();
322 bool CheckClose();
323 void Finish();
324};
325
326
327
328} // end namespace happyhttp
329
330
331#endif // HAPPYHTTP_H
332
333
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette