aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2007-08-30 06:59:15 +0000
committerChristian Grothoff <christian@grothoff.org>2007-08-30 06:59:15 +0000
commitb259da7c7f97e1fbafeef634bd16af3a21f83e72 (patch)
tree6d51feb9f34832e27e831c8a05bc865186f35a67
parent44f694198ba0d2b9b7172468989a83f6e1e51929 (diff)
downloadlibmicrohttpd-b259da7c7f97e1fbafeef634bd16af3a21f83e72.tar.gz
libmicrohttpd-b259da7c7f97e1fbafeef634bd16af3a21f83e72.zip
improving API to allow clients to associate state with a connection and to be notified about request termination
-rw-r--r--src/daemon/connection.c52
-rw-r--r--src/daemon/daemon.c16
-rw-r--r--src/daemon/daemontest.c3
-rw-r--r--src/daemon/daemontest_get.c3
-rw-r--r--src/daemon/daemontest_large_put.c3
-rw-r--r--src/daemon/daemontest_long_header.c3
-rw-r--r--src/daemon/daemontest_post.c3
-rw-r--r--src/daemon/daemontest_put.c3
-rw-r--r--src/daemon/fileserver_example.c3
-rw-r--r--src/daemon/internal.h12
-rw-r--r--src/daemon/minimal_example.c3
-rw-r--r--src/include/microhttpd.h82
12 files changed, 156 insertions, 30 deletions
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index cdc8540b..1b7a04ed 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -181,6 +181,22 @@ MHD_need_100_continue (struct MHD_Connection *connection)
181} 181}
182 182
183/** 183/**
184 * A serious error occured, close the
185 * connection (and notify the application).
186 */
187static void
188connection_close_error(struct MHD_Connection * connection)
189{
190 CLOSE (connection->socket_fd);
191 connection->socket_fd = -1;
192 if (connection->daemon->notify_completed != NULL)
193 connection->daemon->notify_completed(connection->daemon->notify_completed_cls,
194 connection,
195 &connection->client_context,
196 MHD_REQUEST_TERMINATED_WITH_ERROR);
197}
198
199/**
184 * Prepare the response buffer of this connection for 200 * Prepare the response buffer of this connection for
185 * sending. Assumes that the response mutex is 201 * sending. Assumes that the response mutex is
186 * already held. If the transmission is complete, 202 * already held. If the transmission is complete,
@@ -209,8 +225,7 @@ ready_response (struct MHD_Connection *connection)
209 "Closing connection (end of response)\n"); 225 "Closing connection (end of response)\n");
210#endif 226#endif
211 response->total_size = connection->messagePos; 227 response->total_size = connection->messagePos;
212 CLOSE (connection->socket_fd); 228 connection_close_error(connection);
213 connection->socket_fd = -1;
214 return MHD_NO; 229 return MHD_NO;
215 } 230 }
216 response->data_start = connection->messagePos; 231 response->data_start = connection->messagePos;
@@ -746,8 +761,7 @@ MHD_parse_connection_headers (struct MHD_Connection *connection)
746DIE: 761DIE:
747 MHD_DLOG (connection->daemon, 762 MHD_DLOG (connection->daemon,
748 "Closing connection (problem parsing headers)\n"); 763 "Closing connection (problem parsing headers)\n");
749 CLOSE (connection->socket_fd); 764 connection_close_error(connection);
750 connection->socket_fd = -1;
751} 765}
752 766
753 767
@@ -889,13 +903,13 @@ MHD_call_connection_handler (struct MHD_Connection *connection)
889 connection->url, 903 connection->url,
890 connection->method, 904 connection->method,
891 connection->version, 905 connection->version,
892 connection->read_buffer, &processed)) 906 connection->read_buffer, &processed,
907 &connection->client_context))
893 { 908 {
894 /* serios internal error, close connection */ 909 /* serios internal error, close connection */
895 MHD_DLOG (connection->daemon, 910 MHD_DLOG (connection->daemon,
896 "Internal application error, closing connection.\n"); 911 "Internal application error, closing connection.\n");
897 CLOSE (connection->socket_fd); 912 connection_close_error(connection);
898 connection->socket_fd = -1;
899 return; 913 return;
900 } 914 }
901 /* dh left "processed" bytes in buffer for next time... */ 915 /* dh left "processed" bytes in buffer for next time... */
@@ -934,8 +948,7 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
934 if (connection->pool == NULL) 948 if (connection->pool == NULL)
935 { 949 {
936 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n"); 950 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
937 CLOSE (connection->socket_fd); 951 connection_close_error(connection);
938 connection->socket_fd = -1;
939 return MHD_NO; 952 return MHD_NO;
940 } 953 }
941 if ((connection->readLoc >= connection->read_buffer_size) && 954 if ((connection->readLoc >= connection->read_buffer_size) &&
@@ -973,8 +986,7 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
973 return MHD_NO; 986 return MHD_NO;
974 MHD_DLOG (connection->daemon, 987 MHD_DLOG (connection->daemon,
975 "Failed to receive data: %s\n", STRERROR (errno)); 988 "Failed to receive data: %s\n", STRERROR (errno));
976 CLOSE (connection->socket_fd); 989 connection_close_error(connection);
977 connection->socket_fd = -1;
978 return MHD_YES; 990 return MHD_YES;
979 } 991 }
980 if (bytes_read == 0) 992 if (bytes_read == 0)
@@ -1150,8 +1162,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1150 return MHD_YES; 1162 return MHD_YES;
1151 MHD_DLOG (connection->daemon, 1163 MHD_DLOG (connection->daemon,
1152 "Failed to send data: %s\n", STRERROR (errno)); 1164 "Failed to send data: %s\n", STRERROR (errno));
1153 CLOSE (connection->socket_fd); 1165 connection_close_error(connection);
1154 connection->socket_fd = -1;
1155 return MHD_YES; 1166 return MHD_YES;
1156 } 1167 }
1157#if DEBUG_SEND_DATA 1168#if DEBUG_SEND_DATA
@@ -1176,8 +1187,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1176 /* oops - close! */ 1187 /* oops - close! */
1177 MHD_DLOG (connection->daemon, 1188 MHD_DLOG (connection->daemon,
1178 "Closing connection (failed to create response header)\n"); 1189 "Closing connection (failed to create response header)\n");
1179 CLOSE (connection->socket_fd); 1190 connection_close_error(connection);
1180 connection->socket_fd = -1;
1181 return MHD_NO; 1191 return MHD_NO;
1182 } 1192 }
1183 ret = SEND (connection->socket_fd, 1193 ret = SEND (connection->socket_fd,
@@ -1189,8 +1199,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1189 return MHD_YES; 1199 return MHD_YES;
1190 MHD_DLOG (connection->daemon, 1200 MHD_DLOG (connection->daemon,
1191 "Failed to send data: %s\n", STRERROR (errno)); 1201 "Failed to send data: %s\n", STRERROR (errno));
1192 CLOSE (connection->socket_fd); 1202 connection_close_error(connection);
1193 connection->socket_fd = -1;
1194 return MHD_YES; 1203 return MHD_YES;
1195 } 1204 }
1196#if DEBUG_SEND_DATA 1205#if DEBUG_SEND_DATA
@@ -1240,8 +1249,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1240 return MHD_YES; 1249 return MHD_YES;
1241 MHD_DLOG (connection->daemon, 1250 MHD_DLOG (connection->daemon,
1242 "Failed to send data: %s\n", STRERROR (errno)); 1251 "Failed to send data: %s\n", STRERROR (errno));
1243 CLOSE (connection->socket_fd); 1252 connection_close_error(connection);
1244 connection->socket_fd = -1;
1245 return MHD_YES; 1253 return MHD_YES;
1246 } 1254 }
1247#if DEBUG_SEND_DATA 1255#if DEBUG_SEND_DATA
@@ -1259,6 +1267,12 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1259 (connection->headersReceived == 0)) 1267 (connection->headersReceived == 0))
1260 abort (); /* internal error */ 1268 abort (); /* internal error */
1261 MHD_destroy_response (response); 1269 MHD_destroy_response (response);
1270 if (connection->daemon->notify_completed != NULL)
1271 connection->daemon->notify_completed(connection->daemon->notify_completed_cls,
1272 connection,
1273 &connection->client_context,
1274 MHD_REQUEST_TERMINATED_COMPLETED_OK);
1275 connection->client_context = NULL;
1262 connection->continuePos = 0; 1276 connection->continuePos = 0;
1263 connection->responseCode = 0; 1277 connection->responseCode = 0;
1264 connection->response = NULL; 1278 connection->response = NULL;
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index 35eeccce..2dd7551f 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -354,6 +354,11 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
354#endif 354#endif
355 CLOSE (pos->socket_fd); 355 CLOSE (pos->socket_fd);
356 pos->socket_fd = -1; 356 pos->socket_fd = -1;
357 if (pos->daemon->notify_completed != NULL)
358 pos->daemon->notify_completed(pos->daemon->notify_completed_cls,
359 pos,
360 &pos->client_context,
361 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
357 } 362 }
358 if (pos->socket_fd == -1) 363 if (pos->socket_fd == -1)
359 { 364 {
@@ -680,6 +685,10 @@ MHD_start_daemon (unsigned int options,
680 case MHD_OPTION_CONNECTION_TIMEOUT: 685 case MHD_OPTION_CONNECTION_TIMEOUT:
681 retVal->connection_timeout = va_arg (ap, unsigned int); 686 retVal->connection_timeout = va_arg (ap, unsigned int);
682 break; 687 break;
688 case MHD_OPTION_NOTIFY_COMPLETED:
689 retVal->notify_completed = va_arg(ap, MHD_RequestCompletedCallback);
690 retVal->notify_completed_cls = va_arg(ap, void *);
691 break;
683 default: 692 default:
684 fprintf (stderr, 693 fprintf (stderr,
685 "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n"); 694 "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n");
@@ -733,7 +742,12 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
733 MHD_DLOG (daemon, 742 MHD_DLOG (daemon,
734 "MHD shutdown, closing active connections\n"); 743 "MHD shutdown, closing active connections\n");
735#endif 744#endif
736 CLOSE (daemon->connections->socket_fd); 745 if (daemon->notify_completed != NULL)
746 daemon->notify_completed(daemon->notify_completed_cls,
747 daemon->connections,
748 &daemon->connections->client_context,
749 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
750 CLOSE (daemon->connections->socket_fd);
737 daemon->connections->socket_fd = -1; 751 daemon->connections->socket_fd = -1;
738 } 752 }
739 MHD_cleanup_connections (daemon); 753 MHD_cleanup_connections (daemon);
diff --git a/src/daemon/daemontest.c b/src/daemon/daemontest.c
index 53f56989..2ecb87f2 100644
--- a/src/daemon/daemontest.c
+++ b/src/daemon/daemontest.c
@@ -64,7 +64,8 @@ ahc_nothing (void *cls,
64 const char *url, 64 const char *url,
65 const char *method, 65 const char *method,
66 const char *version, 66 const char *version,
67 const char *upload_data, unsigned int *upload_data_size) 67 const char *upload_data, unsigned int *upload_data_size,
68 void ** unused)
68{ 69{
69 return MHD_NO; 70 return MHD_NO;
70} 71}
diff --git a/src/daemon/daemontest_get.c b/src/daemon/daemontest_get.c
index e8ce1e7a..79726a11 100644
--- a/src/daemon/daemontest_get.c
+++ b/src/daemon/daemontest_get.c
@@ -63,7 +63,8 @@ ahc_echo (void *cls,
63 const char *url, 63 const char *url,
64 const char *method, 64 const char *method,
65 const char *version, 65 const char *version,
66 const char *upload_data, unsigned int *upload_data_size) 66 const char *upload_data, unsigned int *upload_data_size,
67 void ** unused)
67{ 68{
68 const char *me = cls; 69 const char *me = cls;
69 struct MHD_Response *response; 70 struct MHD_Response *response;
diff --git a/src/daemon/daemontest_large_put.c b/src/daemon/daemontest_large_put.c
index e176d29c..f4ae5583 100644
--- a/src/daemon/daemontest_large_put.c
+++ b/src/daemon/daemontest_large_put.c
@@ -85,7 +85,8 @@ ahc_echo (void *cls,
85 const char *url, 85 const char *url,
86 const char *method, 86 const char *method,
87 const char *version, 87 const char *version,
88 const char *upload_data, unsigned int *upload_data_size) 88 const char *upload_data, unsigned int *upload_data_size,
89 void ** unused)
89{ 90{
90 int *done = cls; 91 int *done = cls;
91 struct MHD_Response *response; 92 struct MHD_Response *response;
diff --git a/src/daemon/daemontest_long_header.c b/src/daemon/daemontest_long_header.c
index 6377ac07..6a451136 100644
--- a/src/daemon/daemontest_long_header.c
+++ b/src/daemon/daemontest_long_header.c
@@ -69,7 +69,8 @@ ahc_echo (void *cls,
69 const char *url, 69 const char *url,
70 const char *method, 70 const char *method,
71 const char *version, 71 const char *version,
72 const char *upload_data, unsigned int *upload_data_size) 72 const char *upload_data, unsigned int *upload_data_size,
73 void ** unused)
73{ 74{
74 const char *me = cls; 75 const char *me = cls;
75 struct MHD_Response *response; 76 struct MHD_Response *response;
diff --git a/src/daemon/daemontest_post.c b/src/daemon/daemontest_post.c
index ec60575b..10f6ea97 100644
--- a/src/daemon/daemontest_post.c
+++ b/src/daemon/daemontest_post.c
@@ -69,7 +69,8 @@ ahc_echo (void *cls,
69 const char *url, 69 const char *url,
70 const char *method, 70 const char *method,
71 const char *version, 71 const char *version,
72 const char *upload_data, unsigned int *upload_data_size) 72 const char *upload_data, unsigned int *upload_data_size,
73 void ** unused)
73{ 74{
74 struct MHD_Response *response; 75 struct MHD_Response *response;
75 int ret; 76 int ret;
diff --git a/src/daemon/daemontest_put.c b/src/daemon/daemontest_put.c
index bd3e0a52..f61cfb8e 100644
--- a/src/daemon/daemontest_put.c
+++ b/src/daemon/daemontest_put.c
@@ -76,7 +76,8 @@ ahc_echo (void *cls,
76 const char *url, 76 const char *url,
77 const char *method, 77 const char *method,
78 const char *version, 78 const char *version,
79 const char *upload_data, unsigned int *upload_data_size) 79 const char *upload_data, unsigned int *upload_data_size,
80 void ** unused)
80{ 81{
81 int *done = cls; 82 int *done = cls;
82 struct MHD_Response *response; 83 struct MHD_Response *response;
diff --git a/src/daemon/fileserver_example.c b/src/daemon/fileserver_example.c
index 85b154e3..15b6aa24 100644
--- a/src/daemon/fileserver_example.c
+++ b/src/daemon/fileserver_example.c
@@ -52,7 +52,8 @@ ahc_echo (void *cls,
52 const char *url, 52 const char *url,
53 const char *method, 53 const char *method,
54 const char *upload_data, 54 const char *upload_data,
55 const char *version, unsigned int *upload_data_size) 55 const char *version, unsigned int *upload_data_size,
56 void ** unused)
56{ 57{
57 struct MHD_Response *response; 58 struct MHD_Response *response;
58 int ret; 59 int ret;
diff --git a/src/daemon/internal.h b/src/daemon/internal.h
index 353312b4..b6f8336e 100644
--- a/src/daemon/internal.h
+++ b/src/daemon/internal.h
@@ -203,6 +203,14 @@ struct MHD_Connection
203 struct MemoryPool *pool; 203 struct MemoryPool *pool;
204 204
205 /** 205 /**
206 * We allow the main application to associate some
207 * pointer with the connection. Here is where we
208 * store it. (MHD does not know or care what it
209 * is).
210 */
211 void * client_context;
212
213 /**
206 * Request method. Should be GET/POST/etc. Allocated 214 * Request method. Should be GET/POST/etc. Allocated
207 * in pool. 215 * in pool.
208 */ 216 */
@@ -376,6 +384,10 @@ struct MHD_Daemon
376 384
377 void *apc_cls; 385 void *apc_cls;
378 386
387 MHD_RequestCompletedCallback notify_completed;
388
389 void * notify_completed_cls;
390
379 /** 391 /**
380 * PID of the select thread (if we have internal select) 392 * PID of the select thread (if we have internal select)
381 */ 393 */
diff --git a/src/daemon/minimal_example.c b/src/daemon/minimal_example.c
index 8de0064e..80442072 100644
--- a/src/daemon/minimal_example.c
+++ b/src/daemon/minimal_example.c
@@ -41,7 +41,8 @@ ahc_echo (void *cls,
41 const char *url, 41 const char *url,
42 const char *method, 42 const char *method,
43 const char *upload_data, 43 const char *upload_data,
44 const char *version, unsigned int *upload_data_size) 44 const char *version, unsigned int *upload_data_size,
45 void ** unused)
45{ 46{
46 const char *me = cls; 47 const char *me = cls;
47 struct MHD_Response *response; 48 struct MHD_Response *response;
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index d09c66a9..3a46c085 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -84,7 +84,7 @@ extern "C"
84/** 84/**
85 * Current version of the library. 85 * Current version of the library.
86 */ 86 */
87#define MHD_VERSION 0x00000003 87#define MHD_VERSION 0x00000004
88 88
89/** 89/**
90 * MHD-internal return codes. 90 * MHD-internal return codes.
@@ -319,6 +319,20 @@ enum MHD_OPTION
319 */ 319 */
320 MHD_OPTION_CONNECTION_TIMEOUT = 3, 320 MHD_OPTION_CONNECTION_TIMEOUT = 3,
321 321
322 /**
323 * Register a function that should be called whenever a request has
324 * been completed (this can be used for application-specific clean
325 * up). Requests that have never been presented to the application
326 * (via MHD_AccessHandlerCallback) will not result in
327 * notifications.<p>
328 *
329 * This option should be followed by TWO pointers. First a pointer
330 * to a function of type "MHD_RequestCompletedCallback" and second a
331 * pointer to a closure to pass to the request completed callback.
332 * The second pointer maybe NULL.
333 */
334 MHD_OPTION_NOTIFY_COMPLETED = 4,
335
322}; 336};
323 337
324/** 338/**
@@ -362,6 +376,40 @@ enum MHD_ValueKind
362}; 376};
363 377
364/** 378/**
379 * The MHD_RequestTerminationCode specifies reasons
380 * why a request has been terminated (or completed).
381 */
382enum MHD_RequestTerminationCode
383{
384
385 /**
386 * We finished sending the response.
387 */
388 MHD_REQUEST_TERMINATED_COMPLETED_OK = 0,
389
390 /**
391 * Error handling the connection (resources
392 * exhausted, other side closed connection,
393 * application error accepting request, etc.)
394 */
395 MHD_REQUEST_TERMINATED_WITH_ERROR = 1,
396
397 /**
398 * No activity on the connection for the number
399 * of seconds specified using
400 * MHD_OPTION_CONNECTION_TIMEOUT.
401 */
402 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED = 2,
403
404 /**
405 * We had to close the session since MHD was being
406 * shut down.
407 */
408 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN = 3,
409
410};
411
412/**
365 * Handle for the daemon (listening on a socket for HTTP traffic). 413 * Handle for the daemon (listening on a socket for HTTP traffic).
366 */ 414 */
367struct MHD_Daemon; 415struct MHD_Daemon;
@@ -398,6 +446,8 @@ typedef int
398 * callbacks to provide content to give back to the client and return 446 * callbacks to provide content to give back to the client and return
399 * an HTTP status code (i.e. 200 for OK, 404, etc.). 447 * an HTTP status code (i.e. 200 for OK, 404, etc.).
400 * 448 *
449 * @param cls argument given together with the function
450 * pointer when the handler was registered with MHD
401 * @param url the requested url 451 * @param url the requested url
402 * @param method the HTTP method used ("GET", "PUT", etc.) 452 * @param method the HTTP method used ("GET", "PUT", etc.)
403 * @param version the HTTP version string (i.e. "HTTP/1.1") 453 * @param version the HTTP version string (i.e. "HTTP/1.1")
@@ -411,6 +461,16 @@ typedef int
411 * @param upload_data_size set initially to the size of the 461 * @param upload_data_size set initially to the size of the
412 * upload_data provided; the method must update this 462 * upload_data provided; the method must update this
413 * value to the number of bytes NOT processed; 463 * value to the number of bytes NOT processed;
464 * @param con_cls pointer that the callback can set to some
465 * address and that will be preserved by MHD for future
466 * calls for this request; since the access handler may
467 * be called many times (i.e., for a PUT/POST operation
468 * with plenty of upload data) this allows the application
469 * to easily associate some request-specific state.
470 * If necessary, this state can be cleaned up in the
471 * global "MHD_RequestCompleted" callback (which
472 * can be set with the MHD_OPTION_NOTIFY_COMPLETED).
473 * Initially, <tt>*con_cls</tt> will be NULL.
414 * @return MHS_YES if the connection was handled successfully, 474 * @return MHS_YES if the connection was handled successfully,
415 * MHS_NO if the socket must be closed due to a serios 475 * MHS_NO if the socket must be closed due to a serios
416 * error while handling the request 476 * error while handling the request
@@ -422,7 +482,25 @@ typedef int
422 const char *method, 482 const char *method,
423 const char *version, 483 const char *version,
424 const char *upload_data, 484 const char *upload_data,
425 unsigned int *upload_data_size); 485 unsigned int *upload_data_size,
486 void ** con_cls);
487
488/**
489 * Signature of the callback used by MHD to notify the
490 * application about completed requests.
491 *
492 * @param cls client-defined closure
493 * @param connection connection handle
494 * @param con_cls value as set by the last call to
495 * the MHD_AccessHandlerCallback
496 * @param toe reason for request termination
497 * @see MHD_OPTION_NOTIFY_COMPLETED
498 */
499typedef void
500 (*MHD_RequestCompletedCallback) (void *cls,
501 struct MHD_Connection * connection,
502 void ** con_cls,
503 enum MHD_RequestTerminationCode toe);
426 504
427/** 505/**
428 * Iterator over key-value pairs. This iterator 506 * Iterator over key-value pairs. This iterator