diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2020-08-06 14:40:17 +0200 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2020-08-06 14:40:17 +0200 |
commit | 6ab14a20690a499ad32e3f2ad448d64d4e6b65fc (patch) | |
tree | 7866fb31e10cd49b2bb00eaf23134945b506624d /src/rest/gnunet-rest-server.c | |
parent | 1d4f5263ae72c12a42ec166ec8b1769620baaeda (diff) | |
download | gnunet-6ab14a20690a499ad32e3f2ad448d64d4e6b65fc.tar.gz gnunet-6ab14a20690a499ad32e3f2ad448d64d4e6b65fc.zip |
-fix various bugs
Diffstat (limited to 'src/rest/gnunet-rest-server.c')
-rw-r--r-- | src/rest/gnunet-rest-server.c | 241 |
1 files changed, 208 insertions, 33 deletions
diff --git a/src/rest/gnunet-rest-server.c b/src/rest/gnunet-rest-server.c index 44d4f345e..436b5b205 100644 --- a/src/rest/gnunet-rest-server.c +++ b/src/rest/gnunet-rest-server.c | |||
@@ -184,6 +184,42 @@ struct MhdConnectionHandle | |||
184 | int state; | 184 | int state; |
185 | }; | 185 | }; |
186 | 186 | ||
187 | /** | ||
188 | * Accepted requests | ||
189 | */ | ||
190 | struct AcceptedRequest | ||
191 | { | ||
192 | /** | ||
193 | * DLL | ||
194 | */ | ||
195 | struct AcceptedRequest *next; | ||
196 | |||
197 | /** | ||
198 | * DLL | ||
199 | */ | ||
200 | struct AcceptedRequest *prev; | ||
201 | |||
202 | /** | ||
203 | * Socket | ||
204 | */ | ||
205 | struct GNUNET_NETWORK_Handle *sock; | ||
206 | |||
207 | /** | ||
208 | * Connection | ||
209 | */ | ||
210 | struct MhdConnectionHandle *con_handle; | ||
211 | }; | ||
212 | |||
213 | /** | ||
214 | * AcceptedRequest list head | ||
215 | */ | ||
216 | static struct AcceptedRequest *req_list_head; | ||
217 | |||
218 | /** | ||
219 | * AcceptedRequest list tail | ||
220 | */ | ||
221 | static struct AcceptedRequest *req_list_tail; | ||
222 | |||
187 | /* ************************* Global helpers ********************* */ | 223 | /* ************************* Global helpers ********************* */ |
188 | 224 | ||
189 | 225 | ||
@@ -238,7 +274,6 @@ cleanup_url_map (void *cls, const struct GNUNET_HashCode *key, void *value) | |||
238 | return GNUNET_YES; | 274 | return GNUNET_YES; |
239 | } | 275 | } |
240 | 276 | ||
241 | |||
242 | static void | 277 | static void |
243 | cleanup_handle (struct MhdConnectionHandle *handle) | 278 | cleanup_handle (struct MhdConnectionHandle *handle) |
244 | { | 279 | { |
@@ -268,6 +303,19 @@ cleanup_handle (struct MhdConnectionHandle *handle) | |||
268 | GNUNET_free (handle); | 303 | GNUNET_free (handle); |
269 | } | 304 | } |
270 | 305 | ||
306 | static void | ||
307 | cleanup_ar (struct AcceptedRequest *ar) | ||
308 | { | ||
309 | if (NULL != ar->con_handle) | ||
310 | { | ||
311 | cleanup_handle (ar->con_handle); | ||
312 | } | ||
313 | GNUNET_NETWORK_socket_free_memory_only_ (ar->sock); | ||
314 | GNUNET_CONTAINER_DLL_remove (req_list_head, | ||
315 | req_list_tail, | ||
316 | ar); | ||
317 | GNUNET_free (ar); | ||
318 | } | ||
271 | 319 | ||
272 | static int | 320 | static int |
273 | header_iterator (void *cls, | 321 | header_iterator (void *cls, |
@@ -404,22 +452,29 @@ create_response (void *cls, | |||
404 | void **con_cls) | 452 | void **con_cls) |
405 | { | 453 | { |
406 | char *origin; | 454 | char *origin; |
455 | struct AcceptedRequest *ar; | ||
407 | struct GNUNET_HashCode key; | 456 | struct GNUNET_HashCode key; |
408 | struct MhdConnectionHandle *con_handle; | 457 | struct MhdConnectionHandle *con_handle; |
409 | struct GNUNET_REST_RequestHandle *rest_conndata_handle; | 458 | struct GNUNET_REST_RequestHandle *rest_conndata_handle; |
410 | struct PluginListEntry *ple; | 459 | struct PluginListEntry *ple; |
411 | 460 | ||
412 | con_handle = *con_cls; | 461 | ar = *con_cls; |
462 | if (NULL == ar) | ||
463 | { | ||
464 | GNUNET_break (0); | ||
465 | return MHD_NO; | ||
466 | } | ||
413 | 467 | ||
414 | if (NULL == *con_cls) | 468 | if (NULL == ar->con_handle) |
415 | { | 469 | { |
416 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New connection %s\n", url); | 470 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New connection %s\n", url); |
417 | con_handle = GNUNET_new (struct MhdConnectionHandle); | 471 | con_handle = GNUNET_new (struct MhdConnectionHandle); |
418 | con_handle->con = con; | 472 | con_handle->con = con; |
419 | con_handle->state = GN_REST_STATE_INIT; | 473 | con_handle->state = GN_REST_STATE_INIT; |
420 | *con_cls = con_handle; | 474 | ar->con_handle = con_handle; |
421 | return MHD_YES; | 475 | return MHD_YES; |
422 | } | 476 | } |
477 | con_handle = ar->con_handle; | ||
423 | if (GN_REST_STATE_INIT == con_handle->state) | 478 | if (GN_REST_STATE_INIT == con_handle->state) |
424 | { | 479 | { |
425 | rest_conndata_handle = GNUNET_new (struct GNUNET_REST_RequestHandle); | 480 | rest_conndata_handle = GNUNET_new (struct GNUNET_REST_RequestHandle); |
@@ -535,7 +590,7 @@ create_response (void *cls, | |||
535 | MHD_RESULT ret = MHD_queue_response (con, | 590 | MHD_RESULT ret = MHD_queue_response (con, |
536 | con_handle->status, | 591 | con_handle->status, |
537 | con_handle->response); | 592 | con_handle->response); |
538 | cleanup_handle (con_handle); | 593 | //cleanup_handle (con_handle); |
539 | return ret; | 594 | return ret; |
540 | } | 595 | } |
541 | } | 596 | } |
@@ -543,27 +598,6 @@ create_response (void *cls, | |||
543 | 598 | ||
544 | /* ******************** MHD HTTP setup and event loop ******************** */ | 599 | /* ******************** MHD HTTP setup and event loop ******************** */ |
545 | 600 | ||
546 | /** | ||
547 | * Function called when MHD decides that we are done with a connection. | ||
548 | * | ||
549 | * @param cls NULL | ||
550 | * @param connection connection handle | ||
551 | * @param con_cls value as set by the last call to | ||
552 | * the MHD_AccessHandlerCallback, should be our handle | ||
553 | * @param toe reason for request termination (ignored) | ||
554 | */ | ||
555 | static void | ||
556 | mhd_completed_cb (void *cls, | ||
557 | struct MHD_Connection *connection, | ||
558 | void **con_cls, | ||
559 | enum MHD_RequestTerminationCode toe) | ||
560 | { | ||
561 | if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe) | ||
562 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
563 | "MHD encountered error handling request: %d\n", | ||
564 | toe); | ||
565 | } | ||
566 | |||
567 | 601 | ||
568 | /** | 602 | /** |
569 | * Kill the MHD daemon. | 603 | * Kill the MHD daemon. |
@@ -671,6 +705,135 @@ schedule_httpd () | |||
671 | GNUNET_NETWORK_fdset_destroy (wws); | 705 | GNUNET_NETWORK_fdset_destroy (wws); |
672 | } | 706 | } |
673 | 707 | ||
708 | /** | ||
709 | * Function called when MHD first processes an incoming connection. | ||
710 | * Gives us the respective URI information. | ||
711 | * | ||
712 | * We use this to associate the `struct MHD_Connection` with our | ||
713 | * internal `struct AcceptedRequest` data structure (by checking | ||
714 | * for matching sockets). | ||
715 | * | ||
716 | * @param cls the HTTP server handle (a `struct MhdHttpList`) | ||
717 | * @param url the URL that is being requested | ||
718 | * @param connection MHD connection object for the request | ||
719 | * @return the `struct Socks5Request` that this @a connection is for | ||
720 | */ | ||
721 | static void * | ||
722 | mhd_log_callback (void *cls, | ||
723 | const char *url, | ||
724 | struct MHD_Connection *connection) | ||
725 | { | ||
726 | struct AcceptedRequest *ar; | ||
727 | const union MHD_ConnectionInfo *ci; | ||
728 | |||
729 | ci = MHD_get_connection_info (connection, | ||
730 | MHD_CONNECTION_INFO_SOCKET_CONTEXT); | ||
731 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing %s\n", url); | ||
732 | if (NULL == ci) | ||
733 | { | ||
734 | GNUNET_break (0); | ||
735 | return NULL; | ||
736 | } | ||
737 | ar = ci->socket_context; | ||
738 | return ar; | ||
739 | } | ||
740 | |||
741 | |||
742 | |||
743 | /** | ||
744 | * Function called when MHD decides that we are done with a connection. | ||
745 | * | ||
746 | * @param cls NULL | ||
747 | * @param connection connection handle | ||
748 | * @param con_cls value as set by the last call to | ||
749 | * the MHD_AccessHandlerCallback, should be our handle | ||
750 | * @param toe reason for request termination (ignored) | ||
751 | */ | ||
752 | static void | ||
753 | mhd_completed_cb (void *cls, | ||
754 | struct MHD_Connection *connection, | ||
755 | void **con_cls, | ||
756 | enum MHD_RequestTerminationCode toe) | ||
757 | { | ||
758 | struct AcceptedRequest *ar = *con_cls; | ||
759 | if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe) | ||
760 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
761 | "MHD encountered error handling request: %d\n", | ||
762 | toe); | ||
763 | if (NULL == ar) | ||
764 | return; | ||
765 | if (NULL != ar->con_handle) | ||
766 | { | ||
767 | cleanup_handle (ar->con_handle); | ||
768 | ar->con_handle = NULL; | ||
769 | } | ||
770 | schedule_httpd (); | ||
771 | *con_cls = NULL; | ||
772 | } | ||
773 | |||
774 | /** | ||
775 | * Function called when MHD connection is opened or closed. | ||
776 | * | ||
777 | * @param cls NULL | ||
778 | * @param connection connection handle | ||
779 | * @param con_cls value as set by the last call to | ||
780 | * the MHD_AccessHandlerCallback, should be our `struct Socks5Request *` | ||
781 | * @param toe connection notification type | ||
782 | */ | ||
783 | static void | ||
784 | mhd_connection_cb (void *cls, | ||
785 | struct MHD_Connection *connection, | ||
786 | void **con_cls, | ||
787 | enum MHD_ConnectionNotificationCode cnc) | ||
788 | { | ||
789 | struct AcceptedRequest *ar; | ||
790 | const union MHD_ConnectionInfo *ci; | ||
791 | int sock; | ||
792 | |||
793 | switch (cnc) | ||
794 | { | ||
795 | case MHD_CONNECTION_NOTIFY_STARTED: | ||
796 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection started...\n"); | ||
797 | ci = MHD_get_connection_info (connection, | ||
798 | MHD_CONNECTION_INFO_CONNECTION_FD); | ||
799 | if (NULL == ci) | ||
800 | { | ||
801 | GNUNET_break (0); | ||
802 | return; | ||
803 | } | ||
804 | sock = ci->connect_fd; | ||
805 | for (ar = req_list_head; NULL != ar; ar = ar->next) | ||
806 | { | ||
807 | if (GNUNET_NETWORK_get_fd (ar->sock) == sock) | ||
808 | { | ||
809 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
810 | "Context set...\n"); | ||
811 | *con_cls = ar; | ||
812 | break; | ||
813 | } | ||
814 | } | ||
815 | break; | ||
816 | |||
817 | case MHD_CONNECTION_NOTIFY_CLOSED: | ||
818 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
819 | "Connection closed... cleaning up\n"); | ||
820 | ar = *con_cls; | ||
821 | if (NULL == ar) | ||
822 | { | ||
823 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
824 | "Connection stale!\n"); | ||
825 | return; | ||
826 | } | ||
827 | cleanup_ar (ar); | ||
828 | *con_cls = NULL; | ||
829 | break; | ||
830 | |||
831 | default: | ||
832 | GNUNET_break (0); | ||
833 | } | ||
834 | } | ||
835 | |||
836 | |||
674 | 837 | ||
675 | /** | 838 | /** |
676 | * Task run whenever HTTP server operations are pending. | 839 | * Task run whenever HTTP server operations are pending. |
@@ -696,7 +859,7 @@ static void | |||
696 | do_accept (void *cls) | 859 | do_accept (void *cls) |
697 | { | 860 | { |
698 | struct GNUNET_NETWORK_Handle *lsock = cls; | 861 | struct GNUNET_NETWORK_Handle *lsock = cls; |
699 | struct GNUNET_NETWORK_Handle *s; | 862 | struct AcceptedRequest *ar; |
700 | int fd; | 863 | int fd; |
701 | const struct sockaddr *addr; | 864 | const struct sockaddr *addr; |
702 | socklen_t len; | 865 | socklen_t len; |
@@ -718,24 +881,30 @@ do_accept (void *cls) | |||
718 | } | 881 | } |
719 | else | 882 | else |
720 | GNUNET_assert (0); | 883 | GNUNET_assert (0); |
721 | s = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL); | 884 | ar = GNUNET_new (struct AcceptedRequest); |
722 | if (NULL == s) | 885 | ar->sock = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL); |
886 | if (NULL == ar->sock) | ||
723 | { | 887 | { |
888 | GNUNET_free (ar); | ||
724 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "accept"); | 889 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "accept"); |
725 | return; | 890 | return; |
726 | } | 891 | } |
727 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 892 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
728 | "Got an inbound connection, waiting for data\n"); | 893 | "Got an inbound connection, waiting for data\n"); |
729 | fd = GNUNET_NETWORK_get_fd (s); | 894 | fd = GNUNET_NETWORK_get_fd (ar->sock); |
730 | addr = GNUNET_NETWORK_get_addr (s); | 895 | addr = GNUNET_NETWORK_get_addr (ar->sock); |
731 | len = GNUNET_NETWORK_get_addrlen (s); | 896 | len = GNUNET_NETWORK_get_addrlen (ar->sock); |
897 | GNUNET_CONTAINER_DLL_insert (req_list_head, | ||
898 | req_list_tail, | ||
899 | ar); | ||
732 | if (MHD_YES != MHD_add_connection (httpd, fd, addr, len)) | 900 | if (MHD_YES != MHD_add_connection (httpd, fd, addr, len)) |
733 | { | 901 | { |
902 | GNUNET_NETWORK_socket_close (ar->sock); | ||
903 | GNUNET_free (ar); | ||
734 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 904 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
735 | _ ("Failed to pass client to MHD\n")); | 905 | _ ("Failed to pass client to MHD\n")); |
736 | return; | 906 | return; |
737 | } | 907 | } |
738 | GNUNET_free (s); | ||
739 | schedule_httpd (); | 908 | schedule_httpd (); |
740 | } | 909 | } |
741 | 910 | ||
@@ -1032,6 +1201,12 @@ run (void *cls, | |||
1032 | NULL, | 1201 | NULL, |
1033 | MHD_OPTION_CONNECTION_TIMEOUT, | 1202 | MHD_OPTION_CONNECTION_TIMEOUT, |
1034 | (unsigned int) 16, | 1203 | (unsigned int) 16, |
1204 | MHD_OPTION_NOTIFY_CONNECTION, | ||
1205 | &mhd_connection_cb, | ||
1206 | NULL, | ||
1207 | MHD_OPTION_URI_LOG_CALLBACK, | ||
1208 | mhd_log_callback, | ||
1209 | NULL, | ||
1035 | MHD_OPTION_NOTIFY_COMPLETED, | 1210 | MHD_OPTION_NOTIFY_COMPLETED, |
1036 | &mhd_completed_cb, | 1211 | &mhd_completed_cb, |
1037 | NULL, | 1212 | NULL, |