diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2012-02-13 16:02:44 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2012-02-13 16:02:44 +0000 |
commit | 2e2e5b4a8e5cebd71b880da8c613be4a49f44fe2 (patch) | |
tree | 270c64858fd4494c0d62970b7aa5926d185cef46 /src/transport/plugin_transport_tcp.c | |
parent | 5b9e61b9c3832e69164ee8574fff6711b2f18ef6 (diff) | |
download | gnunet-2e2e5b4a8e5cebd71b880da8c613be4a49f44fe2.tar.gz gnunet-2e2e5b4a8e5cebd71b880da8c613be4a49f44fe2.zip |
removing legacy send functions from plugins and renaming new send function
Diffstat (limited to 'src/transport/plugin_transport_tcp.c')
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 335 |
1 files changed, 1 insertions, 334 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index 2ce3cc8c7..4157024c9 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -863,337 +863,6 @@ disconnect_session (struct Session *session) | |||
863 | 863 | ||
864 | 864 | ||
865 | /** | 865 | /** |
866 | * Given two otherwise equivalent sessions, pick the better one. | ||
867 | * | ||
868 | * @param s1 one session (also default) | ||
869 | * @param s2 other session | ||
870 | * @return "better" session (more active) | ||
871 | */ | ||
872 | static struct Session * | ||
873 | select_better_session (struct Session *s1, struct Session *s2) | ||
874 | { | ||
875 | if (s1 == NULL) | ||
876 | return s2; | ||
877 | if (s2 == NULL) | ||
878 | return s1; | ||
879 | if ((s1->expecting_welcome == GNUNET_NO) && | ||
880 | (s2->expecting_welcome == GNUNET_YES)) | ||
881 | return s1; | ||
882 | if ((s1->expecting_welcome == GNUNET_YES) && | ||
883 | (s2->expecting_welcome == GNUNET_NO)) | ||
884 | return s2; | ||
885 | if (s1->last_activity.abs_value < s2->last_activity.abs_value) | ||
886 | return s2; | ||
887 | if (s1->last_activity.abs_value > s2->last_activity.abs_value) | ||
888 | return s1; | ||
889 | if ((GNUNET_YES == s1->inbound) && (GNUNET_NO == s2->inbound)) | ||
890 | return s1; | ||
891 | if ((GNUNET_NO == s1->inbound) && (GNUNET_YES == s2->inbound)) | ||
892 | return s2; | ||
893 | return s1; | ||
894 | } | ||
895 | |||
896 | |||
897 | |||
898 | /** | ||
899 | * Function that can be used by the transport service to transmit | ||
900 | * a message using the plugin. Note that in the case of a | ||
901 | * peer disconnecting, the continuation MUST be called | ||
902 | * prior to the disconnect notification itself. This function | ||
903 | * will be called with this peer's HELLO message to initiate | ||
904 | * a fresh connection to another peer. | ||
905 | * | ||
906 | * @param cls closure | ||
907 | * @param target who should receive this message | ||
908 | * @param msg the message to transmit | ||
909 | * @param msgbuf_size number of bytes in 'msg' | ||
910 | * @param priority how important is the message (most plugins will | ||
911 | * ignore message priority and just FIFO) | ||
912 | * @param timeout how long to wait at most for the transmission (does not | ||
913 | * require plugins to discard the message after the timeout, | ||
914 | * just advisory for the desired delay; most plugins will ignore | ||
915 | * this as well) | ||
916 | * @param session which session must be used (or NULL for "any") | ||
917 | * @param addr the address to use (can be NULL if the plugin | ||
918 | * is "on its own" (i.e. re-use existing TCP connection)) | ||
919 | * @param addrlen length of the address in bytes | ||
920 | * @param force_address GNUNET_YES if the plugin MUST use the given address, | ||
921 | * GNUNET_NO means the plugin may use any other address and | ||
922 | * GNUNET_SYSERR means that only reliable existing | ||
923 | * bi-directional connections should be used (regardless | ||
924 | * of address) | ||
925 | * @param cont continuation to call once the message has | ||
926 | * been transmitted (or if the transport is ready | ||
927 | * for the next transmission call; or if the | ||
928 | * peer disconnected...); can be NULL | ||
929 | * @param cont_cls closure for cont | ||
930 | * @return number of bytes used (on the physical network, with overheads); | ||
931 | * -1 on hard errors (i.e. address invalid); 0 is a legal value | ||
932 | * and does NOT mean that the message was not transmitted (DV and NAT) | ||
933 | */ | ||
934 | static ssize_t | ||
935 | tcp_plugin_send_old (void *cls, const struct GNUNET_PeerIdentity *target, | ||
936 | const char *msg, size_t msgbuf_size, uint32_t priority, | ||
937 | struct GNUNET_TIME_Relative timeout, struct Session *session, | ||
938 | const void *addr, size_t addrlen, int force_address, | ||
939 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) | ||
940 | { | ||
941 | struct Plugin *plugin = cls; | ||
942 | struct Session *cand_session; | ||
943 | struct Session *next; | ||
944 | struct PendingMessage *pm; | ||
945 | struct GNUNET_CONNECTION_Handle *sa; | ||
946 | int af; | ||
947 | const void *sb; | ||
948 | size_t sbs; | ||
949 | struct sockaddr_in a4; | ||
950 | struct sockaddr_in6 a6; | ||
951 | const struct IPv4TcpAddress *t4; | ||
952 | const struct IPv6TcpAddress *t6; | ||
953 | unsigned int is_natd; | ||
954 | |||
955 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
956 | gettext_noop ("# bytes TCP was asked to transmit"), | ||
957 | msgbuf_size, GNUNET_NO); | ||
958 | /* FIXME: we could do this cheaper with a hash table | ||
959 | * where we could restrict the iteration to entries that match | ||
960 | * the target peer... */ | ||
961 | is_natd = GNUNET_NO; | ||
962 | if (session == NULL) | ||
963 | { | ||
964 | cand_session = NULL; | ||
965 | next = plugin->sessions; | ||
966 | while (NULL != (session = next)) | ||
967 | { | ||
968 | next = session->next; | ||
969 | GNUNET_assert (session->client != NULL); | ||
970 | if (0 != | ||
971 | memcmp (target, &session->target, | ||
972 | sizeof (struct GNUNET_PeerIdentity))) | ||
973 | continue; | ||
974 | if (((GNUNET_SYSERR == force_address) && | ||
975 | (session->expecting_welcome == GNUNET_NO)) || | ||
976 | (GNUNET_NO == force_address)) | ||
977 | { | ||
978 | cand_session = select_better_session (cand_session, session); | ||
979 | continue; | ||
980 | } | ||
981 | if (GNUNET_SYSERR == force_address) | ||
982 | continue; | ||
983 | GNUNET_break (GNUNET_YES == force_address); | ||
984 | if (addr == NULL) | ||
985 | { | ||
986 | GNUNET_break (0); | ||
987 | break; | ||
988 | } | ||
989 | if ((addrlen != session->connect_alen) && (session->is_nat == GNUNET_NO)) | ||
990 | continue; | ||
991 | if ((0 != memcmp (session->connect_addr, addr, addrlen)) && | ||
992 | (session->is_nat == GNUNET_NO)) | ||
993 | continue; | ||
994 | cand_session = select_better_session (cand_session, session); | ||
995 | } | ||
996 | session = cand_session; | ||
997 | } | ||
998 | if ((session == NULL) && (addrlen == 0)) | ||
999 | { | ||
1000 | #if DEBUG_TCP | ||
1001 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1002 | "Asked to transmit to `%4s' without address and I have no existing connection (failing).\n", | ||
1003 | GNUNET_i2s (target)); | ||
1004 | #endif | ||
1005 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1006 | gettext_noop | ||
1007 | ("# bytes discarded by TCP (no address and no connection)"), | ||
1008 | msgbuf_size, GNUNET_NO); | ||
1009 | return -1; | ||
1010 | } | ||
1011 | if (session == NULL) | ||
1012 | { | ||
1013 | if (addrlen == sizeof (struct IPv6TcpAddress)) | ||
1014 | { | ||
1015 | GNUNET_assert (NULL != addr); /* make static analysis happy */ | ||
1016 | t6 = addr; | ||
1017 | af = AF_INET6; | ||
1018 | memset (&a6, 0, sizeof (a6)); | ||
1019 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
1020 | a6.sin6_len = sizeof (a6); | ||
1021 | #endif | ||
1022 | a6.sin6_family = AF_INET6; | ||
1023 | a6.sin6_port = t6->t6_port; | ||
1024 | if (t6->t6_port == 0) | ||
1025 | is_natd = GNUNET_YES; | ||
1026 | memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof (struct in6_addr)); | ||
1027 | sb = &a6; | ||
1028 | sbs = sizeof (a6); | ||
1029 | } | ||
1030 | else if (addrlen == sizeof (struct IPv4TcpAddress)) | ||
1031 | { | ||
1032 | GNUNET_assert (NULL != addr); /* make static analysis happy */ | ||
1033 | t4 = addr; | ||
1034 | af = AF_INET; | ||
1035 | memset (&a4, 0, sizeof (a4)); | ||
1036 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
1037 | a4.sin_len = sizeof (a4); | ||
1038 | #endif | ||
1039 | a4.sin_family = AF_INET; | ||
1040 | a4.sin_port = t4->t4_port; | ||
1041 | if (t4->t4_port == 0) | ||
1042 | is_natd = GNUNET_YES; | ||
1043 | a4.sin_addr.s_addr = t4->ipv4_addr; | ||
1044 | sb = &a4; | ||
1045 | sbs = sizeof (a4); | ||
1046 | } | ||
1047 | else | ||
1048 | { | ||
1049 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp", | ||
1050 | _("Address of unexpected length: %u\n"), addrlen); | ||
1051 | GNUNET_break (0); | ||
1052 | return -1; | ||
1053 | } | ||
1054 | |||
1055 | if ((is_natd == GNUNET_YES) && (addrlen == sizeof (struct IPv6TcpAddress))) | ||
1056 | return -1; /* NAT client only works with IPv4 addresses */ | ||
1057 | if (0 == plugin->max_connections) | ||
1058 | return -1; /* saturated */ | ||
1059 | |||
1060 | if ((is_natd == GNUNET_YES) && (NULL != plugin->nat) && | ||
1061 | (GNUNET_NO == | ||
1062 | GNUNET_CONTAINER_multihashmap_contains (plugin->nat_wait_conns, | ||
1063 | &target->hashPubKey))) | ||
1064 | { | ||
1065 | #if DEBUG_TCP_NAT | ||
1066 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1067 | _("Found valid IPv4 NAT address (creating session)!\n")); | ||
1068 | #endif | ||
1069 | session = create_session (plugin, target, NULL, GNUNET_YES); | ||
1070 | GNUNET_assert (session != NULL); | ||
1071 | |||
1072 | /* create new message entry */ | ||
1073 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size); | ||
1074 | /* FIXME: the memset of this malloc can be up to 2% of our total runtime */ | ||
1075 | pm->msg = (const char *) &pm[1]; | ||
1076 | memcpy (&pm[1], msg, msgbuf_size); | ||
1077 | /* FIXME: this memcpy can be up to 7% of our total run-time | ||
1078 | * (for transport service) */ | ||
1079 | pm->message_size = msgbuf_size; | ||
1080 | pm->timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1081 | pm->transmit_cont = cont; | ||
1082 | pm->transmit_cont_cls = cont_cls; | ||
1083 | |||
1084 | /* append pm to pending_messages list */ | ||
1085 | GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head, | ||
1086 | session->pending_messages_tail, pm); | ||
1087 | |||
1088 | GNUNET_assert (GNUNET_CONTAINER_multihashmap_put | ||
1089 | (plugin->nat_wait_conns, &target->hashPubKey, session, | ||
1090 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) == | ||
1091 | GNUNET_OK); | ||
1092 | #if DEBUG_TCP_NAT | ||
1093 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1094 | "Created NAT WAIT connection to `%4s' at `%s'\n", | ||
1095 | GNUNET_i2s (target), GNUNET_a2s (sb, sbs)); | ||
1096 | #endif | ||
1097 | GNUNET_NAT_run_client (plugin->nat, &a4); | ||
1098 | return 0; | ||
1099 | } | ||
1100 | if ((is_natd == GNUNET_YES) && | ||
1101 | (GNUNET_YES == | ||
1102 | GNUNET_CONTAINER_multihashmap_contains (plugin->nat_wait_conns, | ||
1103 | &target->hashPubKey))) | ||
1104 | { | ||
1105 | /* Only do one NAT punch attempt per peer identity */ | ||
1106 | return -1; | ||
1107 | } | ||
1108 | sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs); | ||
1109 | if (sa == NULL) | ||
1110 | { | ||
1111 | #if DEBUG_TCP | ||
1112 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1113 | "Failed to create connection to `%4s' at `%s'\n", | ||
1114 | GNUNET_i2s (target), GNUNET_a2s (sb, sbs)); | ||
1115 | #endif | ||
1116 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1117 | gettext_noop | ||
1118 | ("# bytes discarded by TCP (failed to connect)"), | ||
1119 | msgbuf_size, GNUNET_NO); | ||
1120 | return -1; | ||
1121 | } | ||
1122 | GNUNET_assert (0 != plugin->max_connections); | ||
1123 | plugin->max_connections--; | ||
1124 | #if DEBUG_TCP_NAT | ||
1125 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1126 | "Asked to transmit to `%4s', creating fresh session using address `%s'.\n", | ||
1127 | GNUNET_i2s (target), GNUNET_a2s (sb, sbs)); | ||
1128 | #endif | ||
1129 | session = | ||
1130 | create_session (plugin, target, | ||
1131 | GNUNET_SERVER_connect_socket (plugin->server, sa), | ||
1132 | GNUNET_NO); | ||
1133 | session->connect_addr = GNUNET_malloc (addrlen); | ||
1134 | memcpy (session->connect_addr, addr, addrlen); | ||
1135 | session->connect_alen = addrlen; | ||
1136 | if (addrlen != 0) | ||
1137 | { | ||
1138 | struct GNUNET_ATS_Information ats; | ||
1139 | ats = plugin->env->get_address_type (plugin->env->cls, sb ,sbs); | ||
1140 | session->ats_address_network_type = ats.value; | ||
1141 | } | ||
1142 | else | ||
1143 | GNUNET_break (0); | ||
1144 | } | ||
1145 | else /* session != NULL */ | ||
1146 | { | ||
1147 | /* check if session is valid */ | ||
1148 | struct Session *ses = plugin->sessions; | ||
1149 | |||
1150 | if (0 != | ||
1151 | memcmp (target, &session->target, sizeof (struct GNUNET_PeerIdentity))) | ||
1152 | { | ||
1153 | GNUNET_break (0); | ||
1154 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1155 | "Got session %p for `%s', but should be for peer `%s'!\n", | ||
1156 | session, GNUNET_i2s (&session->target), | ||
1157 | GNUNET_h2s (&target->hashPubKey)); | ||
1158 | return -1; | ||
1159 | } | ||
1160 | |||
1161 | while ((ses != NULL) && (ses != session)) | ||
1162 | ses = ses->next; | ||
1163 | if (ses == NULL) | ||
1164 | { | ||
1165 | return -1; | ||
1166 | } | ||
1167 | } | ||
1168 | GNUNET_assert (session != NULL); | ||
1169 | GNUNET_assert (session->client != NULL); | ||
1170 | GNUNET_SERVER_client_set_timeout (session->client, | ||
1171 | GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); | ||
1172 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1173 | gettext_noop ("# bytes currently in TCP buffers"), | ||
1174 | msgbuf_size, GNUNET_NO); | ||
1175 | /* create new message entry */ | ||
1176 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size); | ||
1177 | pm->msg = (const char *) &pm[1]; | ||
1178 | memcpy (&pm[1], msg, msgbuf_size); | ||
1179 | pm->message_size = msgbuf_size; | ||
1180 | pm->timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1181 | pm->transmit_cont = cont; | ||
1182 | pm->transmit_cont_cls = cont_cls; | ||
1183 | |||
1184 | /* append pm to pending_messages list */ | ||
1185 | GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head, | ||
1186 | session->pending_messages_tail, pm); | ||
1187 | #if DEBUG_TCP | ||
1188 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1189 | "Asked to transmit %u bytes to `%s', added message to list.\n", | ||
1190 | msgbuf_size, GNUNET_i2s (target)); | ||
1191 | #endif | ||
1192 | process_pending_messages (session); | ||
1193 | return msgbuf_size; | ||
1194 | } | ||
1195 | |||
1196 | /** | ||
1197 | * Function that can be used by the transport service to transmit | 866 | * Function that can be used by the transport service to transmit |
1198 | * a message using the plugin. Note that in the case of a | 867 | * a message using the plugin. Note that in the case of a |
1199 | * peer disconnecting, the continuation MUST be called | 868 | * peer disconnecting, the continuation MUST be called |
@@ -2285,9 +1954,7 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
2285 | } | 1954 | } |
2286 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); | 1955 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); |
2287 | api->cls = plugin; | 1956 | api->cls = plugin; |
2288 | api->send = &tcp_plugin_send_old; | 1957 | api->send = &tcp_plugin_send; |
2289 | |||
2290 | api->send_with_session = &tcp_plugin_send; | ||
2291 | api->get_session = &tcp_plugin_get_session; | 1958 | api->get_session = &tcp_plugin_get_session; |
2292 | 1959 | ||
2293 | api->disconnect = &tcp_plugin_disconnect; | 1960 | api->disconnect = &tcp_plugin_disconnect; |