diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2012-08-24 13:02:21 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2012-08-24 13:02:21 +0000 |
commit | aee1bb6ec558c431f68c07df6e90198a31cd5f91 (patch) | |
tree | 2f34c8da27b7ec8f5d6f1bf947cf0b935e6a131b /src | |
parent | e58a85b4f948b764544a48a684a20e7a1522367e (diff) | |
download | gnunet-aee1bb6ec558c431f68c07df6e90198a31cd5f91.tar.gz gnunet-aee1bb6ec558c431f68c07df6e90198a31cd5f91.zip |
code
Diffstat (limited to 'src')
-rw-r--r-- | src/transport/plugin_transport_http_server.c | 582 |
1 files changed, 321 insertions, 261 deletions
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c index e3cd73559..cd539a861 100644 --- a/src/transport/plugin_transport_http_server.c +++ b/src/transport/plugin_transport_http_server.c | |||
@@ -46,14 +46,14 @@ | |||
46 | #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_server_done | 46 | #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_server_done |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define HTTP_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) | ||
50 | |||
51 | #define TESTING GNUNET_NO | 49 | #define TESTING GNUNET_NO |
52 | 50 | ||
53 | #if TESTING | 51 | #if TESTING |
54 | #define TIMEOUT_LOG GNUNET_ERROR_TYPE_ERROR | 52 | #define TIMEOUT_LOG GNUNET_ERROR_TYPE_ERROR |
55 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | 53 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) |
54 | #define HTTP_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
56 | #else | 55 | #else |
56 | #define HTTP_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) | ||
57 | #define TIMEOUT_LOG GNUNET_ERROR_TYPE_DEBUG | 57 | #define TIMEOUT_LOG GNUNET_ERROR_TYPE_DEBUG |
58 | #define TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT | 58 | #define TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT |
59 | #endif | 59 | #endif |
@@ -123,14 +123,11 @@ struct Session | |||
123 | */ | 123 | */ |
124 | void *addr; | 124 | void *addr; |
125 | 125 | ||
126 | size_t addrlen; | ||
127 | 126 | ||
128 | /** | 127 | /** |
129 | * Inbound or outbound connection | 128 | * Address length |
130 | * Outbound: GNUNET_NO (client is used to send and receive) | ||
131 | * Inbound : GNUNET_YES (server is used to send and receive) | ||
132 | */ | 129 | */ |
133 | int inbound; | 130 | size_t addrlen; |
134 | 131 | ||
135 | /** | 132 | /** |
136 | * Unique HTTP/S connection tag for this connection | 133 | * Unique HTTP/S connection tag for this connection |
@@ -143,6 +140,11 @@ struct Session | |||
143 | uint32_t ats_address_network_type; | 140 | uint32_t ats_address_network_type; |
144 | 141 | ||
145 | /** | 142 | /** |
143 | * Was session given to transport service? | ||
144 | */ | ||
145 | int session_passed; | ||
146 | |||
147 | /** | ||
146 | * Absolute time when to receive data again | 148 | * Absolute time when to receive data again |
147 | * Used for receive throttling | 149 | * Used for receive throttling |
148 | */ | 150 | */ |
@@ -261,9 +263,9 @@ struct HTTP_Server_Plugin | |||
261 | * A full session consists of 2 semi-connections: send and receive | 263 | * A full session consists of 2 semi-connections: send and receive |
262 | * If not both directions are established the server keeps this sessions here | 264 | * If not both directions are established the server keeps this sessions here |
263 | */ | 265 | */ |
264 | struct Session *server_semi_head; | 266 | //struct Session *server_semi_head; |
265 | 267 | ||
266 | struct Session *server_semi_tail; | 268 | //struct Session *server_semi_tail; |
267 | 269 | ||
268 | /** | 270 | /** |
269 | * List of own addresses | 271 | * List of own addresses |
@@ -429,6 +431,25 @@ static void | |||
429 | server_stop_session_timeout (struct Session *s); | 431 | server_stop_session_timeout (struct Session *s); |
430 | 432 | ||
431 | /** | 433 | /** |
434 | * Disconnect a session | ||
435 | */ | ||
436 | int | ||
437 | server_disconnect (struct Session *s); | ||
438 | |||
439 | int | ||
440 | server_exist_session (struct HTTP_Server_Plugin *plugin, struct Session *s); | ||
441 | |||
442 | /** | ||
443 | * Reschedule the execution of both IPv4 and IPv6 server | ||
444 | * @param plugin the plugin | ||
445 | * @param server which server to schedule v4 or v6? | ||
446 | * @param now GNUNET_YES to schedule execution immediately, GNUNET_NO to wait | ||
447 | * until timeout | ||
448 | */ | ||
449 | static void | ||
450 | server_reschedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *server, int now); | ||
451 | |||
452 | /** | ||
432 | * Function that can be used by the transport service to transmit | 453 | * Function that can be used by the transport service to transmit |
433 | * a message using the plugin. Note that in the case of a | 454 | * a message using the plugin. Note that in the case of a |
434 | * peer disconnecting, the continuation MUST be called | 455 | * peer disconnecting, the continuation MUST be called |
@@ -464,12 +485,34 @@ http_server_plugin_send (void *cls, | |||
464 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) | 485 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) |
465 | { | 486 | { |
466 | struct HTTP_Server_Plugin *plugin = cls; | 487 | struct HTTP_Server_Plugin *plugin = cls; |
488 | struct HTTP_Message *msg; | ||
467 | int bytes_sent = 0; | 489 | int bytes_sent = 0; |
468 | 490 | ||
469 | GNUNET_assert (plugin != NULL); | 491 | GNUNET_assert (plugin != NULL); |
470 | GNUNET_assert (session != NULL); | 492 | GNUNET_assert (session != NULL); |
471 | 493 | ||
472 | GNUNET_break (0); | 494 | if (GNUNET_NO == server_exist_session (plugin, session)) |
495 | { | ||
496 | GNUNET_break (0); | ||
497 | return GNUNET_SYSERR; | ||
498 | } | ||
499 | GNUNET_assert (NULL != session->server_send); | ||
500 | |||
501 | /* create new message and schedule */ | ||
502 | bytes_sent = sizeof (struct HTTP_Message) + msgbuf_size; | ||
503 | msg = GNUNET_malloc (bytes_sent); | ||
504 | msg->next = NULL; | ||
505 | msg->size = msgbuf_size; | ||
506 | msg->pos = 0; | ||
507 | msg->buf = (char *) &msg[1]; | ||
508 | msg->transmit_cont = cont; | ||
509 | msg->transmit_cont_cls = cont_cls; | ||
510 | memcpy (msg->buf, msgbuf, msgbuf_size); | ||
511 | |||
512 | GNUNET_CONTAINER_DLL_insert_tail (session->msg_head, session->msg_tail, msg); | ||
513 | |||
514 | server_reschedule (session->plugin, session->server_send->mhd_daemon, GNUNET_YES); | ||
515 | server_reschedule_session_timeout (session); | ||
473 | 516 | ||
474 | /* struct Plugin *plugin = cls; */ | 517 | /* struct Plugin *plugin = cls; */ |
475 | return bytes_sent; | 518 | return bytes_sent; |
@@ -488,8 +531,27 @@ http_server_plugin_send (void *cls, | |||
488 | static void | 531 | static void |
489 | http_server_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) | 532 | http_server_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) |
490 | { | 533 | { |
491 | // struct Plugin *plugin = cls; | 534 | struct HTTP_Server_Plugin *plugin = cls; |
492 | GNUNET_break (0); | 535 | struct Session *next = NULL; |
536 | struct Session *pos = NULL; | ||
537 | |||
538 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
539 | "Transport tells me to disconnect `%s'\n", | ||
540 | GNUNET_i2s (target)); | ||
541 | |||
542 | next = plugin->head; | ||
543 | while (NULL != (pos = next)) | ||
544 | { | ||
545 | next = pos->next; | ||
546 | if (0 == memcmp (target, &pos->target, sizeof (struct GNUNET_PeerIdentity))) | ||
547 | { | ||
548 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
549 | "Disconnecting session %p to `%s'\n", | ||
550 | pos, GNUNET_i2s (target)); | ||
551 | GNUNET_assert (GNUNET_OK == server_disconnect (pos)); | ||
552 | } | ||
553 | } | ||
554 | |||
493 | } | 555 | } |
494 | 556 | ||
495 | 557 | ||
@@ -509,18 +571,23 @@ static int | |||
509 | http_server_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) | 571 | http_server_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) |
510 | { | 572 | { |
511 | struct HTTP_Server_Plugin *plugin = cls; | 573 | struct HTTP_Server_Plugin *plugin = cls; |
512 | struct HttpAddressWrapper *w = plugin->addr_head; | 574 | struct HttpAddressWrapper *next; |
575 | struct HttpAddressWrapper *pos; | ||
576 | |||
513 | 577 | ||
514 | if ((NULL != plugin->ext_addr) && GNUNET_YES == (http_common_cmp_addresses (addr, addrlen, plugin->ext_addr, plugin->ext_addr_len))) | 578 | if ((NULL != plugin->ext_addr) && GNUNET_YES == (http_common_cmp_addresses (addr, addrlen, plugin->ext_addr, plugin->ext_addr_len))) |
515 | return GNUNET_OK; | 579 | return GNUNET_OK; |
516 | 580 | ||
517 | while (NULL != w) | 581 | next = plugin->addr_head; |
582 | while (NULL != (pos = next)) | ||
518 | { | 583 | { |
584 | next = pos->next; | ||
519 | if (GNUNET_YES == (http_common_cmp_addresses(addr, | 585 | if (GNUNET_YES == (http_common_cmp_addresses(addr, |
520 | addrlen, | 586 | addrlen, |
521 | w->addr, | 587 | pos->addr, |
522 | w->addrlen))) | 588 | pos->addrlen))) |
523 | return GNUNET_OK; | 589 | return GNUNET_OK; |
590 | |||
524 | } | 591 | } |
525 | 592 | ||
526 | return GNUNET_NO; | 593 | return GNUNET_NO; |
@@ -583,55 +650,6 @@ server_delete_session (struct Session *s) | |||
583 | GNUNET_free (s); | 650 | GNUNET_free (s); |
584 | } | 651 | } |
585 | 652 | ||
586 | int | ||
587 | server_disconnect (struct Session *s) | ||
588 | { | ||
589 | struct ServerConnection * send; | ||
590 | struct ServerConnection * recv; | ||
591 | |||
592 | send = (struct ServerConnection *) s->server_send; | ||
593 | if (s->server_send != NULL) | ||
594 | { | ||
595 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, | ||
596 | "Server: %p / %p Terminating inbound PUT session to peer `%s'\n", | ||
597 | s, s->server_send, GNUNET_i2s (&s->target)); | ||
598 | |||
599 | send->disconnect = GNUNET_YES; | ||
600 | #if MHD_VERSION >= 0x00090E00 | ||
601 | MHD_set_connection_option (send->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, | ||
602 | 1); | ||
603 | #endif | ||
604 | } | ||
605 | |||
606 | recv = (struct ServerConnection *) s->server_recv; | ||
607 | if (recv != NULL) | ||
608 | { | ||
609 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, | ||
610 | "Server: %p / %p Terminating inbound GET session to peer `%s'\n", | ||
611 | s, s->server_recv, GNUNET_i2s (&s->target)); | ||
612 | |||
613 | recv->disconnect = GNUNET_YES; | ||
614 | #if MHD_VERSION >= 0x00090E00 | ||
615 | MHD_set_connection_option (recv->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, | ||
616 | 1); | ||
617 | #endif | ||
618 | } | ||
619 | |||
620 | /* Schedule connection immediately */ | ||
621 | #if 0 | ||
622 | if (s->addrlen == sizeof (struct IPv4HttpAddress)) | ||
623 | { | ||
624 | server_reschedule (s->plugin, s->plugin->server_v4, GNUNET_YES); | ||
625 | } | ||
626 | else if (s->addrlen == sizeof (struct IPv6HttpAddress)) | ||
627 | { | ||
628 | server_reschedule (s->plugin, s->plugin->server_v6, GNUNET_YES); | ||
629 | } | ||
630 | #endif | ||
631 | return GNUNET_OK; | ||
632 | |||
633 | } | ||
634 | |||
635 | 653 | ||
636 | /** | 654 | /** |
637 | * Cancel timeout | 655 | * Cancel timeout |
@@ -703,6 +721,70 @@ server_reschedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *server, | |||
703 | } | 721 | } |
704 | } | 722 | } |
705 | 723 | ||
724 | int | ||
725 | server_disconnect (struct Session *s) | ||
726 | { | ||
727 | struct ServerConnection * send; | ||
728 | struct ServerConnection * recv; | ||
729 | |||
730 | send = (struct ServerConnection *) s->server_send; | ||
731 | if (s->server_send != NULL) | ||
732 | { | ||
733 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, | ||
734 | "Server: %p / %p Terminating inbound PUT session to peer `%s'\n", | ||
735 | s, s->server_send, GNUNET_i2s (&s->target)); | ||
736 | |||
737 | send->disconnect = GNUNET_YES; | ||
738 | #if MHD_VERSION >= 0x00090E00 | ||
739 | MHD_set_connection_option (send->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, | ||
740 | 1); | ||
741 | #endif | ||
742 | server_reschedule (s->plugin, send->mhd_daemon, GNUNET_YES); | ||
743 | } | ||
744 | |||
745 | recv = (struct ServerConnection *) s->server_recv; | ||
746 | if (recv != NULL) | ||
747 | { | ||
748 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, | ||
749 | "Server: %p / %p Terminating inbound GET session to peer `%s'\n", | ||
750 | s, s->server_recv, GNUNET_i2s (&s->target)); | ||
751 | |||
752 | recv->disconnect = GNUNET_YES; | ||
753 | #if MHD_VERSION >= 0x00090E00 | ||
754 | MHD_set_connection_option (recv->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, | ||
755 | 1); | ||
756 | #endif | ||
757 | server_reschedule (s->plugin, recv->mhd_daemon, GNUNET_YES); | ||
758 | } | ||
759 | return GNUNET_OK; | ||
760 | } | ||
761 | |||
762 | static void | ||
763 | server_mhd_connection_timeout (struct HTTP_Server_Plugin *plugin, struct Session *s, int to) | ||
764 | { | ||
765 | #if MHD_VERSION >= 0x00090E00 | ||
766 | /* Setting timeouts for other connections */ | ||
767 | if (s->server_recv != NULL) | ||
768 | { | ||
769 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
770 | "Setting timeout for %p to %u sec.\n", s->server_recv, to); | ||
771 | MHD_set_connection_option (s->server_recv->mhd_conn, | ||
772 | MHD_CONNECTION_OPTION_TIMEOUT, | ||
773 | to); | ||
774 | server_reschedule (plugin, s->server_recv->mhd_daemon, GNUNET_NO); | ||
775 | } | ||
776 | if (s->server_send != NULL) | ||
777 | { | ||
778 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
779 | "Setting timeout for %p to %u sec.\n", s->server_send, to); | ||
780 | MHD_set_connection_option (s->server_send->mhd_conn, | ||
781 | MHD_CONNECTION_OPTION_TIMEOUT, | ||
782 | to); | ||
783 | server_reschedule (plugin, s->server_send->mhd_daemon, GNUNET_NO); | ||
784 | } | ||
785 | #endif | ||
786 | } | ||
787 | |||
706 | 788 | ||
707 | static struct ServerConnection * | 789 | static struct ServerConnection * |
708 | server_lookup_connection (struct HTTP_Server_Plugin *plugin, | 790 | server_lookup_connection (struct HTTP_Server_Plugin *plugin, |
@@ -710,7 +792,6 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
710 | const char *method) | 792 | const char *method) |
711 | { | 793 | { |
712 | struct Session *s = NULL; | 794 | struct Session *s = NULL; |
713 | struct Session *t; | ||
714 | struct ServerConnection *sc = NULL; | 795 | struct ServerConnection *sc = NULL; |
715 | const union MHD_ConnectionInfo *conn_info; | 796 | const union MHD_ConnectionInfo *conn_info; |
716 | struct GNUNET_ATS_Information ats; | 797 | struct GNUNET_ATS_Information ats; |
@@ -721,6 +802,7 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
721 | struct GNUNET_PeerIdentity target; | 802 | struct GNUNET_PeerIdentity target; |
722 | uint32_t tag = 0; | 803 | uint32_t tag = 0; |
723 | int direction = GNUNET_SYSERR; | 804 | int direction = GNUNET_SYSERR; |
805 | int to; | ||
724 | 806 | ||
725 | /* url parsing variables */ | 807 | /* url parsing variables */ |
726 | size_t url_len; | 808 | size_t url_len; |
@@ -831,135 +913,74 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
831 | plugin->cur_connections, plugin->max_connections); | 913 | plugin->cur_connections, plugin->max_connections); |
832 | 914 | ||
833 | /* find duplicate session */ | 915 | /* find duplicate session */ |
834 | t = plugin->head; | 916 | s = plugin->head; |
835 | while (t != NULL) | 917 | while (s != NULL) |
836 | { | 918 | { |
837 | if ((t->inbound) && | 919 | if ((0 == memcmp (&s->target, &target, sizeof (struct GNUNET_PeerIdentity))) && |
838 | (0 == memcmp (&t->target, &target, sizeof (struct GNUNET_PeerIdentity))) | 920 | (s->tag == tag)) |
839 | && | ||
840 | /* FIXME add source address comparison */ | ||
841 | (t->tag == tag)) | ||
842 | break; | 921 | break; |
843 | t = t->next; | 922 | s = s->next; |
844 | } | 923 | } |
845 | if (t != NULL) | 924 | if (s != NULL) |
846 | { | 925 | { |
847 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | 926 | if ((_RECEIVE == direction) && (NULL != s->server_recv)) |
848 | "Duplicate session, dismissing new connection from peer `%s'\n", | 927 | { |
849 | GNUNET_i2s (&target)); | 928 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
850 | goto error; | 929 | "Duplicate PUT connection from `%s' tag %u, dismissing new connection\n", |
930 | GNUNET_i2s (&target), | ||
931 | tag); | ||
932 | goto error; | ||
933 | } | ||
934 | if ((_SEND == direction) && (NULL != s->server_send)) | ||
935 | { | ||
936 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
937 | "Duplicate GET connection from `%s' tag %u, dismissing new connection\n", | ||
938 | GNUNET_i2s (&target), | ||
939 | tag); | ||
940 | goto error; | ||
941 | } | ||
851 | } | 942 | } |
852 | 943 | else | |
853 | /* find semi-session */ | ||
854 | t = plugin->server_semi_head; | ||
855 | |||
856 | while (t != NULL) | ||
857 | { | 944 | { |
858 | /* FIXME add source address comparison */ | 945 | /* create new session */ |
859 | if ((0 == memcmp (&t->target, &target, sizeof (struct GNUNET_PeerIdentity))) | 946 | switch (conn_info->client_addr->sa_family) |
860 | && (t->tag == tag)) | ||
861 | { | 947 | { |
948 | case (AF_INET): | ||
949 | addr = http_common_address_from_socket (plugin->protocol, conn_info->client_addr, sizeof (struct sockaddr_in)); | ||
950 | addr_len = http_common_address_get_size (addr); | ||
951 | ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in)); | ||
952 | break; | ||
953 | case (AF_INET6): | ||
954 | addr = http_common_address_from_socket (plugin->protocol, conn_info->client_addr, sizeof (struct sockaddr_in6)); | ||
955 | addr_len = http_common_address_get_size (addr); | ||
956 | ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in6)); | ||
862 | break; | 957 | break; |
958 | default: | ||
959 | GNUNET_break (0); | ||
960 | goto error; | ||
863 | } | 961 | } |
864 | t = t->next; | ||
865 | } | ||
866 | 962 | ||
867 | if (t == NULL) | ||
868 | goto create; | ||
869 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
870 | "Found existing semi-session for `%s'\n", | ||
871 | GNUNET_i2s (&target)); | ||
872 | |||
873 | if ((direction == _SEND) && (t->server_send != NULL)) | ||
874 | { | ||
875 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | 963 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
876 | "Duplicate GET session, dismissing new connection from peer `%s'\n", | 964 | "Creating new session for peer `%s' connecting from `%s'\n", |
877 | GNUNET_i2s (&target)); | 965 | GNUNET_i2s (&target), |
878 | goto error; | 966 | http_common_plugin_address_to_string (NULL, addr, addr_len)); |
879 | } | 967 | |
880 | else | 968 | s = GNUNET_malloc (sizeof (struct Session)); |
881 | { | 969 | memcpy (&s->target, &target, sizeof (struct GNUNET_PeerIdentity)); |
882 | s = t; | 970 | s->plugin = plugin; |
883 | GNUNET_CONTAINER_DLL_remove (plugin->server_semi_head, | 971 | s->addr = addr; |
884 | plugin->server_semi_tail, s); | 972 | s->addrlen = addr_len; |
973 | s->ats_address_network_type = ats.value; | ||
974 | s->next_receive = GNUNET_TIME_UNIT_ZERO_ABS; | ||
975 | s->tag = tag; | ||
976 | s->server_recv = NULL; | ||
977 | s->server_send = NULL; | ||
978 | s->session_passed = GNUNET_NO; | ||
979 | server_start_session_timeout(s); | ||
885 | GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); | 980 | GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); |
886 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
887 | "Found matching semi-session, merging session for peer `%s'\n", | ||
888 | GNUNET_i2s (&target)); | ||
889 | GNUNET_assert (NULL != s); | ||
890 | goto found; | ||
891 | } | ||
892 | if ((direction == _RECEIVE) && (t->server_recv != NULL)) | ||
893 | { | ||
894 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
895 | "Duplicate PUT session, dismissing new connection from peer `%s'\n", | ||
896 | GNUNET_i2s (&target)); | ||
897 | goto error; | ||
898 | } | ||
899 | else | ||
900 | { | ||
901 | s = t; | ||
902 | GNUNET_CONTAINER_DLL_remove (plugin->server_semi_head, | ||
903 | plugin->server_semi_tail, s); | ||
904 | GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); | ||
905 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
906 | "Found matching semi-session, merging session for peer `%s'\n", | ||
907 | GNUNET_i2s (&target)); | ||
908 | GNUNET_assert (NULL != s); | ||
909 | goto found; | ||
910 | } | 981 | } |
911 | 982 | ||
912 | create: | ||
913 | /* create new session */ | ||
914 | |||
915 | switch (conn_info->client_addr->sa_family) | ||
916 | { | ||
917 | case (AF_INET): | ||
918 | addr = http_common_address_from_socket (plugin->protocol, conn_info->client_addr, sizeof (struct sockaddr_in)); | ||
919 | addr_len = http_common_address_get_size (addr); | ||
920 | ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in)); | ||
921 | break; | ||
922 | case (AF_INET6): | ||
923 | addr = http_common_address_from_socket (plugin->protocol, conn_info->client_addr, sizeof (struct sockaddr_in6)); | ||
924 | addr_len = http_common_address_get_size (addr); | ||
925 | ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in6)); | ||
926 | break; | ||
927 | default: | ||
928 | GNUNET_break (0); | ||
929 | goto error; | ||
930 | } | ||
931 | |||
932 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
933 | "Creating new session for peer `%s' connecting from `%s'\n", | ||
934 | GNUNET_i2s (&target), | ||
935 | http_common_plugin_address_to_string (NULL, addr, addr_len)); | ||
936 | |||
937 | s = GNUNET_malloc (sizeof (struct Session)); | ||
938 | memcpy (&s->target, &target, sizeof (struct GNUNET_PeerIdentity)); | ||
939 | s->plugin = plugin; | ||
940 | s->addr = addr; | ||
941 | s->addrlen = addr_len; | ||
942 | s->ats_address_network_type = ats.value; | ||
943 | s->inbound = GNUNET_YES; | ||
944 | s->next_receive = GNUNET_TIME_UNIT_ZERO_ABS; | ||
945 | s->tag = tag; | ||
946 | s->server_recv = NULL; | ||
947 | s->server_send = NULL; | ||
948 | |||
949 | server_start_session_timeout(s); | ||
950 | |||
951 | GNUNET_CONTAINER_DLL_insert (plugin->server_semi_head, | ||
952 | plugin->server_semi_tail, s); | ||
953 | goto found; | ||
954 | error: | ||
955 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
956 | "Invalid connection request\n"); | ||
957 | return NULL; | ||
958 | |||
959 | found: | ||
960 | |||
961 | sc = GNUNET_malloc (sizeof (struct ServerConnection)); | 983 | sc = GNUNET_malloc (sizeof (struct ServerConnection)); |
962 | |||
963 | if (conn_info->client_addr->sa_family == AF_INET) | 984 | if (conn_info->client_addr->sa_family == AF_INET) |
964 | sc->mhd_daemon = plugin->server_v4; | 985 | sc->mhd_daemon = plugin->server_v4; |
965 | if (conn_info->client_addr->sa_family == AF_INET6) | 986 | if (conn_info->client_addr->sa_family == AF_INET6) |
@@ -973,16 +994,31 @@ found: | |||
973 | s->server_recv = sc; | 994 | s->server_recv = sc; |
974 | 995 | ||
975 | #if MHD_VERSION >= 0x00090E00 | 996 | #if MHD_VERSION >= 0x00090E00 |
976 | int to = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value / 1000); | 997 | if ((NULL == s->server_recv) || (NULL == s->server_send)) |
998 | { | ||
999 | to = (HTTP_NOT_VALIDATED_TIMEOUT.rel_value / 1000); | ||
1000 | MHD_set_connection_option (mhd_connection, MHD_CONNECTION_OPTION_TIMEOUT, to); | ||
1001 | server_reschedule (plugin, sc->mhd_daemon, GNUNET_NO); | ||
1002 | } | ||
1003 | else | ||
1004 | { | ||
1005 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1006 | "Session %p for peer `%s' fully connected\n", | ||
1007 | s, GNUNET_i2s (&target)); | ||
1008 | to = (TIMEOUT.rel_value / 1000); | ||
1009 | server_mhd_connection_timeout (plugin, s, to); | ||
1010 | } | ||
977 | 1011 | ||
978 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | 1012 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
979 | "Setting timeout for %p to %u sec.\n", sc, to); | 1013 | "Setting timeout for %p to %u sec.\n", sc, to); |
980 | MHD_set_connection_option (mhd_connection, MHD_CONNECTION_OPTION_TIMEOUT, to); | ||
981 | |||
982 | server_reschedule (plugin, sc->mhd_daemon, GNUNET_NO); | ||
983 | #endif | 1014 | #endif |
984 | return sc; | 1015 | return sc; |
985 | 1016 | ||
1017 | /* Error condition */ | ||
1018 | error: | ||
1019 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1020 | "Invalid connection request\n"); | ||
1021 | return NULL; | ||
986 | } | 1022 | } |
987 | 1023 | ||
988 | static struct Session * | 1024 | static struct Session * |
@@ -994,9 +1030,6 @@ server_lookup_session (struct HTTP_Server_Plugin *plugin, | |||
994 | for (s = plugin->head; NULL != s; s = s->next) | 1030 | for (s = plugin->head; NULL != s; s = s->next) |
995 | if ((s->server_recv == sc) || (s->server_send == sc)) | 1031 | if ((s->server_recv == sc) || (s->server_send == sc)) |
996 | return s; | 1032 | return s; |
997 | for (s = plugin->server_semi_head; NULL != s; s = s->next) | ||
998 | if ((s->server_recv == sc) || (s->server_send == sc)) | ||
999 | return s; | ||
1000 | return NULL; | 1033 | return NULL; |
1001 | } | 1034 | } |
1002 | 1035 | ||
@@ -1055,6 +1088,9 @@ server_send_callback (void *cls, uint64_t pos, char *buf, size_t max) | |||
1055 | } | 1088 | } |
1056 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, | 1089 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, |
1057 | "Sent %u bytes\n", s, bytes_read); | 1090 | "Sent %u bytes\n", s, bytes_read); |
1091 | |||
1092 | |||
1093 | |||
1058 | return bytes_read; | 1094 | return bytes_read; |
1059 | } | 1095 | } |
1060 | 1096 | ||
@@ -1089,13 +1125,12 @@ server_receive_mst_cb (void *cls, void *client, | |||
1089 | message, | 1125 | message, |
1090 | (const struct GNUNET_ATS_Information *) &atsi, 2, | 1126 | (const struct GNUNET_ATS_Information *) &atsi, 2, |
1091 | s, s->addr, s->addrlen); | 1127 | s, s->addr, s->addrlen); |
1092 | 1128 | s->session_passed = GNUNET_YES; | |
1093 | s->next_receive = | 1129 | s->next_receive = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay); |
1094 | GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay); | ||
1095 | if (delay.rel_value > 0) | 1130 | if (delay.rel_value > 0) |
1096 | { | 1131 | { |
1097 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | 1132 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
1098 | "Server: peer `%s' address `%s' next read delayed for %llu ms\n", | 1133 | "Peer `%s' address `%s' next read delayed for %llu ms\n", |
1099 | GNUNET_i2s (&s->target), | 1134 | GNUNET_i2s (&s->target), |
1100 | http_common_plugin_address_to_string (NULL, s->addr, s->addrlen), | 1135 | http_common_plugin_address_to_string (NULL, s->addr, s->addrlen), |
1101 | delay); | 1136 | delay); |
@@ -1104,7 +1139,6 @@ server_receive_mst_cb (void *cls, void *client, | |||
1104 | return GNUNET_OK; | 1139 | return GNUNET_OK; |
1105 | } | 1140 | } |
1106 | 1141 | ||
1107 | |||
1108 | static int | 1142 | static int |
1109 | server_access_cb (void *cls, struct MHD_Connection *mhd_connection, | 1143 | server_access_cb (void *cls, struct MHD_Connection *mhd_connection, |
1110 | const char *url, const char *method, const char *version, | 1144 | const char *url, const char *method, const char *version, |
@@ -1152,8 +1186,8 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection, | |||
1152 | if (sc->disconnect == GNUNET_YES) | 1186 | if (sc->disconnect == GNUNET_YES) |
1153 | { | 1187 | { |
1154 | /* Sent HTTP/1.1: 200 OK as PUT Response\ */ | 1188 | /* Sent HTTP/1.1: 200 OK as PUT Response\ */ |
1155 | response = | 1189 | response = MHD_create_response_from_data (strlen ("Thank you!"), |
1156 | MHD_create_response_from_data (strlen ("Thank you!"), "Thank you!", | 1190 | "Thank you!", |
1157 | MHD_NO, MHD_NO); | 1191 | MHD_NO, MHD_NO); |
1158 | res = MHD_queue_response (mhd_connection, MHD_HTTP_OK, response); | 1192 | res = MHD_queue_response (mhd_connection, MHD_HTTP_OK, response); |
1159 | MHD_destroy_response (response); | 1193 | MHD_destroy_response (response); |
@@ -1214,43 +1248,15 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection, | |||
1214 | } | 1248 | } |
1215 | GNUNET_SERVER_mst_receive (s->msg_tk, s, upload_data, | 1249 | GNUNET_SERVER_mst_receive (s->msg_tk, s, upload_data, |
1216 | *upload_data_size, GNUNET_NO, GNUNET_NO); | 1250 | *upload_data_size, GNUNET_NO, GNUNET_NO); |
1217 | |||
1218 | #if MHD_VERSION >= 0x00090E00 | 1251 | #if MHD_VERSION >= 0x00090E00 |
1219 | int to = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value / 1000); | 1252 | server_mhd_connection_timeout (plugin, s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value / 1000); |
1220 | struct ServerConnection *t = NULL; | ||
1221 | |||
1222 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1223 | "Received %u bytes\n", *upload_data_size); | ||
1224 | /* Setting timeouts for other connections */ | ||
1225 | if (s->server_recv != NULL) | ||
1226 | { | ||
1227 | t = s->server_recv; | ||
1228 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1229 | "Setting timeout for %p to %u sec.\n", t, | ||
1230 | to); | ||
1231 | MHD_set_connection_option (t->mhd_conn, | ||
1232 | MHD_CONNECTION_OPTION_TIMEOUT, | ||
1233 | to); | ||
1234 | server_reschedule (plugin, t->mhd_daemon, GNUNET_NO); | ||
1235 | } | ||
1236 | if (s->server_send != NULL) | ||
1237 | { | ||
1238 | t = s->server_send; | ||
1239 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1240 | "Setting timeout for %p to %u sec.\n", t, | ||
1241 | to); | ||
1242 | MHD_set_connection_option (t->mhd_conn, | ||
1243 | MHD_CONNECTION_OPTION_TIMEOUT, | ||
1244 | to); | ||
1245 | server_reschedule (plugin, t->mhd_daemon, GNUNET_NO); | ||
1246 | } | ||
1247 | #endif | 1253 | #endif |
1248 | (*upload_data_size) = 0; | 1254 | (*upload_data_size) = 0; |
1249 | } | 1255 | } |
1250 | else | 1256 | else |
1251 | { | 1257 | { |
1252 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1258 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1253 | "Server: %p no inbound bandwidth available! Next read was delayed by %llu ms\n", | 1259 | "%p no inbound bandwidth available! Next read was delayed by %llu ms\n", |
1254 | s, now.abs_value - s->next_receive.abs_value); | 1260 | s, now.abs_value - s->next_receive.abs_value); |
1255 | } | 1261 | } |
1256 | return MHD_YES; | 1262 | return MHD_YES; |
@@ -1265,8 +1271,93 @@ static void | |||
1265 | server_disconnect_cb (void *cls, struct MHD_Connection *connection, | 1271 | server_disconnect_cb (void *cls, struct MHD_Connection *connection, |
1266 | void **httpSessionCache) | 1272 | void **httpSessionCache) |
1267 | { | 1273 | { |
1268 | /* FIXME SPLIT */ | 1274 | struct ServerConnection *sc = *httpSessionCache; |
1269 | GNUNET_break (0); | 1275 | struct Session *s = NULL; |
1276 | struct Session *t = NULL; | ||
1277 | struct HTTP_Server_Plugin *plugin = NULL; | ||
1278 | |||
1279 | if (sc == NULL) | ||
1280 | return; | ||
1281 | |||
1282 | if (NULL == (s = server_lookup_session (p, sc))) | ||
1283 | return; | ||
1284 | |||
1285 | GNUNET_assert (NULL != p); | ||
1286 | for (t = p->head; t != NULL; t = t->next) | ||
1287 | { | ||
1288 | if (t == s) | ||
1289 | break; | ||
1290 | } | ||
1291 | if (NULL == t) | ||
1292 | return; | ||
1293 | |||
1294 | plugin = s->plugin; | ||
1295 | if (sc->direction == _SEND) | ||
1296 | { | ||
1297 | |||
1298 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1299 | "Peer `%s' connection %p, GET on address `%s' disconnected\n", | ||
1300 | GNUNET_i2s (&s->target), s->server_send, | ||
1301 | http_common_plugin_address_to_string (NULL, s->addr, s->addrlen)); | ||
1302 | s->server_send = NULL; | ||
1303 | if (NULL != (s->server_recv)) | ||
1304 | { | ||
1305 | s->server_recv->disconnect = GNUNET_YES; | ||
1306 | GNUNET_assert (NULL != s->server_recv->mhd_conn); | ||
1307 | #if MHD_VERSION >= 0x00090E00 | ||
1308 | MHD_set_connection_option (s->server_recv->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, | ||
1309 | 1); | ||
1310 | #endif | ||
1311 | server_reschedule (plugin, s->server_recv->mhd_daemon, GNUNET_NO); | ||
1312 | } | ||
1313 | } | ||
1314 | if (sc->direction == _RECEIVE) | ||
1315 | { | ||
1316 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1317 | "Peer `%s' connection %p PUT on address `%s' disconnected\n", | ||
1318 | GNUNET_i2s (&s->target), s->server_recv, | ||
1319 | http_common_plugin_address_to_string (NULL, s->addr, s->addrlen)); | ||
1320 | s->server_recv = NULL; | ||
1321 | if (NULL != (s->server_send)) | ||
1322 | { | ||
1323 | s->server_send->disconnect = GNUNET_YES; | ||
1324 | GNUNET_assert (NULL != s->server_send->mhd_conn); | ||
1325 | #if MHD_VERSION >= 0x00090E00 | ||
1326 | MHD_set_connection_option (s->server_send->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, | ||
1327 | 1); | ||
1328 | #endif | ||
1329 | server_reschedule (plugin, s->server_send->mhd_daemon, GNUNET_NO); | ||
1330 | } | ||
1331 | if (s->msg_tk != NULL) | ||
1332 | { | ||
1333 | GNUNET_SERVER_mst_destroy (s->msg_tk); | ||
1334 | s->msg_tk = NULL; | ||
1335 | } | ||
1336 | } | ||
1337 | |||
1338 | GNUNET_free (sc); | ||
1339 | plugin->cur_connections--; | ||
1340 | if ((s->server_send == NULL) && (s->server_recv == NULL)) | ||
1341 | { | ||
1342 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1343 | "Peer `%s' on address `%s' disconnected\n", | ||
1344 | GNUNET_i2s (&s->target), | ||
1345 | http_common_plugin_address_to_string (NULL, s->addr, s->addrlen)); | ||
1346 | if (s->msg_tk != NULL) | ||
1347 | { | ||
1348 | GNUNET_SERVER_mst_destroy (s->msg_tk); | ||
1349 | s->msg_tk = NULL; | ||
1350 | } | ||
1351 | |||
1352 | GNUNET_CONTAINER_DLL_remove(plugin->head, plugin->tail, s); | ||
1353 | server_stop_session_timeout (s); | ||
1354 | if (GNUNET_YES == s->session_passed) | ||
1355 | plugin->env->session_end (plugin->env->cls, &s->target, s); | ||
1356 | GNUNET_free (s->addr); | ||
1357 | GNUNET_free (s); | ||
1358 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1359 | "Session %p destroyed\n", s); | ||
1360 | } | ||
1270 | } | 1361 | } |
1271 | 1362 | ||
1272 | /** | 1363 | /** |
@@ -1364,7 +1455,8 @@ server_v6_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1364 | * @return gnunet task identifier | 1455 | * @return gnunet task identifier |
1365 | */ | 1456 | */ |
1366 | static GNUNET_SCHEDULER_TaskIdentifier | 1457 | static GNUNET_SCHEDULER_TaskIdentifier |
1367 | server_schedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *daemon_handle, | 1458 | server_schedule (struct HTTP_Server_Plugin *plugin, |
1459 | struct MHD_Daemon *daemon_handle, | ||
1368 | int now) | 1460 | int now) |
1369 | { | 1461 | { |
1370 | GNUNET_SCHEDULER_TaskIdentifier ret; | 1462 | GNUNET_SCHEDULER_TaskIdentifier ret; |
@@ -1728,9 +1820,6 @@ server_start (struct HTTP_Server_Plugin *plugin) | |||
1728 | void | 1820 | void |
1729 | server_stop (struct HTTP_Server_Plugin *plugin) | 1821 | server_stop (struct HTTP_Server_Plugin *plugin) |
1730 | { | 1822 | { |
1731 | struct Session *s = NULL; | ||
1732 | struct Session *t = NULL; | ||
1733 | |||
1734 | struct MHD_Daemon *server_v4_tmp = plugin->server_v4; | 1823 | struct MHD_Daemon *server_v4_tmp = plugin->server_v4; |
1735 | plugin->server_v4 = NULL; | 1824 | plugin->server_v4 = NULL; |
1736 | 1825 | ||
@@ -1758,35 +1847,6 @@ server_stop (struct HTTP_Server_Plugin *plugin) | |||
1758 | MHD_stop_daemon (server_v6_tmp); | 1847 | MHD_stop_daemon (server_v6_tmp); |
1759 | } | 1848 | } |
1760 | 1849 | ||
1761 | /* cleaning up semi-sessions never propagated */ | ||
1762 | s = plugin->server_semi_head; | ||
1763 | while (s != NULL) | ||
1764 | { | ||
1765 | #if VERBOSE_SERVER | ||
1766 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1767 | "Deleting semi-sessions %p\n", s); | ||
1768 | #endif | ||
1769 | t = s->next; | ||
1770 | struct HTTP_Message *msg = s->msg_head; | ||
1771 | struct HTTP_Message *tmp = NULL; | ||
1772 | |||
1773 | while (msg != NULL) | ||
1774 | { | ||
1775 | tmp = msg->next; | ||
1776 | |||
1777 | GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); | ||
1778 | if (msg->transmit_cont != NULL) | ||
1779 | { | ||
1780 | msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR); | ||
1781 | } | ||
1782 | GNUNET_free (msg); | ||
1783 | msg = tmp; | ||
1784 | } | ||
1785 | |||
1786 | server_delete_session (s); | ||
1787 | s = t; | ||
1788 | } | ||
1789 | |||
1790 | p = NULL; | 1850 | p = NULL; |
1791 | 1851 | ||
1792 | #if BUILD_HTTPS | 1852 | #if BUILD_HTTPS |