diff options
author | Christian Grothoff <christian@grothoff.org> | 2007-06-13 21:57:36 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2007-06-13 21:57:36 +0000 |
commit | 817a963a53ce67d3efbcf223df0bbe35299dc38e (patch) | |
tree | e2d4dd680d13980efde175b50c81c354dfaf2c87 | |
parent | b0912d1929accce21b75c97ab69c4c499ca9e921 (diff) | |
download | libmicrohttpd-817a963a53ce67d3efbcf223df0bbe35299dc38e.tar.gz libmicrohttpd-817a963a53ce67d3efbcf223df0bbe35299dc38e.zip |
essentials implemented
-rw-r--r-- | README | 12 | ||||
-rw-r--r-- | src/daemon/daemon.c | 21 | ||||
-rw-r--r-- | src/daemon/session.c | 132 | ||||
-rw-r--r-- | src/daemon/session.h | 7 |
4 files changed, 117 insertions, 55 deletions
@@ -5,11 +5,6 @@ things need to be implemented (in list of importance) | |||
5 | before certain features can be used at all: | 5 | before certain features can be used at all: |
6 | 6 | ||
7 | 7 | ||
8 | For ANYTHING: | ||
9 | ============= | ||
10 | session.c: | ||
11 | - MHD_session_get_fdset (essentially not implemented) | ||
12 | |||
13 | For GET args: | 8 | For GET args: |
14 | ============= | 9 | ============= |
15 | session.c: | 10 | session.c: |
@@ -26,6 +21,13 @@ For COOKIES: | |||
26 | session.c: | 21 | session.c: |
27 | - MHD_parse_session_headers: take cookie header apart | 22 | - MHD_parse_session_headers: take cookie header apart |
28 | 23 | ||
24 | For http-compliance: | ||
25 | ==================== | ||
26 | session.c: | ||
27 | - send proper error code back if headers are too long | ||
28 | (investigate what we should do with those headers, | ||
29 | read? give user control?) | ||
30 | |||
29 | For IPv6: | 31 | For IPv6: |
30 | ========= | 32 | ========= |
31 | daemon.c: | 33 | daemon.c: |
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 2a2636db..490317ea 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -163,7 +163,8 @@ MHD_handle_connection(void * data) { | |||
163 | 163 | ||
164 | if (con == NULL) | 164 | if (con == NULL) |
165 | abort(); | 165 | abort(); |
166 | while (! con->daemon->shutdown) { | 166 | while ( (! con->daemon->shutdown) && |
167 | (con->socket_fd != -1) ) { | ||
167 | FD_ZERO(&rs); | 168 | FD_ZERO(&rs); |
168 | FD_ZERO(&ws); | 169 | FD_ZERO(&ws); |
169 | FD_ZERO(&es); | 170 | FD_ZERO(&es); |
@@ -189,8 +190,10 @@ MHD_handle_connection(void * data) { | |||
189 | (MHD_YES != MHD_session_handle_write(con)) ) ) | 190 | (MHD_YES != MHD_session_handle_write(con)) ) ) |
190 | break; | 191 | break; |
191 | } | 192 | } |
192 | close(con->socket_fd); | 193 | if (con->socket_fd != -1) { |
193 | con->socket_fd = -1; | 194 | close(con->socket_fd); |
195 | con->socket_fd = -1; | ||
196 | } | ||
194 | return NULL; | 197 | return NULL; |
195 | } | 198 | } |
196 | 199 | ||
@@ -260,6 +263,11 @@ MHD_accept_connection(struct MHD_Daemon * daemon) { | |||
260 | * Free resources associated with all closed sessions. | 263 | * Free resources associated with all closed sessions. |
261 | * (destroy responses, free buffers, etc.). A session | 264 | * (destroy responses, free buffers, etc.). A session |
262 | * is known to be closed if the socket_fd is -1. | 265 | * is known to be closed if the socket_fd is -1. |
266 | * | ||
267 | * Also performs session actions that need to be run | ||
268 | * even if the session is not selectable (such as | ||
269 | * calling the application again with upload data when | ||
270 | * the upload data buffer is full). | ||
263 | */ | 271 | */ |
264 | static void | 272 | static void |
265 | MHD_cleanup_sessions(struct MHD_Daemon * daemon) { | 273 | MHD_cleanup_sessions(struct MHD_Daemon * daemon) { |
@@ -295,6 +303,13 @@ MHD_cleanup_sessions(struct MHD_Daemon * daemon) { | |||
295 | MHD_destroy_response(pos->response); | 303 | MHD_destroy_response(pos->response); |
296 | free(pos); | 304 | free(pos); |
297 | } | 305 | } |
306 | |||
307 | if ( (pos->headersReceived == 1) && | ||
308 | (pos->read_buffer_size == pos->readLoc) && | ||
309 | (pos->readLoc > 0) ) | ||
310 | MHD_call_session_handler(pos); | ||
311 | |||
312 | |||
298 | prev = pos; | 313 | prev = pos; |
299 | pos = pos->next; | 314 | pos = pos->next; |
300 | } | 315 | } |
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; |
diff --git a/src/daemon/session.h b/src/daemon/session.h index 0097a398..bf072901 100644 --- a/src/daemon/session.h +++ b/src/daemon/session.h | |||
@@ -44,6 +44,13 @@ MHD_session_get_fdset(struct MHD_Session * session, | |||
44 | 44 | ||
45 | 45 | ||
46 | /** | 46 | /** |
47 | * Call the handler of the application for this | ||
48 | * session. | ||
49 | */ | ||
50 | void | ||
51 | MHD_call_session_handler(struct MHD_Session * session); | ||
52 | |||
53 | /** | ||
47 | * This function handles a particular connection when it has been | 54 | * This function handles a particular connection when it has been |
48 | * determined that there is data to be read off a socket. All implementations | 55 | * determined that there is data to be read off a socket. All implementations |
49 | * (multithreaded, external select, internal select) call this function | 56 | * (multithreaded, external select, internal select) call this function |