diff options
Diffstat (limited to 'src/mesh/gnunet-service-mesh-new.c')
-rw-r--r-- | src/mesh/gnunet-service-mesh-new.c | 869 |
1 files changed, 116 insertions, 753 deletions
diff --git a/src/mesh/gnunet-service-mesh-new.c b/src/mesh/gnunet-service-mesh-new.c index 8c98d4a34..0fb4766ea 100644 --- a/src/mesh/gnunet-service-mesh-new.c +++ b/src/mesh/gnunet-service-mesh-new.c | |||
@@ -370,22 +370,22 @@ struct MeshTunnel | |||
370 | GNUNET_PEER_Id dest; | 370 | GNUNET_PEER_Id dest; |
371 | 371 | ||
372 | /** | 372 | /** |
373 | * Next hop in the tunnel. | 373 | * Next hop in the tunnel. If 0, @c client must be set. |
374 | */ | 374 | */ |
375 | GNUNET_PEER_Id next_hop; | 375 | GNUNET_PEER_Id next_hop; |
376 | 376 | ||
377 | /** | 377 | /** |
378 | * Previous hop in the tunnel. | 378 | * Previous hop in the tunnel. If 0, @c owner must be set. |
379 | */ | 379 | */ |
380 | GNUNET_PEER_Id prev_hop; | 380 | GNUNET_PEER_Id prev_hop; |
381 | 381 | ||
382 | /** | 382 | /** |
383 | * Flow control information about @c next_hop. | 383 | * Flow control information about @c next_hop or @c client. |
384 | */ | 384 | */ |
385 | struct MeshFlowControl next_fc; | 385 | struct MeshFlowControl next_fc; |
386 | 386 | ||
387 | /** | 387 | /** |
388 | * Flow control information about @c prev_hop. | 388 | * Flow control information about @c prev_hop or @c owner. |
389 | */ | 389 | */ |
390 | struct MeshFlowControl prev_fc; | 390 | struct MeshFlowControl prev_fc; |
391 | 391 | ||
@@ -395,35 +395,15 @@ struct MeshTunnel | |||
395 | struct MeshClient *owner; | 395 | struct MeshClient *owner; |
396 | 396 | ||
397 | /** | 397 | /** |
398 | * Task to keep the used paths alive at the owner, | 398 | * Client destination of the tunnel, if any. |
399 | * time tunnel out on all the other peers. | ||
400 | */ | ||
401 | GNUNET_SCHEDULER_TaskIdentifier maintenance_task; | ||
402 | |||
403 | /** | ||
404 | * Clients that have been informed about and want to stay in the tunnel. | ||
405 | */ | ||
406 | struct MeshClient **clients; | ||
407 | |||
408 | /** | ||
409 | * Flow control info for each client. | ||
410 | */ | 399 | */ |
411 | struct MeshTunnelClientInfo *clients_fc; | 400 | struct MeshClient *client; |
412 | 401 | ||
413 | /** | 402 | /** |
414 | * Number of elements in clients/clients_fc | 403 | * Task to keep the used paths alive at the owner, |
415 | */ | 404 | * time tunnel out on all the other peers. |
416 | unsigned int nclients; | ||
417 | |||
418 | /** | ||
419 | * Clients that have been informed but requested to leave the tunnel. | ||
420 | */ | ||
421 | struct MeshClient **ignore; | ||
422 | |||
423 | /** | ||
424 | * Number of elements in clients | ||
425 | */ | 405 | */ |
426 | unsigned int nignore; | 406 | GNUNET_SCHEDULER_TaskIdentifier maintenance_task; |
427 | 407 | ||
428 | /** | 408 | /** |
429 | * Path being used for the tunnel. | 409 | * Path being used for the tunnel. |
@@ -441,43 +421,13 @@ struct MeshTunnel | |||
441 | * Total messages pending for this tunnels, payload or not. | 421 | * Total messages pending for this tunnels, payload or not. |
442 | */ | 422 | */ |
443 | unsigned int pending_messages; | 423 | unsigned int pending_messages; |
444 | |||
445 | /** | ||
446 | * If the tunnel is empty, destoy it. | ||
447 | */ | ||
448 | GNUNET_SCHEDULER_TaskIdentifier delayed_destroy; | ||
449 | }; | ||
450 | |||
451 | |||
452 | /** | ||
453 | * Info about a leaf client of a tunnel, needed to perform flow control. | ||
454 | */ | ||
455 | struct MeshTunnelClientInfo | ||
456 | { | ||
457 | /** | ||
458 | * PID of the last packet sent to the client (FWD). | ||
459 | */ | ||
460 | uint32_t fwd_pid; | ||
461 | |||
462 | /** | ||
463 | * PID of the last packet received from the client (BCK). | ||
464 | */ | ||
465 | uint32_t bck_pid; | ||
466 | |||
467 | /** | ||
468 | * Maximum PID allowed (FWD ACK received). | ||
469 | */ | ||
470 | uint32_t fwd_ack; | ||
471 | |||
472 | /** | ||
473 | * Last ACK sent to that child (BCK ACK). | ||
474 | */ | ||
475 | uint32_t bck_ack; | ||
476 | }; | 424 | }; |
477 | 425 | ||
478 | 426 | ||
479 | /** | 427 | /** |
480 | * Struct containing information about a client of the service | 428 | * Struct containing information about a client of the service |
429 | * | ||
430 | * TODO: add a list of 'waiting' types | ||
481 | */ | 431 | */ |
482 | struct MeshClient | 432 | struct MeshClient |
483 | { | 433 | { |
@@ -501,10 +451,6 @@ struct MeshClient | |||
501 | */ | 451 | */ |
502 | struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels; | 452 | struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels; |
503 | 453 | ||
504 | /** | ||
505 | * Tunnels this client has rejected, indexed by incoming local id | ||
506 | */ | ||
507 | struct GNUNET_CONTAINER_MultiHashMap *ignore_tunnels; | ||
508 | /** | 454 | /** |
509 | * Handle to communicate with the client | 455 | * Handle to communicate with the client |
510 | */ | 456 | */ |
@@ -810,15 +756,6 @@ tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid); | |||
810 | 756 | ||
811 | 757 | ||
812 | /** | 758 | /** |
813 | * Delete an active client from the tunnel. | ||
814 | * | ||
815 | * @param t Tunnel. | ||
816 | * @param c Client. | ||
817 | */ | ||
818 | static void | ||
819 | tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c); | ||
820 | |||
821 | /** | ||
822 | * Notify a tunnel that a connection has broken that affects at least | 759 | * Notify a tunnel that a connection has broken that affects at least |
823 | * some of its peers. | 760 | * some of its peers. |
824 | * | 761 | * |
@@ -835,28 +772,6 @@ tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, | |||
835 | 772 | ||
836 | 773 | ||
837 | /** | 774 | /** |
838 | * Get the current ack value for a tunnel, for data going from root to leaves, | ||
839 | * taking in account the tunnel mode and the status of all children and clients. | ||
840 | * | ||
841 | * @param t Tunnel. | ||
842 | * | ||
843 | * @return Maximum PID allowed. | ||
844 | */ | ||
845 | static uint32_t | ||
846 | tunnel_get_fwd_ack (struct MeshTunnel *t); | ||
847 | |||
848 | |||
849 | /** | ||
850 | * Add a client to a tunnel, initializing all needed data structures. | ||
851 | * | ||
852 | * @param t Tunnel to which add the client. | ||
853 | * @param c Client which to add to the tunnel. | ||
854 | */ | ||
855 | static void | ||
856 | tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c); | ||
857 | |||
858 | |||
859 | /** | ||
860 | * Use the given path for the tunnel. | 775 | * Use the given path for the tunnel. |
861 | * | 776 | * |
862 | * @param t Tunnel to update. | 777 | * @param t Tunnel to update. |
@@ -999,103 +914,10 @@ client_get (struct GNUNET_SERVER_Client *client) | |||
999 | 914 | ||
1000 | 915 | ||
1001 | /** | 916 | /** |
1002 | * Checks if a given client has subscribed to certain message type | ||
1003 | * | ||
1004 | * @param message_type Type of message to check | ||
1005 | * @param c Client to check | ||
1006 | * | ||
1007 | * @return GNUNET_YES or GNUNET_NO, depending on subscription status | ||
1008 | * | ||
1009 | * A real hash function alone takes 8-10us out of the ~55us for the whole | ||
1010 | * process of retransmitting the message from one local client to another. | ||
1011 | * GMC_hash32 aim to imporve this speed. | ||
1012 | */ | ||
1013 | static int | ||
1014 | client_is_subscribed (uint16_t message_type, struct MeshClient *c) | ||
1015 | { | ||
1016 | struct GNUNET_HashCode hc; | ||
1017 | |||
1018 | if (NULL == c->types) | ||
1019 | return GNUNET_NO; | ||
1020 | |||
1021 | GMC_hash32 ((uint32_t) message_type, &hc); | ||
1022 | return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc); | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | /** | ||
1027 | * Check whether client wants traffic from a tunnel. | ||
1028 | * | ||
1029 | * @param c Client to check. | ||
1030 | * @param t Tunnel to be found. | ||
1031 | * | ||
1032 | * @return GNUNET_YES if client knows tunnel. | ||
1033 | * | ||
1034 | * TODO look in client hashmap | ||
1035 | */ | ||
1036 | static int | ||
1037 | client_wants_tunnel (struct MeshClient *c, struct MeshTunnel *t) | ||
1038 | { | ||
1039 | unsigned int i; | ||
1040 | |||
1041 | for (i = 0; i < t->nclients; i++) | ||
1042 | if (t->clients[i] == c) | ||
1043 | return GNUNET_YES; | ||
1044 | return GNUNET_NO; | ||
1045 | } | ||
1046 | |||
1047 | |||
1048 | /** | ||
1049 | * Check whether client has been informed about a tunnel. | ||
1050 | * | ||
1051 | * @param c Client to check. | ||
1052 | * @param t Tunnel to be found. | ||
1053 | * | ||
1054 | * @return GNUNET_YES if client knows tunnel. | ||
1055 | * | ||
1056 | * TODO look in client hashmap | ||
1057 | */ | ||
1058 | static int | ||
1059 | client_knows_tunnel (struct MeshClient *c, struct MeshTunnel *t) | ||
1060 | { | ||
1061 | unsigned int i; | ||
1062 | |||
1063 | for (i = 0; i < t->nignore; i++) | ||
1064 | if (t->ignore[i] == c) | ||
1065 | return GNUNET_YES; | ||
1066 | return client_wants_tunnel(c, t); | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | /** | ||
1071 | * Marks a client as uninterested in traffic from the tunnel, updating both | ||
1072 | * client and tunnel to reflect this. | ||
1073 | * | ||
1074 | * @param c Client that doesn't want traffic anymore. | ||
1075 | * @param t Tunnel which should be ignored. | ||
1076 | * | ||
1077 | * FIXME when to delete an incoming tunnel? | ||
1078 | */ | ||
1079 | static void | ||
1080 | client_ignore_tunnel (struct MeshClient *c, struct MeshTunnel *t) | ||
1081 | { | ||
1082 | struct GNUNET_HashCode hash; | ||
1083 | |||
1084 | GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); | ||
1085 | GNUNET_break (GNUNET_YES == | ||
1086 | GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, | ||
1087 | &hash, t)); | ||
1088 | GNUNET_break (GNUNET_YES == | ||
1089 | GNUNET_CONTAINER_multihashmap_put (c->ignore_tunnels, &hash, t, | ||
1090 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
1091 | tunnel_delete_active_client (t, c); | ||
1092 | GNUNET_array_append (t->ignore, t->nignore, c); | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | /** | ||
1097 | * Deletes a tunnel from a client (either owner or destination). To be used on | 917 | * Deletes a tunnel from a client (either owner or destination). To be used on |
1098 | * tunnel destroy, otherwise, use client_ignore_tunnel. | 918 | * tunnel destroy. |
919 | * | ||
920 | * FIXME use fast hash | ||
1099 | * | 921 | * |
1100 | * @param c Client whose tunnel to delete. | 922 | * @param c Client whose tunnel to delete. |
1101 | * @param t Tunnel which should be deleted. | 923 | * @param t Tunnel which should be deleted. |
@@ -1113,117 +935,18 @@ client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t) | |||
1113 | &hash, | 935 | &hash, |
1114 | t)); | 936 | t)); |
1115 | } | 937 | } |
1116 | else | 938 | else if (c == t->client) |
1117 | { | 939 | { |
1118 | GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); | 940 | GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); |
1119 | // FIXME XOR? | ||
1120 | GNUNET_assert (GNUNET_YES == | 941 | GNUNET_assert (GNUNET_YES == |
1121 | GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, | 942 | GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, |
1122 | &hash, | 943 | &hash, |
1123 | t) || | ||
1124 | GNUNET_YES == | ||
1125 | GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels, | ||
1126 | &hash, | ||
1127 | t)); | 944 | t)); |
1128 | } | 945 | } |
1129 | } | 946 | else |
1130 | |||
1131 | |||
1132 | /** | ||
1133 | * Send the message to all clients that have subscribed to its type | ||
1134 | * | ||
1135 | * @param msg Pointer to the message itself | ||
1136 | * @param payload Pointer to the payload of the message. | ||
1137 | * @param t The tunnel to whose clients this message goes. | ||
1138 | * | ||
1139 | * @return number of clients this message was sent to | ||
1140 | */ | ||
1141 | static unsigned int | ||
1142 | send_subscribed_clients (const struct GNUNET_MessageHeader *msg, | ||
1143 | const struct GNUNET_MessageHeader *payload, | ||
1144 | struct MeshTunnel *t) | ||
1145 | { | ||
1146 | struct MeshClient *c; | ||
1147 | MESH_TunnelNumber *tid; | ||
1148 | unsigned int count; | ||
1149 | uint16_t type; | ||
1150 | char cbuf[htons (msg->size)]; | ||
1151 | |||
1152 | type = ntohs (payload->type); | ||
1153 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending to clients...\n"); | ||
1154 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "message of type %s\n", | ||
1155 | GNUNET_MESH_DEBUG_M2S (type)); | ||
1156 | |||
1157 | memcpy (cbuf, msg, sizeof (cbuf)); | ||
1158 | switch (htons (msg->type)) | ||
1159 | { | ||
1160 | struct GNUNET_MESH_Unicast *uc; | ||
1161 | struct GNUNET_MESH_ToOrigin *to; | ||
1162 | |||
1163 | case GNUNET_MESSAGE_TYPE_MESH_UNICAST: | ||
1164 | uc = (struct GNUNET_MESH_Unicast *) cbuf; | ||
1165 | tid = &uc->tid; | ||
1166 | break; | ||
1167 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: | ||
1168 | to = (struct GNUNET_MESH_ToOrigin *) cbuf; | ||
1169 | tid = &to->tid; | ||
1170 | break; | ||
1171 | default: | ||
1172 | GNUNET_break (0); | ||
1173 | return 0; | ||
1174 | } | ||
1175 | |||
1176 | for (count = 0, c = clients_head; c != NULL; c = c->next) | ||
1177 | { | 947 | { |
1178 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client %u\n", c->id); | 948 | GNUNET_break (0); |
1179 | if (client_is_subscribed (type, c)) | ||
1180 | { | ||
1181 | if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN) | ||
1182 | { | ||
1183 | if (c != t->owner) | ||
1184 | continue; | ||
1185 | *tid = htonl (t->local_tid); | ||
1186 | } | ||
1187 | else | ||
1188 | { | ||
1189 | if (GNUNET_NO == client_knows_tunnel (c, t)) | ||
1190 | { | ||
1191 | /* This client doesn't know the tunnel */ | ||
1192 | struct GNUNET_MESH_TunnelNotification tmsg; | ||
1193 | struct GNUNET_HashCode hash; | ||
1194 | |||
1195 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending tunnel create\n"); | ||
1196 | tmsg.header.size = htons (sizeof (tmsg)); | ||
1197 | tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); | ||
1198 | GNUNET_PEER_resolve (t->id.oid, &tmsg.peer); | ||
1199 | tmsg.tunnel_id = htonl (t->local_tid_dest); | ||
1200 | tmsg.opt = 0; | ||
1201 | if (GNUNET_YES == t->nobuffer) | ||
1202 | tmsg.opt |= MESH_TUNNEL_OPT_NOBUFFER; | ||
1203 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1204 | &tmsg.header, GNUNET_NO); | ||
1205 | tunnel_add_client (t, c); | ||
1206 | GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), | ||
1207 | &hash); | ||
1208 | GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put ( | ||
1209 | c->incoming_tunnels, &hash, t, | ||
1210 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
1211 | } | ||
1212 | *tid = htonl (t->local_tid_dest); | ||
1213 | } | ||
1214 | |||
1215 | /* Check if the client wants to get traffic from the tunnel */ | ||
1216 | if (GNUNET_NO == client_wants_tunnel(c, t)) | ||
1217 | continue; | ||
1218 | count++; | ||
1219 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending\n"); | ||
1220 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1221 | (struct GNUNET_MessageHeader | ||
1222 | *) cbuf, GNUNET_NO); | ||
1223 | } | ||
1224 | } | 949 | } |
1225 | |||
1226 | return count; | ||
1227 | } | 950 | } |
1228 | 951 | ||
1229 | 952 | ||
@@ -1234,45 +957,17 @@ send_subscribed_clients (const struct GNUNET_MessageHeader *msg, | |||
1234 | * @param t Tunnel that was destroyed. | 957 | * @param t Tunnel that was destroyed. |
1235 | */ | 958 | */ |
1236 | static void | 959 | static void |
1237 | send_clients_tunnel_destroy (struct MeshTunnel *t) | 960 | send_client_tunnel_destroy (struct MeshTunnel *t) |
1238 | { | 961 | { |
1239 | struct GNUNET_MESH_TunnelMessage msg; | 962 | struct GNUNET_MESH_TunnelMessage msg; |
1240 | 963 | ||
964 | if (NULL == t->client) | ||
965 | return; | ||
1241 | msg.header.size = htons (sizeof (msg)); | 966 | msg.header.size = htons (sizeof (msg)); |
1242 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); | 967 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); |
1243 | msg.tunnel_id = htonl (t->local_tid_dest); | 968 | msg.tunnel_id = htonl (t->local_tid_dest); |
1244 | GNUNET_SERVER_notification_context_broadcast (nc, &msg.header, GNUNET_NO); | 969 | GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, |
1245 | } | 970 | &msg.header, GNUNET_NO); |
1246 | |||
1247 | |||
1248 | /** | ||
1249 | * Notify clients of tunnel disconnections, if needed. | ||
1250 | * In case the origin disconnects, the destination clients get a tunnel destroy | ||
1251 | * notification. If the last destination disconnects (only one remaining client | ||
1252 | * in tunnel), the origin gets a (local ID) peer disconnected. | ||
1253 | * Note that the function must be called BEFORE removing the client from | ||
1254 | * the tunnel. | ||
1255 | * | ||
1256 | * @param t Tunnel that was destroyed. | ||
1257 | * @param c Client that disconnected. | ||
1258 | */ | ||
1259 | static void | ||
1260 | send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c) | ||
1261 | { | ||
1262 | unsigned int i; | ||
1263 | |||
1264 | if (c == t->owner) | ||
1265 | { | ||
1266 | struct GNUNET_MESH_TunnelMessage msg; | ||
1267 | |||
1268 | msg.header.size = htons (sizeof (msg)); | ||
1269 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); | ||
1270 | msg.tunnel_id = htonl (t->local_tid_dest); | ||
1271 | for (i = 0; i < t->nclients; i++) | ||
1272 | GNUNET_SERVER_notification_context_unicast (nc, t->clients[i]->handle, | ||
1273 | &msg.header, GNUNET_NO); | ||
1274 | } | ||
1275 | // FIXME when to disconnect an incoming tunnel? | ||
1276 | } | 971 | } |
1277 | 972 | ||
1278 | 973 | ||
@@ -2084,81 +1779,34 @@ tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) | |||
2084 | 1779 | ||
2085 | 1780 | ||
2086 | /** | 1781 | /** |
2087 | * Delete an active client from the tunnel. | 1782 | * Add a client to a tunnel, initializing all needed data structures. |
1783 | * | ||
1784 | * FIXME: make static after implementing port numbers | ||
2088 | * | 1785 | * |
2089 | * @param t Tunnel. | 1786 | * @param t Tunnel to which add the client. |
2090 | * @param c Client. | 1787 | * @param c Client which to add to the tunnel. |
2091 | */ | 1788 | */ |
2092 | static void | 1789 | void |
2093 | tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c) | 1790 | tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c) |
2094 | { | 1791 | { |
2095 | unsigned int i; | 1792 | if (NULL != t->client) |
2096 | |||
2097 | for (i = 0; i < t->nclients; i++) | ||
2098 | { | 1793 | { |
2099 | if (t->clients[i] == c) | 1794 | GNUNET_break(0); |
2100 | { | 1795 | return; |
2101 | t->clients[i] = t->clients[t->nclients - 1]; | ||
2102 | t->clients_fc[i] = t->clients_fc[t->nclients - 1]; | ||
2103 | GNUNET_array_grow (t->clients, t->nclients, t->nclients - 1); | ||
2104 | t->nclients++; | ||
2105 | GNUNET_array_grow (t->clients_fc, t->nclients, t->nclients - 1); | ||
2106 | break; | ||
2107 | } | ||
2108 | } | 1796 | } |
2109 | } | 1797 | if (0 != t->next_hop) |
2110 | |||
2111 | |||
2112 | /** | ||
2113 | * Delete an ignored client from the tunnel. | ||
2114 | * | ||
2115 | * @param t Tunnel. | ||
2116 | * @param c Client. | ||
2117 | */ | ||
2118 | static void | ||
2119 | tunnel_delete_ignored_client (struct MeshTunnel *t, const struct MeshClient *c) | ||
2120 | { | ||
2121 | unsigned int i; | ||
2122 | |||
2123 | for (i = 0; i < t->nignore; i++) | ||
2124 | { | 1798 | { |
2125 | if (t->ignore[i] == c) | 1799 | GNUNET_break(0); |
2126 | { | 1800 | return; |
2127 | t->ignore[i] = t->ignore[t->nignore - 1]; | ||
2128 | GNUNET_array_grow (t->ignore, t->nignore, t->nignore - 1); | ||
2129 | break; | ||
2130 | } | ||
2131 | } | 1801 | } |
2132 | } | 1802 | t->client = c; |
2133 | 1803 | t->next_fc.last_ack_sent = t->prev_fc.last_pid_recv + 1; | |
2134 | 1804 | t->next_fc.last_pid_sent = t->prev_fc.last_pid_recv; | |
2135 | /** | 1805 | t->next_fc.last_ack_recv = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE - 1; |
2136 | * Delete a client from the tunnel. It should be only done on | 1806 | t->next_fc.last_pid_recv = (uint32_t) -1; /* Expected next: 0 */ |
2137 | * client disconnection, otherwise use client_ignore_tunnel. | 1807 | t->next_fc.poll_task = GNUNET_SCHEDULER_NO_TASK; |
2138 | * | 1808 | t->next_fc.poll_time = GNUNET_TIME_UNIT_SECONDS; |
2139 | * @param t Tunnel. | 1809 | t->next_fc.queue_n = 0; |
2140 | * @param c Client. | ||
2141 | */ | ||
2142 | static void | ||
2143 | tunnel_delete_client (struct MeshTunnel *t, const struct MeshClient *c) | ||
2144 | { | ||
2145 | tunnel_delete_ignored_client (t, c); | ||
2146 | tunnel_delete_active_client (t, c); | ||
2147 | } | ||
2148 | |||
2149 | /* FIXME check initial values */ | ||
2150 | static void | ||
2151 | tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c) | ||
2152 | { | ||
2153 | struct MeshTunnelClientInfo clinfo; | ||
2154 | |||
2155 | GNUNET_array_append (t->clients, t->nclients, c); | ||
2156 | clinfo.fwd_ack = t->prev_fc.last_pid_recv + 1; | ||
2157 | clinfo.fwd_pid = t->prev_fc.last_pid_recv; | ||
2158 | clinfo.bck_ack = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE - 1; | ||
2159 | clinfo.bck_pid = (uint32_t) -1; /* Expected next: 0 */ | ||
2160 | t->nclients--; /* Double append */ | ||
2161 | GNUNET_array_append (t->clients_fc, t->nclients, clinfo); | ||
2162 | } | 1810 | } |
2163 | 1811 | ||
2164 | 1812 | ||
@@ -2238,134 +1886,6 @@ tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, | |||
2238 | 1886 | ||
2239 | 1887 | ||
2240 | /** | 1888 | /** |
2241 | * Get the Flow Control info of a client. | ||
2242 | * | ||
2243 | * @param t Tunnel on which to look. | ||
2244 | * @param c Client whose ACK to get. | ||
2245 | * | ||
2246 | * @return ACK value. | ||
2247 | */ | ||
2248 | static struct MeshTunnelClientInfo * | ||
2249 | tunnel_get_client_fc (struct MeshTunnel *t, | ||
2250 | struct MeshClient *c) | ||
2251 | { | ||
2252 | unsigned int i; | ||
2253 | |||
2254 | for (i = 0; i < t->nclients; i++) | ||
2255 | { | ||
2256 | if (t->clients[i] != c) | ||
2257 | continue; | ||
2258 | return &t->clients_fc[i]; | ||
2259 | } | ||
2260 | GNUNET_assert (0); | ||
2261 | return NULL; // avoid compiler / coverity complaints | ||
2262 | } | ||
2263 | |||
2264 | |||
2265 | /** | ||
2266 | * Set the FWD ACK value of a client in a particular tunnel. | ||
2267 | * | ||
2268 | * @param t Tunnel affected. | ||
2269 | * @param c Client whose ACK to set. | ||
2270 | * @param ack ACK value. | ||
2271 | */ | ||
2272 | static void | ||
2273 | tunnel_set_client_fwd_ack (struct MeshTunnel *t, | ||
2274 | struct MeshClient *c, | ||
2275 | uint32_t ack) | ||
2276 | { | ||
2277 | unsigned int i; | ||
2278 | |||
2279 | for (i = 0; i < t->nclients; i++) | ||
2280 | { | ||
2281 | if (t->clients[i] != c) | ||
2282 | continue; | ||
2283 | t->clients_fc[i].fwd_ack = ack; | ||
2284 | return; | ||
2285 | } | ||
2286 | GNUNET_break (0); | ||
2287 | } | ||
2288 | |||
2289 | |||
2290 | /** | ||
2291 | * Get the highest ACK value of all clients in a particular tunnel, | ||
2292 | * according to the buffering/speed settings. | ||
2293 | * | ||
2294 | * @param t Tunnel on which to look. | ||
2295 | * | ||
2296 | * @return Corresponding ACK value (max uint32_t). | ||
2297 | * If no clients are suscribed, -1LL. | ||
2298 | */ | ||
2299 | static int64_t | ||
2300 | tunnel_get_clients_fwd_ack (struct MeshTunnel *t) | ||
2301 | { | ||
2302 | unsigned int i; | ||
2303 | int64_t ack; | ||
2304 | |||
2305 | if (0 == t->nclients) | ||
2306 | { | ||
2307 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2308 | " tunnel has no clients, no FWD ACK\n"); | ||
2309 | return -1LL; | ||
2310 | } | ||
2311 | |||
2312 | for (ack = -1LL, i = 0; i < t->nclients; i++) | ||
2313 | { | ||
2314 | if (-1LL == ack || | ||
2315 | GNUNET_YES == GMC_is_pid_bigger (ack, t->clients_fc[i].fwd_ack)) | ||
2316 | { | ||
2317 | ack = t->clients_fc[i].fwd_ack; | ||
2318 | } | ||
2319 | } | ||
2320 | |||
2321 | if (GNUNET_YES == t->nobuffer && | ||
2322 | GMC_is_pid_bigger(ack, t->prev_fc.last_pid_recv)) | ||
2323 | ack = (uint32_t) t->prev_fc.last_pid_recv + 1; // Might overflow, it's ok. | ||
2324 | |||
2325 | return (uint32_t) ack; | ||
2326 | } | ||
2327 | |||
2328 | |||
2329 | /** FIXME | ||
2330 | * Get the current fwd ack value for a tunnel, taking in account the tunnel | ||
2331 | * mode and the status of all children nodes. | ||
2332 | * | ||
2333 | * @param t Tunnel. | ||
2334 | * | ||
2335 | * @return Maximum PID allowed. | ||
2336 | */ | ||
2337 | static uint32_t | ||
2338 | tunnel_get_fwd_ack (struct MeshTunnel *t) | ||
2339 | { | ||
2340 | uint32_t ack; | ||
2341 | uint32_t buffer_free; | ||
2342 | int64_t client_ack; | ||
2343 | |||
2344 | buffer_free = t->queue_max - t->next_fc.queue_n; | ||
2345 | client_ack = tunnel_get_clients_fwd_ack (t); | ||
2346 | if (GNUNET_YES == t->nobuffer) | ||
2347 | { | ||
2348 | ack = t->prev_fc.last_ack_sent; | ||
2349 | } | ||
2350 | else | ||
2351 | { | ||
2352 | ack = t->prev_fc.last_ack_sent + buffer_free; // Overflow? OK! | ||
2353 | } | ||
2354 | if (-1LL == client_ack) | ||
2355 | { | ||
2356 | client_ack = ack; | ||
2357 | } | ||
2358 | /* FIXME check */ | ||
2359 | ack = GMC_max_pid ((uint32_t) client_ack, ack); | ||
2360 | |||
2361 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2362 | "c %u, bf %u, cl %lld, ACK: %u\n", | ||
2363 | t->prev_fc.last_ack_sent, buffer_free, client_ack, ack); | ||
2364 | return ack; | ||
2365 | } | ||
2366 | |||
2367 | |||
2368 | /** | ||
2369 | * Build a local ACK message and send it to a local client. | 1889 | * Build a local ACK message and send it to a local client. |
2370 | * | 1890 | * |
2371 | * @param t Tunnel on which to send the ACK. | 1891 | * @param t Tunnel on which to send the ACK. |
@@ -2410,36 +1930,6 @@ send_ack (struct MeshTunnel *t, GNUNET_PEER_Id peer, uint32_t ack) | |||
2410 | 1930 | ||
2411 | 1931 | ||
2412 | /** | 1932 | /** |
2413 | * Notify a the owner of a tunnel about how many more | ||
2414 | * payload packages will we accept on a given tunnel. | ||
2415 | * | ||
2416 | * @param t Tunnel on which to send the ACK. | ||
2417 | */ | ||
2418 | static void | ||
2419 | tunnel_send_client_fwd_ack (struct MeshTunnel *t) | ||
2420 | { | ||
2421 | uint32_t ack; | ||
2422 | |||
2423 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2424 | "Sending client FWD ACK on tunnel %X\n", | ||
2425 | t->local_tid); | ||
2426 | |||
2427 | ack = tunnel_get_fwd_ack (t); | ||
2428 | |||
2429 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); | ||
2430 | if (t->prev_fc.last_ack_sent == ack) | ||
2431 | { | ||
2432 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " same as last, not sending!\n"); | ||
2433 | return; | ||
2434 | } | ||
2435 | |||
2436 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending!\n"); | ||
2437 | t->prev_fc.last_ack_sent = ack; | ||
2438 | send_local_ack (t, t->owner, ack); | ||
2439 | } | ||
2440 | |||
2441 | |||
2442 | /** | ||
2443 | * Send an ACK informing the predecessor about the available buffer space. | 1933 | * Send an ACK informing the predecessor about the available buffer space. |
2444 | * In case there is no predecessor, inform the owning client. | 1934 | * In case there is no predecessor, inform the owning client. |
2445 | * If buffering is off, send only on behalf of children or self if endpoint. | 1935 | * If buffering is off, send only on behalf of children or self if endpoint. |
@@ -2455,11 +1945,6 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) | |||
2455 | { | 1945 | { |
2456 | uint32_t ack; | 1946 | uint32_t ack; |
2457 | 1947 | ||
2458 | if (NULL != t->owner) | ||
2459 | { | ||
2460 | tunnel_send_client_fwd_ack (t); | ||
2461 | return; | ||
2462 | } | ||
2463 | /* Is it after unicast retransmission? */ | 1948 | /* Is it after unicast retransmission? */ |
2464 | switch (type) | 1949 | switch (type) |
2465 | { | 1950 | { |
@@ -2498,112 +1983,28 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) | |||
2498 | } | 1983 | } |
2499 | 1984 | ||
2500 | /* Ok, ACK might be necessary, what PID to ACK? */ | 1985 | /* Ok, ACK might be necessary, what PID to ACK? */ |
2501 | ack = tunnel_get_fwd_ack (t); | 1986 | ack = t->prev_fc.last_pid_recv + t->queue_max - t->next_fc.queue_n; |
2502 | if (ack == t->prev_fc.last_ack_sent && GNUNET_NO == t->force_ack) | 1987 | if (ack == t->prev_fc.last_ack_sent && GNUNET_NO == t->force_ack) |
2503 | { | 1988 | { |
2504 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not ready\n"); | 1989 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); |
2505 | return; | 1990 | return; |
2506 | } | 1991 | } |
2507 | 1992 | ||
2508 | t->prev_fc.last_ack_sent = ack; | 1993 | t->prev_fc.last_ack_sent = ack; |
2509 | send_ack (t, t->prev_hop, ack); | 1994 | if (0 != t->prev_hop) |
1995 | send_ack (t, t->prev_hop, ack); | ||
1996 | else if (NULL != t->owner) | ||
1997 | send_local_ack (t, t->owner, ack); | ||
1998 | else | ||
1999 | GNUNET_break (0); | ||
2510 | debug_fwd_ack++; | 2000 | debug_fwd_ack++; |
2511 | t->force_ack = GNUNET_NO; | 2001 | t->force_ack = GNUNET_NO; |
2512 | } | 2002 | } |
2513 | 2003 | ||
2514 | 2004 | ||
2515 | /** | 2005 | /** |
2516 | * Send a child node a BCK ACK to allow him to send more to_origin data. | 2006 | * Send an ACK informing the children node/client about the available |
2517 | * | 2007 | * buffer space. |
2518 | * @param t Tunnel. | ||
2519 | * @param id Id of the child node. | ||
2520 | */ | ||
2521 | static void | ||
2522 | tunnel_send_mesh_bck_ack (struct MeshTunnel *t, | ||
2523 | GNUNET_PEER_Id peer) | ||
2524 | { | ||
2525 | uint32_t ack = 0; // FIXME | ||
2526 | |||
2527 | ack = t->next_fc.last_pid_recv + t->queue_max - t->prev_fc.queue_n; | ||
2528 | |||
2529 | if (t->next_fc.last_ack_sent == ack && GNUNET_NO == t->force_ack) | ||
2530 | { | ||
2531 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2532 | " Not sending ACK, not needed\n"); | ||
2533 | return; | ||
2534 | } | ||
2535 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2536 | " Sending BCK ACK %u (last sent: %u)\n", | ||
2537 | ack, t->next_fc.last_ack_sent); | ||
2538 | t->next_fc.last_ack_sent = ack; | ||
2539 | |||
2540 | send_ack (t, peer, ack); | ||
2541 | } | ||
2542 | |||
2543 | |||
2544 | /** | ||
2545 | * @brief Send BCK ACKs to clients to allow them more to_origin traffic | ||
2546 | * | ||
2547 | * Iterates over all clients and sends BCK ACKs to the ones that need it. | ||
2548 | * | ||
2549 | * FIXME fc: what happens if we have 2 clients but q_size is 1? | ||
2550 | * - implement a size 1 buffer in each client_fc AND children_fc | ||
2551 | * to hold at least 1 message per "child". | ||
2552 | * problem: violates no buffer policy | ||
2553 | * - ack 0 and make "children" poll for transmission slots | ||
2554 | * problem: big overhead, extra latency even in low traffic | ||
2555 | * settings | ||
2556 | * | ||
2557 | * @param t Tunnel on which to send the BCK ACKs. | ||
2558 | */ | ||
2559 | static void | ||
2560 | tunnel_send_clients_bck_ack (struct MeshTunnel *t) | ||
2561 | { | ||
2562 | unsigned int i; | ||
2563 | unsigned int tunnel_delta; | ||
2564 | |||
2565 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Sending BCK ACK to clients\n"); | ||
2566 | |||
2567 | tunnel_delta = t->queue_max - t->next_fc.queue_n; | ||
2568 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " tunnel delta: %u\n", tunnel_delta); | ||
2569 | |||
2570 | /* Find client whom to allow to send to origin (with lowest buffer space) */ | ||
2571 | for (i = 0; i < t->nclients; i++) | ||
2572 | { | ||
2573 | struct MeshTunnelClientInfo *clinfo; | ||
2574 | unsigned int delta; | ||
2575 | |||
2576 | clinfo = &t->clients_fc[i]; | ||
2577 | delta = clinfo->bck_ack - clinfo->bck_pid; | ||
2578 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client %u delta: %u\n", | ||
2579 | t->clients[i]->id, delta); | ||
2580 | |||
2581 | if ((GNUNET_NO == t->nobuffer && tunnel_delta > delta) || | ||
2582 | (GNUNET_YES == t->nobuffer && 0 == delta)) | ||
2583 | { | ||
2584 | uint32_t ack; | ||
2585 | |||
2586 | ack = clinfo->bck_pid; | ||
2587 | ack += t->nobuffer ? 1 : tunnel_delta; | ||
2588 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2589 | " sending ack to client %u: %u\n", | ||
2590 | t->clients[i]->id, ack); | ||
2591 | send_local_ack (t, t->clients[i], ack); | ||
2592 | clinfo->bck_ack = ack; | ||
2593 | } | ||
2594 | else | ||
2595 | { | ||
2596 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2597 | " not sending ack to client %u (td %u, d %u)\n", | ||
2598 | t->clients[i]->id, tunnel_delta, delta); | ||
2599 | } | ||
2600 | } | ||
2601 | } | ||
2602 | |||
2603 | |||
2604 | /** | ||
2605 | * Send an ACK informing the children nodes and destination clients about | ||
2606 | * the available buffer space. | ||
2607 | * If buffering is off, send only on behalf of root (can be self). | 2008 | * If buffering is off, send only on behalf of root (can be self). |
2608 | * If buffering is on, send when sent to predecessor and buffer space is free. | 2009 | * If buffering is on, send when sent to predecessor and buffer space is free. |
2609 | * Note that although the name is bck_ack, the BCK mean backwards *traffic*, | 2010 | * Note that although the name is bck_ack, the BCK mean backwards *traffic*, |
@@ -2615,6 +2016,7 @@ tunnel_send_clients_bck_ack (struct MeshTunnel *t) | |||
2615 | static void | 2016 | static void |
2616 | tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) | 2017 | tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) |
2617 | { | 2018 | { |
2019 | uint32_t ack; | ||
2618 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2020 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2619 | "Sending BCK ACK on tunnel %u [%u] due to %s\n", | 2021 | "Sending BCK ACK on tunnel %u [%u] due to %s\n", |
2620 | t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type)); | 2022 | t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type)); |
@@ -2625,7 +2027,7 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) | |||
2625 | if (GNUNET_YES == t->nobuffer) | 2027 | if (GNUNET_YES == t->nobuffer) |
2626 | { | 2028 | { |
2627 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2029 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2628 | " Not sending ACK, nobuffer\n"); | 2030 | " Not sending ACK, nobuffer + traffic\n"); |
2629 | return; | 2031 | return; |
2630 | } | 2032 | } |
2631 | break; | 2033 | break; |
@@ -2639,8 +2041,25 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) | |||
2639 | GNUNET_break (0); | 2041 | GNUNET_break (0); |
2640 | } | 2042 | } |
2641 | 2043 | ||
2642 | tunnel_send_clients_bck_ack (t); | 2044 | ack = t->next_fc.last_pid_recv + t->queue_max - t->prev_fc.queue_n; |
2643 | tunnel_send_mesh_bck_ack (t, t->next_hop); | 2045 | |
2046 | if (t->next_fc.last_ack_sent == ack && GNUNET_NO == t->force_ack) | ||
2047 | { | ||
2048 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2049 | " Not sending ACK, not needed\n"); | ||
2050 | return; | ||
2051 | } | ||
2052 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2053 | " Sending BCK ACK %u (last sent: %u)\n", | ||
2054 | ack, t->next_fc.last_ack_sent); | ||
2055 | t->next_fc.last_ack_sent = ack; | ||
2056 | |||
2057 | if (0 != t->next_hop) | ||
2058 | send_ack (t, t->next_hop, ack); | ||
2059 | else if (NULL != t->client) | ||
2060 | send_local_ack (t, t->client, ack); | ||
2061 | else | ||
2062 | GNUNET_break (0); | ||
2644 | t->force_ack = GNUNET_NO; | 2063 | t->force_ack = GNUNET_NO; |
2645 | } | 2064 | } |
2646 | 2065 | ||
@@ -2780,7 +2199,6 @@ tunnel_destroy (struct MeshTunnel *t) | |||
2780 | { | 2199 | { |
2781 | struct MeshClient *c; | 2200 | struct MeshClient *c; |
2782 | struct GNUNET_HashCode hash; | 2201 | struct GNUNET_HashCode hash; |
2783 | unsigned int i; | ||
2784 | int r; | 2202 | int r; |
2785 | 2203 | ||
2786 | if (NULL == t) | 2204 | if (NULL == t) |
@@ -2807,6 +2225,7 @@ tunnel_destroy (struct MeshTunnel *t) | |||
2807 | r = GNUNET_SYSERR; | 2225 | r = GNUNET_SYSERR; |
2808 | } | 2226 | } |
2809 | 2227 | ||
2228 | // FIXME use fast hash | ||
2810 | if (NULL != c) | 2229 | if (NULL != c) |
2811 | { | 2230 | { |
2812 | GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); | 2231 | GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); |
@@ -2818,10 +2237,10 @@ tunnel_destroy (struct MeshTunnel *t) | |||
2818 | } | 2237 | } |
2819 | } | 2238 | } |
2820 | 2239 | ||
2821 | GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); | 2240 | // FIXME use fast hash |
2822 | for (i = 0; i < t->nclients; i++) | 2241 | if (NULL != t->client) |
2823 | { | 2242 | { |
2824 | c = t->clients[i]; | 2243 | GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); |
2825 | if (GNUNET_YES != | 2244 | if (GNUNET_YES != |
2826 | GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t)) | 2245 | GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t)) |
2827 | { | 2246 | { |
@@ -2829,22 +2248,13 @@ tunnel_destroy (struct MeshTunnel *t) | |||
2829 | r = GNUNET_SYSERR; | 2248 | r = GNUNET_SYSERR; |
2830 | } | 2249 | } |
2831 | } | 2250 | } |
2832 | for (i = 0; i < t->nignore; i++) | 2251 | |
2252 | if (GNUNET_YES != | ||
2253 | GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t)) | ||
2833 | { | 2254 | { |
2834 | c = t->ignore[i]; | 2255 | GNUNET_break (0); |
2835 | if (GNUNET_YES != | 2256 | r = GNUNET_SYSERR; |
2836 | GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels, &hash, t)) | ||
2837 | { | ||
2838 | GNUNET_break (0); | ||
2839 | r = GNUNET_SYSERR; | ||
2840 | } | ||
2841 | } | 2257 | } |
2842 | |||
2843 | (void) GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t); | ||
2844 | GNUNET_free_non_null (t->clients); | ||
2845 | GNUNET_free_non_null (t->ignore); | ||
2846 | GNUNET_free_non_null (t->clients_fc); | ||
2847 | |||
2848 | peer_cancel_queues (t->next_hop, t); | 2258 | peer_cancel_queues (t->next_hop, t); |
2849 | peer_cancel_queues (t->prev_hop, t); | 2259 | peer_cancel_queues (t->prev_hop, t); |
2850 | 2260 | ||
@@ -2862,22 +2272,11 @@ tunnel_destroy (struct MeshTunnel *t) | |||
2862 | /** | 2272 | /** |
2863 | * Tunnel is empty: destroy it. | 2273 | * Tunnel is empty: destroy it. |
2864 | * | 2274 | * |
2865 | * @param cls Closure (Tunnel). | 2275 | * @param t Tunnel to destroy. |
2866 | * @param tc TaskContext. | ||
2867 | */ | 2276 | */ |
2868 | static void | 2277 | static void |
2869 | tunnel_destroy_empty_delayed (void *cls, | 2278 | tunnel_destroy_empty (struct MeshTunnel *t) |
2870 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
2871 | { | 2279 | { |
2872 | struct MeshTunnel *t = cls; | ||
2873 | |||
2874 | t->delayed_destroy = GNUNET_SCHEDULER_NO_TASK; | ||
2875 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
2876 | return; | ||
2877 | |||
2878 | if (0 != t->nclients) | ||
2879 | return; | ||
2880 | |||
2881 | #if MESH_DEBUG | 2280 | #if MESH_DEBUG |
2882 | { | 2281 | { |
2883 | struct GNUNET_PeerIdentity id; | 2282 | struct GNUNET_PeerIdentity id; |
@@ -2898,40 +2297,6 @@ tunnel_destroy_empty_delayed (void *cls, | |||
2898 | 2297 | ||
2899 | 2298 | ||
2900 | /** | 2299 | /** |
2901 | * Schedule tunnel destruction if is empty and no new traffic comes in a time. | ||
2902 | * | ||
2903 | * @param t Tunnel to destroy if empty. | ||
2904 | */ | ||
2905 | static void | ||
2906 | tunnel_destroy_empty (struct MeshTunnel *t) | ||
2907 | { | ||
2908 | if (GNUNET_SCHEDULER_NO_TASK != t->delayed_destroy || | ||
2909 | 0 != t->nclients) | ||
2910 | { | ||
2911 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u %u\n", | ||
2912 | t->delayed_destroy, t->nclients); | ||
2913 | return; | ||
2914 | } | ||
2915 | |||
2916 | #if MESH_DEBUG | ||
2917 | { | ||
2918 | struct GNUNET_PeerIdentity id; | ||
2919 | |||
2920 | GNUNET_PEER_resolve (t->id.oid, &id); | ||
2921 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2922 | "scheduling destruction of empty tunnel %s [%X]\n", | ||
2923 | GNUNET_i2s (&id), t->id.tid); | ||
2924 | } | ||
2925 | #endif | ||
2926 | |||
2927 | t->delayed_destroy = | ||
2928 | GNUNET_SCHEDULER_add_delayed (TUNNEL_DESTROY_EMPTY_TIME, | ||
2929 | &tunnel_destroy_empty_delayed, | ||
2930 | t); | ||
2931 | } | ||
2932 | |||
2933 | |||
2934 | /** | ||
2935 | * Create a new tunnel | 2300 | * Create a new tunnel |
2936 | * | 2301 | * |
2937 | * @param owner Who is the owner of the tunnel (short ID). | 2302 | * @param owner Who is the owner of the tunnel (short ID). |
@@ -3024,11 +2389,10 @@ tunnel_destroy_iterator (void *cls, | |||
3024 | struct MeshTunnel *t = value; | 2389 | struct MeshTunnel *t = value; |
3025 | struct MeshClient *c = cls; | 2390 | struct MeshClient *c = cls; |
3026 | 2391 | ||
3027 | send_client_tunnel_disconnect (t, c); | 2392 | send_client_tunnel_destroy (t); |
3028 | if (c != t->owner) | 2393 | if (c != t->owner) |
3029 | { | 2394 | { |
3030 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %u is destination.\n", c->id); | 2395 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %u is destination.\n", c->id); |
3031 | tunnel_delete_client (t, c); | ||
3032 | client_delete_tunnel (c, t); | 2396 | client_delete_tunnel (c, t); |
3033 | tunnel_destroy_empty (t); | 2397 | tunnel_destroy_empty (t); |
3034 | return GNUNET_OK; | 2398 | return GNUNET_OK; |
@@ -3060,10 +2424,11 @@ tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
3060 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 2424 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
3061 | "Tunnel %s [%X] timed out. Destroying.\n", | 2425 | "Tunnel %s [%X] timed out. Destroying.\n", |
3062 | GNUNET_i2s(&id), t->id.tid); | 2426 | GNUNET_i2s(&id), t->id.tid); |
3063 | send_clients_tunnel_destroy (t); | 2427 | send_client_tunnel_destroy (t); |
3064 | tunnel_destroy (t); | 2428 | tunnel_destroy (t); |
3065 | } | 2429 | } |
3066 | 2430 | ||
2431 | |||
3067 | /** | 2432 | /** |
3068 | * Resets the tunnel timeout. Starts it if no timeout was running. | 2433 | * Resets the tunnel timeout. Starts it if no timeout was running. |
3069 | * | 2434 | * |
@@ -3833,7 +3198,7 @@ handle_mesh_path_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
3833 | if (own_pos < path->length - 1) | 3198 | if (own_pos < path->length - 1) |
3834 | send_prebuilt_message (message, path->peers[own_pos + 1], t); | 3199 | send_prebuilt_message (message, path->peers[own_pos + 1], t); |
3835 | else | 3200 | else |
3836 | send_client_tunnel_disconnect(t, NULL); | 3201 | send_client_tunnel_destroy (t); |
3837 | 3202 | ||
3838 | // tunnel_delete_peer (t, path->peers[path->length - 1]); FIXME | 3203 | // tunnel_delete_peer (t, path->peers[path->length - 1]); FIXME |
3839 | path_destroy (path); | 3204 | path_destroy (path); |
@@ -3894,7 +3259,6 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
3894 | { | 3259 | { |
3895 | struct GNUNET_MESH_TunnelDestroy *msg; | 3260 | struct GNUNET_MESH_TunnelDestroy *msg; |
3896 | struct MeshTunnel *t; | 3261 | struct MeshTunnel *t; |
3897 | GNUNET_PEER_Id pid; | ||
3898 | 3262 | ||
3899 | msg = (struct GNUNET_MESH_TunnelDestroy *) message; | 3263 | msg = (struct GNUNET_MESH_TunnelDestroy *) message; |
3900 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3264 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -3915,20 +3279,13 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
3915 | 1, GNUNET_NO); | 3279 | 1, GNUNET_NO); |
3916 | return GNUNET_OK; | 3280 | return GNUNET_OK; |
3917 | } | 3281 | } |
3918 | pid = GNUNET_PEER_search (peer); | 3282 | // TODO check owner's signature |
3919 | if (pid != t->prev_hop && 0 < t->nclients) | ||
3920 | { | ||
3921 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3922 | "still in use by %u clients\n", | ||
3923 | t->nclients); | ||
3924 | return GNUNET_OK; | ||
3925 | } | ||
3926 | if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) | 3283 | if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) |
3927 | { | 3284 | { |
3928 | /* Tunnel was incoming, notify clients */ | 3285 | /* Tunnel was incoming, notify clients */ |
3929 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n", | 3286 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n", |
3930 | t->local_tid, t->local_tid_dest); | 3287 | t->local_tid, t->local_tid_dest); |
3931 | send_clients_tunnel_destroy (t); | 3288 | send_client_tunnel_destroy (t); |
3932 | } | 3289 | } |
3933 | tunnel_send_destroy (t); | 3290 | tunnel_send_destroy (t); |
3934 | t->destroy = GNUNET_YES; | 3291 | t->destroy = GNUNET_YES; |
@@ -4008,13 +3365,24 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
4008 | tunnel_reset_timeout (t); | 3365 | tunnel_reset_timeout (t); |
4009 | if (t->dest == myid) | 3366 | if (t->dest == myid) |
4010 | { | 3367 | { |
3368 | if (NULL == t->client) | ||
3369 | { | ||
3370 | GNUNET_break (0); | ||
3371 | return GNUNET_OK; | ||
3372 | } | ||
4011 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3373 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
4012 | " it's for us! sending to clients...\n"); | 3374 | " it's for us! sending to clients...\n"); |
4013 | GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO); | 3375 | GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO); |
4014 | send_subscribed_clients (message, &msg[1].header, t); | 3376 | GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, |
3377 | message, GNUNET_NO); | ||
4015 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); | 3378 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); |
4016 | return GNUNET_OK; | 3379 | return GNUNET_OK; |
4017 | } | 3380 | } |
3381 | if (0 == t->next_hop) | ||
3382 | { | ||
3383 | GNUNET_break (0); | ||
3384 | return GNUNET_OK; | ||
3385 | } | ||
4018 | ttl = ntohl (msg->ttl); | 3386 | ttl = ntohl (msg->ttl); |
4019 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); | 3387 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); |
4020 | if (ttl == 0) | 3388 | if (ttl == 0) |
@@ -4585,11 +3953,8 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
4585 | &tunnel_destroy_iterator, c); | 3953 | &tunnel_destroy_iterator, c); |
4586 | GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels, | 3954 | GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels, |
4587 | &tunnel_destroy_iterator, c); | 3955 | &tunnel_destroy_iterator, c); |
4588 | GNUNET_CONTAINER_multihashmap_iterate (c->ignore_tunnels, | ||
4589 | &tunnel_destroy_iterator, c); | ||
4590 | GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels); | 3956 | GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels); |
4591 | GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels); | 3957 | GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels); |
4592 | GNUNET_CONTAINER_multihashmap_destroy (c->ignore_tunnels); | ||
4593 | 3958 | ||
4594 | if (NULL != c->types) | 3959 | if (NULL != c->types) |
4595 | GNUNET_CONTAINER_multihashmap_destroy (c->types); | 3960 | GNUNET_CONTAINER_multihashmap_destroy (c->types); |
@@ -4668,7 +4033,6 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client, | |||
4668 | GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c); | 4033 | GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c); |
4669 | c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); | 4034 | c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); |
4670 | c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); | 4035 | c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); |
4671 | c->ignore_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); | ||
4672 | GNUNET_SERVER_notification_context_add (nc, client); | 4036 | GNUNET_SERVER_notification_context_add (nc, client); |
4673 | GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO); | 4037 | GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO); |
4674 | 4038 | ||
@@ -4801,14 +4165,13 @@ handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client, | |||
4801 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 4165 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
4802 | return; | 4166 | return; |
4803 | } | 4167 | } |
4804 | if (c != t->owner || tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) | 4168 | if (c == t->client) |
4805 | { | 4169 | { |
4806 | client_ignore_tunnel (c, t); | ||
4807 | tunnel_destroy_empty (t); | 4170 | tunnel_destroy_empty (t); |
4808 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 4171 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
4809 | return; | 4172 | return; |
4810 | } | 4173 | } |
4811 | send_client_tunnel_disconnect (t, c); | 4174 | send_client_tunnel_destroy (t); |
4812 | client_delete_tunnel (c, t); | 4175 | client_delete_tunnel (c, t); |
4813 | 4176 | ||
4814 | /* Don't try to ACK the client about the tunnel_destroy multicast packet */ | 4177 | /* Don't try to ACK the client about the tunnel_destroy multicast packet */ |
@@ -4985,7 +4348,7 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, | |||
4985 | const struct GNUNET_MessageHeader *message) | 4348 | const struct GNUNET_MessageHeader *message) |
4986 | { | 4349 | { |
4987 | struct GNUNET_MESH_ToOrigin *data_msg; | 4350 | struct GNUNET_MESH_ToOrigin *data_msg; |
4988 | struct MeshTunnelClientInfo *clinfo; | 4351 | struct MeshFlowControl *fc; |
4989 | struct MeshClient *c; | 4352 | struct MeshClient *c; |
4990 | struct MeshTunnel *t; | 4353 | struct MeshTunnel *t; |
4991 | MESH_TunnelNumber tid; | 4354 | MESH_TunnelNumber tid; |
@@ -5034,7 +4397,7 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, | |||
5034 | } | 4397 | } |
5035 | 4398 | ||
5036 | /* It should be sent by someone who has this as incoming tunnel. */ | 4399 | /* It should be sent by someone who has this as incoming tunnel. */ |
5037 | if (GNUNET_NO == client_knows_tunnel (c, t)) | 4400 | if (t->client != c) |
5038 | { | 4401 | { |
5039 | GNUNET_break (0); | 4402 | GNUNET_break (0); |
5040 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 4403 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -5042,18 +4405,18 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, | |||
5042 | } | 4405 | } |
5043 | 4406 | ||
5044 | /* PID should be as expected */ | 4407 | /* PID should be as expected */ |
5045 | clinfo = tunnel_get_client_fc (t, c); | 4408 | fc = &t->next_fc; |
5046 | if (ntohl (data_msg->pid) != clinfo->bck_pid + 1) | 4409 | if (ntohl (data_msg->pid) != fc->last_pid_recv + 1) |
5047 | { | 4410 | { |
5048 | GNUNET_break (0); | 4411 | GNUNET_break (0); |
5049 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 4412 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
5050 | "To Origin PID, expected %u, got %u\n", | 4413 | "To Origin PID, expected %u, got %u\n", |
5051 | clinfo->bck_pid + 1, | 4414 | fc->last_pid_recv + 1, |
5052 | ntohl (data_msg->pid)); | 4415 | ntohl (data_msg->pid)); |
5053 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 4416 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
5054 | return; | 4417 | return; |
5055 | } | 4418 | } |
5056 | clinfo->bck_pid++; | 4419 | fc->last_pid_recv++; |
5057 | 4420 | ||
5058 | /* Ok, everything is correct, send the message | 4421 | /* Ok, everything is correct, send the message |
5059 | * (pretend we got it from a mesh peer) | 4422 | * (pretend we got it from a mesh peer) |
@@ -5063,8 +4426,8 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, | |||
5063 | struct GNUNET_MESH_ToOrigin *copy; | 4426 | struct GNUNET_MESH_ToOrigin *copy; |
5064 | 4427 | ||
5065 | /* Work around 'const' limitation */ | 4428 | /* Work around 'const' limitation */ |
5066 | copy = (struct GNUNET_MESH_ToOrigin *) buf; | ||
5067 | memcpy (buf, data_msg, size); | 4429 | memcpy (buf, data_msg, size); |
4430 | copy = (struct GNUNET_MESH_ToOrigin *) buf; | ||
5068 | GNUNET_PEER_resolve (t->id.oid, ©->oid); | 4431 | GNUNET_PEER_resolve (t->id.oid, ©->oid); |
5069 | copy->tid = htonl (t->id.tid); | 4432 | copy->tid = htonl (t->id.tid); |
5070 | copy->ttl = htonl (default_ttl); | 4433 | copy->ttl = htonl (default_ttl); |
@@ -5126,16 +4489,16 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client, | |||
5126 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); | 4489 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); |
5127 | 4490 | ||
5128 | /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */ | 4491 | /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */ |
5129 | if (NULL != t->owner && t->owner->handle == client) | 4492 | if (t->owner == c) |
5130 | { | 4493 | { |
5131 | /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */ | 4494 | /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */ |
5132 | t->next_fc.last_ack_sent = ack; | 4495 | t->prev_fc.last_ack_recv = ack; |
5133 | tunnel_send_bck_ack(t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); | 4496 | tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); |
5134 | } | 4497 | } |
5135 | else | 4498 | else |
5136 | { | 4499 | { |
5137 | /* The client doesn't own the tunnel, this ACK is for FWD traffic. */ | 4500 | /* The client doesn't own the tunnel, this ACK is for FWD traffic. */ |
5138 | tunnel_set_client_fwd_ack (t, c, ack); | 4501 | t->next_fc.last_ack_recv = ack; |
5139 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); | 4502 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); |
5140 | } | 4503 | } |
5141 | 4504 | ||