diff options
Diffstat (limited to 'src/daemon/session.c')
-rw-r--r-- | src/daemon/session.c | 132 |
1 files changed, 85 insertions, 47 deletions
diff --git a/src/daemon/session.c b/src/daemon/session.c index fc713137..ed1b6b88 100644 --- a/src/daemon/session.c +++ b/src/daemon/session.c | |||
@@ -109,7 +109,9 @@ MHD_queue_response(struct MHD_Session * session, | |||
109 | struct MHD_Response * response) { | 109 | struct MHD_Response * response) { |
110 | if ( (session == NULL) || | 110 | if ( (session == NULL) || |
111 | (response == NULL) || | 111 | (response == NULL) || |
112 | (session->response != NULL) ) | 112 | (session->response != NULL) || |
113 | (session->bodyReceived == 0) || | ||
114 | (session->headers_received == 0) ) | ||
113 | return MHD_NO; | 115 | return MHD_NO; |
114 | MHD_increment_response_rc(response); | 116 | MHD_increment_response_rc(response); |
115 | session->response = response; | 117 | session->response = response; |
@@ -129,13 +131,15 @@ MHD_session_get_fdset(struct MHD_Session * session, | |||
129 | fd_set * write_fd_set, | 131 | fd_set * write_fd_set, |
130 | fd_set * except_fd_set, | 132 | fd_set * except_fd_set, |
131 | int * max_fd) { | 133 | int * max_fd) { |
132 | /* FIXME: need to be VERY careful here | 134 | if ( (session->headers_received == 0) || |
133 | determining when the socket is ready for | 135 | (session->readLoc < session->read_buffer_size) ) |
134 | reading/writing; plenty of cases to handle! | 136 | FD_SET(session->socket_fd, read_fd_set); |
135 | (the current code is one big bug) */ | 137 | if (session->response != NULL) |
136 | FD_SET(session->socket_fd, read_fd_set); | 138 | FD_SET(session->socket_fd, write_fd_set); |
137 | FD_SET(session->socket_fd, write_fd_set); | 139 | if ( (session->socket_fd > *max_fd) && |
138 | if (session->socket_fd > *max_fd) | 140 | ( (session->headers_received == 0) || |
141 | (session->readLoc < session->read_buffer_size) || | ||
142 | (session->response != NULL) ) ) | ||
139 | *max_fd = session->socket_fd; | 143 | *max_fd = session->socket_fd; |
140 | return MHD_YES; | 144 | return MHD_YES; |
141 | } | 145 | } |
@@ -233,6 +237,7 @@ MHD_parse_session_headers(struct MHD_Session * session) { | |||
233 | httpType = strstr(uri, " "); | 237 | httpType = strstr(uri, " "); |
234 | if (httpType != NULL) | 238 | if (httpType != NULL) |
235 | httpType[0] = '\0'; | 239 | httpType[0] = '\0'; |
240 | /* FIXME: parse URI some more here */ | ||
236 | session->url = strdup(uri); | 241 | session->url = strdup(uri); |
237 | /* do we want to do anything with httpType? */ | 242 | /* do we want to do anything with httpType? */ |
238 | free(line); | 243 | free(line); |
@@ -267,9 +272,9 @@ MHD_parse_session_headers(struct MHD_Session * session) { | |||
267 | hdr->kind = MHD_HEADER_KIND; | 272 | hdr->kind = MHD_HEADER_KIND; |
268 | session->headers_received = hdr; | 273 | session->headers_received = hdr; |
269 | } | 274 | } |
275 | /* FIXME: here: find cookie header and parse that! */ | ||
270 | if (session->bodyReceived == 0) | 276 | if (session->bodyReceived == 0) |
271 | return; | 277 | return; |
272 | /* FIXME: here: find cookie header and parse that! */ | ||
273 | return; | 278 | return; |
274 | DIE: | 279 | DIE: |
275 | close(session->socket_fd); | 280 | close(session->socket_fd); |
@@ -295,6 +300,48 @@ MHD_find_access_handler(struct MHD_Session * session) { | |||
295 | } | 300 | } |
296 | 301 | ||
297 | /** | 302 | /** |
303 | * Call the handler of the application for this | ||
304 | * session. | ||
305 | */ | ||
306 | void | ||
307 | MHD_call_session_handler(struct MHD_Session * session) { | ||
308 | struct MHD_Access_Handler * ah; | ||
309 | unsigned int processed; | ||
310 | |||
311 | if (session->headers_received == 0) | ||
312 | abort(); /* bad timing... */ | ||
313 | ah = MHD_find_access_handler(session); | ||
314 | processed = session->readLoc; | ||
315 | if (MHD_NO == ah->dh(ah->dh_cls, | ||
316 | session, | ||
317 | session->url, | ||
318 | session->method, | ||
319 | session->read_buffer, | ||
320 | &processed)) { | ||
321 | /* serios internal error, close connection */ | ||
322 | MHD_DLOG(session->daemon, | ||
323 | "Internal application error, closing connection."); | ||
324 | close(session->socket_fd); | ||
325 | session->socket_fd = -1; | ||
326 | return; | ||
327 | } | ||
328 | /* dh left "processed" bytes in buffer for next time... */ | ||
329 | memmove(session->read_buffer, | ||
330 | &session->read_buffer[session->readLoc - processed], | ||
331 | processed); | ||
332 | session->readLoc = processed; | ||
333 | session->uploadSize -= processed; | ||
334 | if (session->uploadSize == 0) { | ||
335 | session->bodyReceived = 1; | ||
336 | session->readLoc = 0; | ||
337 | session->read_buffer_size = 0; | ||
338 | free(session->read_buffer); | ||
339 | session->read_buffer = NULL; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | |||
344 | /** | ||
298 | * This function handles a particular connection when it has been | 345 | * This function handles a particular connection when it has been |
299 | * determined that there is data to be read off a socket. All implementations | 346 | * determined that there is data to be read off a socket. All implementations |
300 | * (multithreaded, external select, internal select) call this function | 347 | * (multithreaded, external select, internal select) call this function |
@@ -304,16 +351,10 @@ int | |||
304 | MHD_session_handle_read(struct MHD_Session * session) { | 351 | MHD_session_handle_read(struct MHD_Session * session) { |
305 | int bytes_read; | 352 | int bytes_read; |
306 | void * tmp; | 353 | void * tmp; |
307 | struct MHD_Access_Handler * ah; | 354 | |
308 | unsigned int processed; | ||
309 | 355 | ||
310 | if (session->bodyReceived) { | 356 | if ( (session->readLoc >= session->read_buffer_size) && |
311 | MHD_DLOG(session->daemon, | 357 | (session->headers_received == 0) ) { |
312 | "Unexpected call to %s.\n", | ||
313 | __FUNCTION__); | ||
314 | return MHD_NO; | ||
315 | } | ||
316 | if (session->readLoc >= session->read_buffer_size) { | ||
317 | /* need to grow read buffer */ | 358 | /* need to grow read buffer */ |
318 | tmp = malloc(session->read_buffer_size * 2 + MHD_MAX_BUF_SIZE); | 359 | tmp = malloc(session->read_buffer_size * 2 + MHD_MAX_BUF_SIZE); |
319 | memcpy(tmp, | 360 | memcpy(tmp, |
@@ -321,6 +362,12 @@ MHD_session_handle_read(struct MHD_Session * session) { | |||
321 | session->read_buffer_size); | 362 | session->read_buffer_size); |
322 | session->read_buffer_size = session->read_buffer_size * 2 + MHD_MAX_BUF_SIZE; | 363 | session->read_buffer_size = session->read_buffer_size * 2 + MHD_MAX_BUF_SIZE; |
323 | } | 364 | } |
365 | if (session->readLoc >= session->read_buffer_size) { | ||
366 | MHD_DLOG(session->daemon, | ||
367 | "Unexpected call to %s.\n", | ||
368 | __FUNCTION__); | ||
369 | return MHD_NO; | ||
370 | } | ||
324 | bytes_read = recv(session->socket_fd, | 371 | bytes_read = recv(session->socket_fd, |
325 | &session->read_buffer[session->readLoc], | 372 | &session->read_buffer[session->readLoc], |
326 | session->read_buffer_size - session->readLoc, | 373 | session->read_buffer_size - session->readLoc, |
@@ -331,39 +378,24 @@ MHD_session_handle_read(struct MHD_Session * session) { | |||
331 | MHD_DLOG(session->daemon, | 378 | MHD_DLOG(session->daemon, |
332 | "Failed to receive data: %s\n", | 379 | "Failed to receive data: %s\n", |
333 | strerror(errno)); | 380 | strerror(errno)); |
334 | return MHD_NO; | 381 | close(session->socket_fd); |
382 | session->socket_fd = -1; | ||
383 | return MHD_YES; | ||
335 | } | 384 | } |
336 | if (bytes_read == 0) { | 385 | if (bytes_read == 0) { |
337 | /* other side closed connection */ | 386 | /* other side closed connection */ |
387 | /* FIXME: proper handling of end of upload! | ||
388 | If we were receiving an unbounded upload, | ||
389 | we should finish up nicely now! */ | ||
338 | close(session->socket_fd); | 390 | close(session->socket_fd); |
339 | session->socket_fd = -1; | 391 | session->socket_fd = -1; |
340 | return MHD_NO; | 392 | return MHD_YES; |
341 | } | 393 | } |
342 | session->readLoc += bytes_read; | 394 | session->readLoc += bytes_read; |
343 | if (session->headersReceived == 0) | 395 | if (session->headersReceived == 0) |
344 | MHD_parse_session_headers(session); | 396 | MHD_parse_session_headers(session); |
345 | if (session->headersReceived == 1) { | 397 | if (session->headersReceived == 1) |
346 | ah = MHD_find_access_handler(session); | 398 | MHD_call_session_handler(session); |
347 | processed = session->readLoc; | ||
348 | if (MHD_NO == ah->dh(ah->dh_cls, | ||
349 | session, | ||
350 | session->url, | ||
351 | session->method, | ||
352 | session->read_buffer, | ||
353 | &processed)) { | ||
354 | /* serios error, close connection */ | ||
355 | close(session->socket_fd); | ||
356 | session->socket_fd = -1; | ||
357 | return MHD_NO; | ||
358 | } | ||
359 | /* dh left "processed" bytes in buffer for next time... */ | ||
360 | memmove(session->read_buffer, | ||
361 | &session->read_buffer[session->readLoc - processed], | ||
362 | processed); | ||
363 | session->readLoc = processed; | ||
364 | session->uploadSize -= processed; | ||
365 | /* FIXME: proper handling of end of upload! */ | ||
366 | } | ||
367 | return MHD_YES; | 399 | return MHD_YES; |
368 | } | 400 | } |
369 | 401 | ||
@@ -447,7 +479,7 @@ MHD_session_handle_write(struct MHD_Session * session) { | |||
447 | strerror(errno)); | 479 | strerror(errno)); |
448 | close(session->socket_fd); | 480 | close(session->socket_fd); |
449 | session->socket_fd = -1; | 481 | session->socket_fd = -1; |
450 | return MHD_NO; | 482 | return MHD_YES; |
451 | } | 483 | } |
452 | session->writeLoc += ret; | 484 | session->writeLoc += ret; |
453 | if (session->writeLoc == session->write_buffer_size) { | 485 | if (session->writeLoc == session->write_buffer_size) { |
@@ -489,7 +521,7 @@ MHD_session_handle_write(struct MHD_Session * session) { | |||
489 | response->data_start = session->messagePos; | 521 | response->data_start = session->messagePos; |
490 | response->data_size = ret; | 522 | response->data_size = ret; |
491 | if (ret == 0) | 523 | if (ret == 0) |
492 | return MHD_YES; /* or NO? */ | 524 | return MHD_YES; |
493 | } | 525 | } |
494 | 526 | ||
495 | /* transmit */ | 527 | /* transmit */ |
@@ -499,17 +531,23 @@ MHD_session_handle_write(struct MHD_Session * session) { | |||
499 | 0); | 531 | 0); |
500 | if (response->crc != NULL) | 532 | if (response->crc != NULL) |
501 | pthread_mutex_unlock(&response->mutex); | 533 | pthread_mutex_unlock(&response->mutex); |
502 | if (ret == -1) { | 534 | if (ret < 0) { |
503 | if (errno == EINTR) | 535 | if (errno == EINTR) |
504 | return MHD_YES; | 536 | return MHD_YES; |
505 | MHD_DLOG(session->daemon, | 537 | MHD_DLOG(session->daemon, |
506 | "Failed to send data: %s\n", | 538 | "Failed to send data: %s\n", |
507 | strerror(errno)); | 539 | strerror(errno)); |
508 | return MHD_NO; | 540 | close(session->socket_fd); |
541 | session->socket_fd = -1; | ||
542 | return MHD_YES; | ||
509 | } | 543 | } |
510 | session->messagePos += ret; | 544 | session->messagePos += ret; |
545 | if (session->messagePos > response->data_size) | ||
546 | abort(); /* internal error */ | ||
511 | if (session->messagePos == response->data_size) { | 547 | if (session->messagePos == response->data_size) { |
512 | /* reset session, wait for next request! */ | 548 | if ( (session->bodyReceived == 0) || |
549 | (session->headers_received == 0) ) | ||
550 | abort(); /* internal error */ | ||
513 | MHD_destroy_response(response); | 551 | MHD_destroy_response(response); |
514 | session->responseCode = 0; | 552 | session->responseCode = 0; |
515 | session->response = NULL; | 553 | session->response = NULL; |