00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __WWWAPI_H__
00012 #define __WWWAPI_H__
00013
00014 #include "stdtp.h"
00015 #include "sync.h"
00016 #include "sockio.h"
00017 #include "database.h"
00018
00019 BEGIN_GIGABASE_NAMESPACE
00020
00021 enum WWWencodingType {
00022 TAG = 0,
00023 HTML = 1,
00024 URL = 2,
00025 ENTITY = 3
00026 };
00027
00028
00029
00030
00031
00032
00033
00034 class GIGABASE_DLL_ENTRY WWWconnection {
00035 friend class WWWapi;
00036 friend class CGIapi;
00037 friend class QueueManager;
00038 friend class HTTPapi;
00039
00040 public:
00041
00042 typedef void (*UserDataDestructor)(void* userData);
00043 typedef bool (*handler)(WWWconnection& con);
00044
00045 void* userData;
00046 UserDataDestructor userDataDestructor;
00047
00048 void setUserData(void* data, UserDataDestructor destructor = NULL) {
00049 userData = data;
00050 userDataDestructor = destructor;
00051 }
00052
00053
00054
00055
00056 WWWconnection& append(char const* str);
00057
00058
00059
00060 WWWconnection& append(const void *buf, int len);
00061
00062 WWWconnection& operator << (char const* str) {
00063 return append(str);
00064 }
00065 #ifdef UNICODE
00066 WWWconnection& append(wchar_t const* str);
00067 WWWconnection& operator << (wchar_t const* str) {
00068 return append(str);
00069 }
00070 #endif
00071
00072 void setEncoding(WWWencodingType type) { encoding = type; }
00073
00074 WWWconnection& operator << (WWWencodingType type) {
00075 setEncoding(type);
00076 return *this;
00077 }
00078 WWWconnection& operator << (double value) {
00079 char buf[32];
00080 sprintf(buf, "%f", value);
00081 return append(buf);
00082 }
00083
00084 WWWconnection& operator << (db_int8 value) {
00085 char buf[32];
00086 sprintf(buf, INT8_FORMAT, value);
00087 return append(buf);
00088 }
00089
00090 WWWconnection& operator << (int value) {
00091 char buf[32];
00092 sprintf(buf, "%d", value);
00093 return append(buf);
00094 }
00095
00096 WWWconnection& operator << (oid_t value) {
00097 char buf[32];
00098 sprintf(buf, "%ld", (long)value);
00099 return append(buf);
00100 }
00101
00102 char* getStub() { return stub; }
00103
00104 char* getAddress() { return address; }
00105
00106 char* getPeer() { return peer; }
00107
00108
00109
00110
00111 bool terminatedBy(char const* str) const;
00112
00113
00114
00115
00116
00117
00118
00119
00120 char* get(char const* name, int n = 0);
00121
00122
00123
00124
00125 void addPair(char const* name, char const* value);
00126
00127
00128 WWWconnection();
00129 ~WWWconnection();
00130
00131 protected:
00132 enum { hash_table_size = 1013 };
00133 socket_t* sock;
00134 char* reply_buf;
00135 size_t reply_buf_size;
00136 size_t reply_buf_used;
00137 char* stub;
00138 char* address;
00139 char* peer;
00140
00141 WWWconnection* next;
00142 WWWencodingType encoding;
00143
00144
00145 struct name_value_pair {
00146 name_value_pair* next;
00147 char const* name;
00148 char const* value;
00149 unsigned hash_code;
00150 };
00151
00152 name_value_pair* hash_table[hash_table_size];
00153 name_value_pair* free_pairs;
00154
00155 char* extendBuffer(size_t inc);
00156
00157
00158
00159
00160
00161
00162
00163 void reset();
00164
00165
00166
00167
00168 char* unpack(char* body, size_t body_length);
00169 };
00170
00171
00172 class GIGABASE_DLL_ENTRY WWWapi {
00173 public:
00174 struct dispatcher {
00175 char const* page;
00176 WWWconnection::handler func;
00177
00178 unsigned hash_code;
00179 dispatcher* collision_chain;
00180 };
00181
00182 protected:
00183 socket_t* sock;
00184 bool canceled;
00185 char* address;
00186 dbDatabase& db;
00187 enum { hash_table_size = 113 };
00188 dispatcher* hash_table[hash_table_size];
00189 char* rootPath;
00190
00191 bool dispatch(WWWconnection& con, char* page);
00192
00193 public:
00194 WWWapi(dbDatabase& db, int n_handlers, dispatcher* dispatch_table, char const* rootpath=NULL);
00195
00196 virtual ~WWWapi();
00197
00198
00199
00200 bool open(char const* socket_address = "localhost:80",
00201 socket_t::socket_domain domain = socket_t::sock_global_domain,
00202 int listen_queue = DEFAULT_LISTEN_QUEUE_SIZE);
00203
00204
00205
00206
00207
00208 virtual bool serve(WWWconnection& con) = 0;
00209
00210
00211
00212
00213 bool connect(WWWconnection& con);
00214
00215
00216
00217
00218 void cancel();
00219
00220
00221
00222
00223 void close();
00224 };
00225
00226
00227
00228
00229
00230 class GIGABASE_DLL_ENTRY CGIapi : public WWWapi {
00231 public:
00232 virtual bool serve(WWWconnection& con);
00233
00234 CGIapi(dbDatabase& db, int n_handlers, dispatcher* dispatch_table, const char* rootpath=NULL)
00235 : WWWapi(db, n_handlers, dispatch_table, rootpath) {}
00236 };
00237
00238
00239
00240
00241
00242 class GIGABASE_DLL_ENTRY HTTPapi : public WWWapi {
00243 protected:
00244 time_t connectionHoldTimeout;
00245 bool keepConnectionAlive;
00246
00247 bool handleRequest(WWWconnection& con, char* begin, char* end,
00248 char* host, bool& result);
00249
00250 public:
00251 virtual bool serve(WWWconnection& con);
00252
00253 HTTPapi(dbDatabase& db, int n_handlers, dispatcher* dispatch_table,
00254 bool persistentConnections = false,
00255 time_t connectionHoldTimeoutSec = WAIT_FOREVER,
00256 const char * rootpath=NULL)
00257 : WWWapi(db, n_handlers, dispatch_table, rootpath)
00258 {
00259 keepConnectionAlive = persistentConnections;
00260 connectionHoldTimeout = connectionHoldTimeoutSec;
00261 }
00262 };
00263
00264 class GIGABASE_DLL_ENTRY QueueManager {
00265 WWWconnection* connectionPool;
00266 WWWconnection* freeList;
00267 WWWconnection* waitList;
00268 dbMutex mutex;
00269 dbSemaphore go;
00270 dbEvent done;
00271 dbThread* threads;
00272 int nThreads;
00273 WWWapi* server;
00274 dbDatabase& db;
00275
00276 static void thread_proc handleThread(void* arg);
00277 void handle();
00278
00279 public:
00280 void stop();
00281 void start();
00282 void cleanup(WWWconnection::handler cleanupfunc);
00283
00284 QueueManager(WWWapi& api,
00285 dbDatabase& db,
00286 int nThreads = 8,
00287 int connectionQueueLen = 64
00288 );
00289 ~QueueManager();
00290 };
00291
00292 END_GIGABASE_NAMESPACE
00293
00294
00295 #endif
00296
00297
00298