aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2012-08-24 13:02:21 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2012-08-24 13:02:21 +0000
commitaee1bb6ec558c431f68c07df6e90198a31cd5f91 (patch)
tree2f34c8da27b7ec8f5d6f1bf947cf0b935e6a131b /src
parente58a85b4f948b764544a48a684a20e7a1522367e (diff)
downloadgnunet-aee1bb6ec558c431f68c07df6e90198a31cd5f91.tar.gz
gnunet-aee1bb6ec558c431f68c07df6e90198a31cd5f91.zip
code
Diffstat (limited to 'src')
-rw-r--r--src/transport/plugin_transport_http_server.c582
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
429server_stop_session_timeout (struct Session *s); 431server_stop_session_timeout (struct Session *s);
430 432
431/** 433/**
434 * Disconnect a session
435 */
436int
437server_disconnect (struct Session *s);
438
439int
440server_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 */
449static void
450server_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,
488static void 531static void
489http_server_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) 532http_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
509http_server_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) 571http_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
586int
587server_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
724int
725server_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
762static void
763server_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
707static struct ServerConnection * 789static struct ServerConnection *
708server_lookup_connection (struct HTTP_Server_Plugin *plugin, 790server_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
912create:
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;
954error:
955 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
956 "Invalid connection request\n");
957 return NULL;
958
959found:
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
988static struct Session * 1024static 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
1108static int 1142static int
1109server_access_cb (void *cls, struct MHD_Connection *mhd_connection, 1143server_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
1265server_disconnect_cb (void *cls, struct MHD_Connection *connection, 1271server_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 */
1366static GNUNET_SCHEDULER_TaskIdentifier 1457static GNUNET_SCHEDULER_TaskIdentifier
1367server_schedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *daemon_handle, 1458server_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)
1728void 1820void
1729server_stop (struct HTTP_Server_Plugin *plugin) 1821server_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