aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README12
-rw-r--r--src/daemon/daemon.c21
-rw-r--r--src/daemon/session.c132
-rw-r--r--src/daemon/session.h7
4 files changed, 117 insertions, 55 deletions
diff --git a/README b/README
index 70219998..ab45ad10 100644
--- a/README
+++ b/README
@@ -5,11 +5,6 @@ things need to be implemented (in list of importance)
5before certain features can be used at all: 5before certain features can be used at all:
6 6
7 7
8For ANYTHING:
9=============
10session.c:
11- MHD_session_get_fdset (essentially not implemented)
12
13For GET args: 8For GET args:
14============= 9=============
15session.c: 10session.c:
@@ -26,6 +21,13 @@ For COOKIES:
26session.c: 21session.c:
27- MHD_parse_session_headers: take cookie header apart 22- MHD_parse_session_headers: take cookie header apart
28 23
24For http-compliance:
25====================
26session.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
29For IPv6: 31For IPv6:
30========= 32=========
31daemon.c: 33daemon.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 */
264static void 272static void
265MHD_cleanup_sessions(struct MHD_Daemon * daemon) { 273MHD_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 */
306void
307MHD_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
304MHD_session_handle_read(struct MHD_Session * session) { 351MHD_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 */
50void
51MHD_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