VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox4/include/HappyHttp.h@ 7219

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

The Giant CDDL Dual-License Header Change.

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