↑ 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