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 (&lt; &gt; &amp; &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