* STRUCTURE:
* - DATA STRUCTURES
* - GLOBAL VARIABLES
+ * - MESH NETWORK HANDLER HELPERS
* - MESH NETWORK HANDLES
+ * - MESH LOCAL HANDLER HELPERS
* - MESH LOCAL HANDLES
+ * - PERIODIC FUNCTIONS
* - MAIN FUNCTIONS (main & run)
*
* TODO:
- * - soft stateing (keep-alive (CHANGE?) / timeout / disconnect) -- not a message issue
* - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
* - partial disconnect reporting -- same as error reporting?
* - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
* - speed requirement specification (change?) in mesh API -- API call
+ * - add ping message (connection confirmation, others?)
*/
#include "platform.h"
#include "mesh_protocol.h"
#include "gnunet_dht_service.h"
+#define REFRESH_PATH_TIME GNUNET_TIME_relative_multiply(\
+ GNUNET_TIME_UNIT_SECONDS,\
+ 300)
+
/******************************************************************************/
/************************ DATA STRUCTURES ****************************/
/******************************************************************************/
+/**
+ * Information regarding a path
+ */
+struct MeshPath
+{
+
+ /**
+ * Linked list
+ */
+ struct MeshPath *next;
+ struct MeshPath *prev;
+
+ /**
+ * Whether the path is serving traffic in a tunnel or is a backup
+ */
+ int in_use;
+
+ /**
+ * List of all the peers that form the path from origin to target
+ */
+ GNUNET_PEER_Id *peers;
+
+ /**
+ * Number of peers (hops) in the path
+ */
+ unsigned int length;
+};
+
+
/**
* All the states a peer participating in a tunnel can be in.
*/
MESH_PEER_RECONNECTING
};
+
/**
* Struct containing all information regarding a given peer
*/
enum MeshPeerState state;
/**
- * When to try to establish contact again?
+ * Last time we heard from this peer
*/
- struct GNUNET_TIME_Absolute next_reconnect_attempt;
+ struct GNUNET_TIME_Absolute last_contact;
/**
* Number of attempts to reconnect so far
int n_reconnect_attempts;
/**
- * First hop whom to send data to reach this peer in the current active path
+ * Paths to reach the peer
*/
- GNUNET_PEER_Id first_hop;
+ struct MeshPath *path;
+ struct MeshPath *path_tail;
/**
* Handle to stop the DHT search for a path to this peer
};
-typedef uint32_t MESH_PathID;
-
-
-/**
- * Information regarding a path
- */
-struct MeshPath
-{
- /**
- * Double linked list
- */
- struct MeshPath *next;
- struct MeshPath *prev;
-
- /**
- * Id of the path, in case it's needed
- */
- MESH_PathID id;
-
- /**
- * Whether the path is serving traffic in a tunnel or is a backup
- */
- int in_use;
-
- /**
- * List of all the peers that form the path from origin to target
- */
- GNUNET_PEER_Id *peers;
-
- /**
- * Number of peers (hops) in the path
- */
- int length;
-};
-
/**
* Data scheduled to transmit (to local client or remote peer)
*/
struct GNUNET_TIME_Absolute timestamp;
/**
- * Peers in the tunnel, for future optimizations
+ * Peers in the tunnelindexed by PeerIdentity (MeshPeerInfo)
*/
struct GNUNET_CONTAINER_MultiHashMap* peers;
*/
unsigned int peers_total;
- /**
- * Paths (used and backup)
- */
- struct MeshPath *paths_head;
- struct MeshPath *paths_tail;
/**
* Client owner of the tunnel, if any
* Linked list
*/
struct MeshClient *next;
+ struct MeshClient *prev;
/**
* Tunnels that belong to this client, indexed by local id
* All the clients
*/
static struct MeshClient *clients;
+static struct MeshClient *clients_tail;
/**
- * Tunnels known, indexed by MESH_TunnelID
+ * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
*/
struct GNUNET_CONTAINER_MultiHashMap *tunnels;
+/**
+ * Peers known, indexed by PeerIdentity (MeshPeerInfo)
+ */
+struct GNUNET_CONTAINER_MultiHashMap *peers;
+
/**
* Handle to communicate with core
*/
static GNUNET_PEER_Id myid;
/**
- * Tunnel ID for the next created tunnel
+ * Tunnel ID for the next created tunnel (global tunnel number)
*/
static MESH_TunnelNumber next_tid;
/****************** GENERAL HELPER FUNCTIONS ************************/
/******************************************************************************/
+/**
+ * Retrieve the MeshPeerInfo stucture associated with the peer, create one
+ * and inster it in the appropiate structures if the peer is not known yet.
+ * @param peer Identity of the peer
+ * @return Existing or newly created peer info
+ */
+static struct MeshPeerInfo *
+get_peer_info (const struct GNUNET_PeerIdentity *peer)
+{
+ struct MeshPeerInfo * peer_info;
+
+ peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
+ &peer->hashPubKey);
+ if (NULL == peer_info) {
+ peer_info = (struct MeshPeerInfo *)
+ GNUNET_malloc(sizeof(struct MeshPeerInfo));
+ GNUNET_CONTAINER_multihashmap_put(peers,
+ &peer->hashPubKey,
+ peer_info,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+ peer_info->id = GNUNET_PEER_intern(peer);
+ peer_info->state = MESH_PEER_SEARCHING;
+ }
+
+ return peer_info;
+}
+
+/**
+ * Find the first peer whom to send a packet to go down this path
+ * @param path The path to use
+ * @return short id of the next peer, myid in case of local delivery,
+ * or 0 in case of error
+ */
+static GNUNET_PEER_Id
+get_first_hop (struct MeshPath *path)
+{
+ unsigned int i;
+
+ if (NULL == path) return 0;
+ if (path->in_use == 0) return 0;
+
+ for (i = 0; i < path->length; i++) {
+ if (path->peers[i] == myid) {
+ if (i < path->length - 1) {
+ return path->peers[i+1];
+ } else {
+ return myid;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * Get the cost of the path.
+ * @param path The path to analyze
+ * @return Number of hops to reach destination, UINT_MAX in case the peer is not
+ * in the path
+ */
+static unsigned int
+get_path_cost(struct MeshPath *path)
+{
+ unsigned int i;
+
+ if (NULL == path) return UINT_MAX;
+ for (i = 0; i < path->length; i++) {
+ if (path->peers[i] == myid) {
+ return path->length - i;
+ }
+ }
+ return UINT_MAX;
+}
+
+
+/**
+ * Add the path to the peer and update the path used to reach it in case this
+ * is the shortest.
+ * @param peer_info Destination peer to add the path to.
+ * @param path New path to add. Last peer must be the peer in arg 1.
+ */
+static void
+add_path_to_peer(struct MeshPeerInfo *peer_info, struct MeshPath *path)
+{
+ unsigned int i;
+ unsigned int new_cost;
+ unsigned int best_cost;
+ struct MeshPath *aux;
+ struct MeshPath *best;
+
+ if (NULL == peer_info || NULL == path) return;
+
+ new_cost = get_path_cost(path);
+ best_cost = UINT_MAX;
+ best = NULL;
+ for (aux = peer_info->path; aux != NULL; aux = aux->next) {
+ if ((i = get_path_cost(aux)) < best_cost) {
+ best = aux;
+ best_cost = i;
+ }
+ }
+ if (best_cost < new_cost) {
+ path->in_use = 0;
+ GNUNET_CONTAINER_DLL_insert_tail(peer_info->path,
+ peer_info->path_tail,
+ path);
+ } else {
+ if (NULL != best) best->in_use = 0;
+ path->in_use = 1;
+ GNUNET_CONTAINER_DLL_insert(peer_info->path,
+ peer_info->path_tail,
+ path);
+ }
+ return;
+}
+
+
/**
* Check if client has registered with the service and has not disconnected
* @param client the client to check
return NULL;
}
+
/**
* Search for a tunnel among the tunnels for a client
* @param client the client whose tunnels to search in
return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
}
-#if LATER
/**
- * Search for a tunnel by global ID
+ * Search for a tunnel by global ID using PEER_ID
+ * @param pi owner of the tunnel
+ * @param tid global tunnel number
+ * @return tunnel handler, NULL if doesn't exist
*/
static struct MeshTunnel *
-retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
+retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
{
struct MESH_TunnelID id;
GNUNET_HashCode hash;
- id.oid = GNUNET_PEER_intern(oid);
- GNUNET_PEER_change_rc(id.oid, -1);
+ id.oid = pi;
id.tid = tid;
GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
}
-#endif
+
+
+
+/**
+ * Search for a tunnel by global ID using full PeerIdentities
+ * @param oid owner of the tunnel
+ * @param tid global tunnel number
+ * @return tunnel handler, NULL if doesn't exist
+ */
+static struct MeshTunnel *
+retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
+{
+ GNUNET_PEER_Id pi;
+
+ pi = GNUNET_PEER_intern(oid);
+ GNUNET_PEER_change_rc(pi, -1);
+ return retrieve_tunnel_by_pi(pi, tid);
+}
+
/**
* Destroy the path and free any allocated resources linked to it
* @return GNUNET_OK on success
*/
static int
-destroy_path(struct MeshTunnel *t, struct MeshPath *p)
+destroy_path(struct MeshPath *p)
{
GNUNET_PEER_decrement_rcs(p->peers, p->length);
GNUNET_free(p->peers);
- GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
GNUNET_free(p);
return GNUNET_OK;
}
* @return GNUNET_OK on success
*/
static int
-destroy_peer_info(struct MeshTunnel *t, struct MeshPeerInfo *pi)
+destroy_peer_info(struct MeshPeerInfo *pi)
{
+ GNUNET_HashCode hash;
+ struct GNUNET_PeerIdentity id;
+
+ GNUNET_PEER_resolve(pi->id, &id);
GNUNET_PEER_change_rc(pi->id, -1);
- /* FIXME delete from list */
+ GNUNET_CRYPTO_hash(&id, sizeof(struct GNUNET_PeerIdentity), &hash);
+
+ GNUNET_CONTAINER_multihashmap_remove(peers, &hash, pi);
GNUNET_free(pi);
return GNUNET_OK;
}
#endif
+
/**
* Destroy the tunnel and free any allocated resources linked to it
* @param c client the tunnel belongs to
* @return GNUNET_OK on success
*/
static int
-destroy_tunnel(struct MeshClient *c, struct MeshTunnel *t)
+destroy_tunnel(struct MeshTunnel *t)
{
- struct MeshPath *path;
- GNUNET_HashCode hash;
- int r;
+// struct MeshPath *path;
+ struct MeshClient *c;
+ GNUNET_HashCode hash;
+ int r;
if (NULL == t) return GNUNET_OK;
- for (path = t->paths_head; path != NULL; path = t->paths_head) {
- if(GNUNET_OK != destroy_path(t, path)) r = GNUNET_SYSERR;
- }
+ c = t->client;
GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
}
/******************************************************************************/
-/******************** MESH NETWORK HANDLERS **************************/
+/**************** MESH NETWORK HANDLER HELPERS ***********************/
/******************************************************************************/
/**
- * FIXME: rewrite
* Function called to notify a client about the socket
* being ready to queue more data. "buf" will be
* NULL and "size" zero if the socket was closed for
static size_t
send_core_create_path_for_peer (void *cls, size_t size, void *buf)
{
- size_t size_needed;
- struct MeshPeerInfo *peer_info;
+ struct MeshPeerInfo *peer_info = cls;
struct GNUNET_MESH_ManipulatePath *msg;
struct MeshPath *p;
- struct GNUNET_PeerIdentity peer_id;
struct GNUNET_PeerIdentity *peer_ptr;
+ struct GNUNET_PeerIdentity id;
+ size_t size_needed;
int i;
if (0 == size && NULL == buf) {
- // TODO retry? cancel?
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
+ GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
+ GNUNET_CORE_notify_transmit_ready(core_handle,
+ 0,
+ 0,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &id,
+ sizeof(struct GNUNET_MESH_ManipulatePath)
+ + (peer_info->path->length
+ * sizeof (struct GNUNET_PeerIdentity)),
+ &send_core_create_path_for_peer,
+ peer_info);
return 0;
}
- peer_info = (struct MeshPeerInfo *)cls;
- peer_info->dhtget = NULL;
-// p = peer_info->t->paths_head;
+ p = peer_info->path;
while (NULL != p) {
- if (p->peers[p->length-1] == peer_info->id) {
+ if (p->in_use) {
break;
}
p = p->next;
}
msg = (struct GNUNET_MESH_ManipulatePath *) buf;
- msg->header.size = htons(sizeof(struct GNUNET_MESH_ManipulatePath));
+ msg->header.size = htons(size_needed);
msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
- msg->speed_min = 0;
peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
for (i = 0; i < p->length; i++) {
- GNUNET_PEER_resolve(p->peers[i], &peer_id);
- memcpy(&peer_ptr[i], &peer_id, sizeof(struct GNUNET_PeerIdentity));
+ GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
}
- peer_info->state = MESH_PEER_WAITING;
+ peer_info->state = MESH_PEER_WAITING; // TODO maybe already ready?
return size_needed;
}
-
+#if LATER
/**
* Send another peer a notification to destroy a tunnel
* @param cls The tunnel to destroy
destroy_tunnel(c, t);
return sizeof(struct GNUNET_MESH_TunnelMessage);
}
+#endif
+
+
+/******************************************************************************/
+/******************** MESH NETWORK HANDLERS **************************/
+/******************************************************************************/
/**
const struct GNUNET_TRANSPORT_ATS_Information
*atsi)
{
- /* Extract path */
- /* Find origin & self */
- /* Search for origin in local tunnels */
- /* Create tunnel / add path */
- /* Retransmit to next link in chain, if any (core_notify + callback) */
+ unsigned int own_pos;
+ uint16_t size;
+ uint16_t i;
+ MESH_TunnelNumber tid;
+ struct GNUNET_MESH_ManipulatePath *msg;
+ struct GNUNET_PeerIdentity *pi;
+ GNUNET_HashCode hash;
+ struct MeshPath *path;
+ struct MeshPeerInfo *peer_info;
+ struct MeshTunnel *t;
+
+
+ size = ntohs(message->size);
+ if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+ "received create path message too short\n");
+ return GNUNET_OK;
+ }
+
+ size -= sizeof(struct GNUNET_MESH_ManipulatePath);
+ if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+ "create path message lacks enough peers\n");
+ return GNUNET_OK;
+ }
+ if (size % sizeof(struct GNUNET_PeerIdentity)) {
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+ "create path message of wrong size\n");
+ return GNUNET_OK;
+ }
+ msg = (struct GNUNET_MESH_ManipulatePath *) message;
+ size /= sizeof(struct GNUNET_PeerIdentity);
+
+ tid = ntohl(msg->tid);
+ pi = (struct GNUNET_PeerIdentity *) &msg[1];
+ t = retrieve_tunnel(pi, tid);
+
+ if (NULL == t) {
+ t = GNUNET_malloc(sizeof(struct MeshTunnel));
+ t->id.oid = GNUNET_PEER_intern(pi);
+ t->id.tid = tid;
+ t->local_tid = 0;
+ t->client = NULL;
+ t->peers = GNUNET_CONTAINER_multihashmap_create(32);
+
+ GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
+ if (GNUNET_OK !=
+ GNUNET_CONTAINER_multihashmap_put(tunnels,
+ &hash,
+ t,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+ "create path: could not store tunnel in hashmap\n");
+ return GNUNET_OK;
+ }
+
+ }
+ peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
+ &pi[size - 1].hashPubKey);
+ if (NULL == peer_info) {
+ peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
+ peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
+ peer_info->state = MESH_PEER_WAITING;
+ GNUNET_CONTAINER_multihashmap_put(peers,
+ &pi[size - 1].hashPubKey,
+ peer_info,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+ }
+
+ path = GNUNET_malloc(sizeof(struct MeshPath));
+ path->length = size;
+ path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
+ own_pos = 0;
+ for (i = 0; i < size; i++) {
+ path->peers[i] = GNUNET_PEER_intern(&pi[i]);
+ if (path->peers[i] == myid) own_pos = i;
+ }
+ if (own_pos == 0) { /* cannot be self, must be 'not found' */
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+ "create path: self not found in path through self\n");
+ destroy_path(path);
+ /* FIXME destroy tunnel? leave for timeout? */
+ return 0;
+ }
+ if (own_pos == size - 1) { /* it is for us! */
+ destroy_path(path); /* not needed anymore */
+ /* TODO: send ack? new meesage type? */
+ } else {
+ add_path_to_peer(peer_info, path);
+ /* TODO: Retransmit to next link in chain, if any (core_notify + callback) */
+ }
return GNUNET_OK;
}
/******************************************************************************/
-/********************* MESH LOCAL HANDLES **************************/
+/**************** MESH LOCAL HANDLER HELPERS ***********************/
/******************************************************************************/
+/**
+ * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
+ * client when the client disconnects.
+ * @param cls closure (client that is disconnecting)
+ * @param key the hash of the local tunnel id (used to access the hashmap)
+ * @param value the value stored at the key (tunnel to destroy)
+ * @return GNUNET_OK on success
+ */
static int
delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
int r;
- r = destroy_tunnel((struct MeshClient *) cls, (struct MeshTunnel *) value);
+ r = destroy_tunnel((struct MeshTunnel *) value);
return r;
}
+#if LATER
/**
* notify_client_connection_failure: notify a client that the connection to the
* requested remote peer is not possible (for instance, no route found)
- * Function called when the socket is ready to queue more data."buf" will be
+ * Function called when the socket is ready to queue more data. "buf" will be
* NULL and "size" zero if the socket was closed for writing in the meantime.
*
* @param cls closure
return size_needed;
}
+#endif
+
+
+/**
+ * Send keepalive packets for a peer
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct MeshPeerInfo *peer_info = cls;
+ struct GNUNET_PeerIdentity id;
+
+ if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
+ GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
+ GNUNET_CORE_notify_transmit_ready(core_handle,
+ 0,
+ 0,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &id,
+ sizeof(struct GNUNET_MESH_ManipulatePath)
+ + (peer_info->path->length
+ * sizeof (struct GNUNET_PeerIdentity)),
+ &send_core_create_path_for_peer,
+ peer_info);
+
+ return;
+}
/**
- * FIXME: rewrite
* Function to process paths received for a new peer addition. The recorded
* paths form the initial tunnel, which can be optimized later.
* Called on each result obtained for the DHT search.
size_t size,
const void *data)
{
- struct MeshPeerInfo *peer_info;
- struct MeshTunnel *t;
+ struct MeshPeerInfo *peer_info = cls;
struct MeshPath *p;
+ struct GNUNET_PeerIdentity pi;
int i;
- peer_info = (struct MeshPeerInfo *)cls;
-// t = peer_info->t;
- t = NULL; // FIXME
-
- if (NULL == get_path || NULL == put_path) {
- // TODO: find ourselves some alternate initial path to the destination
- GNUNET_SERVER_notify_transmit_ready(
- t->client->handle,
- sizeof(struct GNUNET_MESH_PeerControl),
- GNUNET_TIME_UNIT_FOREVER_REL,
- ¬ify_client_connection_failure,
- peer_info
- );
+ if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
+ // Find ourselves some alternate initial path to the destination: retry
+ GNUNET_DHT_get_stop(peer_info->dhtget);
+ GNUNET_PEER_resolve(peer_info->id, &pi);
+ peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_BLOCK_TYPE_ANY,
+ &pi.hashPubKey,
+ 4, /* replication level */
+ GNUNET_DHT_RO_RECORD_ROUTE,
+ NULL, /* bloom filter */
+ 0, /* mutator */
+ NULL, /* xquery */
+ 0, /* xquery bits */
+ dht_get_response_handler,
+ (void *)peer_info);
}
p = GNUNET_malloc(sizeof(struct MeshPath));
- GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
for (i = 0; get_path[i] != NULL; i++);
for (i--; i >= 0; i--) {
p->peers = GNUNET_realloc(p->peers,
p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
p->length++;
}
- // p->id = 0; // FIXME generate ID or remove field
- p->in_use = 0;
- // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
+ add_path_to_peer(peer_info, p);
GNUNET_CORE_notify_transmit_ready(core_handle,
0,
0,
* sizeof (struct GNUNET_PeerIdentity)),
&send_core_create_path_for_peer,
peer_info);
+ GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
return;
}
+/******************************************************************************/
+/********************* MESH LOCAL HANDLES **************************/
+/******************************************************************************/
+
+
/**
* Handler for client disconnection
*
struct MeshClient *next;
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "MESH: client disconnected\n");
+ "client disconnected\n");
c = clients;
while (NULL != c) {
if (c->handle == client) {
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "MESH: matching client found, cleaning\n");
+ " matching client found, cleaning\n");
GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
&delete_tunnel_entry,
c);
GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
if(0 != c->app_counter) GNUNET_free (c->apps);
if(0 != c->type_counter) GNUNET_free (c->types);
+ GNUNET_CONTAINER_DLL_remove(clients, clients_tail, c);
next = c->next;
GNUNET_free (c);
c = next;
} else {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ " ... searching\n");
c = c->next;
}
}
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ " done!\n");
return;
}
{
struct GNUNET_MESH_ClientConnect *cc_msg;
struct MeshClient *c;
- unsigned int payload_size;
+ unsigned int size;
uint16_t types;
uint16_t apps;
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "MESH: new client connected\n");
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
/* Check data sanity */
- payload_size = ntohs(message->size)
- - sizeof(struct GNUNET_MESH_ClientConnect);
+ size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
types = ntohs(cc_msg->types);
apps = ntohs(cc_msg->applications);
- if (payload_size !=
+ if (size !=
types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
{
GNUNET_break(0);
apps * sizeof(GNUNET_MESH_ApplicationType));
}
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "MESH: client has %u+%u subscriptions\n",
+ " client has %u+%u subscriptions\n",
c->type_counter,
c->app_counter);
- /* Insert new client in DLL */
- /* FIXME insert client */
- c->tunnels = GNUNET_CONTAINER_multihashmap_create(100);
+ GNUNET_CONTAINER_DLL_insert(clients, clients_tail, c);
+ c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
GNUNET_SERVER_receive_done(client, GNUNET_OK);
GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
return;
}
- t = GNUNET_malloc(sizeof(struct MeshTunnel ));
- // FIXME:what if all 2^32 ID are taken?
- while (NULL != retrieve_tunnel_by_local_id(c, next_tid)) next_tid++;
+
+ t = GNUNET_malloc(sizeof(struct MeshTunnel));
+ while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
+ next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
t->id.tid = next_tid++;
t->id.oid = myid;
t->local_tid = ntohl(t_msg->tunnel_id);
t->client = c;
+ t->peers = GNUNET_CONTAINER_multihashmap_create(32);
GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
if (GNUNET_OK !=
return;
}
- /* FIXME insert */
+ GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
+ if (GNUNET_OK !=
+ GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+ {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
GNUNET_SERVER_receive_done(client, GNUNET_OK);
return;
/* Retrieve tunnel */
tid = ntohl(tunnel_msg->tunnel_id);
+
+ /* Remove from local id hashmap */
GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
- GNUNET_CONTAINER_multihashmap_remove_all(c->tunnels, &hash);
- GNUNET_CORE_notify_transmit_ready(core_handle,
- 1,
- 1,
- GNUNET_TIME_UNIT_FOREVER_REL,
- NULL,
- sizeof(struct GNUNET_MESH_TunnelMessage),
- &send_p2p_tunnel_destroy,
- t);
+ GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
+ /* Remove from global id hashmap */
+ GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
+ GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
+
+// notify_tunnel_destroy(t);
GNUNET_SERVER_receive_done(client, GNUNET_OK);
return;
}
struct MeshTunnel *t;
MESH_TunnelNumber tid;
struct MeshPeerInfo *peer_info;
- GNUNET_HashCode key;
/* Sanity check for client registration */
peer_msg = (struct GNUNET_MESH_PeerControl *)message;
/* Sanity check for message size */
- if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
+ if (sizeof(struct GNUNET_MESH_PeerControl)
+ != ntohs(peer_msg->header.size))
+ {
GNUNET_break(0);
GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
return;
return;
}
- /* Ok, add peer to tunnel */
- peer_info = (struct MeshPeerInfo *) GNUNET_malloc(sizeof(struct MeshPeerInfo));
- peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
- peer_info->state = MESH_PEER_SEARCHING;
t->peers_total++;
- /* FIXME insert */
- /* Start DHT search */
- GNUNET_CRYPTO_hash (&peer_msg->peer,
- sizeof(struct GNUNET_PeerIdentity),
- &key);
- peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
+ peer_info = get_peer_info(&peer_msg->peer);
+
+ /* Start DHT search if needed */
+ if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
+ peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
GNUNET_TIME_UNIT_FOREVER_REL,
GNUNET_BLOCK_TYPE_ANY,
- &key,
+ &peer_msg->peer.hashPubKey,
4, /* replication level */
GNUNET_DHT_RO_RECORD_ROUTE,
NULL, /* bloom filter */
0, /* xquery bits */
dht_get_response_handler,
(void *)peer_info);
+ }
GNUNET_SERVER_receive_done(client, GNUNET_OK);
return;
struct GNUNET_MESH_PeerControl *peer_msg;
struct MeshClient *c;
struct MeshTunnel *t;
- struct MeshPath *p;
- struct MeshPath *aux_path;
MESH_TunnelNumber tid;
GNUNET_PEER_Id peer_id;
}
peer_msg = (struct GNUNET_MESH_PeerControl *)message;
/* Sanity check for message size */
- if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
+ if (sizeof(struct GNUNET_MESH_PeerControl)
+ != ntohs(peer_msg->header.size))
+ {
GNUNET_break(0);
GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
return;
/* Ok, delete peer from tunnel */
peer_id = GNUNET_PEER_intern(&peer_msg->peer);
- /* Delete paths */
- p = t->paths_head;
- while (p != NULL) {
- if (p->peers[p->length-1] == peer_id) { /* one path per destination */
- GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
- GNUNET_PEER_decrement_rcs(p->peers, p->length);
- aux_path = p;
- p = p->next;
- GNUNET_free(aux_path);
- } else {
- p = p->next;
- }
- }
-
+ /* FIXME Delete paths */
/* FIXME Delete peer info */
GNUNET_PEER_change_rc(peer_id, -1);
}
data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
/* Sanity check for message size */
- if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
+ if (sizeof(struct GNUNET_MESH_PeerControl)
+ != ntohs(data_msg->header.size))
+ {
GNUNET_break(0);
GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
return;
const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_TRANSPORT_ATS_Information *atsi)
{
- GNUNET_PEER_Id pid;
+// GNUNET_PEER_Id pid;
+ struct MeshPeerInfo *peer_info;
+ struct MeshPath *path;
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Peer connected\n");
- pid = GNUNET_PEER_intern(peer);
- if (myid == pid) {
+ peer_info = get_peer_info(peer);
+ if (myid == peer_info->id) {
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
" (self)\n");
}
+ path = GNUNET_malloc(sizeof(struct MeshPath));
+ path->length = 2;
+ path->peers = GNUNET_malloc(sizeof(GNUNET_PEER_Id) * 2);
+ path->peers[0] = myid;
+ path->peers[1] = peer_info->id;
+ add_path_to_peer(peer_info, path);
return;
}
const struct
GNUNET_PeerIdentity *peer)
{
+ GNUNET_PEER_Id pid;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Peer disconnected\n");
+ pid = GNUNET_PEER_intern(peer);
+ GNUNET_PEER_change_rc(pid, -1);
+ if (myid == pid) {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " (self)\n");
+ }
return;
}
+
/******************************************************************************/
/************************ MAIN FUNCTIONS ****************************/
/******************************************************************************/
shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "MESH shutting down\n");
+ "shutting down\n");
if (core_handle != NULL) {
GNUNET_CORE_disconnect (core_handle);
core_handle = NULL;
if (dht_handle != NULL) {
GNUNET_DHT_disconnect (dht_handle);
dht_handle = NULL;
- }
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "shut down\n");
}
/**
const struct GNUNET_CONFIGURATION_Handle *c)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "MESH starting to run\n");
+ "starting to run\n");
GNUNET_SERVER_add_handlers (server, plugin_handlers);
GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
core_handle = GNUNET_CORE_connect (c, /* Main configuration */
- 32, /* queue size */
+ 1, /* queue size */
NULL, /* Closure passed to MESH functions */
&core_init, /* Call core_init once connected */
&core_connect, /* Handle connects */
if (core_handle == NULL) {
GNUNET_break(0);
}
- dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
+ dht_handle = GNUNET_DHT_connect(c, 64);
if (dht_handle == NULL) {
GNUNET_break(0);
}
next_tid = 0;
+ tunnels = GNUNET_CONTAINER_multihashmap_create(32);
+ peers = GNUNET_CONTAINER_multihashmap_create(32);
+ clients = NULL;
+ clients_tail = NULL;
+
/* Scheduled the task to clean up when shutdown is called */
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
&shutdown_task, NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "end if run()\n");
}
/**
"mesh",
GNUNET_SERVICE_OPTION_NONE,
&run, NULL)) ? 0 : 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "end of main()\n");
return ret;
}