aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2011-10-26 18:06:30 +0000
committerBart Polot <bart@net.in.tum.de>2011-10-26 18:06:30 +0000
commit8941e9c8c609bfa3d0943bd26f7c3f8e62df7701 (patch)
tree1c53ecf5bc4a76295a4381ca6338a9abee17792b
parent2b70d89a9849a1f84326176b7c8c4d1101e9aaa4 (diff)
downloadgnunet-8941e9c8c609bfa3d0943bd26f7c3f8e62df7701.tar.gz
gnunet-8941e9c8c609bfa3d0943bd26f7c3f8e62df7701.zip
Fixed #1857
-rw-r--r--src/mesh/gnunet-service-mesh.c130
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 */
696static void 705static void
697client_allow_send(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 706client_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 */
899static void
900data_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 */
1823static int 1866static int
1824tunnel_send_multicast (struct MeshTunnel *t, 1867tunnel_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);