1 #include <stdio.h>
  2 #include <errno.h>
  3 #include "rh_string.h"
  4 #include "rh_event.h"
  5 #include "client.h"
  6 #include "server.h"
  7 
  8 static void client_read (int fd, short rh_events, void *arg);
  9 static void client_write (int fd, short rh_events, void *arg);
 10 
 11 int client_init (client_t *client, rh_socket_t *client_socket, server_t *server)
 12 {
 13         memset (client, 0, sizeof(*client) - sizeof(client->buffer.data));
 14                 
 15         SIMPLEQ_INIT(&client->request);
 16 
 17         if (NULL == client_socket)
 18                 return 0;
 19         
 20         if (NULL == server) {
 21                 errno = EINVAL;
 22                 return -1;
 23         }
 24         
 25         TAILQ_INSERT_HEAD(&server->clients, client, clients);
 26         
 27         client->socket = *client_socket;
 28 
 29         if (-1 == rh_socket_set (&client->socket, RH_SOCKET_NONBLOCK)) {
 30                 return -1;
 31         }
 32 
 33         client->server = server;
 34                 
 35         client->buffer.used = 0;
 36 
 37         rh_event_set (  &client->socket.event_read,
 38                         server->ev_base,
 39                         client->socket.fd,
 40                         RH_EVENT_READ | RH_EVENT_ERROR | RH_EVENT_TIMEOUT,
 41                         client_read,
 42                         client);
 43         
 44         rh_event_set (  &client->socket.event_write,
 45                         server->ev_base,
 46                         client->socket.fd,
 47                         RH_EVENT_WRITE | RH_EVENT_ERROR | RH_EVENT_TIMEOUT,
 48                         client_write,
 49                         client);
 50                 
 51         if (-1 == rh_event_add (&client->socket.event_read))
 52                 return -1;
 53 
 54         client->keepalive = RHTTPD_KEEPALIVE_MAX;
 55 
 56         return 0;
 57 }
 58 
 59 static void client_free_requests (struct client *client)
 60 {
 61         struct http_request *request;
 62         
 63         for (;;) {
 64                 request = SIMPLEQ_FIRST(&client->request);
 65                 if (NULL == request)
 66                         break;
 67                 
 68                 SIMPLEQ_REMOVE_HEAD(&client->request, request, request);
 69                 
 70                 http_request_free (request);
 71         }
 72 }
 73 
 74 void client_free (client_t *client)
 75 {
 76         client_destroy (client);
 77         memcache_push (client->server->memcache, client, sizeof(*client));
 78 }
 79 
 80 void client_destroy (client_t *client)
 81 {
 82         TAILQ_REMOVE(&client->server->clients, client, clients);
 83         
 84         rh_socket_close (&client->socket);
 85         client_free_requests (client);
 86 }
 87 
 88 void client_reset (client_t *client)
 89 {
 90         client_free_requests (client);
 91         client->buffer.used = 0;
 92 }
 93 
 94 static void client_read (int fd, short rh_events, void *arg)
 95 {
 96         client_t        *client = arg;
 97         const char      *buffer;
 98         size_t          nbuffer;
 99         ssize_t         bytes;
100 
101 #if 0
102         printf ("%s (%3d, %hd, %p)\n", __FUNCTION__, fd, rh_events, arg);
103 #endif
104         
105         if (rh_events & (RH_EVENT_ERROR | RH_EVENT_TIMEOUT) )
106                 goto error_out;
107 
108         /*
109          *
110          * read ()
111          *
112          */
113                 
114         bytes = rh_socket_read (&client->socket,
115                         client->buffer.data + client->buffer.used,
116                         sizeof(client->buffer.data) - client->buffer.used);
117                 
118         if (bytes < 1) {
119                 if (bytes == -1 && (EAGAIN == errno || EINTR == errno))
120                         return;
121                 
122                 goto error_out;
123         }
124                 
125         client->buffer.used += bytes;
126         
127         buffer = client->buffer.data;
128         nbuffer = client->buffer.used;
129         
130         while (nbuffer) {
131                 const char      *rnrn;
132                 size_t          nrnrn;
133                 http_request_t  *request;
134                 int             parse;
135 
136                 
137                 /*
138                  * split by "\r\n\r\n" and parse
139                  *
140                  */
141                 
142                 rnrn = rh_str_rnrn (buffer, nbuffer);
143 
144                 if (NULL == rnrn)
145                         break;
146 
147                 rnrn += CONST_LEN(NL NL);
148 
149                 nrnrn = rnrn - buffer;
150                 rnrn = buffer;
151 
152                 buffer += nrnrn;
153                 nbuffer -= nrnrn;
154 
155                 request = http_request_alloc (client);
156                 if (NULL == request)
157                         goto error_out;
158 
159 #if 0
160                 printf ("RAW-REQ [%.*s]\n", nrnrn, rnrn);
161 #endif
162 
163                 parse = http_header_parse (
164                                 &request->header_in,
165                                 HTTP_HEADER_SERVER,
166                                 rnrn, nrnrn);
167                 
168                 if (0 != parse) {
169                         request->header_out.status = request->header_in.status;
170                         
171                         if (0 != handler_base_prepend_handler (
172                                         &request->handler,
173                                         client->server->handler_error) )
174                         {
175                                 goto error_out;
176                         }
177                 
178                         request->keepalive = 0;
179 
180                         nbuffer = 0;
181                         break;
182                 }
183 
184 #ifdef RHTTPD_DUMP_RECIEVED_HEADER
185                 http_header_dump (&request->header_in);
186 #endif
187 
188                 /* pipeline only if keep-alive */
189                 request->keepalive = request->header_in.keepalive;
190                 
191                 if (request->keepalive < 1)
192                         client->keepalive = 0;
193 
194                 if (client->keepalive < 1) {
195                         request->keepalive = 0;
196                 } else {
197                         client->keepalive -= 1;
198                         request->keepalive = client->keepalive;
199                         request->header_out.keepalive_header = request->header_in.keepalive_header;
200                 }
201                         
202 
203                 request->header_out.keepalive = request->keepalive;
204                 
205                 if (!request->keepalive) {
206                         nbuffer = 0;
207                         break;
208                 }
209         }
210         
211         if (0 == nbuffer) {
212                 client->buffer.used = 0;
213         } else
214         if (nbuffer < client->buffer.used) {
215                 memmove (client->buffer.data, buffer, nbuffer);
216                 client->buffer.used = nbuffer;
217         }
218                 
219         if (SIMPLEQ_EMPTY(&client->request))
220                 return;
221         
222         if (!RH_EVENT_ISSET(&client->socket.event_write)) {
223                 if (0 != rh_socket_set (&client->socket, RH_SOCKET_CORK_ON))
224                         goto error_out;
225                 
226                 if (0 != rh_event_add  (&client->socket.event_write))
227                         goto error_out;
228         }
229 
230         return;
231 
232 error_out:
233         client_free (client);
234         return;
235 }
236 
237 static void client_write (int fd, short rh_events, void *arg)
238 {
239         client_t        *client = arg;
240         
241 #if 0
242         printf ("%s(%3d, %hd, %p)\n", __FUNCTION__, fd, rh_events, arg);
243 #endif
244         
245         if (rh_events & (RH_EVENT_ERROR | RH_EVENT_TIMEOUT) )
246                 goto error_out;
247 
248         if (SIMPLEQ_EMPTY(&client->request)) {
249                 goto error_out;
250         }
251         
252         for (;;) {
253                 http_request_t                  *request;
254                 ssize_t                         bytes;
255                 handler_t                       *handler;
256                 struct http_request_list        *request_list;
257 
258                 request_list = &client->request;
259                 request = SIMPLEQ_FIRST(request_list);
260         
261 #if 0
262                 /* any sub requests? */
263                 if (TAILQ_EMPTY(&request->handler.handler)) {
264                         for (;;) {
265                                 if (SIMPLEQ_EMPTY(&request->sub_request))
266                                         break;
267 
268                                 request_list = &request->sub_request;
269                                 request = SIMPLEQ_FIRST(request_list);
270                 
271                                 if (!TAILQ_EMPTY(&request->handler.handler))
272                                         break;
273                         }
274                 }
275 #endif
276 
277                 while ( (handler = TAILQ_FIRST(&request->handler.handler)) ) {
278                         if (NULL == handler->request)
279                                 handler->request = request;
280                         
281                         switch (HANDLER_CALL(handler, exec)) {
282                         
283                         case HANDLER_SUCCESS:
284                                 /* current handler is done, pick next */
285                                 handler_free (handler);
286                                 continue;
287                         
288                         case HANDLER_AGAIN:
289                                 /* nothing */
290                                 continue;
291 
292                         case HANDLER_WRITE_DATA:
293                                 break;
294 
295                         case HANDLER_FAILURE:
296                                 if (handler->def->type > HANDLER_TYPE_CONTENT)
297                                         goto error_out;
298 
299                                 if (0 != handler_base_remove_handlers (
300                                                 &request->handler,
301                                                 HANDLER_TYPE_CONTENT) )
302                                 {
303                                         goto error_out;
304                                 }
305                                                 
306                                 if (0 != handler_base_prepend_handler (
307                                                 &request->handler,
308                                                 client->server->handler_error) )
309                                 {
310                                         goto error_out;
311                                 }
312                                 continue;
313 
314                         case HANDLER_STOP:
315                                 handler_base_destroy (&request->handler);
316                                 break;
317                         
318                         default:
319                                 goto error_out;
320                         }
321 
322                         break;
323                 }
324                 
325                 if (0 == request->have_write_setup) {
326                         if (0 != http_request_write_setup (request)) {
327                                 goto error_out;
328                         }
329                 }
330         
331                 bytes = rh_chunk_write (request->chunk_current,
332                                         client->socket.fd);
333                 
334                 if (bytes < 1) {
335                         if (bytes == -1) {
336                                 switch (errno) {
337                                 case EINTR:
338                                 case EAGAIN:
339                                         return;
340                                 }
341                         }
342 
343                         goto error_out;
344                 }
345                 
346                 if (!rh_chunk_done(request->chunk_current) )
347                         continue;
348 
349                 if (    request->chunk_current == &request->chunk_header &&
350                         request->chunk_content.size_in > 0)
351                 {
352                         request->chunk_current = &request->chunk_content;
353                         continue;
354                 }
355 
356                 if (!TAILQ_EMPTY(&request->handler.handler))
357                         continue;
358                         
359                 if (!request->keepalive) {
360                         rh_socket_set (&client->socket, RH_SOCKET_CORK_OFF);
361                         client_free (client);
362                         return;
363                 }
364 #if 0           
365                 if (!SIMPLEQ_EMPTY(&request->sub_request))
366                         continue;
367 #endif
368                 
369                 SIMPLEQ_REMOVE_HEAD(request_list, request, request);
370                 http_request_free (request);
371 
372                 if (SIMPLEQ_EMPTY(&client->request)) {
373                         rh_socket_set (&client->socket, RH_SOCKET_CORK_OFF);
374 
375                         if (0 != rh_event_del (&client->socket.event_write))
376                                 goto error_out;
377 
378                         return;
379                 }
380         }
381 
382         return;
383         
384 error_out:
385         client_free(client);
386         return;
387 }


syntax highlighted by Code2HTML, v. 0.9.1