diff options
author | Bart Polot <bart@net.in.tum.de> | 2011-10-26 18:06:30 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2011-10-26 18:06:30 +0000 |
commit | 8941e9c8c609bfa3d0943bd26f7c3f8e62df7701 (patch) | |
tree | 1c53ecf5bc4a76295a4381ca6338a9abee17792b /src | |
parent | 2b70d89a9849a1f84326176b7c8c4d1101e9aaa4 (diff) | |
download | gnunet-8941e9c8c609bfa3d0943bd26f7c3f8e62df7701.tar.gz gnunet-8941e9c8c609bfa3d0943bd26f7c3f8e62df7701.zip |
Fixed #1857
Diffstat (limited to 'src')
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 130 |
1 files changed, 90 insertions, 40 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 1ec2371dc..97593d3bb 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c | |||
@@ -108,7 +108,7 @@ struct MeshDataDescriptor | |||
108 | 108 | ||
109 | /** Used to allow a client send more traffic to the service after a | 109 | /** Used to allow a client send more traffic to the service after a |
110 | * previous packet was tried to be sent to a neighbor and couldn't */ | 110 | * previous packet was tried to be sent to a neighbor and couldn't */ |
111 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | 111 | GNUNET_SCHEDULER_TaskIdentifier *timeout_task; |
112 | }; | 112 | }; |
113 | 113 | ||
114 | 114 | ||
@@ -693,6 +693,15 @@ client_is_subscribed (uint16_t message_type, struct MeshClient *c) | |||
693 | return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc); | 693 | return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc); |
694 | } | 694 | } |
695 | 695 | ||
696 | |||
697 | /** | ||
698 | * Allow a client to send more data after transmitting a multicast message | ||
699 | * which some neighbor has not yet accepted altough a reasonable time has | ||
700 | * passed. | ||
701 | * | ||
702 | * @param cls Closure (DataDescriptor containing the task identifier) | ||
703 | * @param tc Task Context | ||
704 | */ | ||
696 | static void | 705 | static void |
697 | client_allow_send(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 706 | client_allow_send(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
698 | { | 707 | { |
@@ -700,7 +709,12 @@ client_allow_send(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
700 | 709 | ||
701 | if (GNUNET_SCHEDULER_REASON_SHUTDOWN == tc->reason) | 710 | if (GNUNET_SCHEDULER_REASON_SHUTDOWN == tc->reason) |
702 | return; | 711 | return; |
703 | info->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 712 | #if MESH_DEBUG |
713 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
714 | "MESH: CLIENT ALLOW SEND DESPITE %u COPIES PENDING\n", | ||
715 | *(info->copies)); | ||
716 | #endif | ||
717 | *(info->timeout_task) = GNUNET_SCHEDULER_NO_TASK; | ||
704 | GNUNET_SERVER_receive_done(info->client, GNUNET_OK); | 718 | GNUNET_SERVER_receive_done(info->client, GNUNET_OK); |
705 | } | 719 | } |
706 | 720 | ||
@@ -878,6 +892,36 @@ send_core_data_multicast (void *cls, size_t size, void *buf); | |||
878 | 892 | ||
879 | 893 | ||
880 | /** | 894 | /** |
895 | * Decrements the reference counter and frees all resources if needed | ||
896 | * | ||
897 | * @param dd Data Descriptor used in a multicast message | ||
898 | */ | ||
899 | static void | ||
900 | data_descriptor_decrement_multicast (struct MeshDataDescriptor *dd) | ||
901 | { | ||
902 | if (0 == --(*(dd->copies))) | ||
903 | { | ||
904 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Last copy!\n"); | ||
905 | if (NULL != dd->client) | ||
906 | { | ||
907 | if (GNUNET_SCHEDULER_NO_TASK != *(dd->timeout_task)) | ||
908 | { | ||
909 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
910 | "MESH: cancelling client timeout (%u)...\n", | ||
911 | *(dd->timeout_task)); | ||
912 | GNUNET_SCHEDULER_cancel(*(dd->timeout_task)); | ||
913 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: notifying client...\n"); | ||
914 | GNUNET_SERVER_receive_done (dd->client, GNUNET_OK); | ||
915 | } | ||
916 | GNUNET_free (dd->timeout_task); | ||
917 | } | ||
918 | GNUNET_free (dd->copies); | ||
919 | GNUNET_free (dd->data); | ||
920 | } | ||
921 | } | ||
922 | |||
923 | |||
924 | /** | ||
881 | * Cancel a core transmission that was already requested and free all resources | 925 | * Cancel a core transmission that was already requested and free all resources |
882 | * associated to the request. | 926 | * associated to the request. |
883 | * | 927 | * |
@@ -914,11 +958,7 @@ peer_info_cancel_transmission(struct MeshPeerInfo *peer, unsigned int i) | |||
914 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: | 958 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: |
915 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type payload\n"); | 959 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type payload\n"); |
916 | dd = peer->infos[i]; | 960 | dd = peer->infos[i]; |
917 | if (0 == --(*dd->copies)) | 961 | data_descriptor_decrement_multicast (dd); |
918 | { | ||
919 | GNUNET_free (dd->copies); | ||
920 | GNUNET_free (dd->data); | ||
921 | } | ||
922 | break; | 962 | break; |
923 | case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: | 963 | case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: |
924 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type create path\n"); | 964 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type create path\n"); |
@@ -1460,7 +1500,8 @@ path_add_to_peer (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path) | |||
1460 | } | 1500 | } |
1461 | } | 1501 | } |
1462 | } | 1502 | } |
1463 | GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail, | 1503 | GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, |
1504 | peer_info->path_tail, | ||
1464 | path); | 1505 | path); |
1465 | return; | 1506 | return; |
1466 | } | 1507 | } |
@@ -1819,6 +1860,8 @@ tunnel_notify_connection_broken (struct MeshTunnel *t, | |||
1819 | * @param msg Message to be sent | 1860 | * @param msg Message to be sent |
1820 | * | 1861 | * |
1821 | * @return Number of copies sent. | 1862 | * @return Number of copies sent. |
1863 | * | ||
1864 | * TODO: unifiy shared resources and reference counter management | ||
1822 | */ | 1865 | */ |
1823 | static int | 1866 | static int |
1824 | tunnel_send_multicast (struct MeshTunnel *t, | 1867 | tunnel_send_multicast (struct MeshTunnel *t, |
@@ -1827,6 +1870,8 @@ tunnel_send_multicast (struct MeshTunnel *t, | |||
1827 | struct GNUNET_PeerIdentity neighbor; | 1870 | struct GNUNET_PeerIdentity neighbor; |
1828 | struct MeshDataDescriptor *info; | 1871 | struct MeshDataDescriptor *info; |
1829 | struct MeshTunnelTreeNode *n; | 1872 | struct MeshTunnelTreeNode *n; |
1873 | struct MeshTunnelTreeNode *counter; | ||
1874 | GNUNET_SCHEDULER_TaskIdentifier *task; | ||
1830 | unsigned int *copies; | 1875 | unsigned int *copies; |
1831 | unsigned int i; | 1876 | unsigned int i; |
1832 | size_t size; | 1877 | size_t size; |
@@ -1844,12 +1889,20 @@ tunnel_send_multicast (struct MeshTunnel *t, | |||
1844 | return 0; | 1889 | return 0; |
1845 | } | 1890 | } |
1846 | copies = GNUNET_malloc (sizeof (unsigned int)); | 1891 | copies = GNUNET_malloc (sizeof (unsigned int)); |
1847 | for (*copies = 0; NULL != n; n = n->next) | 1892 | for (counter = n; NULL != counter; counter = counter->next) |
1848 | (*copies)++; | 1893 | (*copies)++; |
1849 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (%u copies)\n", *copies); | 1894 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (%u copies)\n", *copies); |
1850 | n = t->tree->me->children_head; | ||
1851 | data = GNUNET_malloc (size); | 1895 | data = GNUNET_malloc (size); |
1852 | memcpy (data, msg, size); | 1896 | memcpy (data, msg, size); |
1897 | if (NULL != t->client) | ||
1898 | { | ||
1899 | task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier)); | ||
1900 | *task = GNUNET_SCHEDULER_add_delayed (UNACKNOWLEDGED_WAIT, | ||
1901 | &client_allow_send, | ||
1902 | t->client->handle); | ||
1903 | } | ||
1904 | else | ||
1905 | task = NULL; // So GCC shuts up about task being potentially uninitialized | ||
1853 | while (NULL != n) | 1906 | while (NULL != n) |
1854 | { | 1907 | { |
1855 | info = GNUNET_malloc (sizeof (struct MeshDataDescriptor)); | 1908 | info = GNUNET_malloc (sizeof (struct MeshDataDescriptor)); |
@@ -1859,9 +1912,7 @@ tunnel_send_multicast (struct MeshTunnel *t, | |||
1859 | if (NULL != t->client) | 1912 | if (NULL != t->client) |
1860 | { | 1913 | { |
1861 | info->client = t->client->handle; | 1914 | info->client = t->client->handle; |
1862 | info->timeout_task = GNUNET_SCHEDULER_add_delayed (UNACKNOWLEDGED_WAIT, | 1915 | info->timeout_task = task; |
1863 | &client_allow_send, | ||
1864 | t->client->handle); | ||
1865 | } | 1916 | } |
1866 | info->destination = n->peer; | 1917 | info->destination = n->peer; |
1867 | GNUNET_PEER_resolve (n->peer, &neighbor); | 1918 | GNUNET_PEER_resolve (n->peer, &neighbor); |
@@ -2220,25 +2271,7 @@ send_core_data_multicast (void *cls, size_t size, void *buf) | |||
2220 | } | 2271 | } |
2221 | } | 2272 | } |
2222 | #endif | 2273 | #endif |
2223 | if (0 == --(*info->copies)) | 2274 | data_descriptor_decrement_multicast (info); |
2224 | { | ||
2225 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Last copy!\n"); | ||
2226 | if (NULL != info->client) | ||
2227 | { | ||
2228 | if (GNUNET_SCHEDULER_NO_TASK != info->timeout_task) | ||
2229 | { | ||
2230 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2231 | "MESH: cancelling client timeout (%u)...\n", | ||
2232 | info->timeout_task); | ||
2233 | GNUNET_SCHEDULER_cancel(info->timeout_task); | ||
2234 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: notifying client...\n"); | ||
2235 | GNUNET_SERVER_receive_done (info->client, GNUNET_OK); | ||
2236 | } | ||
2237 | } | ||
2238 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: freeing memory...\n"); | ||
2239 | GNUNET_free (info->data); | ||
2240 | GNUNET_free (info->copies); | ||
2241 | } | ||
2242 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: freeing info...\n"); | 2275 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: freeing info...\n"); |
2243 | GNUNET_free (info); | 2276 | GNUNET_free (info); |
2244 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: return %u\n", total_size); | 2277 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: return %u\n", total_size); |
@@ -2653,8 +2686,10 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2653 | t = tunnel_get (&msg->oid, ntohl (msg->tid)); | 2686 | t = tunnel_get (&msg->oid, ntohl (msg->tid)); |
2654 | if (NULL == t) | 2687 | if (NULL == t) |
2655 | { | 2688 | { |
2656 | /* TODO notify back: we don't know this tunnel */ | 2689 | /* Probably already got the message from another path, |
2657 | GNUNET_break_op (0); | 2690 | * destroyed the tunnel and retransmitted to children. |
2691 | * Safe to ignore. | ||
2692 | */ | ||
2658 | return GNUNET_OK; | 2693 | return GNUNET_OK; |
2659 | } | 2694 | } |
2660 | if (t->id.oid == myid) | 2695 | if (t->id.oid == myid) |
@@ -3196,7 +3231,11 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
3196 | 3231 | ||
3197 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: client disconnected\n"); | 3232 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: client disconnected\n"); |
3198 | if (client == NULL) | 3233 | if (client == NULL) |
3199 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (SERVER DOWN)\n"); | 3234 | { |
3235 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (SERVER DOWN)\n"); | ||
3236 | return; | ||
3237 | } | ||
3238 | GNUNET_SERVER_client_drop (client); | ||
3200 | c = clients; | 3239 | c = clients; |
3201 | while (NULL != c) | 3240 | while (NULL != c) |
3202 | { | 3241 | { |
@@ -3231,6 +3270,7 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
3231 | GNUNET_CONTAINER_multihashmap_destroy (c->types); | 3270 | GNUNET_CONTAINER_multihashmap_destroy (c->types); |
3232 | next = c->next; | 3271 | next = c->next; |
3233 | GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c); | 3272 | GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c); |
3273 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CLIENT FREE at %p\n", c); | ||
3234 | GNUNET_free (c); | 3274 | GNUNET_free (c); |
3235 | c = next; | 3275 | c = next; |
3236 | } | 3276 | } |
@@ -3261,6 +3301,7 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client, | |||
3261 | uint16_t i; | 3301 | uint16_t i; |
3262 | 3302 | ||
3263 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n"); | 3303 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n"); |
3304 | GNUNET_SERVER_client_keep (client); | ||
3264 | /* Check data sanity */ | 3305 | /* Check data sanity */ |
3265 | size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect); | 3306 | size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect); |
3266 | cc_msg = (struct GNUNET_MESH_ClientConnect *) message; | 3307 | cc_msg = (struct GNUNET_MESH_ClientConnect *) message; |
@@ -3279,6 +3320,7 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client, | |||
3279 | #if MESH_DEBUG | 3320 | #if MESH_DEBUG |
3280 | c->id = next_client_id++; | 3321 | c->id = next_client_id++; |
3281 | #endif | 3322 | #endif |
3323 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CLIENT NEW %u at %p\n", c->id, c); | ||
3282 | c->handle = client; | 3324 | c->handle = client; |
3283 | a = (GNUNET_MESH_ApplicationType *) &cc_msg[1]; | 3325 | a = (GNUNET_MESH_ApplicationType *) &cc_msg[1]; |
3284 | if (napps > 0) | 3326 | if (napps > 0) |
@@ -3392,19 +3434,26 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, | |||
3392 | } | 3434 | } |
3393 | 3435 | ||
3394 | t = GNUNET_malloc (sizeof (struct MeshTunnel)); | 3436 | t = GNUNET_malloc (sizeof (struct MeshTunnel)); |
3395 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CREATED TUNNEL at %p\n", t); | ||
3396 | while (NULL != tunnel_get_by_pi (myid, next_tid)) | 3437 | while (NULL != tunnel_get_by_pi (myid, next_tid)) |
3397 | next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; | 3438 | next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; |
3398 | t->id.tid = next_tid++; | 3439 | t->id.tid = next_tid++; |
3399 | t->id.oid = myid; | 3440 | t->id.oid = myid; |
3400 | t->local_tid = ntohl (t_msg->tunnel_id); | 3441 | t->local_tid = ntohl (t_msg->tunnel_id); |
3442 | #if MESH_DEBUG | ||
3443 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3444 | "MESH: CREATED TUNNEL %s [%x] (%x)\n", | ||
3445 | GNUNET_i2s (&my_full_id), | ||
3446 | t->id.tid, | ||
3447 | t->local_tid); | ||
3448 | #endif | ||
3401 | t->client = c; | 3449 | t->client = c; |
3402 | t->peers = GNUNET_CONTAINER_multihashmap_create (32); | 3450 | t->peers = GNUNET_CONTAINER_multihashmap_create (32); |
3403 | 3451 | ||
3404 | GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); | 3452 | GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); |
3405 | if (GNUNET_OK != | 3453 | if (GNUNET_OK != |
3406 | GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t, | 3454 | GNUNET_CONTAINER_multihashmap_put ( |
3407 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | 3455 | c->tunnels, &hash, t, |
3456 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
3408 | { | 3457 | { |
3409 | GNUNET_break (0); | 3458 | GNUNET_break (0); |
3410 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 3459 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -3413,8 +3462,9 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, | |||
3413 | 3462 | ||
3414 | GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash); | 3463 | GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash); |
3415 | if (GNUNET_OK != | 3464 | if (GNUNET_OK != |
3416 | GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t, | 3465 | GNUNET_CONTAINER_multihashmap_put ( |
3417 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | 3466 | tunnels, &hash, t, |
3467 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
3418 | { | 3468 | { |
3419 | GNUNET_break (0); | 3469 | GNUNET_break (0); |
3420 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 3470 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |