diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2012-02-16 11:54:12 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2012-02-16 11:54:12 +0000 |
commit | e686141383bfc85a709d125f6d37d23918937028 (patch) | |
tree | 610904ca7be7977afc51114a112d671468fc2c64 /src/transport/plugin_transport_tcp.c | |
parent | 6788139a93a9f114971c3702bb449158f1f87746 (diff) | |
download | gnunet-e686141383bfc85a709d125f6d37d23918937028.tar.gz gnunet-e686141383bfc85a709d125f6d37d23918937028.zip |
- fixing assertion in gnunet_service_ats_addresses
Diffstat (limited to 'src/transport/plugin_transport_tcp.c')
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 356 |
1 files changed, 195 insertions, 161 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index 325ebaf8b..83db537fc 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -270,19 +270,22 @@ struct Session | |||
270 | /** | 270 | /** |
271 | * Address of the other peer (either based on our 'connect' | 271 | * Address of the other peer (either based on our 'connect' |
272 | * call or on our 'accept' call). | 272 | * call or on our 'accept' call). |
273 | * | ||
274 | * struct IPv4TcpAddress or struct IPv6TcpAddress | ||
275 | * | ||
273 | */ | 276 | */ |
274 | void *connect_addr; | 277 | void *addr; |
275 | 278 | ||
276 | /** | 279 | /** |
277 | * Last activity on this connection. Used to select preferred | 280 | * Length of connect_addr. |
278 | * connection. | ||
279 | */ | 281 | */ |
280 | struct GNUNET_TIME_Absolute last_activity; | 282 | size_t addrlen; |
281 | 283 | ||
282 | /** | 284 | /** |
283 | * Length of connect_addr. | 285 | * Last activity on this connection. Used to select preferred |
286 | * connection. | ||
284 | */ | 287 | */ |
285 | size_t connect_alen; | 288 | struct GNUNET_TIME_Absolute last_activity; |
286 | 289 | ||
287 | /** | 290 | /** |
288 | * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO) | 291 | * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO) |
@@ -326,11 +329,6 @@ struct Plugin | |||
326 | */ | 329 | */ |
327 | struct GNUNET_NAT_Handle *nat; | 330 | struct GNUNET_NAT_Handle *nat; |
328 | 331 | ||
329 | /** | ||
330 | * List of open TCP sessions. | ||
331 | */ | ||
332 | struct Session *sessions; | ||
333 | |||
334 | struct GNUNET_CONTAINER_MultiHashMap * sessionmap; | 332 | struct GNUNET_CONTAINER_MultiHashMap * sessionmap; |
335 | 333 | ||
336 | /** | 334 | /** |
@@ -527,6 +525,27 @@ tcp_address_to_string (void *cls, const void *addr, size_t addrlen) | |||
527 | } | 525 | } |
528 | 526 | ||
529 | 527 | ||
528 | struct SessionClientCtx | ||
529 | { | ||
530 | const struct GNUNET_SERVER_Client *client; | ||
531 | struct Session *ret; | ||
532 | }; | ||
533 | |||
534 | int session_lookup_by_client_it (void *cls, | ||
535 | const GNUNET_HashCode * key, | ||
536 | void *value) | ||
537 | { | ||
538 | struct SessionClientCtx *sc_ctx = cls; | ||
539 | struct Session *s = value; | ||
540 | |||
541 | if (s->client == sc_ctx->client) | ||
542 | { | ||
543 | sc_ctx->ret = s; | ||
544 | return GNUNET_NO; | ||
545 | } | ||
546 | return GNUNET_YES; | ||
547 | } | ||
548 | |||
530 | /** | 549 | /** |
531 | * Find the session handle for the given client. | 550 | * Find the session handle for the given client. |
532 | * | 551 | * |
@@ -535,15 +554,16 @@ tcp_address_to_string (void *cls, const void *addr, size_t addrlen) | |||
535 | * @return NULL if no matching session exists | 554 | * @return NULL if no matching session exists |
536 | */ | 555 | */ |
537 | static struct Session * | 556 | static struct Session * |
538 | find_session_by_client (struct Plugin *plugin, | 557 | lookup_session_by_client (struct Plugin *plugin, |
539 | const struct GNUNET_SERVER_Client *client) | 558 | const struct GNUNET_SERVER_Client *client) |
540 | { | 559 | { |
541 | struct Session *ret; | 560 | struct SessionClientCtx sc_ctx; |
561 | sc_ctx.client = client; | ||
562 | sc_ctx.ret = NULL; | ||
542 | 563 | ||
543 | ret = plugin->sessions; | 564 | GNUNET_CONTAINER_multihashmap_iterate (plugin->sessionmap, &session_lookup_by_client_it, &sc_ctx); |
544 | while ((ret != NULL) && (client != ret->client)) | 565 | |
545 | ret = ret->next; | 566 | return sc_ctx.ret; |
546 | return ret; | ||
547 | } | 567 | } |
548 | 568 | ||
549 | 569 | ||
@@ -570,20 +590,15 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target, | |||
570 | GNUNET_assert (client != NULL); | 590 | GNUNET_assert (client != NULL); |
571 | else | 591 | else |
572 | GNUNET_assert (client == NULL); | 592 | GNUNET_assert (client == NULL); |
573 | #if DEBUG_TCP | 593 | |
574 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 594 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
575 | "Creating new session for peer `%4s'\n", | 595 | "Creating new session for peer `%4s'\n", |
576 | GNUNET_i2s (target)); | 596 | GNUNET_i2s (target)); |
577 | #endif | 597 | |
578 | ret = GNUNET_malloc (sizeof (struct Session)); | 598 | ret = GNUNET_malloc (sizeof (struct Session)); |
579 | ret->last_activity = GNUNET_TIME_absolute_get (); | 599 | ret->last_activity = GNUNET_TIME_absolute_get (); |
580 | ret->plugin = plugin; | 600 | ret->plugin = plugin; |
581 | ret->is_nat = is_nat; | 601 | ret->is_nat = is_nat; |
582 | if (is_nat != GNUNET_YES) /* If not a NAT WAIT conn, add it to global list */ | ||
583 | { | ||
584 | ret->next = plugin->sessions; | ||
585 | plugin->sessions = ret; | ||
586 | } | ||
587 | ret->client = client; | 602 | ret->client = client; |
588 | ret->target = *target; | 603 | ret->target = *target; |
589 | ret->expecting_welcome = GNUNET_YES; | 604 | ret->expecting_welcome = GNUNET_YES; |
@@ -783,32 +798,16 @@ process_pending_messages (struct Session *session) | |||
783 | static void | 798 | static void |
784 | disconnect_session (struct Session *session) | 799 | disconnect_session (struct Session *session) |
785 | { | 800 | { |
786 | struct Session *prev; | ||
787 | struct Session *pos; | ||
788 | struct PendingMessage *pm; | 801 | struct PendingMessage *pm; |
802 | struct Plugin * plugin = session->plugin; | ||
789 | 803 | ||
790 | #if DEBUG_TCP | ||
791 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 804 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
792 | "Disconnecting from `%4s' at %s.\n", | 805 | "Disconnecting session %p for peer `%s' address `%s'\n", |
806 | session, | ||
793 | GNUNET_i2s (&session->target), | 807 | GNUNET_i2s (&session->target), |
794 | (session->connect_addr != | 808 | tcp_address_to_string(NULL, session->addr, session->addrlen)); |
795 | NULL) ? tcp_address_to_string (session->plugin, | 809 | |
796 | session->connect_addr, | 810 | GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(plugin->sessionmap, &session->target.hashPubKey, session)); |
797 | session->connect_alen) : | ||
798 | "*"); | ||
799 | #endif | ||
800 | /* remove from session list */ | ||
801 | prev = NULL; | ||
802 | pos = session->plugin->sessions; | ||
803 | while (pos != session) | ||
804 | { | ||
805 | prev = pos; | ||
806 | pos = pos->next; | ||
807 | } | ||
808 | if (prev == NULL) | ||
809 | session->plugin->sessions = session->next; | ||
810 | else | ||
811 | prev->next = session->next; | ||
812 | 811 | ||
813 | /* clean up state */ | 812 | /* clean up state */ |
814 | if (session->transmit_handle != NULL) | 813 | if (session->transmit_handle != NULL) |
@@ -856,7 +855,7 @@ disconnect_session (struct Session *session) | |||
856 | GNUNET_STATISTICS_update (session->plugin->env->stats, | 855 | GNUNET_STATISTICS_update (session->plugin->env->stats, |
857 | gettext_noop ("# TCP sessions active"), -1, | 856 | gettext_noop ("# TCP sessions active"), -1, |
858 | GNUNET_NO); | 857 | GNUNET_NO); |
859 | GNUNET_free_non_null (session->connect_addr); | 858 | GNUNET_free_non_null (session->addr); |
860 | GNUNET_assert (NULL == session->transmit_handle); | 859 | GNUNET_assert (NULL == session->transmit_handle); |
861 | GNUNET_free (session); | 860 | GNUNET_free (session); |
862 | } | 861 | } |
@@ -921,11 +920,11 @@ tcp_plugin_send (void *cls, | |||
921 | /* append pm to pending_messages list */ | 920 | /* append pm to pending_messages list */ |
922 | GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head, | 921 | GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head, |
923 | session->pending_messages_tail, pm); | 922 | session->pending_messages_tail, pm); |
924 | #if DEBUG_TCP | 923 | |
925 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 924 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
926 | "Asked to transmit %u bytes to `%s', added message to list.\n", | 925 | "Asked to transmit %u bytes to `%s', added message to list.\n", |
927 | msgbuf_size, GNUNET_i2s (&session->target)); | 926 | msgbuf_size, GNUNET_i2s (&session->target)); |
928 | #endif | 927 | |
929 | process_pending_messages (session); | 928 | process_pending_messages (session); |
930 | return msgbuf_size; | 929 | return msgbuf_size; |
931 | } | 930 | } |
@@ -937,18 +936,44 @@ struct SessionItCtx | |||
937 | struct Session * result; | 936 | struct Session * result; |
938 | }; | 937 | }; |
939 | 938 | ||
940 | int session_it (void *cls, | 939 | int session_lookup_it (void *cls, |
941 | const GNUNET_HashCode * key, | 940 | const GNUNET_HashCode * key, |
942 | void *value) | 941 | void *value) |
943 | { | 942 | { |
944 | struct SessionItCtx * si_ctx = cls; | 943 | struct SessionItCtx * si_ctx = cls; |
945 | struct Session * session = value; | 944 | struct Session * session = value; |
946 | 945 | #if 0 | |
947 | if (session->connect_alen != si_ctx->addrlen) | 946 | char * a1 = strdup (tcp_address_to_string(NULL, session->addr, session->addrlen)); |
947 | char * a2 = strdup (tcp_address_to_string(NULL, si_ctx->addr, si_ctx->addrlen)); | ||
948 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp", | ||
949 | "Comparing: %s %u <-> %s %u\n", | ||
950 | a1, | ||
951 | session->addrlen, | ||
952 | a2, | ||
953 | si_ctx->addrlen); | ||
954 | GNUNET_free (a1); | ||
955 | GNUNET_free (a2); | ||
956 | #endif | ||
957 | if (session->addrlen != si_ctx->addrlen) | ||
958 | { | ||
948 | return GNUNET_YES; | 959 | return GNUNET_YES; |
949 | if (0 != memcmp (&session->connect_addr, si_ctx->addr, si_ctx->addrlen)) | 960 | } |
961 | if (0 != memcmp (session->addr, si_ctx->addr, si_ctx->addrlen)) | ||
962 | { | ||
950 | return GNUNET_YES; | 963 | return GNUNET_YES; |
951 | 964 | } | |
965 | #if 0 | ||
966 | a1 = strdup (tcp_address_to_string(NULL, session->addr, session->addrlen)); | ||
967 | a2 = strdup (tcp_address_to_string(NULL, si_ctx->addr, si_ctx->addrlen)); | ||
968 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp", | ||
969 | "Comparing: %s %u <-> %s %u , OK!\n", | ||
970 | a1, | ||
971 | session->addrlen, | ||
972 | a2, | ||
973 | si_ctx->addrlen); | ||
974 | GNUNET_free (a1); | ||
975 | GNUNET_free (a2); | ||
976 | #endif | ||
952 | /* Found existing session */ | 977 | /* Found existing session */ |
953 | si_ctx->result = session; | 978 | si_ctx->result = session; |
954 | return GNUNET_NO; | 979 | return GNUNET_NO; |
@@ -987,12 +1012,33 @@ tcp_plugin_get_session (void *cls, | |||
987 | 1012 | ||
988 | addrlen = address->address_length; | 1013 | addrlen = address->address_length; |
989 | 1014 | ||
990 | #if DEBUG_TCP | ||
991 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1015 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
992 | "Trying to get session for `%s' address length %i\n", | 1016 | "Trying to get session for `%s' address length %i\n", |
993 | tcp_address_to_string(NULL, address->address, address->address_length), | 1017 | tcp_address_to_string(NULL, address->address, address->address_length), |
994 | addrlen); | 1018 | addrlen); |
995 | #endif | 1019 | |
1020 | /* look for existing session */ | ||
1021 | if (GNUNET_CONTAINER_multihashmap_contains(plugin->sessionmap, &address->peer.hashPubKey)) | ||
1022 | { | ||
1023 | struct SessionItCtx si_ctx; | ||
1024 | |||
1025 | si_ctx.addr = (void *) address->address; | ||
1026 | si_ctx.addrlen = address->address_length; | ||
1027 | |||
1028 | si_ctx.result = NULL; | ||
1029 | |||
1030 | GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessionmap, &address->peer.hashPubKey, &session_lookup_it, &si_ctx); | ||
1031 | if (si_ctx.result != NULL) | ||
1032 | { | ||
1033 | session = si_ctx.result; | ||
1034 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1035 | "Found exisiting session for `%s' address `%s' session %p\n", | ||
1036 | GNUNET_i2s (&address->peer), | ||
1037 | tcp_address_to_string(NULL, address->address, address->address_length), | ||
1038 | session); | ||
1039 | return session; | ||
1040 | } | ||
1041 | } | ||
996 | 1042 | ||
997 | if (addrlen == sizeof (struct IPv6TcpAddress)) | 1043 | if (addrlen == sizeof (struct IPv6TcpAddress)) |
998 | { | 1044 | { |
@@ -1036,21 +1082,6 @@ tcp_plugin_get_session (void *cls, | |||
1036 | return NULL; | 1082 | return NULL; |
1037 | } | 1083 | } |
1038 | 1084 | ||
1039 | /* look for existing session */ | ||
1040 | if (GNUNET_CONTAINER_multihashmap_contains(plugin->sessionmap, &address->peer.hashPubKey)) | ||
1041 | { | ||
1042 | struct SessionItCtx si_ctx; | ||
1043 | si_ctx.addr = &sbs; | ||
1044 | si_ctx.addrlen = sbs; | ||
1045 | si_ctx.result = NULL; | ||
1046 | GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessionmap, &address->peer.hashPubKey, &session_it, &si_ctx); | ||
1047 | if (si_ctx.result != NULL) | ||
1048 | { | ||
1049 | session = si_ctx.result; | ||
1050 | return session; | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | if ((is_natd == GNUNET_YES) && (addrlen == sizeof (struct IPv6TcpAddress))) | 1085 | if ((is_natd == GNUNET_YES) && (addrlen == sizeof (struct IPv6TcpAddress))) |
1055 | return NULL; /* NAT client only works with IPv4 addresses */ | 1086 | return NULL; /* NAT client only works with IPv4 addresses */ |
1056 | 1087 | ||
@@ -1073,6 +1104,8 @@ tcp_plugin_get_session (void *cls, | |||
1073 | _("Found valid IPv4 NAT address (creating session)!\n")); | 1104 | _("Found valid IPv4 NAT address (creating session)!\n")); |
1074 | #endif | 1105 | #endif |
1075 | session = create_session (plugin, &address->peer, NULL, GNUNET_YES); | 1106 | session = create_session (plugin, &address->peer, NULL, GNUNET_YES); |
1107 | session->addrlen = 0; | ||
1108 | session->addr = NULL; | ||
1076 | GNUNET_assert (session != NULL); | 1109 | GNUNET_assert (session != NULL); |
1077 | 1110 | ||
1078 | GNUNET_assert (GNUNET_CONTAINER_multihashmap_put | 1111 | GNUNET_assert (GNUNET_CONTAINER_multihashmap_put |
@@ -1100,18 +1133,18 @@ tcp_plugin_get_session (void *cls, | |||
1100 | return NULL; | 1133 | return NULL; |
1101 | } | 1134 | } |
1102 | plugin->max_connections--; | 1135 | plugin->max_connections--; |
1103 | #if DEBUG_TCP_NAT | 1136 | |
1104 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1137 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
1105 | "Asked to transmit to `%4s', creating fresh session using address `%s'.\n", | 1138 | "Asked to transmit to `%4s', creating fresh session using address `%s'.\n", |
1106 | GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs)); | 1139 | GNUNET_i2s (&address->peer), GNUNET_a2s (sb, sbs)); |
1107 | #endif | 1140 | |
1108 | session = create_session (plugin, | 1141 | session = create_session (plugin, |
1109 | &address->peer, | 1142 | &address->peer, |
1110 | GNUNET_SERVER_connect_socket (plugin->server, sa), | 1143 | GNUNET_SERVER_connect_socket (plugin->server, sa), |
1111 | GNUNET_NO); | 1144 | GNUNET_NO); |
1112 | session->connect_addr = GNUNET_malloc (addrlen); | 1145 | session->addr = GNUNET_malloc (addrlen); |
1113 | memcpy (session->connect_addr, address->address, addrlen); | 1146 | memcpy (session->addr, address->address, addrlen); |
1114 | session->connect_alen = addrlen; | 1147 | session->addrlen = addrlen; |
1115 | if (addrlen != 0) | 1148 | if (addrlen != 0) |
1116 | { | 1149 | { |
1117 | struct GNUNET_ATS_Information ats; | 1150 | struct GNUNET_ATS_Information ats; |
@@ -1123,6 +1156,12 @@ tcp_plugin_get_session (void *cls, | |||
1123 | 1156 | ||
1124 | GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &address->peer.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | 1157 | GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &address->peer.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); |
1125 | 1158 | ||
1159 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1160 | "Creating new session for `%s' address `%s' session %p\n", | ||
1161 | GNUNET_i2s (&address->peer), | ||
1162 | tcp_address_to_string(NULL, address->address, address->address_length), | ||
1163 | session); | ||
1164 | |||
1126 | /* Send TCP Welcome */ | 1165 | /* Send TCP Welcome */ |
1127 | process_pending_messages (session); | 1166 | process_pending_messages (session); |
1128 | 1167 | ||
@@ -1130,6 +1169,20 @@ tcp_plugin_get_session (void *cls, | |||
1130 | } | 1169 | } |
1131 | 1170 | ||
1132 | 1171 | ||
1172 | int session_disconnect_it (void *cls, | ||
1173 | const GNUNET_HashCode * key, | ||
1174 | void *value) | ||
1175 | { | ||
1176 | struct Session *session = value; | ||
1177 | |||
1178 | GNUNET_STATISTICS_update (session->plugin->env->stats, | ||
1179 | gettext_noop | ||
1180 | ("# transport-service disconnect requests for TCP"), | ||
1181 | 1, GNUNET_NO); | ||
1182 | disconnect_session (session); | ||
1183 | return GNUNET_YES; | ||
1184 | } | ||
1185 | |||
1133 | /** | 1186 | /** |
1134 | * Function that can be called to force a disconnect from the | 1187 | * Function that can be called to force a disconnect from the |
1135 | * specified neighbour. This should also cancel all previously | 1188 | * specified neighbour. This should also cancel all previously |
@@ -1150,34 +1203,11 @@ static void | |||
1150 | tcp_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) | 1203 | tcp_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) |
1151 | { | 1204 | { |
1152 | struct Plugin *plugin = cls; | 1205 | struct Plugin *plugin = cls; |
1153 | struct Session *session; | ||
1154 | struct Session *next; | ||
1155 | struct PendingMessage *pm; | ||
1156 | 1206 | ||
1157 | #if DEBUG_TCP | ||
1158 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1207 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
1159 | "Asked to cancel session with `%4s'\n", GNUNET_i2s (target)); | 1208 | "Disconnecting peer `%4s'\n", GNUNET_i2s (target)); |
1160 | #endif | 1209 | |
1161 | next = plugin->sessions; | 1210 | GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessionmap, &target->hashPubKey, session_disconnect_it, plugin); |
1162 | while (NULL != (session = next)) | ||
1163 | { | ||
1164 | next = session->next; | ||
1165 | if (0 != | ||
1166 | memcmp (target, &session->target, sizeof (struct GNUNET_PeerIdentity))) | ||
1167 | continue; | ||
1168 | pm = session->pending_messages_head; | ||
1169 | while (pm != NULL) | ||
1170 | { | ||
1171 | pm->transmit_cont = NULL; | ||
1172 | pm->transmit_cont_cls = NULL; | ||
1173 | pm = pm->next; | ||
1174 | } | ||
1175 | GNUNET_STATISTICS_update (session->plugin->env->stats, | ||
1176 | gettext_noop | ||
1177 | ("# transport-service disconnect requests for TCP"), | ||
1178 | 1, GNUNET_NO); | ||
1179 | disconnect_session (session); | ||
1180 | } | ||
1181 | } | 1211 | } |
1182 | 1212 | ||
1183 | 1213 | ||
@@ -1466,16 +1496,16 @@ handle_tcp_nat_probe (void *cls, struct GNUNET_SERVER_Client *client, | |||
1466 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); | 1496 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); |
1467 | t4->t4_port = s4->sin_port; | 1497 | t4->t4_port = s4->sin_port; |
1468 | t4->ipv4_addr = s4->sin_addr.s_addr; | 1498 | t4->ipv4_addr = s4->sin_addr.s_addr; |
1469 | session->connect_addr = t4; | 1499 | session->addr = t4; |
1470 | session->connect_alen = sizeof (struct IPv4TcpAddress); | 1500 | session->addrlen = sizeof (struct IPv4TcpAddress); |
1471 | break; | 1501 | break; |
1472 | case AF_INET6: | 1502 | case AF_INET6: |
1473 | s6 = vaddr; | 1503 | s6 = vaddr; |
1474 | t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress)); | 1504 | t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress)); |
1475 | t6->t6_port = s6->sin6_port; | 1505 | t6->t6_port = s6->sin6_port; |
1476 | memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof (struct in6_addr)); | 1506 | memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof (struct in6_addr)); |
1477 | session->connect_addr = t6; | 1507 | session->addr = t6; |
1478 | session->connect_alen = sizeof (struct IPv6TcpAddress); | 1508 | session->addrlen = sizeof (struct IPv6TcpAddress); |
1479 | break; | 1509 | break; |
1480 | default: | 1510 | default: |
1481 | GNUNET_break_op (0); | 1511 | GNUNET_break_op (0); |
@@ -1491,8 +1521,8 @@ handle_tcp_nat_probe (void *cls, struct GNUNET_SERVER_Client *client, | |||
1491 | } | 1521 | } |
1492 | GNUNET_free (vaddr); | 1522 | GNUNET_free (vaddr); |
1493 | 1523 | ||
1494 | session->next = plugin->sessions; | 1524 | GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &session->target.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); |
1495 | plugin->sessions = session; | 1525 | |
1496 | GNUNET_STATISTICS_update (plugin->env->stats, | 1526 | GNUNET_STATISTICS_update (plugin->env->stats, |
1497 | gettext_noop ("# TCP sessions active"), 1, | 1527 | gettext_noop ("# TCP sessions active"), 1, |
1498 | GNUNET_NO); | 1528 | GNUNET_NO); |
@@ -1531,42 +1561,42 @@ handle_tcp_welcome (void *cls, struct GNUNET_SERVER_Client *client, | |||
1531 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 1561 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
1532 | return; | 1562 | return; |
1533 | } | 1563 | } |
1534 | #if DEBUG_TCP | 1564 | |
1535 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1565 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
1536 | "Received %s message from `%4s'.\n", "WELCOME", | 1566 | "Received %s message from `%4s'\n", "WELCOME", |
1537 | GNUNET_i2s (&wm->clientIdentity)); | 1567 | GNUNET_i2s (&wm->clientIdentity)); |
1538 | #endif | ||
1539 | GNUNET_STATISTICS_update (plugin->env->stats, | 1568 | GNUNET_STATISTICS_update (plugin->env->stats, |
1540 | gettext_noop ("# TCP WELCOME messages received"), 1, | 1569 | gettext_noop ("# TCP WELCOME messages received"), 1, |
1541 | GNUNET_NO); | 1570 | GNUNET_NO); |
1542 | session = find_session_by_client (plugin, client); | ||
1543 | 1571 | ||
1544 | if (session == NULL) | 1572 | session = lookup_session_by_client (plugin, client); |
1573 | if (session != NULL) | ||
1545 | { | 1574 | { |
1546 | #if DEBUG_TCP_NAT | ||
1547 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1548 | "Received %s message from a `%4s', creating new session\n", | ||
1549 | "WELCOME", GNUNET_i2s (&wm->clientIdentity)); | ||
1550 | #endif | ||
1551 | GNUNET_SERVER_client_keep (client); | ||
1552 | session = create_session (plugin, &wm->clientIdentity, client, GNUNET_NO); | ||
1553 | session->inbound = GNUNET_YES; | ||
1554 | if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) | 1575 | if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) |
1555 | { | 1576 | { |
1556 | #if DEBUG_TCP_NAT | ||
1557 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1577 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
1558 | "Found address `%s' for incoming connection\n", | 1578 | "Found existing session %p for peer `%s'\n", |
1579 | session, | ||
1559 | GNUNET_a2s (vaddr, alen)); | 1580 | GNUNET_a2s (vaddr, alen)); |
1560 | #endif | 1581 | GNUNET_free (vaddr); |
1582 | } | ||
1583 | } | ||
1584 | else | ||
1585 | { | ||
1586 | GNUNET_SERVER_client_keep (client); | ||
1587 | session = create_session (plugin, &wm->clientIdentity, client, GNUNET_NO); | ||
1588 | session->inbound = GNUNET_YES; | ||
1561 | 1589 | ||
1590 | if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) | ||
1591 | { | ||
1562 | if (alen == sizeof (struct sockaddr_in)) | 1592 | if (alen == sizeof (struct sockaddr_in)) |
1563 | { | 1593 | { |
1564 | s4 = vaddr; | 1594 | s4 = vaddr; |
1565 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); | 1595 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); |
1566 | t4->t4_port = s4->sin_port; | 1596 | t4->t4_port = s4->sin_port; |
1567 | t4->ipv4_addr = s4->sin_addr.s_addr; | 1597 | t4->ipv4_addr = s4->sin_addr.s_addr; |
1568 | session->connect_addr = t4; | 1598 | session->addr = t4; |
1569 | session->connect_alen = sizeof (struct IPv4TcpAddress); | 1599 | session->addrlen = sizeof (struct IPv4TcpAddress); |
1570 | } | 1600 | } |
1571 | else if (alen == sizeof (struct sockaddr_in6)) | 1601 | else if (alen == sizeof (struct sockaddr_in6)) |
1572 | { | 1602 | { |
@@ -1574,8 +1604,8 @@ handle_tcp_welcome (void *cls, struct GNUNET_SERVER_Client *client, | |||
1574 | t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress)); | 1604 | t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress)); |
1575 | t6->t6_port = s6->sin6_port; | 1605 | t6->t6_port = s6->sin6_port; |
1576 | memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof (struct in6_addr)); | 1606 | memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof (struct in6_addr)); |
1577 | session->connect_addr = t6; | 1607 | session->addr = t6; |
1578 | session->connect_alen = sizeof (struct IPv6TcpAddress); | 1608 | session->addrlen = sizeof (struct IPv6TcpAddress); |
1579 | } | 1609 | } |
1580 | 1610 | ||
1581 | struct GNUNET_ATS_Information ats; | 1611 | struct GNUNET_ATS_Information ats; |
@@ -1591,19 +1621,7 @@ handle_tcp_welcome (void *cls, struct GNUNET_SERVER_Client *client, | |||
1591 | "Did not obtain TCP socket address for incoming connection\n"); | 1621 | "Did not obtain TCP socket address for incoming connection\n"); |
1592 | #endif | 1622 | #endif |
1593 | } | 1623 | } |
1594 | process_pending_messages (session); | 1624 | GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &wm->clientIdentity.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); |
1595 | } | ||
1596 | else | ||
1597 | { | ||
1598 | #if DEBUG_TCP_NAT | ||
1599 | if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) | ||
1600 | { | ||
1601 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1602 | "Found address `%s' (already have session)\n", | ||
1603 | GNUNET_a2s (vaddr, alen)); | ||
1604 | GNUNET_free (vaddr); | ||
1605 | } | ||
1606 | #endif | ||
1607 | } | 1625 | } |
1608 | 1626 | ||
1609 | if (session->expecting_welcome != GNUNET_YES) | 1627 | if (session->expecting_welcome != GNUNET_YES) |
@@ -1614,6 +1632,10 @@ handle_tcp_welcome (void *cls, struct GNUNET_SERVER_Client *client, | |||
1614 | } | 1632 | } |
1615 | session->last_activity = GNUNET_TIME_absolute_get (); | 1633 | session->last_activity = GNUNET_TIME_absolute_get (); |
1616 | session->expecting_welcome = GNUNET_NO; | 1634 | session->expecting_welcome = GNUNET_NO; |
1635 | |||
1636 | |||
1637 | process_pending_messages (session); | ||
1638 | |||
1617 | GNUNET_SERVER_client_set_timeout (client, | 1639 | GNUNET_SERVER_client_set_timeout (client, |
1618 | GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); | 1640 | GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); |
1619 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1641 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
@@ -1672,20 +1694,30 @@ handle_tcp_data (void *cls, struct GNUNET_SERVER_Client *client, | |||
1672 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1694 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1673 | return; | 1695 | return; |
1674 | } | 1696 | } |
1675 | session = find_session_by_client (plugin, client); | 1697 | session = lookup_session_by_client (plugin, client); |
1676 | if ((NULL == session) || (GNUNET_YES == session->expecting_welcome)) | 1698 | if (NULL == session) |
1677 | { | 1699 | { |
1700 | /* No inbound session found */ | ||
1701 | GNUNET_break_op (0); | ||
1702 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1703 | return; | ||
1704 | } | ||
1705 | else if (GNUNET_YES == session->expecting_welcome) | ||
1706 | { | ||
1707 | /* Session is expecting WELCOME message */ | ||
1708 | GNUNET_break_op (0); | ||
1678 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 1709 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
1679 | return; | 1710 | return; |
1680 | } | 1711 | } |
1712 | |||
1681 | session->last_activity = GNUNET_TIME_absolute_get (); | 1713 | session->last_activity = GNUNET_TIME_absolute_get (); |
1682 | #if DEBUG_TCP | 1714 | |
1683 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1715 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
1684 | "Passing %u bytes of type %u from `%4s' to transport service.\n", | 1716 | "Passing %u bytes of type %u from `%4s' to transport service.\n", |
1685 | (unsigned int) ntohs (message->size), | 1717 | (unsigned int) ntohs (message->size), |
1686 | (unsigned int) ntohs (message->type), | 1718 | (unsigned int) ntohs (message->type), |
1687 | GNUNET_i2s (&session->target)); | 1719 | GNUNET_i2s (&session->target)); |
1688 | #endif | 1720 | |
1689 | GNUNET_STATISTICS_update (plugin->env->stats, | 1721 | GNUNET_STATISTICS_update (plugin->env->stats, |
1690 | gettext_noop ("# bytes received via TCP"), | 1722 | gettext_noop ("# bytes received via TCP"), |
1691 | ntohs (message->size), GNUNET_NO); | 1723 | ntohs (message->size), GNUNET_NO); |
@@ -1697,14 +1729,13 @@ handle_tcp_data (void *cls, struct GNUNET_SERVER_Client *client, | |||
1697 | distance[1].value = session->ats_address_network_type; | 1729 | distance[1].value = session->ats_address_network_type; |
1698 | GNUNET_break (ntohl(session->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); | 1730 | GNUNET_break (ntohl(session->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); |
1699 | 1731 | ||
1700 | delay = | 1732 | delay = plugin->env->receive (plugin->env->cls, |
1701 | plugin->env->receive (plugin->env->cls, &session->target, message, | 1733 | &session->target, |
1702 | (const struct GNUNET_ATS_Information *) &distance, | 1734 | message, |
1703 | 1, session, | 1735 | (const struct GNUNET_ATS_Information *) &distance, |
1704 | (GNUNET_YES == | 1736 | 1, session, |
1705 | session->inbound) ? NULL : session->connect_addr, | 1737 | (GNUNET_YES == session->inbound) ? NULL : session->addr, |
1706 | (GNUNET_YES == | 1738 | (GNUNET_YES == session->inbound) ? 0 : session->addrlen); |
1707 | session->inbound) ? 0 : session->connect_alen); | ||
1708 | if (delay.rel_value == 0) | 1739 | if (delay.rel_value == 0) |
1709 | { | 1740 | { |
1710 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1741 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
@@ -1740,17 +1771,17 @@ disconnect_notify (void *cls, struct GNUNET_SERVER_Client *client) | |||
1740 | if (client == NULL) | 1771 | if (client == NULL) |
1741 | return; | 1772 | return; |
1742 | plugin->max_connections++; | 1773 | plugin->max_connections++; |
1743 | session = find_session_by_client (plugin, client); | 1774 | session = lookup_session_by_client (plugin, client); |
1744 | if (session == NULL) | 1775 | if (session == NULL) |
1745 | return; /* unknown, nothing to do */ | 1776 | return; /* unknown, nothing to do */ |
1746 | #if DEBUG_TCP | 1777 | #if DEBUG_TCP |
1747 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1778 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
1748 | "Destroying session of `%4s' with %s due to network-level disconnect.\n", | 1779 | "Destroying session of `%4s' with %s due to network-level disconnect.\n", |
1749 | GNUNET_i2s (&session->target), | 1780 | GNUNET_i2s (&session->target), |
1750 | (session->connect_addr != | 1781 | (session->addr != |
1751 | NULL) ? tcp_address_to_string (session->plugin, | 1782 | NULL) ? tcp_address_to_string (session->plugin, |
1752 | session->connect_addr, | 1783 | session->addr, |
1753 | session->connect_alen) : | 1784 | session->addrlen) : |
1754 | "*"); | 1785 | "*"); |
1755 | #endif | 1786 | #endif |
1756 | GNUNET_STATISTICS_update (session->plugin->env->stats, | 1787 | GNUNET_STATISTICS_update (session->plugin->env->stats, |
@@ -2016,11 +2047,14 @@ libgnunet_plugin_transport_tcp_done (void *cls) | |||
2016 | { | 2047 | { |
2017 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; | 2048 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; |
2018 | struct Plugin *plugin = api->cls; | 2049 | struct Plugin *plugin = api->cls; |
2019 | struct Session *session; | ||
2020 | struct TCPProbeContext *tcp_probe; | 2050 | struct TCPProbeContext *tcp_probe; |
2021 | 2051 | ||
2022 | while (NULL != (session = plugin->sessions)) | 2052 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", "Shutting down TCP plugin\n"); |
2023 | disconnect_session (session); | 2053 | |
2054 | |||
2055 | /* Removing leftover sessions */ | ||
2056 | GNUNET_CONTAINER_multihashmap_iterate(plugin->sessionmap, &session_disconnect_it, NULL); | ||
2057 | |||
2024 | if (plugin->service != NULL) | 2058 | if (plugin->service != NULL) |
2025 | GNUNET_SERVICE_stop (plugin->service); | 2059 | GNUNET_SERVICE_stop (plugin->service); |
2026 | else | 2060 | else |