diff options
Diffstat (limited to 'src/daemon/session.c')
-rw-r--r-- | src/daemon/session.c | 303 |
1 files changed, 145 insertions, 158 deletions
diff --git a/src/daemon/session.c b/src/daemon/session.c index c50af0ba..fa3864ca 100644 --- a/src/daemon/session.c +++ b/src/daemon/session.c | |||
@@ -26,17 +26,6 @@ | |||
26 | * @version 0.1.0 | 26 | * @version 0.1.0 |
27 | */ | 27 | */ |
28 | 28 | ||
29 | |||
30 | #include <stdio.h> | ||
31 | #include <stdlib.h> | ||
32 | #include <netdb.h> | ||
33 | #include <string.h> | ||
34 | #include <unistd.h> | ||
35 | #include <stdarg> | ||
36 | #include <fcntl.h> | ||
37 | #include <pthread.h> | ||
38 | #include <netinet/in.h> | ||
39 | |||
40 | #include "microhttpd.h" | 29 | #include "microhttpd.h" |
41 | #include "session.h" | 30 | #include "session.h" |
42 | #include "response.h" | 31 | #include "response.h" |
@@ -55,7 +44,7 @@ | |||
55 | int | 44 | int |
56 | MHD_get_session_values(struct MHD_Session * session, | 45 | MHD_get_session_values(struct MHD_Session * session, |
57 | enum MHD_ValueKind kind, | 46 | enum MHD_ValueKind kind, |
58 | MHD_KeyValueIterator * iterator, | 47 | MHD_KeyValueIterator iterator, |
59 | void * iterator_cls) { | 48 | void * iterator_cls) { |
60 | int ret; | 49 | int ret; |
61 | struct MHD_HTTP_Header * pos; | 50 | struct MHD_HTTP_Header * pos; |
@@ -95,7 +84,6 @@ MHD_lookup_session_value(struct MHD_Session * session, | |||
95 | 84 | ||
96 | if (session == NULL) | 85 | if (session == NULL) |
97 | return NULL; | 86 | return NULL; |
98 | ret = 0; | ||
99 | pos = session->headers_received; | 87 | pos = session->headers_received; |
100 | while (pos != NULL) { | 88 | while (pos != NULL) { |
101 | if ( (0 != (pos->kind & kind)) && | 89 | if ( (0 != (pos->kind & kind)) && |
@@ -145,7 +133,8 @@ MHD_session_get_fdset(struct MHD_Session * session, | |||
145 | int * max_fd) { | 133 | int * max_fd) { |
146 | /* FIXME: need to be VERY careful here | 134 | /* FIXME: need to be VERY careful here |
147 | determining when the socket is ready for | 135 | determining when the socket is ready for |
148 | reading/writing; plenty of cases to handle! */ | 136 | reading/writing; plenty of cases to handle! |
137 | (the current code is one big bug) */ | ||
149 | FD_SET(session->socket_fd, read_fd_set); | 138 | FD_SET(session->socket_fd, read_fd_set); |
150 | FD_SET(session->socket_fd, write_fd_set); | 139 | FD_SET(session->socket_fd, write_fd_set); |
151 | if (session->socket_fd > *max_fd) | 140 | if (session->socket_fd > *max_fd) |
@@ -165,6 +154,7 @@ MHD_session_get_fdset(struct MHD_Session * session, | |||
165 | */ | 154 | */ |
166 | static void | 155 | static void |
167 | MHD_parse_URL(struct MHD_Session * session) { | 156 | MHD_parse_URL(struct MHD_Session * session) { |
157 | #if 0 | ||
168 | char * working; | 158 | char * working; |
169 | int pos,i; | 159 | int pos,i; |
170 | 160 | ||
@@ -179,10 +169,10 @@ MHD_parse_URL(struct MHD_Session * session) { | |||
179 | pos = 0; | 169 | pos = 0; |
180 | 170 | ||
181 | session->documentName = session->headers[0]->value+pos; | 171 | session->documentName = session->headers[0]->value+pos; |
172 | #endif | ||
182 | } | 173 | } |
183 | 174 | ||
184 | 175 | ||
185 | |||
186 | /** | 176 | /** |
187 | * This function is designed to parse the input buffer of a given session. | 177 | * This function is designed to parse the input buffer of a given session. |
188 | * | 178 | * |
@@ -195,6 +185,7 @@ MHD_parse_URL(struct MHD_Session * session) { | |||
195 | */ | 185 | */ |
196 | static void | 186 | static void |
197 | MHD_parse_session_headers(struct MHD_Session * session) { | 187 | MHD_parse_session_headers(struct MHD_Session * session) { |
188 | #if 0 | ||
198 | const char * crlfcrlf = "\r\n\r\n"; | 189 | const char * crlfcrlf = "\r\n\r\n"; |
199 | const char * crlf = "\r\n"; | 190 | const char * crlf = "\r\n"; |
200 | 191 | ||
@@ -249,8 +240,7 @@ MHD_parse_session_headers(struct MHD_Session * session) { | |||
249 | session->headers[session->firstFreeHeader++] = newHeader; | 240 | session->headers[session->firstFreeHeader++] = newHeader; |
250 | curTok = strtok_r(NULL, crlf, &saveptr); | 241 | curTok = strtok_r(NULL, crlf, &saveptr); |
251 | } | 242 | } |
252 | 243 | #endif | |
253 | return numBytes; | ||
254 | } | 244 | } |
255 | 245 | ||
256 | 246 | ||
@@ -269,7 +259,7 @@ MHD_find_access_handler(struct MHD_Session * session) { | |||
269 | * (multithreaded, external select, internal select) call this function | 259 | * (multithreaded, external select, internal select) call this function |
270 | * to handle reads. | 260 | * to handle reads. |
271 | */ | 261 | */ |
272 | static int | 262 | int |
273 | MHD_session_handle_read(struct MHD_Session * session) { | 263 | MHD_session_handle_read(struct MHD_Session * session) { |
274 | int bytes_read; | 264 | int bytes_read; |
275 | void * tmp; | 265 | void * tmp; |
@@ -322,8 +312,8 @@ MHD_session_handle_read(struct MHD_Session * session) { | |||
322 | return MHD_NO; | 312 | return MHD_NO; |
323 | } | 313 | } |
324 | /* dh left "processed" bytes in buffer for next time... */ | 314 | /* dh left "processed" bytes in buffer for next time... */ |
325 | memmove(session->readBuffer, | 315 | memmove(session->read_buffer, |
326 | &session->readBuffer[session->readLoc - processed], | 316 | &session->read_buffer[session->readLoc - processed], |
327 | processed); | 317 | processed); |
328 | session->readLoc = processed; | 318 | session->readLoc = processed; |
329 | session->uploadSize -= processed; | 319 | session->uploadSize -= processed; |
@@ -332,157 +322,154 @@ MHD_session_handle_read(struct MHD_Session * session) { | |||
332 | return MHD_YES; | 322 | return MHD_YES; |
333 | } | 323 | } |
334 | 324 | ||
325 | /** | ||
326 | * Allocate the session's write buffer and | ||
327 | * fill it with all of the headers from the | ||
328 | * HTTPd's response. | ||
329 | */ | ||
330 | static void | ||
331 | MHD_build_header_response(struct MHD_Session * session) { | ||
332 | size_t size; | ||
333 | size_t off; | ||
334 | struct MHD_HTTP_Header * pos; | ||
335 | char code[32]; | ||
336 | char * data; | ||
337 | |||
338 | sprintf(code, | ||
339 | "HTTP/1.1 %u\r\n", | ||
340 | session->responseCode); | ||
341 | off = strlen(code); | ||
342 | /* estimate size */ | ||
343 | size = off + 2; /* extra \r\n at the end */ | ||
344 | pos = session->response->first_header; | ||
345 | while (pos != NULL) { | ||
346 | size += strlen(pos->header) + strlen(pos->value) + 4; /* colon, space, linefeeds */ | ||
347 | pos = pos->next; | ||
348 | } | ||
349 | /* produce data */ | ||
350 | data = malloc(size); | ||
351 | memcpy(data, | ||
352 | code, | ||
353 | off); | ||
354 | pos = session->response->first_header; | ||
355 | while (pos != NULL) { | ||
356 | sprintf(&data[off], | ||
357 | "%s: %s\r\n", | ||
358 | pos->header, | ||
359 | pos->value); | ||
360 | off += strlen(pos->header) + strlen(pos->value) + 4; | ||
361 | pos = pos->next; | ||
362 | } | ||
363 | if (off != size) | ||
364 | abort(); | ||
365 | session->write_buffer = data; | ||
366 | session->write_buffer_size = size; | ||
367 | } | ||
335 | 368 | ||
336 | /** | 369 | /** |
337 | * This function was created to handle writes to sockets when it has been | 370 | * This function was created to handle writes to sockets when it has |
338 | * determined that the socket can be written to. If there is no data | 371 | * been determined that the socket can be written to. All |
339 | * to be written, however, the function call does nothing. All implementations | 372 | * implementations (multithreaded, external select, internal select) |
340 | * (multithreaded, external select, internal select) call this function | 373 | * call this function |
341 | */ | 374 | */ |
342 | int | 375 | int |
343 | MHD_session_handle_write(struct MHD_Session * session) { | 376 | MHD_session_handle_write(struct MHD_Session * session) { |
344 | struct MHD_Response * response; | 377 | struct MHD_Response * response; |
345 | int i; | 378 | int ret; |
346 | char * buffer[2048]; | ||
347 | char * responseMessage; | ||
348 | int numBytesInMessage; | ||
349 | 379 | ||
350 | response = session->response; | 380 | response = session->response; |
351 | if(response == NULL) { | 381 | if(response == NULL) { |
352 | /* FIXME: LOG: why are we here? */ | 382 | /* FIXME: LOG: why are we here? */ |
353 | return MHD_NO; | 383 | return MHD_NO; |
354 | } | 384 | } |
355 | numBytesInMessage = 25; | 385 | if (! session->headersSent) { |
356 | responseMessage = malloc(25); | 386 | if (session->write_buffer == NULL) |
357 | 387 | MHD_build_header_response(session); | |
358 | pthread_mutex_lock(&response->mutex); | 388 | ret = send(session->socket_fd, |
359 | 389 | &session->write_buffer[session->writeLoc], | |
360 | if(!response->headersSent) { | 390 | session->write_buffer_size - session->writeLoc, |
361 | sprintf(responseMessage, "HTTP/1.1 %i Go to hell!\r\n", response->responseCode); | 391 | 0); |
362 | fprintf(stderr, "%s\n", responseMessage); | 392 | if (ret < 0) { |
363 | if(send(session->socket_fd, responseMessage, strlen(responseMessage), 0) != strlen(responseMessage)) { | 393 | if (errno == EINTR) |
364 | fprintf(stderr, "Error! could not send an entire header in one call to send! unable to handle this case as of this time.\n"); | 394 | return MHD_YES; |
365 | pthread_mutex_unlock(&response->mutex); | 395 | /* FIXME: log error */ |
366 | return MHD_NO; | 396 | close(session->socket_fd); |
367 | } | 397 | session->socket_fd = -1; |
368 | 398 | return MHD_NO; | |
369 | for(i = 0; i < MHD_MAX_HEADERS; i++) { | 399 | } |
370 | if(response->headers[i] == NULL) | 400 | session->writeLoc += ret; |
371 | continue; | 401 | if (session->writeLoc == session->write_buffer_size) { |
372 | 402 | session->writeLoc = 0; | |
373 | if(strlen(response->headers[i]->header) + strlen(response->headers[i]->value) + 5 > numBytesInMessage) { | 403 | free(session->write_buffer); |
374 | free(responseMessage); | 404 | session->write_buffer = NULL; |
375 | responseMessage = malloc(strlen(response->headers[i]->header) + strlen(response->headers[i]->value) + 5); | 405 | session->write_buffer_size = 0; |
376 | if(responseMessage == NULL) { | 406 | session->headersSent = 1; |
377 | if(daemon->options & MHD_USE_DEBUG) | 407 | } |
378 | fprintf(stderr, "Error allocating memory!\n"); | 408 | return MHD_YES; |
379 | pthread_mutex_unlock(&response->mutex); | 409 | } |
380 | return MHD_NO; | 410 | if (response->total_size <= session->messagePos) |
381 | } | 411 | abort(); /* internal error */ |
382 | numBytesInMessage = strlen(response->headers[i]->header) + strlen(response->headers[i]->value) + 5; | 412 | if (response->crc != NULL) |
383 | } | 413 | pthread_mutex_lock(&response->mutex); |
384 | sprintf(responseMessage, "%s: %s\r\n", response->headers[i]->header, response->headers[i]->value); | 414 | |
385 | fprintf(stderr, "%s\n", responseMessage); | 415 | /* prepare send buffer */ |
386 | if(send(session->socket_fd, responseMessage, strlen(responseMessage), 0) != strlen(responseMessage)) { | 416 | if ( (response->data == NULL) || |
387 | fprintf(stderr, "Error! could not send an entire header in one call to send! unable to handle this case as of this time.\n"); | 417 | (response->data_start > session->messagePos) || |
388 | pthread_mutex_unlock(&response->mutex); | 418 | (response->data_start + response->data_size < session->messagePos) ) { |
389 | return MHD_NO; | 419 | if (response->data_size == 0) { |
390 | } | 420 | if (response->data != NULL) |
391 | } | 421 | free(response->data); |
392 | 422 | response->data = malloc(MHD_MAX_BUF_SIZE); | |
393 | response->headersSent = 1; | 423 | response->data_size = MHD_MAX_BUF_SIZE; |
394 | } | 424 | } |
395 | 425 | ret = response->crc(response->crc_cls, | |
396 | if(response->data != NULL) { | 426 | session->messagePos, |
397 | if(response->bytesSentSoFar == 0) { | 427 | response->data, |
398 | if(numBytesInMessage < 32) { | 428 | MAX(MHD_MAX_BUF_SIZE, |
399 | free(responseMessage); | 429 | response->data_size - session->messagePos)); |
400 | responseMessage = malloc(32); | 430 | if (ret == -1) { |
401 | if(responseMessage == NULL) { | 431 | /* end of message, signal other side by closing! */ |
402 | if(daemon->options & MHD_USE_DEBUG) | 432 | response->data_size = session->messagePos; |
403 | fprintf(stderr, "Error allocating memory!\n"); | 433 | close(session->socket_fd); |
404 | pthread_mutex_unlock(&response->mutex); | 434 | session->socket_fd = -1; |
405 | return MHD_NO; | 435 | return MHD_YES; |
406 | } | 436 | } |
407 | } | 437 | response->data_start = session->messagePos; |
408 | sprintf(responseMessage, "Content-length: %llu\r\n\r\n", (unsigned long long)response->size); | 438 | response->data_size = ret; |
409 | fprintf(stderr, "%s\n", responseMessage); | 439 | if (ret == 0) |
410 | if(send(session->socket_fd, responseMessage, strlen(responseMessage),0)!= strlen(responseMessage)) { | 440 | return MHD_YES; /* or NO? */ |
411 | fprintf(stderr, "Error! could not send an entire header in one call to send! unable to handle this case as of this time.\n"); | 441 | } |
412 | pthread_mutex_unlock(&response->mutex); | 442 | |
413 | return MHD_NO; | 443 | /* transmit */ |
414 | } | 444 | ret = send(session->socket_fd, |
415 | } | 445 | &response->data[session->messagePos - response->data_start], |
416 | 446 | response->data_size - (session->messagePos - response->data_start), | |
417 | i = send(session->socket_fd, response->data+response->bytesSentSoFar, response->size-response->bytesSentSoFar,0); | 447 | 0); |
418 | response->bytesSentSoFar += i; | 448 | if (response->crc != NULL) |
419 | 449 | pthread_mutex_unlock(&response->mutex); | |
420 | fprintf(stderr, "Sent %i bytes of data\nTotal to send is %llu bytes\n", i, (unsigned long long)response->size); | 450 | if (ret == -1) { |
421 | 451 | if (errno == EINTR) | |
422 | if(response->bytesSentSoFar == response->size) { | 452 | return MHD_YES; |
423 | session->currentResponses[session->currentResponse] = NULL; | 453 | /* FIXME: log */ |
424 | session->currentResponse = (session->currentResponse + 1) % MHD_MAX_RESPONSE; | 454 | return MHD_NO; |
425 | response->currentSession = NULL; | 455 | } |
426 | 456 | session->messagePos += ret; | |
427 | if(response->freeWhenFinished) { | 457 | if (session->messagePos == response->data_size) { |
428 | pthread_mutex_unlock(&response->mutex); | 458 | /* reset session, wait for next request! */ |
429 | MHD_destroy_response(response); | 459 | MHD_destroy_response(response); |
430 | } | 460 | session->responseCode = 0; |
431 | /*THIS NEEDS TO BE HANDLED ANOTHER WAY!!! TIMEOUT, ect..., as of now this is the only way to get test case to work | 461 | session->response = NULL; |
432 | * since client never disconnects on their own! | 462 | session->headersReceived = 0; |
433 | */ | 463 | session->headersSent = 0; |
434 | if(session->currentResponses[session->currentResponse] == NULL) { | 464 | session->bodyReceived = 0; |
435 | MHD_destroy_session(session); | 465 | session->messagePos = 0; |
436 | daemon->connections[connection_id] = NULL; | 466 | free(session->write_buffer); |
437 | return MHD_NO; | 467 | session->write_buffer = NULL; |
438 | } | 468 | session->write_buffer_size = 0; |
439 | } | 469 | } |
440 | } else { | 470 | return MHD_YES; |
441 | if(response->crc == NULL) { | ||
442 | pthread_mutex_unlock(&response->mutex); | ||
443 | return MHD_NO; | ||
444 | } | ||
445 | |||
446 | if(response->bytesSentSoFar == 0) { | ||
447 | if(send(session->socket_fd, "\r\n", response->size,0) != 2) { | ||
448 | fprintf(stderr, "Error! could not send an entire header in one call to send! unable to handle this case as of this time.\n"); | ||
449 | pthread_mutex_unlock(&response->mutex); | ||
450 | return MHD_NO; | ||
451 | } | ||
452 | } | ||
453 | memset(buffer, 0, 2048); | ||
454 | |||
455 | i = response->crc(response->crc_cls, response->bytesSentSoFar, (char *)buffer, 2048); | ||
456 | |||
457 | if(i == -1) { | ||
458 | pthread_mutex_unlock(&response->mutex); | ||
459 | |||
460 | session->currentResponses[session->currentResponse] = NULL; | ||
461 | session->currentResponse = (session->currentResponse + 1) % MHD_MAX_RESPONSE; | ||
462 | response->currentSession = NULL; | ||
463 | |||
464 | if(response->freeWhenFinished) { | ||
465 | pthread_mutex_unlock(&response->mutex); | ||
466 | MHD_destroy_response(response); | ||
467 | } | ||
468 | /*THIS NEEDS TO BE HANDLED ANOTHER WAY!!! TIMEOUT, ect..., as of now this is the only way to get test case to work | ||
469 | * since client never disconnects on their own! | ||
470 | */ | ||
471 | if(session->currentResponses[session->currentResponse] == NULL) { | ||
472 | MHD_destroy_session(session); | ||
473 | daemon->connections[connection_id] = NULL; | ||
474 | return MHD_NO; | ||
475 | } | ||
476 | |||
477 | } else { | ||
478 | i = send(session->socket_fd, buffer, i,0); | ||
479 | response->bytesSentSoFar += i; | ||
480 | } | ||
481 | } | ||
482 | pthread_mutex_unlock(&response->mutex); | ||
483 | return MHD_YES; | ||
484 | } | 471 | } |
485 | 472 | ||
486 | 473 | /* end of session.c */ | |
487 | 474 | ||
488 | 475 | ||