1 //-< WWWAPI.H >------------------------------------------------------*--------* 2 // FastDB Version 1.0 (c) 1999 GARRET * ? * 3 // (Main Memory Database Management System) * /\| * 4 // * / \ * 5 // Created: 27-Mar-99 K.A. Knizhnik * / [] \ * 6 // Last update: 1-Jul-99 K.A. Knizhnik * GARRET * 7 //-------------------------------------------------------------------*--------* 8 // API for creating Internet applications 9 //-------------------------------------------------------------------*--------* 10 11 #ifndef __WWWAPI_H__ 12 #define __WWWAPI_H__ 13 14 #include "stdtp.h" 15 #include "sync.h" 16 #include "sockio.h" 17 #include "database.h" 18 19 BEGIN_FASTDB_NAMESPACE 20 21 enum WWWencodingType { 22 TAG = 0, // HTML tags (no conversion) 23 HTML = 1, // replace ('<','>','"','&') with (< > & &qout;) 24 URL = 2 // replace spaces with '+', and other special characters with %XX 25 }; 26 // 27 // Automatic state shifts after each append operation: 28 // TAG->HTML 29 // HTML->TAG 30 // URL->TAG 31 // 32 33 class FASTDB_DLL_ENTRY WWWconnection { 34 friend class WWWapi; 35 friend class CGIapi; 36 friend class QueueManager; 37 friend class HTTPapi; 38 39 public: 40 41 typedef void (*UserDataDestructor)(void* userData); 42 typedef bool (*handler)(WWWconnection& con); 43 44 void* userData; 45 UserDataDestructor userDataDestructor; 46 47 void setUserData(void* data, UserDataDestructor destructor = NULL) { 48 userData = data; 49 userDataDestructor = destructor; 50 } 51 52 // 53 // Append string to reply buffer 54 // 55 WWWconnection& append(char const* str); 56 WWWconnection& append(wchar_t const* str); 57 // 58 // Append binary data 59 // 60 WWWconnection& append(const void *buf, int len); 61 62 WWWconnection& operator << (char const* str) { 63 return append(str); 64 } 65 WWWconnection& operator << (wchar_t const* str) { 66 return append(str); 67 } 68 setEncoding(WWWencodingType type)69 void setEncoding(WWWencodingType type) { encoding = type; } 70 71 WWWconnection& operator << (WWWencodingType type) { 72 setEncoding(type); 73 return *this; 74 } 75 WWWconnection& operator << (int value) { 76 char buf[32]; 77 sprintf(buf, "%d", value); 78 return append(buf); 79 } 80 WWWconnection& operator << (double value) { 81 char buf[32]; 82 sprintf(buf, "%f", value); 83 return append(buf); 84 } 85 86 WWWconnection& operator << (db_int8 value) { 87 char buf[32]; 88 sprintf(buf, INT8_FORMAT, value); 89 return append(buf); 90 } 91 92 WWWconnection& operator << (oid_t value) { 93 char buf[32]; 94 sprintf(buf, "%ld", (long)value); 95 return append(buf); 96 } 97 getStub()98 char* getStub() { return stub; } 99 getAddress()100 char* getAddress() { return address; } 101 getPeer()102 char* getPeer() { return peer; } 103 104 // 105 // Compare content of the string with the end of the reply buffer 106 // 107 bool terminatedBy(char const* str) const; 108 109 // 110 // Get value of variable from request string. If name is not present in 111 // string NULL is returned. Parameter 'n' can be used to get n-th 112 // value of variable for multiple selection slot. Zero value of n 113 // corresponds to the first variable's value, 1 - to the second,... 114 // When no more values are available NULL is returned. 115 // 116 char* get(char const* name, int n = 0); 117 118 // 119 // Associatte value with name 120 // 121 void addPair(char const* name, char const* value); 122 123 WWWconnection(); 124 ~WWWconnection(); 125 126 protected: 127 enum { hash_table_size = 1013 }; 128 socket_t* sock; 129 char* reply_buf; 130 size_t reply_buf_size; 131 size_t reply_buf_used; 132 char* stub; 133 char* address; 134 char* peer; 135 WWWconnection* next; 136 WWWencodingType encoding; 137 138 139 struct name_value_pair { 140 name_value_pair* next; 141 char const* name; 142 char const* value; 143 unsigned hash_code; 144 }; 145 146 name_value_pair* hash_table[hash_table_size]; 147 name_value_pair* free_pairs; 148 149 char* extendBuffer(size_t inc); 150 151 152 // 153 // Deallocate all resources hold by connection. It is not possible to 154 // call get_value() or reply() method after this. Method reset() 155 // is implicitly called by WWWapi::get() method. 156 // 157 void reset(); 158 159 // 160 // Unpack requests paramters 161 // 162 char* unpack(char* body, size_t body_length); 163 }; 164 165 166 class FASTDB_DLL_ENTRY WWWapi { 167 public: 168 struct dispatcher { 169 char const* page; 170 WWWconnection::handler func; 171 // filled by contracutor of WWWapi 172 unsigned hash_code; 173 dispatcher* collision_chain; 174 }; 175 176 protected: 177 socket_t* sock; 178 bool canceled; 179 char* address; 180 dbDatabase& db; 181 enum { hash_table_size = 113 }; 182 dispatcher* hash_table[hash_table_size]; 183 184 bool dispatch(WWWconnection& con, char* page); 185 186 public: 187 WWWapi(dbDatabase& db, int n_handlers, dispatcher* dispatch_table); 188 virtual~WWWapi(); 189 190 // 191 // Bind and listen socket 192 // 193 bool open(char const* socket_address = "localhost:80", 194 socket_t::socket_domain domain = socket_t::sock_global_domain, 195 int listen_queue = DEFAULT_LISTEN_QUEUE_SIZE); 196 197 198 // 199 // Read and execute requests 200 // 201 virtual bool serve(WWWconnection& con) = 0; 202 203 // 204 // Accept new connection by the socket 205 // 206 bool connect(WWWconnection& con); 207 208 // 209 // Cancel acception of connections 210 // 211 void cancel(); 212 213 // 214 // Close socket 215 // 216 void close(); 217 }; 218 219 220 // 221 // Interaction with WWW server by means of CGI protocol and CGIatub program 222 // 223 class FASTDB_DLL_ENTRY CGIapi : public WWWapi { 224 public: 225 virtual bool serve(WWWconnection& con); 226 CGIapi(dbDatabase & db,int n_handlers,dispatcher * dispatch_table)227 CGIapi(dbDatabase& db, int n_handlers, dispatcher* dispatch_table) 228 : WWWapi(db, n_handlers, dispatch_table) {} 229 }; 230 231 232 // 233 // Built-in implementation of sunset of subset of HTTP protocol 234 // 235 class FASTDB_DLL_ENTRY HTTPapi : public WWWapi { 236 protected: 237 time_t connectionHoldTimeout; 238 bool keepConnectionAlive; 239 240 bool handleRequest(WWWconnection& con, char* begin, char* end, 241 char* host, bool& result); 242 243 public: 244 virtual bool serve(WWWconnection& con); 245 246 HTTPapi(dbDatabase& db, int n_handlers, dispatcher* dispatch_table, 247 bool persistentConnections = false, 248 time_t connectionHoldTimeoutSec = WAIT_FOREVER) WWWapi(db,n_handlers,dispatch_table)249 : WWWapi(db, n_handlers, dispatch_table) 250 { 251 keepConnectionAlive = persistentConnections; 252 connectionHoldTimeout = connectionHoldTimeoutSec; 253 } 254 }; 255 256 class FASTDB_DLL_ENTRY QueueManager { 257 WWWconnection* connectionPool; 258 WWWconnection* freeList; 259 WWWconnection* waitList; 260 dbMutex mutex; 261 dbLocalSemaphore go; 262 dbLocalEvent done; 263 dbThread* threads; 264 int nThreads; 265 WWWapi* server; 266 dbDatabase& db; 267 268 static void thread_proc handleThread(void* arg); 269 void handle(); 270 271 public: 272 void stop(); 273 void start(); 274 275 QueueManager(WWWapi& api, // WWWapi should be opened 276 dbDatabase& db, 277 int nThreads = 8, 278 int connectionQueueLen = 64); 279 ~QueueManager(); 280 }; 281 282 283 END_FASTDB_NAMESPACE 284 285 #endif 286 287 288 289