aboutsummaryrefslogtreecommitdiff
path: root/src/mesh
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2012-01-24 01:32:04 +0000
committerBart Polot <bart@net.in.tum.de>2012-01-24 01:32:04 +0000
commita7191ca787d1274832aede62b44d58063bde3b15 (patch)
treea067088fd1241fe979e662cd40ba7d8ffdce1a29 /src/mesh
parent1ad5bcbf2a889f906307daaa88753f38c8bd5903 (diff)
downloadgnunet-a7191ca787d1274832aede62b44d58063bde3b15.tar.gz
gnunet-a7191ca787d1274832aede62b44d58063bde3b15.zip
Changed incoming tunnel notification to delay until relvant traffic is received from remote peer. Allowed several remote clients for each tunnel.
Diffstat (limited to 'src/mesh')
-rw-r--r--src/mesh/gnunet-service-mesh.c331
1 files changed, 213 insertions, 118 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c
index 1c47d7fcf..b91fb3819 100644
--- a/src/mesh/gnunet-service-mesh.c
+++ b/src/mesh/gnunet-service-mesh.c
@@ -276,8 +276,10 @@ struct MeshTunnel
276 */ 276 */
277 MESH_TunnelNumber local_tid; 277 MESH_TunnelNumber local_tid;
278 278
279 /** 279 /**
280 * Local tunnel number for local destination clients 280 * Local tunnel number for local destination clients (incoming number)
281 * ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV or 0). All clients share the same
282 * number.
281 */ 283 */
282 MESH_TunnelNumber local_tid_dest; 284 MESH_TunnelNumber local_tid_dest;
283 285
@@ -310,12 +312,17 @@ struct MeshTunnel
310 /** 312 /**
311 * Client owner of the tunnel, if any 313 * Client owner of the tunnel, if any
312 */ 314 */
313 struct MeshClient *client; 315 struct MeshClient *owner;
314 316
315 /** 317 /**
316 * Client destination of the tunnel, if any 318 * Clients destination of the tunnel, if any
317 */ 319 */
318 struct MeshClient *client_dest; 320 struct MeshClient **clients;
321
322 /**
323 * Number of destination clients
324 */
325 unsigned int nclients;
319 326
320 /** 327 /**
321 * Messages ready to transmit 328 * Messages ready to transmit
@@ -386,15 +393,24 @@ struct MeshPathInfo
386struct MeshClient 393struct MeshClient
387{ 394{
388 /** 395 /**
389 * Linked list 396 * Linked list next
390 */ 397 */
391 struct MeshClient *next; 398 struct MeshClient *next;
399
400 /**
401 * Linked list prev
402 */
392 struct MeshClient *prev; 403 struct MeshClient *prev;
393 404
394 /** 405 /**
395 * Tunnels that belong to this client, indexed by local id 406 * Tunnels that belong to this client, indexed by local id
396 */ 407 */
397 struct GNUNET_CONTAINER_MultiHashMap *tunnels; 408 struct GNUNET_CONTAINER_MultiHashMap *own_tunnels;
409
410 /**
411 * Tunnels this client has accepted, indexed by incoming local id
412 */
413 struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
398 414
399 /** 415 /**
400 * Handle to communicate with the client 416 * Handle to communicate with the client
@@ -761,7 +777,7 @@ client_allow_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
761 mdata->reference_counter); 777 mdata->reference_counter);
762#endif 778#endif
763 *(mdata->task) = GNUNET_SCHEDULER_NO_TASK; 779 *(mdata->task) = GNUNET_SCHEDULER_NO_TASK;
764 GNUNET_SERVER_receive_done (mdata->t->client->handle, GNUNET_OK); 780 GNUNET_SERVER_receive_done (mdata->t->owner->handle, GNUNET_OK);
765} 781}
766 782
767 783
@@ -778,6 +794,18 @@ tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
778 794
779 795
780/** 796/**
797 * Gets the index in t->clients of the client.
798 *
799 * @param t Tunnel where to find client.
800 * @param c Client to be found.
801 *
802 * @return Index of the client, -1 if not present
803 */
804static int
805tunnel_get_client_index (struct MeshTunnel *t, struct MeshClient *c);
806
807
808/**
781 * Notify a tunnel that a connection has broken that affects at least 809 * Notify a tunnel that a connection has broken that affects at least
782 * some of its peers. 810 * some of its peers.
783 * 811 *
@@ -812,9 +840,9 @@ send_subscribed_clients (const struct GNUNET_MessageHeader *msg,
812 uint16_t type; 840 uint16_t type;
813 char cbuf[htons (msg->size)]; 841 char cbuf[htons (msg->size)];
814 842
843 type = ntohs (payload->type);
815#if MESH_DEBUG 844#if MESH_DEBUG
816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Sending to clients...\n"); 845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Sending to clients...\n");
817 type = ntohs (payload->type);
818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: message of type %u\n", type); 846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: message of type %u\n", type);
819#endif 847#endif
820 848
@@ -858,13 +886,35 @@ send_subscribed_clients (const struct GNUNET_MessageHeader *msg,
858#endif 886#endif
859 if (client_is_subscribed (type, c)) 887 if (client_is_subscribed (type, c))
860 { 888 {
861 // FIXME proper client differentiation mechanism required
862 if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN) 889 if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN)
890 {
891 if (c != t->owner)
892 continue;
863 *tid = htonl (t->local_tid); 893 *tid = htonl (t->local_tid);
864 else if(c == t->client_dest) 894 }
865 *tid = htonl (t->local_tid_dest);
866 else 895 else
867 *tid = htonl (t->local_tid); 896 {
897 if (-1 == tunnel_get_client_index (t, c))
898 {
899 /* This client isn't in the tunnel */
900 struct GNUNET_MESH_TunnelNotification tmsg;
901 GNUNET_HashCode hash;
902
903 tmsg.header.size = htons (sizeof (tmsg));
904 tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
905 GNUNET_PEER_resolve (t->id.oid, &tmsg.peer);
906 tmsg.tunnel_id = htonl (t->local_tid_dest);
907 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
908 &tmsg.header, GNUNET_NO);
909 GNUNET_array_append (t->clients, t->nclients, c);
910 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber),
911 &hash);
912 GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
913 c->incoming_tunnels, &hash, t,
914 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
915 }
916 *tid = htonl (t->local_tid_dest);
917 }
868 count++; 918 count++;
869 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: sending\n"); 919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: sending\n");
870 GNUNET_SERVER_notification_context_unicast (nc, c->handle, 920 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
@@ -892,7 +942,7 @@ send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id)
892 pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); 942 pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
893 pc.tunnel_id = htonl (t->local_tid); 943 pc.tunnel_id = htonl (t->local_tid);
894 GNUNET_PEER_resolve (id, &pc.peer); 944 GNUNET_PEER_resolve (id, &pc.peer);
895 GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, &pc.header, 945 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, &pc.header,
896 GNUNET_NO); 946 GNUNET_NO);
897} 947}
898 948
@@ -916,9 +966,12 @@ send_clients_tunnel_destroy (struct MeshTunnel *t)
916 966
917 967
918/** 968/**
919 * Notify a client that the other local client disconnected, if needed. 969 * Notify clients f tunnel disconnections, if needed.
920 * In case the origin disconnects, the destination get a tunnel destroy 970 * In case the origin disconnects, the destination clients get a tunnel destroy
921 * notification. Otherwise, the origin gets a (local ID) peer disconnected. 971 * notification. If the last destination disconnects (only one remaining client
972 * in tunnel), the origin gets a (local ID) peer disconnected.
973 * Note that the function must be called BEFORE removing the client from
974 * the tunnel.
922 * 975 *
923 * @param t Tunnel that was destroyed. 976 * @param t Tunnel that was destroyed.
924 * @param c Client that disconnected. 977 * @param c Client that disconnected.
@@ -926,25 +979,28 @@ send_clients_tunnel_destroy (struct MeshTunnel *t)
926static void 979static void
927send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c) 980send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c)
928{ 981{
929 if (c == t->client_dest) 982 unsigned int i;
930 {
931 struct GNUNET_MESH_PeerControl msg;
932 983
933 msg.header.size = htons (sizeof (msg)); 984 if (c == t->owner)
934 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
935 msg.tunnel_id = htonl (t->local_tid);
936 msg.peer = my_full_id;
937 GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
938 &msg.header, GNUNET_NO);
939 }
940 else if (NULL != t->client_dest && c == t->client)
941 { 985 {
942 struct GNUNET_MESH_TunnelMessage msg; 986 struct GNUNET_MESH_TunnelMessage msg;
943 987
944 msg.header.size = htons (sizeof (msg)); 988 msg.header.size = htons (sizeof (msg));
945 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); 989 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
946 msg.tunnel_id = htonl (t->local_tid_dest); 990 msg.tunnel_id = htonl (t->local_tid_dest);
947 GNUNET_SERVER_notification_context_unicast (nc, t->client_dest->handle, 991 for (i = 0; i < t->nclients; i++)
992 GNUNET_SERVER_notification_context_unicast (nc, t->clients[i]->handle,
993 &msg.header, GNUNET_NO);
994 }
995 else if (1 == t->nclients && NULL != t->owner)
996 {
997 struct GNUNET_MESH_PeerControl msg;
998
999 msg.header.size = htons (sizeof (msg));
1000 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1001 msg.tunnel_id = htonl (t->local_tid);
1002 msg.peer = my_full_id;
1003 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
948 &msg.header, GNUNET_NO); 1004 &msg.header, GNUNET_NO);
949 } 1005 }
950} 1006}
@@ -1001,7 +1057,7 @@ data_descriptor_decrement_multicast (struct MeshData *mesh_data)
1001 { 1057 {
1002 GNUNET_SCHEDULER_cancel (*(mesh_data->task)); 1058 GNUNET_SCHEDULER_cancel (*(mesh_data->task));
1003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: notifying client...\n"); 1059 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: notifying client...\n");
1004 GNUNET_SERVER_receive_done (mesh_data->t->client->handle, GNUNET_OK); 1060 GNUNET_SERVER_receive_done (mesh_data->t->owner->handle, GNUNET_OK);
1005 } 1061 }
1006 GNUNET_free (mesh_data->task); 1062 GNUNET_free (mesh_data->task);
1007 } 1063 }
@@ -1855,7 +1911,7 @@ tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
1855 GNUNET_HashCode hash; 1911 GNUNET_HashCode hash;
1856 1912
1857 GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash); 1913 GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
1858 return GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash); 1914 return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
1859 } 1915 }
1860} 1916}
1861 1917
@@ -1911,7 +1967,7 @@ notify_peer_disconnected (void *cls, GNUNET_PEER_Id peer_id)
1911 struct MeshPeerInfo *peer; 1967 struct MeshPeerInfo *peer;
1912 struct MeshPathInfo *path_info; 1968 struct MeshPathInfo *path_info;
1913 1969
1914 if (NULL != t->client && NULL != nc) 1970 if (NULL != t->owner && NULL != nc)
1915 { 1971 {
1916 struct GNUNET_MESH_PeerControl msg; 1972 struct GNUNET_MESH_PeerControl msg;
1917 1973
@@ -1919,7 +1975,7 @@ notify_peer_disconnected (void *cls, GNUNET_PEER_Id peer_id)
1919 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); 1975 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1920 msg.tunnel_id = htonl (t->local_tid); 1976 msg.tunnel_id = htonl (t->local_tid);
1921 GNUNET_PEER_resolve (peer_id, &msg.peer); 1977 GNUNET_PEER_resolve (peer_id, &msg.peer);
1922 GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, 1978 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
1923 &msg.header, GNUNET_NO); 1979 &msg.header, GNUNET_NO);
1924 } 1980 }
1925 peer = peer_info_get_short (peer_id); 1981 peer = peer_info_get_short (peer_id);
@@ -2136,7 +2192,7 @@ tunnel_send_multicast (struct MeshTunnel *t,
2136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: not a data packet, no ttl\n"); 2192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: not a data packet, no ttl\n");
2137#endif 2193#endif
2138 } 2194 }
2139 if (NULL != t->client && GNUNET_YES != t->client->shutting_down 2195 if (NULL != t->owner && GNUNET_YES != t->owner->shutting_down
2140 && GNUNET_NO == internal) 2196 && GNUNET_NO == internal)
2141 { 2197 {
2142 mdata->task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier)); 2198 mdata->task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier));
@@ -2156,7 +2212,7 @@ tunnel_send_multicast (struct MeshTunnel *t,
2156 { 2212 {
2157 GNUNET_SCHEDULER_cancel(*(mdata->task)); 2213 GNUNET_SCHEDULER_cancel(*(mdata->task));
2158 GNUNET_free (mdata->task); 2214 GNUNET_free (mdata->task);
2159 GNUNET_SERVER_receive_done(t->client->handle, GNUNET_OK); 2215 GNUNET_SERVER_receive_done(t->owner->handle, GNUNET_OK);
2160 } 2216 }
2161 // FIXME change order? 2217 // FIXME change order?
2162 GNUNET_free (mdata); 2218 GNUNET_free (mdata);
@@ -2170,6 +2226,27 @@ tunnel_send_multicast (struct MeshTunnel *t,
2170 2226
2171 2227
2172/** 2228/**
2229 * Gets the index in t->clients of the client.
2230 *
2231 * @param t Tunnel where to find client.
2232 * @param c Client to be found.
2233 *
2234 * @return Index of the client, -1 if not present
2235 */
2236static int
2237tunnel_get_client_index (struct MeshTunnel *t, struct MeshClient *c)
2238{
2239 int i;
2240
2241 for (i = 0; i < t->nclients; i++)
2242 if (t->clients[i] == c)
2243 break;
2244 if (i < t->nclients)
2245 return i;
2246 return -1;
2247}
2248
2249/**
2173 * Send a message to all peers in this tunnel that the tunnel is no longer 2250 * Send a message to all peers in this tunnel that the tunnel is no longer
2174 * valid. 2251 * valid.
2175 * 2252 *
@@ -2190,7 +2267,7 @@ tunnel_send_destroy (struct MeshTunnel *t)
2190 2267
2191 2268
2192/** 2269/**
2193 * Destroy the tunnel and free any allocated resources linked to it 2270 * Destroy the tunnel and free any allocated resources linked to it.
2194 * 2271 *
2195 * @param t the tunnel to destroy 2272 * @param t the tunnel to destroy
2196 * 2273 *
@@ -2203,13 +2280,14 @@ tunnel_destroy (struct MeshTunnel *t)
2203 struct MeshQueue *q; 2280 struct MeshQueue *q;
2204 struct MeshQueue *qn; 2281 struct MeshQueue *qn;
2205 GNUNET_HashCode hash; 2282 GNUNET_HashCode hash;
2283 unsigned int i;
2206 int r; 2284 int r;
2207 2285
2208 if (NULL == t) 2286 if (NULL == t)
2209 return GNUNET_OK; 2287 return GNUNET_OK;
2210 2288
2211 r = GNUNET_OK; 2289 r = GNUNET_OK;
2212 c = t->client; 2290 c = t->owner;
2213#if MESH_DEBUG 2291#if MESH_DEBUG
2214 { 2292 {
2215 struct GNUNET_PeerIdentity id; 2293 struct GNUNET_PeerIdentity id;
@@ -2227,31 +2305,32 @@ tunnel_destroy (struct MeshTunnel *t)
2227 { 2305 {
2228 r = GNUNET_SYSERR; 2306 r = GNUNET_SYSERR;
2229 } 2307 }
2230 2308
2231 GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); 2309 GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
2232 if (NULL != c && 2310 if (NULL != c &&
2233 GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t)) 2311 GNUNET_YES !=
2312 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
2234 { 2313 {
2235 r = GNUNET_SYSERR; 2314 r = GNUNET_SYSERR;
2236 } 2315 }
2237 c = t->client_dest;
2238 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); 2316 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
2239 if (NULL != c) 2317 for (i = 0; i < t->nclients; i++)
2240 { 2318 {
2319 c = t->clients[i];
2241 if (GNUNET_YES != 2320 if (GNUNET_YES !=
2242 GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t) || 2321 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t))
2243 GNUNET_YES !=
2244 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t))
2245 { 2322 {
2246 r = GNUNET_SYSERR; 2323 r = GNUNET_SYSERR;
2247 } 2324 }
2248 } 2325 }
2249 if (t->local_tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) 2326 if (t->nclients > 0)
2250 { 2327 {
2251 GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); 2328 if (GNUNET_YES !=
2252 GNUNET_break (GNUNET_YES == 2329 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t))
2253 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, 2330 {
2254 t)); 2331 r = GNUNET_SYSERR;
2332 }
2333 GNUNET_free (t->clients);
2255 } 2334 }
2256 if (NULL != t->peers) 2335 if (NULL != t->peers)
2257 { 2336 {
@@ -2298,8 +2377,31 @@ tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer)
2298 2377
2299 2378
2300/** 2379/**
2380 * Removes a client from the tunnel.
2381 *
2382 * @param t Tunnel from which to remove the client.
2383 * @param c Client that should be removed.
2384 *
2385 * FIXME blacklist client to avoid adding it at next data packet
2386 */
2387static void
2388tunnel_delete_client (struct MeshTunnel *t, struct MeshClient *c)
2389{
2390 unsigned int i;
2391
2392 for (i = 0; i < t->nclients; i++)
2393 if (t->clients[i] == c)
2394 break;
2395 GNUNET_assert (i < t->nclients);
2396 t->clients[i] = t->clients [t->nclients - 1];
2397 GNUNET_array_grow (t->clients, t->nclients, t->nclients - 1);
2398}
2399
2400/**
2301 * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a 2401 * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a
2302 * client when the client disconnects. 2402 * client when the client disconnects. If the client is not the owner, the
2403 * owner will get notified if no more clients are in the tunnel and the client
2404 * get removed from the tunnel's list.
2303 * 2405 *
2304 * @param cls closure (client that is disconnecting) 2406 * @param cls closure (client that is disconnecting)
2305 * @param key the hash of the local tunnel id (used to access the hashmap) 2407 * @param key the hash of the local tunnel id (used to access the hashmap)
@@ -2315,14 +2417,13 @@ tunnel_destroy_iterator (void *cls, const GNUNET_HashCode * key, void *value)
2315 int r; 2417 int r;
2316 2418
2317 send_client_tunnel_disconnect(t, c); 2419 send_client_tunnel_disconnect(t, c);
2318 if (c == t->client_dest) 2420 if (c != t->owner)
2319 { 2421 {
2320#if MESH_DEBUG 2422#if MESH_DEBUG
2321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2423 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2322 "Client %u is destination, keeping the tunnel alive.\n", c->id); 2424 "Client %u is destination, keeping the tunnel alive.\n", c->id);
2323#endif 2425#endif
2324 t->client_dest = NULL; 2426 tunnel_delete_client (t, c);
2325 t->local_tid_dest = 0;
2326 return GNUNET_OK; 2427 return GNUNET_OK;
2327 } 2428 }
2328 tunnel_send_destroy(t); 2429 tunnel_send_destroy(t);
@@ -2629,7 +2730,7 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
2629 t->id.tid = tid; 2730 t->id.tid = tid;
2630 while (NULL != tunnel_get_incoming (next_local_tid)) 2731 while (NULL != tunnel_get_incoming (next_local_tid))
2631 next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; 2732 next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
2632 t->local_tid = next_local_tid++; 2733 t->local_tid_dest = next_local_tid++;
2633 next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; 2734 next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
2634 t->tree = tree_new (t->id.oid); 2735 t->tree = tree_new (t->id.oid);
2635 2736
@@ -2643,7 +2744,7 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
2643 return GNUNET_OK; 2744 return GNUNET_OK;
2644 } 2745 }
2645 tunnel_reset_timeout (t); 2746 tunnel_reset_timeout (t);
2646 GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); 2747 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
2647 if (GNUNET_OK != 2748 if (GNUNET_OK !=
2648 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t, 2749 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
2649 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 2750 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
@@ -2708,16 +2809,7 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
2708 peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO); 2809 peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO);
2709 if (NULL == t->peers) 2810 if (NULL == t->peers)
2710 { 2811 {
2711 /* New tunnel! Notify clients! */ 2812 /* New tunnel! Notify clients on data. */
2712 struct GNUNET_MESH_TunnelNotification cmsg;
2713
2714 cmsg.header.size = htons (sizeof (cmsg));
2715 cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
2716 GNUNET_PEER_resolve (t->id.oid, &cmsg.peer);
2717 cmsg.tunnel_id = htonl (t->local_tid);
2718 GNUNET_SERVER_notification_context_broadcast (nc, &cmsg.header,
2719 GNUNET_NO);
2720
2721 t->peers = GNUNET_CONTAINER_multihashmap_create (4); 2813 t->peers = GNUNET_CONTAINER_multihashmap_create (4);
2722 } 2814 }
2723 GNUNET_break (GNUNET_OK == 2815 GNUNET_break (GNUNET_OK ==
@@ -2832,6 +2924,9 @@ handle_mesh_path_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
2832 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Own position: %u\n", own_pos); 2924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Own position: %u\n", own_pos);
2833 if (own_pos < path->length - 1) 2925 if (own_pos < path->length - 1)
2834 send_message (message, &pi[own_pos + 1]); 2926 send_message (message, &pi[own_pos + 1]);
2927 else
2928 send_client_tunnel_disconnect(t, NULL);
2929
2835 tunnel_delete_peer (t, path->peers[path->length - 1]); 2930 tunnel_delete_peer (t, path->peers[path->length - 1]);
2836 path_destroy (path); 2931 path_destroy (path);
2837 return GNUNET_OK; 2932 return GNUNET_OK;
@@ -3118,7 +3213,7 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
3118 3213
3119 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3120 "MESH: it's for us! sending to clients...\n"); 3215 "MESH: it's for us! sending to clients...\n");
3121 if (NULL == t->client) 3216 if (NULL == t->owner)
3122 { 3217 {
3123 /* got data packet for ownerless tunnel */ 3218 /* got data packet for ownerless tunnel */
3124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: no clients!\n"); 3219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: no clients!\n");
@@ -3129,7 +3224,7 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
3129 memcpy (cbuf, message, size); 3224 memcpy (cbuf, message, size);
3130 copy = (struct GNUNET_MESH_ToOrigin *) cbuf; 3225 copy = (struct GNUNET_MESH_ToOrigin *) cbuf;
3131 copy->tid = htonl (t->local_tid); 3226 copy->tid = htonl (t->local_tid);
3132 GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, 3227 GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
3133 &copy->header, GNUNET_YES); 3228 &copy->header, GNUNET_YES);
3134 return GNUNET_OK; 3229 return GNUNET_OK;
3135 } 3230 }
@@ -3202,7 +3297,7 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
3202 if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity))) 3297 if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
3203 { 3298 {
3204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: It's for us!\n"); 3299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: It's for us!\n");
3205 if (NULL == t->client) 3300 if (NULL == t->owner)
3206 { 3301 {
3207 GNUNET_break_op (0); 3302 GNUNET_break_op (0);
3208 return GNUNET_OK; 3303 return GNUNET_OK;
@@ -3448,7 +3543,7 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
3448 GNUNET_break_op (0); 3543 GNUNET_break_op (0);
3449 return; 3544 return;
3450 } 3545 }
3451 GNUNET_assert (NULL != t->client); 3546 GNUNET_assert (NULL != t->owner);
3452 peer_info = peer_info_get (pi); 3547 peer_info = peer_info_get (pi);
3453 (void) GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey, 3548 (void) GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey,
3454 peer_info, 3549 peer_info,
@@ -3506,12 +3601,14 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
3506#endif 3601#endif
3507 GNUNET_SERVER_client_drop (c->handle); 3602 GNUNET_SERVER_client_drop (c->handle);
3508 c->shutting_down = GNUNET_YES; 3603 c->shutting_down = GNUNET_YES;
3509 if (NULL != c->tunnels) 3604 GNUNET_assert (NULL != c->own_tunnels);
3510 { 3605 GNUNET_assert (NULL != c->incoming_tunnels);
3511 GNUNET_CONTAINER_multihashmap_iterate (c->tunnels, 3606 GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels,
3512 &tunnel_destroy_iterator, c); 3607 &tunnel_destroy_iterator, c);
3513 GNUNET_CONTAINER_multihashmap_destroy (c->tunnels); 3608 GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels,
3514 } 3609 &tunnel_destroy_iterator, c);
3610 GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels);
3611 GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels);
3515 3612
3516 /* deregister clients applications */ 3613 /* deregister clients applications */
3517 if (NULL != c->apps) 3614 if (NULL != c->apps)
@@ -3638,7 +3735,8 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
3638 "MESH: client has %u+%u subscriptions\n", napps, ntypes); 3735 "MESH: client has %u+%u subscriptions\n", napps, ntypes);
3639 3736
3640 GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c); 3737 GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
3641 c->tunnels = GNUNET_CONTAINER_multihashmap_create (32); 3738 c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
3739 c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
3642 GNUNET_SERVER_notification_context_add (nc, client); 3740 GNUNET_SERVER_notification_context_add (nc, client);
3643 3741
3644 GNUNET_SERVER_receive_done (client, GNUNET_OK); 3742 GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -3712,12 +3810,12 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
3712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CREATED TUNNEL %s [%x] (%x)\n", 3810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CREATED TUNNEL %s [%x] (%x)\n",
3713 GNUNET_i2s (&my_full_id), t->id.tid, t->local_tid); 3811 GNUNET_i2s (&my_full_id), t->id.tid, t->local_tid);
3714#endif 3812#endif
3715 t->client = c; 3813 t->owner = c;
3716 t->peers = GNUNET_CONTAINER_multihashmap_create (32); 3814 t->peers = GNUNET_CONTAINER_multihashmap_create (32);
3717 3815
3718 GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); 3816 GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
3719 if (GNUNET_OK != 3817 if (GNUNET_OK !=
3720 GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t, 3818 GNUNET_CONTAINER_multihashmap_put (c->own_tunnels, &hash, t,
3721 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) 3819 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
3722 { 3820 {
3723 GNUNET_break (0); 3821 GNUNET_break (0);
@@ -3785,23 +3883,35 @@ handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
3785 3883
3786 /* Remove from local id hashmap */ 3884 /* Remove from local id hashmap */
3787 GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash); 3885 GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
3788 t = GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash); 3886 t = GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
3789 send_client_tunnel_disconnect(t, c); 3887 send_client_tunnel_disconnect(t, c);
3790 GNUNET_assert (GNUNET_YES == 3888 if (c != t->owner)
3791 GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t)); 3889 {
3792 if (c == t->client_dest) 3890 tunnel_delete_client (t, c);
3793 { 3891 if (t->nclients == 0)
3794 GNUNET_assert (GNUNET_YES == 3892 {
3795 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t)); 3893 // TODO: destroy tunnel? what if a packet comes with another message type?
3796 GNUNET_assert (GNUNET_YES == 3894#if 0
3797 GNUNET_CONTAINER_multihashmap_remove (t->peers, &my_full_id.hashPubKey, t)); 3895 GNUNET_assert (GNUNET_YES ==
3798 t->client_dest = NULL; 3896 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels,
3897 &hash, t));
3898#endif
3899 GNUNET_assert (GNUNET_YES ==
3900 GNUNET_CONTAINER_multihashmap_remove (t->peers,
3901 &my_full_id.hashPubKey,
3902 t));
3903 }
3799 t->local_tid_dest = 0; 3904 t->local_tid_dest = 0;
3800 GNUNET_SERVER_receive_done (client, GNUNET_OK); 3905 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3801 return; 3906 return;
3802 } 3907 }
3908 GNUNET_assert (GNUNET_YES ==
3909 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
3910 &hash,
3911 t));
3803 3912
3804 t->client = NULL; 3913 /* Don't try to ACK the client about the tunnel_destroy multicast packet */
3914 t->owner = NULL;
3805 tunnel_send_destroy (t); 3915 tunnel_send_destroy (t);
3806 tunnel_destroy (t); 3916 tunnel_destroy (t);
3807 GNUNET_SERVER_receive_done (client, GNUNET_OK); 3917 GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -3855,7 +3965,7 @@ handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
3855 } 3965 }
3856 3966
3857 /* Does client own tunnel? */ 3967 /* Does client own tunnel? */
3858 if (t->client->handle != client) 3968 if (t->owner->handle != client)
3859 { 3969 {
3860 GNUNET_break (0); 3970 GNUNET_break (0);
3861 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 3971 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
@@ -3919,7 +4029,7 @@ handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
3919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: on tunnel %X\n", t->id.tid); 4029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: on tunnel %X\n", t->id.tid);
3920 4030
3921 /* Does client own tunnel? */ 4031 /* Does client own tunnel? */
3922 if (t->client->handle != client) 4032 if (t->owner->handle != client)
3923 { 4033 {
3924 GNUNET_break (0); 4034 GNUNET_break (0);
3925 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4035 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
@@ -3996,7 +4106,7 @@ handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
3996 } 4106 }
3997 4107
3998 /* Does client own tunnel? */ 4108 /* Does client own tunnel? */
3999 if (t->client->handle != client) 4109 if (t->owner->handle != client)
4000 { 4110 {
4001 GNUNET_break (0); 4111 GNUNET_break (0);
4002 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4112 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
@@ -4013,38 +4123,23 @@ handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
4013 /* Yes! Fast forward, add ourselves to the tunnel and send the 4123 /* Yes! Fast forward, add ourselves to the tunnel and send the
4014 * good news to the client, and alert the destination client of 4124 * good news to the client, and alert the destination client of
4015 * an incoming tunnel. 4125 * an incoming tunnel.
4126 *
4127 * FIXME send a path create to self, avoid code duplication
4016 */ 4128 */
4017 struct GNUNET_MESH_TunnelNotification cmsg;
4018 struct MeshClient *c;
4019
4020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: available locally\n"); 4129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: available locally\n");
4021 GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey, 4130 GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey,
4022 peer_info_get (&my_full_id), 4131 peer_info_get (&my_full_id),
4023 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 4132 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
4024 4133
4025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: notifying client\n"); 4134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: notifying client\n");
4026 send_client_peer_connected (t, myid); 4135 send_client_peer_connected (t, myid);
4027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Done\n"); 4136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Done\n");
4028 GNUNET_SERVER_receive_done (client, GNUNET_OK); 4137 GNUNET_SERVER_receive_done (client, GNUNET_OK);
4029 4138
4030 /* FIXME implement a proper handling of this case,
4031 a client differentiation mechanism */
4032 cmsg.header.size = htons (sizeof (cmsg));
4033 cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
4034 cmsg.peer = my_full_id;
4035 t->local_tid_dest = next_local_tid++; 4139 t->local_tid_dest = next_local_tid++;
4036 cmsg.tunnel_id = htonl (t->local_tid_dest);
4037 c = (struct MeshClient *) GNUNET_CONTAINER_multihashmap_get(applications,
4038 &hash);
4039 t->client_dest = c;
4040 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); 4140 GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
4041 GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t,
4042 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
4043 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t, 4141 GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
4044 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 4142 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
4045 GNUNET_SERVER_notification_context_unicast (nc, c->handle, &cmsg.header,
4046 GNUNET_NO);
4047
4048 4143
4049 return; 4144 return;
4050 } 4145 }
@@ -4117,8 +4212,7 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
4117 } 4212 }
4118 4213
4119 /* Is it a local tunnel? Then, does client own the tunnel? */ 4214 /* Is it a local tunnel? Then, does client own the tunnel? */
4120 if (NULL != t->client && NULL != t->client->handle && 4215 if (t->owner->handle != client)
4121 t->client->handle != client)
4122 { 4216 {
4123 GNUNET_break (0); 4217 GNUNET_break (0);
4124 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4218 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
@@ -4174,9 +4268,6 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
4174 MESH_TunnelNumber tid; 4268 MESH_TunnelNumber tid;
4175 size_t size; 4269 size_t size;
4176 4270
4177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4178 "MESH: Got a ToOrigin request from a client!\n");
4179
4180 /* Sanity check for client registration */ 4271 /* Sanity check for client registration */
4181 if (NULL == (c = client_get (client))) 4272 if (NULL == (c = client_get (client)))
4182 { 4273 {
@@ -4197,6 +4288,10 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
4197 4288
4198 /* Tunnel exists? */ 4289 /* Tunnel exists? */
4199 tid = ntohl (data_msg->tid); 4290 tid = ntohl (data_msg->tid);
4291#if MESH_DEBUG
4292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4293 "MESH: Got a ToOrigin request from a client! Tunnel %X\n", tid);
4294#endif
4200 if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) 4295 if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
4201 { 4296 {
4202 GNUNET_break (0); 4297 GNUNET_break (0);
@@ -4211,8 +4306,8 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
4211 return; 4306 return;
4212 } 4307 }
4213 4308
4214 /* It shouldn't be a local tunnel. */ 4309 /* It should be sent by someone who has this as incoming tunnel. */
4215 if (NULL != t->client && NULL == t->client_dest) 4310 if (-1 == tunnel_get_client_index (t, c))
4216 { 4311 {
4217 GNUNET_break (0); 4312 GNUNET_break (0);
4218 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4313 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
@@ -4289,7 +4384,7 @@ handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
4289 } 4384 }
4290 4385
4291 /* Does client own tunnel? */ 4386 /* Does client own tunnel? */
4292 if (t->client->handle != client) 4387 if (t->owner->handle != client)
4293 { 4388 {
4294 GNUNET_break (0); 4389 GNUNET_break (0);
4295 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 4390 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);