[go: up one dir, main page]

Menu

[r8]: / trunk / ehs.h  Maximize  Restore  History

Download this file

401 lines (266 with data), 13.7 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
/** \mainpage EHS 1.1.3
EHS is a library for embedding HTTP(S) support into a C++ application
Copyright (C) 2004 Zachary J. Hansen
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation;
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
This can be found in the 'COPYING' file.
*/
#ifndef EHS_H
#define EHS_H
///////////////////////////////////
#ifdef _WIN32 // windows headers //
///////////////////////////////////
// Pragma'ing away nasty MS 255-char-name problem. Otherwise
// you will get warnings on many template names that
// "identifier was truncated to '255' characters in the debug information".
#ifdef _MSC_VER
# pragma warning(disable : 4786)
#endif
// to use winsock2.h instead of winsock.h
#define _WIN32_WINNT 0x0400
#include <winsock2.h>
#include <windows.h>
#include <time.h>
#include <assert.h>
// make windows sleep act like UNIX sleep
#define sleep(seconds) (Sleep(seconds * 1000))
///////////////////////////////////
#else // unix headers go here //
///////////////////////////////////
///////////////////////////////////
#endif // end platform headers //
///////////////////////////////////
// EHS headers
#include <ehstypes.h>
#include <datum.h>
#include <networkabstraction.h>
#include <httpresponse.h>
#include <httprequest.h>
#include <string>
extern const char * const EHSconfig;
class EHSServer;
/// EHSConnection abstracts the concept of a connection to an EHS application
/**
* EHSConnection abstracts the concept of a connection to an EHS application.
* It stores file descriptor information, unhandled data, and the current
* state of the request
*/
class EHSConnection {
protected:
int m_nDoneReading; ///< we're never reading from this again
int m_nDisconnected; ///< client has closed connection on us
HttpRequest * m_poCurrentHttpRequest; ///< request we're currently parsing
EHSServer * m_poEHSServer; ///< server with which this is associated
time_t m_nLastActivity; ///< time at which the last activity occured
int m_nRequests; ///< holds id of last request received
int m_nResponses; ///< holds id of last response sent
/// file descriptor associated with this client
NetworkAbstraction * m_poNetworkAbstraction;
/// raw data received from client that doesn't comprise a full request
std::string m_sBuffer;
/// holds out-of-order httpresponses that aren't ready to go out yet
HttpResponseMap m_oHttpResponseMap;
/// holds pending requests
HttpRequestList m_oHttpRequestList;
/// address from which the connection originated
std::string m_sAddress;
/// remote port from which the connection originated
int m_nPort;
public:
/// Constructor
EHSConnection ( NetworkAbstraction * ipoNetworkAbstraction,
EHSServer * ipoEHSServer );
/// destructor
~EHSConnection ( );
pthread_mutex_t m_oMutex; ///< mutex protecting entire object
/// updates the last activity to the current time
void UpdateLastActivity ( ) { m_nLastActivity = time ( NULL ); }
/// returns the time of last activity
time_t LastActivity ( ) { return m_nLastActivity; }
/// returns whether we're still reading from this socket -- mutex must be locked
int StillReading ( ) { return !m_nDoneReading; }
/// returns whether the client has disconnected from us -- mutex must be locked
int Disconnected ( ) { return m_nDisconnected; }
/// call when no more reads will be performed on this object. inDisconnected is true when client has disconnected
void DoneReading ( int inDisconnected );
/// gets the next request object
HttpRequest * GetNextRequest ( );
/// returns true if object should be deleted
int CheckDone ( );
/// Enumeration result for AddBuffer
enum AddBufferResult { ADDBUFFER_INVALID = 0,
ADDBUFFER_OK,
ADDBUFFER_INVALIDREQUEST,
ADDBUFFER_TOOBIG };
/// this is to protect from people being malicious or really stupid
#define MAX_BUFFER_SIZE_BEFORE_BOOT 102400
/// adds new data to psBuffer
AddBufferResult AddBuffer ( char * ipsData, int inSize );
/// sends the actual data back to the client
void SendHttpResponse ( HttpResponse * ipoHttpResponse);
/// adds a response to the response list and sends as many responses as are ready -- takes over the memory in ipoHttpResponse
void AddResponse ( HttpResponse * ipoHttpResponse );
/// returns address of connection
std::string GetAddress ( ) { return m_sAddress; }
/// returns client port of connection
int GetPort ( ) { return m_nPort; }
/// returns true of httprequestlist is not empty
int RequestsPending ( ) { return !m_oHttpRequestList.empty ( ); }
/// returns underlying network abstraction
NetworkAbstraction * GetNetworkAbstraction ( );
};
// predeclare because of circular reference between EHSServer and EHS
class EHSServer;
/// EHS provides HTTP server functionality to a child class
/**
* EHS provides HTTP server functionality to a child class. The child class
* must inherit from it and then override HandleRequest ( ).
*/
class EHS {
protected:
/// stores path => EHSConnection pairs for path/tree traversal
EHSMap oEHSMap;
/// points to the EHS object this object was registered with, NULL if top level
EHS * poParent;
/// the string that this EHS object is regestered as
std::string sRegisteredAs;
/// EHSServer object associated with this EHS object
EHSServer * poEHSServer;
/// source EHS object to route requests to for data instead of processing it ourselves
EHS * m_poSourceEHS;
public:
/// default constructor that can set a parrent and a path name
EHS ( EHS * ipoParent = NULL, std::string isRegisteredAs = "" );
/// destructor
virtual ~EHS ( );
/// set the certificate file for use in HTTPS transactions
void SetCertificateFile ( std::string & irsCertificateFile );
/// set certificate passphrase
void SetCertificatePassphrase ( std::string & irsCertificatePassphrase );
/// sets a new passphrase callback function
void SetPassphraseCallback ( int ( * m_ipfOverridePassphraseCallback ) ( char *, int, int, void * ) );
/// sets the poParent member of this class to the specified EHS. This is how an EHS object can unregister itself on destruction
void SetParent ( EHS * ipoParent, std::string isRegisteredAs );
/// Enumeration for error results for RegisterEHSResult
enum RegisterEHSResult { REGISTEREHSINTERFACE_INVALID = 0,
REGISTEREHSINTERFACE_ALREADYEXISTS,
REGISTEREHSINTERFACE_SUCCESS };
/// this associates an EHS object with this EHS object under the path ipsRegisterPath
RegisterEHSResult
RegisterEHS ( EHS * ipoEHS,
const char * ipsRegisterPath );
/// Enumeration for error results for UnregisterEHSResult
enum UnregisterEHSResult { UNREGISTEREHSINTERFACE_INVALID = 0,
UNREGISTEREHSINTERFACE_NOTREGISTERED,
UNREGISTEREHSINTERFACE_SUCCESS };
/// Unregister an EHS object from the specified path
UnregisterEHSResult
UnregisterEHS ( char * ipsRegisterPath );
/// this is responsible for routing a request through the EHS tree and sending the request to the final destination. It returns the HttpResponse object to be sent back to the client
HttpResponse * RouteRequest ( HttpRequest * ipoHttpRequest );
/// This function should be defined by the subclass
virtual ResponseCode HandleRequest ( HttpRequest * ipoHttpRequest,
HttpResponse * ipoHttpResponse );
/// makes this EHS object get its data from another EHS -- useful for having secure and normal connections share same data
void SetSourceEHS ( EHS & iroSourceEHS );
/// result codes for StartServer and StartSErver_Threaded
enum StartServerResult { STARTSERVER_INVALID = 0,
STARTSERVER_SUCCESS,
STARTSERVER_NODATASPECIFIED,
STARTSERVER_ALREADYRUNNING,
STARTSERVER_SOCKETSNOTINITIALIZED,
STARTSERVER_THREADCREATIONFAILED,
STARTSERVER_FAILED };
/// stores a map with server parameters
EHSServerParameters m_oEHSServerParameters;
/// do everything needed to start server
StartServerResult StartServer ( EHSServerParameters & iroEHSServerParameters );
/// brings down socket stuff. If StartServer_Threaded() was called it also stops that by setting the nServerStopped variable
void StopServer ( );
/// This looks for incoming connections in EHSServer.
void HandleData ( int inTimeoutMilliseconds = 0 );
};
/// EHSServer contains all the network functionality for EHS
/**
* EHSServer has all the network related services for EHS. It is responsible
* for accepting new connections and getting EHSConnection objects set up
*/
class EHSServer {
public:
/// consturctor for an EHSServer -- takes parameters out of ipoTopLevelEHS->m_oEHSServerParameters;
EHSServer ( EHS * ipoTopLevelEHS );
virtual ~EHSServer ( );
/// removes the specified EHSConnection object, returns true if it actually found something to remove
int RemoveEHSConnection ( EHSConnection * ipoEHSConnection );
/// disconnects idle connections
int ClearIdleConnections ( );
/// removes all connections from the server that are no longer active
int RemoveFinishedConnections ( );
/// sets default http response headers, such as date, and content type
void InitHttpResponse ( HttpResponse * ipoHttpResponse );
/// stops the server
void EndServerThread ( char * ipsReason );
/// main function that deals with client connections and getting data
void HandleData ( int inTimeoutMilliseconds, pthread_t inThreadId = NULL );
/// check clients that are already connected
void CheckClientSockets ( );
/// check the listen socket for a new connection
void CheckAcceptSocket ( );
/// Enumeration on the current running status of the EHSServer
enum ServerRunningStatus { SERVERRUNNING_INVALID = 0,
SERVERRUNNING_NOTRUNNING,
SERVERRUNNING_SINGLETHREADED,
SERVERRUNNING_THREADPOOL,
SERVERRUNNING_ONETHREADPERREQUEST
};
/// Current running status of the EHSServer
ServerRunningStatus m_nServerRunningStatus;
/// reason for shutting down
std::string m_sShutdownReason;
/// this runs in a loop until told to stop by StopServer() -- runs off it's own thread created by StartServer_Threaded
void HandleData_Threaded ( );
/// pointer back up to top-most level EHS object
EHS * m_poTopLevelEHS;
/// gets a pending request
HttpRequest * GetNextRequest ( );
/// whether we accepted a new connection last time through
int m_nAcceptedNewConnection;
/// returns number of requests pending
int RequestsPending ( ) { return m_nRequestsPending; }
/// increments the number of pending requests
void IncrementRequestsPending ( ) { m_nRequestsPending++; }
/// mutex for controlling who is accepting or processing jobs
pthread_mutex_t m_oMutex;
/// condition for when a thread is done accepting and there may be more jobs to process
pthread_cond_t m_oDoneAccepting;
/// static method for starting threaded mode -- pthreads can't start a thread on a normal member function, only static
static void * PthreadHandleData_ThreadedStub ( void * ipData );
protected:
/// number of requests waiting to be processed
int m_nRequestsPending;
/// number of threads currently accepting (0 or 1)
int m_nAccepting;
/// this is the server name sent out in the response headers
std::string sServerName;
/// creates the poll array with the accept socket and any connections present
int CreateFdSet ( );
/// this is the read set for sending to select(2)
fd_set m_oReadFds;
/// List of all connections currently attached to the server
EHSConnectionList m_oEHSConnectionList;
/// the network abstraction this server is listening on
NetworkAbstraction * m_poNetworkAbstraction;
/// pthread identifier for the accept thread -- only used when started in threaded mode
pthread_t m_nAcceptThreadId;
/// number of seconds a connection can be idle before disconnect
int m_nIdleTimeout;
};
#endif // EHS_H