aboutsummaryrefslogtreecommitdiff
path: root/src/mesh
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesh')
-rw-r--r--src/mesh/gnunet-service-mesh.c137
-rw-r--r--src/mesh/test_mesh_api.c19
2 files changed, 135 insertions, 21 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c
index f640364b1..eb2382ae1 100644
--- a/src/mesh/gnunet-service-mesh.c
+++ b/src/mesh/gnunet-service-mesh.c
@@ -30,14 +30,15 @@
30 * - MESH NETWORK HANDLES 30 * - MESH NETWORK HANDLES
31 * - MESH LOCAL HANDLER HELPERS 31 * - MESH LOCAL HANDLER HELPERS
32 * - MESH LOCAL HANDLES 32 * - MESH LOCAL HANDLES
33 * - PERIODIC FUNCTIONS
33 * - MAIN FUNCTIONS (main & run) 34 * - MAIN FUNCTIONS (main & run)
34 * 35 *
35 * TODO: 36 * TODO:
36 * - soft stateing (keep-alive (CHANGE?) / timeout / disconnect) -- not a message issue
37 * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message! 37 * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
38 * - partial disconnect reporting -- same as error reporting? 38 * - partial disconnect reporting -- same as error reporting?
39 * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking... 39 * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
40 * - speed requirement specification (change?) in mesh API -- API call 40 * - speed requirement specification (change?) in mesh API -- API call
41 * - add ping message (connection confirmation, others?)
41 */ 42 */
42 43
43#include "platform.h" 44#include "platform.h"
@@ -51,6 +52,10 @@
51#include "mesh_protocol.h" 52#include "mesh_protocol.h"
52#include "gnunet_dht_service.h" 53#include "gnunet_dht_service.h"
53 54
55#define REFRESH_PATH_TIME GNUNET_TIME_relative_multiply(\
56 GNUNET_TIME_UNIT_SECONDS,\
57 300)
58
54 59
55/******************************************************************************/ 60/******************************************************************************/
56/************************ DATA STRUCTURES ****************************/ 61/************************ DATA STRUCTURES ****************************/
@@ -127,9 +132,9 @@ struct MeshPeerInfo
127 enum MeshPeerState state; 132 enum MeshPeerState state;
128 133
129 /** 134 /**
130 * When to try to establish contact again? 135 * Last time we heard from this peer
131 */ 136 */
132 struct GNUNET_TIME_Absolute next_reconnect_attempt; 137 struct GNUNET_TIME_Absolute last_contact;
133 138
134 /** 139 /**
135 * Number of attempts to reconnect so far 140 * Number of attempts to reconnect so far
@@ -266,6 +271,7 @@ struct MeshClient
266 * Linked list 271 * Linked list
267 */ 272 */
268 struct MeshClient *next; 273 struct MeshClient *next;
274 struct MeshClient *prev;
269 275
270 /** 276 /**
271 * Tunnels that belong to this client, indexed by local id 277 * Tunnels that belong to this client, indexed by local id
@@ -299,6 +305,7 @@ struct MeshClient
299 * All the clients 305 * All the clients
300 */ 306 */
301static struct MeshClient *clients; 307static struct MeshClient *clients;
308static struct MeshClient *clients_t;
302 309
303/** 310/**
304 * Tunnels known, indexed by MESH_TunnelID (MeshTunnel) 311 * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
@@ -496,11 +503,23 @@ send_core_create_path_for_peer (void *cls, size_t size, void *buf)
496 struct GNUNET_MESH_ManipulatePath *msg; 503 struct GNUNET_MESH_ManipulatePath *msg;
497 struct MeshPath *p; 504 struct MeshPath *p;
498 struct GNUNET_PeerIdentity *peer_ptr; 505 struct GNUNET_PeerIdentity *peer_ptr;
506 struct GNUNET_PeerIdentity id;
499 size_t size_needed; 507 size_t size_needed;
500 int i; 508 int i;
501 509
502 if (0 == size && NULL == buf) { 510 if (0 == size && NULL == buf) {
503 // TODO retry? cancel? 511 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
512 GNUNET_PEER_resolve(peer_info->path->peers[1], &id);
513 GNUNET_CORE_notify_transmit_ready(core_handle,
514 0,
515 0,
516 GNUNET_TIME_UNIT_SECONDS,
517 &id,
518 sizeof(struct GNUNET_MESH_ManipulatePath)
519 + (peer_info->path->length
520 * sizeof (struct GNUNET_PeerIdentity)),
521 &send_core_create_path_for_peer,
522 peer_info);
504 return 0; 523 return 0;
505 } 524 }
506 p = peer_info->path; 525 p = peer_info->path;
@@ -528,7 +547,7 @@ send_core_create_path_for_peer (void *cls, size_t size, void *buf)
528 GNUNET_PEER_resolve(p->peers[i], peer_ptr++); 547 GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
529 } 548 }
530 549
531 peer_info->state = MESH_PEER_WAITING; 550 peer_info->state = MESH_PEER_WAITING; // TODO maybe already ready?
532 551
533 return size_needed; 552 return size_needed;
534} 553}
@@ -655,7 +674,7 @@ delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
655/** 674/**
656 * notify_client_connection_failure: notify a client that the connection to the 675 * notify_client_connection_failure: notify a client that the connection to the
657 * requested remote peer is not possible (for instance, no route found) 676 * requested remote peer is not possible (for instance, no route found)
658 * Function called when the socket is ready to queue more data."buf" will be 677 * Function called when the socket is ready to queue more data. "buf" will be
659 * NULL and "size" zero if the socket was closed for writing in the meantime. 678 * NULL and "size" zero if the socket was closed for writing in the meantime.
660 * 679 *
661 * @param cls closure 680 * @param cls closure
@@ -796,25 +815,30 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
796 struct MeshClient *next; 815 struct MeshClient *next;
797 816
798 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 817 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
799 "MESH: client disconnected\n"); 818 "client disconnected\n");
800 c = clients; 819 c = clients;
801 while (NULL != c) { 820 while (NULL != c) {
802 if (c->handle == client) { 821 if (c->handle == client) {
803 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 822 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
804 "MESH: matching client found, cleaning\n"); 823 " matching client found, cleaning\n");
805 GNUNET_CONTAINER_multihashmap_iterate(c->tunnels, 824 GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
806 &delete_tunnel_entry, 825 &delete_tunnel_entry,
807 c); 826 c);
808 GNUNET_CONTAINER_multihashmap_destroy(c->tunnels); 827 GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
809 if(0 != c->app_counter) GNUNET_free (c->apps); 828 if(0 != c->app_counter) GNUNET_free (c->apps);
810 if(0 != c->type_counter) GNUNET_free (c->types); 829 if(0 != c->type_counter) GNUNET_free (c->types);
830 GNUNET_CONTAINER_DLL_remove(clients, clients_t, c);
811 next = c->next; 831 next = c->next;
812 GNUNET_free (c); 832 GNUNET_free (c);
813 c = next; 833 c = next;
814 } else { 834 } else {
835 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
836 " ... searching\n");
815 c = c->next; 837 c = c->next;
816 } 838 }
817 } 839 }
840 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
841 " done!\n");
818 return; 842 return;
819} 843}
820 844
@@ -837,7 +861,7 @@ handle_local_new_client (void *cls,
837 uint16_t types; 861 uint16_t types;
838 uint16_t apps; 862 uint16_t apps;
839 863
840 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n"); 864 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
841 /* Check data sanity */ 865 /* Check data sanity */
842 size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect); 866 size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
843 cc_msg = (struct GNUNET_MESH_ClientConnect *) message; 867 cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
@@ -867,12 +891,11 @@ handle_local_new_client (void *cls,
867 apps * sizeof(GNUNET_MESH_ApplicationType)); 891 apps * sizeof(GNUNET_MESH_ApplicationType));
868 } 892 }
869 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 893 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
870 "MESH: client has %u+%u subscriptions\n", 894 " client has %u+%u subscriptions\n",
871 c->type_counter, 895 c->type_counter,
872 c->app_counter); 896 c->app_counter);
873 897
874 c->next = clients; 898 GNUNET_CONTAINER_DLL_insert(clients, clients_t, c);
875 clients = c;
876 c->tunnels = GNUNET_CONTAINER_multihashmap_create(32); 899 c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
877 900
878 GNUNET_SERVER_receive_done(client, GNUNET_OK); 901 GNUNET_SERVER_receive_done(client, GNUNET_OK);
@@ -926,8 +949,8 @@ handle_local_tunnel_create (void *cls,
926 } 949 }
927 950
928 t = GNUNET_malloc(sizeof(struct MeshTunnel)); 951 t = GNUNET_malloc(sizeof(struct MeshTunnel));
929 // FIXME: what if all 2^32 ID are taken? 952 while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
930 while (NULL != retrieve_tunnel_by_pi(myid, next_tid)) next_tid++; 953 next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
931 t->id.tid = next_tid++; 954 t->id.tid = next_tid++;
932 t->id.oid = myid; 955 t->id.oid = myid;
933 t->local_tid = ntohl(t_msg->tunnel_id); 956 t->local_tid = ntohl(t_msg->tunnel_id);
@@ -1412,11 +1435,76 @@ core_disconnect (void *cls,
1412 const struct 1435 const struct
1413 GNUNET_PeerIdentity *peer) 1436 GNUNET_PeerIdentity *peer)
1414{ 1437{
1438 GNUNET_PEER_Id pid;
1415 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1416 "Peer disconnected\n"); 1440 "Peer disconnected\n");
1441 pid = GNUNET_PEER_intern(peer);
1442 GNUNET_PEER_change_rc(pid, -1);
1443 if (myid == pid) {
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1445 " (self)\n");
1446 }
1447 return;
1448}
1449
1450
1451/******************************************************************************/
1452/********************** PERIODIC FUNCTIONS **************************/
1453/******************************************************************************/
1454
1455/**
1456 * Iterator over peers to send keepalive packets when needed.
1457 *
1458 * @param cls unused
1459 * @param key current key code
1460 * @param value value in the hash map
1461 * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
1462 */
1463int
1464path_refresh_peer (void *cls, const GNUNET_HashCode * key, void *value)
1465{
1466 struct MeshPeerInfo *pi = cls;
1467 struct GNUNET_TIME_Absolute threshold;
1468 struct GNUNET_PeerIdentity id;
1469
1470 threshold = GNUNET_TIME_absolute_subtract(GNUNET_TIME_absolute_get(),
1471 REFRESH_PATH_TIME);
1472
1473 if (pi->last_contact.abs_value < threshold.abs_value) {
1474 GNUNET_PEER_resolve(pi->path->peers[1], &id);
1475 GNUNET_CORE_notify_transmit_ready(core_handle,
1476 0,
1477 0,
1478 GNUNET_TIME_UNIT_FOREVER_REL,
1479 &id,
1480 sizeof(struct GNUNET_MESH_ManipulatePath)
1481 + (pi->path->length
1482 * sizeof (struct GNUNET_PeerIdentity)),
1483 &send_core_create_path_for_peer,
1484 pi);
1485 }
1486 return GNUNET_YES;
1487}
1488
1489
1490/**
1491 * Send keepalive packets for all routes
1492 *
1493 * @param cls unused
1494 * @param tc unused
1495 */
1496static void
1497path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1498{
1499 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
1500 GNUNET_CONTAINER_multihashmap_iterate(peers, path_refresh_peer, NULL);
1501 GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME,
1502 &path_refresh,
1503 NULL);
1417 return; 1504 return;
1418} 1505}
1419 1506
1507
1420/******************************************************************************/ 1508/******************************************************************************/
1421/************************ MAIN FUNCTIONS ****************************/ 1509/************************ MAIN FUNCTIONS ****************************/
1422/******************************************************************************/ 1510/******************************************************************************/
@@ -1431,7 +1519,7 @@ static void
1431shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1519shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1432{ 1520{
1433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1434 "MESH shutting down\n"); 1522 "shutting down\n");
1435 if (core_handle != NULL) { 1523 if (core_handle != NULL) {
1436 GNUNET_CORE_disconnect (core_handle); 1524 GNUNET_CORE_disconnect (core_handle);
1437 core_handle = NULL; 1525 core_handle = NULL;
@@ -1439,7 +1527,9 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1439 if (dht_handle != NULL) { 1527 if (dht_handle != NULL) {
1440 GNUNET_DHT_disconnect (dht_handle); 1528 GNUNET_DHT_disconnect (dht_handle);
1441 dht_handle = NULL; 1529 dht_handle = NULL;
1442 } 1530 }
1531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1532 "shut down\n");
1443} 1533}
1444 1534
1445/** 1535/**
@@ -1455,11 +1545,11 @@ run (void *cls,
1455 const struct GNUNET_CONFIGURATION_Handle *c) 1545 const struct GNUNET_CONFIGURATION_Handle *c)
1456{ 1546{
1457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1458 "MESH starting to run\n"); 1548 "starting to run\n");
1459 GNUNET_SERVER_add_handlers (server, plugin_handlers); 1549 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1460 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); 1550 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1461 core_handle = GNUNET_CORE_connect (c, /* Main configuration */ 1551 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1462 32, /* queue size */ 1552 1, /* queue size */
1463 NULL, /* Closure passed to MESH functions */ 1553 NULL, /* Closure passed to MESH functions */
1464 &core_init, /* Call core_init once connected */ 1554 &core_init, /* Call core_init once connected */
1465 &core_connect, /* Handle connects */ 1555 &core_connect, /* Handle connects */
@@ -1481,11 +1571,20 @@ run (void *cls,
1481 1571
1482 tunnels = GNUNET_CONTAINER_multihashmap_create(32); 1572 tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1483 peers = GNUNET_CONTAINER_multihashmap_create(32); 1573 peers = GNUNET_CONTAINER_multihashmap_create(32);
1574 clients = NULL;
1575 clients_t = NULL;
1576
1577 /* Path keepalive */
1578 GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME,
1579 &path_refresh,
1580 NULL);
1484 1581
1485 /* Scheduled the task to clean up when shutdown is called */ 1582 /* Scheduled the task to clean up when shutdown is called */
1486 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 1583 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1487 &shutdown_task, NULL); 1584 &shutdown_task, NULL);
1488 1585
1586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1587 "end if run()\n");
1489} 1588}
1490 1589
1491/** 1590/**
@@ -1506,5 +1605,7 @@ main (int argc, char *const *argv)
1506 "mesh", 1605 "mesh",
1507 GNUNET_SERVICE_OPTION_NONE, 1606 GNUNET_SERVICE_OPTION_NONE,
1508 &run, NULL)) ? 0 : 1; 1607 &run, NULL)) ? 0 : 1;
1608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1609 "end of main()\n");
1509 return ret; 1610 return ret;
1510} 1611}
diff --git a/src/mesh/test_mesh_api.c b/src/mesh/test_mesh_api.c
index c2a03d3b5..08a3b1c3c 100644
--- a/src/mesh/test_mesh_api.c
+++ b/src/mesh/test_mesh_api.c
@@ -29,6 +29,9 @@
29#include "gnunet_dht_service.h" 29#include "gnunet_dht_service.h"
30#include "gnunet_mesh_service_new.h" 30#include "gnunet_mesh_service_new.h"
31 31
32#define VERBOSE 1
33#define VERBOSE_ARM 0
34
32static struct GNUNET_MESH_MessageHandler handlers[] = {{NULL, 0, 0}}; 35static struct GNUNET_MESH_MessageHandler handlers[] = {{NULL, 0, 0}};
33static struct GNUNET_OS_Process *arm_pid; 36static struct GNUNET_OS_Process *arm_pid;
34static struct GNUNET_MESH_Handle *mesh; 37static struct GNUNET_MESH_Handle *mesh;
@@ -94,7 +97,9 @@ run (void *cls,
94 arm_pid = GNUNET_OS_start_process (NULL, NULL, 97 arm_pid = GNUNET_OS_start_process (NULL, NULL,
95 "gnunet-service-arm", 98 "gnunet-service-arm",
96 "gnunet-service-arm", 99 "gnunet-service-arm",
100#if VERBOSE_ARM
97 "-L", "DEBUG", 101 "-L", "DEBUG",
102#endif
98 "-c", "test_mesh.conf", 103 "-c", "test_mesh.conf",
99 NULL); 104 NULL);
100 105
@@ -116,25 +121,33 @@ main (int argc, char *argv[])
116 int ret; 121 int ret;
117 char *const argv2[] = {"test-mesh-api", 122 char *const argv2[] = {"test-mesh-api",
118 "-c", "test_mesh.conf", 123 "-c", "test_mesh.conf",
124#if VERBOSE
119 "-L", "DEBUG", 125 "-L", "DEBUG",
126#endif
120 NULL 127 NULL
121 }; 128 };
122 struct GNUNET_GETOPT_CommandLineOption options[] = { 129 struct GNUNET_GETOPT_CommandLineOption options[] = {
123 GNUNET_GETOPT_OPTION_END 130 GNUNET_GETOPT_OPTION_END
124 }; 131 };
125 GNUNET_log_setup ("test-dht-api","DEBUG", NULL); 132 GNUNET_log_setup ("test-mesh-api",
133#if VERBOSE
134 "DEBUG",
135#else
136 "WARNING",
137#endif
138 NULL);
126 ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, 139 ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1,
127 argv2, "test-mesh-api", "nohelp", 140 argv2, "test-mesh-api", "nohelp",
128 options, &run, NULL); 141 options, &run, NULL);
129 142
130 if ( GNUNET_OK != ret ) { 143 if ( GNUNET_OK != ret ) {
131 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 144 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
132 "test-mesh-api': run failed with error code %d\n", ret); 145 "run failed with error code %d\n", ret);
133 return 1; 146 return 1;
134 } 147 }
135 if ( GNUNET_SYSERR == result ) { 148 if ( GNUNET_SYSERR == result ) {
136 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 149 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
137 "test-mesh-api': test failed\n"); 150 "test failed\n");
138 return 1; 151 return 1;
139 } 152 }
140 return 0; 153 return 0;