X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Fgnunet-service-mesh.c;h=df4f39eedb11e99d0eefb58212093ed010a06136;hb=0b81657b642457b7e15414ded2f66b33ce6835c2;hp=f27291cb6386ef63a4734578a2082aa80fa7e324;hpb=3863fcf57b835f52b641ca5cf7e7dacc0c73b97f;p=oweals%2Fgnunet.git diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index f27291cb6..df4f39eed 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c @@ -371,7 +371,7 @@ get_peer_info (const struct GNUNET_PeerIdentity *peer) } /** - * find the first peer whom to send a packet to go down this path + * 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 @@ -396,10 +396,66 @@ get_first_hop (struct MeshPath *path) 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; } @@ -458,7 +514,7 @@ retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid) } -#if LATER + /** * Search for a tunnel by global ID using full PeerIdentities * @param oid owner of the tunnel @@ -483,7 +539,7 @@ retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) * @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); @@ -491,7 +547,7 @@ destroy_path(struct MeshTunnel *t, struct MeshPath *p) return GNUNET_OK; } - +#if LATER /** * Destroy the peer_info and free any allocated resources linked to it * @param t tunnel the path belongs to @@ -522,14 +578,17 @@ destroy_peer_info(struct MeshPeerInfo *pi) * @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 MeshClient *c; + GNUNET_HashCode hash; + int r; if (NULL == t) return GNUNET_OK; + c = t->client; + GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash); if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) { r = GNUNET_SYSERR; @@ -667,11 +726,98 @@ handle_mesh_path_create (void *cls, 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; } @@ -730,7 +876,7 @@ static struct GNUNET_CORE_MessageHandler core_handlers[] = { 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; }