struct MeshPeerPath *p,
unsigned int own_pos)
{
+ struct GNUNET_PeerIdentity id;
+
GNUNET_assert (0 != own_pos);
tree_add_path(t->tree, p, NULL);
if (NULL == t->tree->me)
t->tree->me = tree_find_peer(t->tree->root, p->peers[own_pos]);
+ GNUNET_PEER_resolve (p->peers[own_pos + 1], &id);
+ tree_update_first_hops(t->tree, t->tree->me, &id);
}
{
struct GNUNET_MESH_Unicast *msg;
struct MeshTunnel *t;
- struct MeshPeerInfo *pi;
+ GNUNET_PEER_Id pid;
size_t size;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "MESH: got a unicast packet from %s\n",
+ GNUNET_i2s (peer));
size = ntohs (message->size);
if (size <
sizeof (struct GNUNET_MESH_Unicast) +
GNUNET_break_op (0);
return GNUNET_OK;
}
- pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
- &msg->destination.hashPubKey);
- if (NULL == pi)
- {
- /* TODO maybe feedback, log to statistics */
- GNUNET_break_op (0);
- return GNUNET_OK;
- }
- if (pi->id == myid)
+ pid = GNUNET_PEER_search(&msg->destination);
+ if (pid == myid)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "MESH: it's for us! sending to clients...\n");
send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
return GNUNET_OK;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "MESH: not for us, retransmitting...\n");
msg = GNUNET_malloc (size);
memcpy (msg, message, size);
GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
GNUNET_TIME_UNIT_FOREVER_REL,
- path_get_first_hop (t->tree, pi->id),
+ path_get_first_hop (t->tree, pid),
size,
&send_core_data_raw, msg);
return GNUNET_OK;
MESH_TunnelNumber tid;
size_t size;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "MESH: Got a unicast request from a client!\n");
+
/* Sanity check for client registration */
if (NULL == (c = client_get (client)))
{
memcpy (buf, data_msg, size);
copy->oid = my_full_id;
copy->tid = htonl (t->id.tid);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "MESH: calling generic handler...\n");
handle_mesh_data_unicast (NULL, &my_full_id, ©->header, NULL);
}
GNUNET_SERVER_receive_done (client, GNUNET_OK);
/* multicast */
struct GNUNET_MESH_Multicast mc;
- GNUNET_assert (size >= sizeof (mc) + th->size);
+ GNUNET_assert (size >= th->size);
psize =
th->notify (th->notify_cls, size - sizeof (mc), &cbuf[sizeof (mc)]);
if (psize > 0)
mc.tid = htonl (th->tunnel->tid);
memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
memcpy (cbuf, &mc, sizeof (mc));
- psize = th->size + sizeof (mc);
+ psize += sizeof (mc);
}
}
else
/* unicast */
struct GNUNET_MESH_Unicast uc;
- GNUNET_assert (size >= sizeof (uc) + th->size);
+ GNUNET_assert (size >= th->size);
psize =
th->notify (th->notify_cls, size - sizeof (uc), &cbuf[sizeof (uc)]);
if (psize > 0)
{
- uc.header.size = htons (sizeof (uc) + th->size);
+ uc.header.size = htons (th->size);
uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
uc.tid = htonl (th->tunnel->tid);
memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
GNUNET_PEER_resolve (th->target, &uc.destination);
memcpy (cbuf, &uc, sizeof (uc));
- psize = th->size + sizeof (uc);
+ psize += sizeof (uc);
}
}
}
uint32_t least_priority;
size_t overhead;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "mesh: mesh notify transmit ready called\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "mesh: target %s\n",
+ GNUNET_i2s (target));
+
GNUNET_assert (NULL != notify);
if (tunnel->mesh->npackets >= tunnel->mesh->max_queue_size &&
tunnel->npackets > 0)
th->notify = notify;
th->notify_cls = notify_cls;
add_to_queue (tunnel->mesh, th);
+ if (NULL != tunnel->mesh->th)
+ return th;
+ tunnel->mesh->th =
+ GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client,
+ th->size,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_YES,
+ &send_callback,
+ tunnel->mesh);
return th;
}
* @param hop If known, ID of the first hop.
* If not known, NULL to find out and pass on children.
*/
-static void
+void
tree_update_first_hops (struct MeshTunnelTree *tree,
struct MeshTunnelTreeNode *parent,
struct GNUNET_PeerIdentity *hop)
}
+
/**
* Integrate a stand alone path into the tunnel tree.
* If the peer toward which the new path is already in the tree, the peer
struct MeshTunnelTreeNode *n;
struct MeshTunnelTreeNode *c;
struct GNUNET_PeerIdentity id;
- struct GNUNET_PeerIdentity *hop;
GNUNET_PEER_Id myid;
int me;
unsigned int i;
n->status = MESH_PEER_SEARCHING;
/* Add info about first hop into hashmap. */
- if (me < p->length - 1)
+ if (-1 != me && me < p->length - 1)
{
- GNUNET_PEER_resolve (p->peers[p->length - 1], &id);
- hop = GNUNET_CONTAINER_multihashmap_get(t->first_hops, &id.hashPubKey);
- if (NULL != hop)
- {
- GNUNET_CONTAINER_multihashmap_remove_all(t->first_hops, &id.hashPubKey);
- GNUNET_free(hop);
- }
- hop = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
- GNUNET_PEER_resolve (p->peers[me + 1], hop);
- GNUNET_CONTAINER_multihashmap_put (t->first_hops, &id.hashPubKey,
- hop,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ GNUNET_PEER_resolve (p->peers[me + 1], &id);
+ tree_update_first_hops(t,
+ tree_find_peer(t->root, p->peers[p->length - 1]),
+ &id);
}
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "tree: New node added.\n");
return GNUNET_OK;
GNUNET_PEER_Id peer);
+/**
+ * Recusively update the info about what is the first hop to reach the node
+ *
+ * @param tree Tree this nodes belongs to
+ * @param parent Node to be start updating
+ * @param hop If known, ID of the first hop.
+ * If not known, NULL to find out and pass on children.
+ */
+void
+tree_update_first_hops (struct MeshTunnelTree *tree,
+ struct MeshTunnelTreeNode *parent,
+ struct GNUNET_PeerIdentity *hop);
+
/**
* Delete the current path to the peer, including all now unused relays.
* The destination peer is NOT destroyed, it is returned in order to either set
*/
#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
-#define OK_GOAL 2
+#define OK_GOAL 4
static int ok;
static struct GNUNET_MESH_Tunnel *t;
+static struct GNUNET_MESH_Tunnel *incoming_t;
+
static uint16_t *mesh_peers;
/**
}
+/**
+ * Transmit ready callback
+ */
+size_t
+tmt_rdy (void *cls, size_t size, void *buf)
+{
+ struct GNUNET_MessageHeader *msg = buf;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: tmt_rdy called\n");
+ if (size < sizeof(struct GNUNET_MessageHeader) || NULL == buf)
+ return 0;
+ msg->size = htons (sizeof(struct GNUNET_MessageHeader));
+ msg->type = htonl ((long) cls);
+ return sizeof(struct GNUNET_MessageHeader);
+}
+
+
+/**
+ * Function is called whenever a message is received.
+ *
+ * @param cls closure (set from GNUNET_MESH_connect)
+ * @param tunnel connection to the other end
+ * @param tunnel_ctx place to store local state associated with the tunnel
+ * @param sender who sent the message
+ * @param message the actual message
+ * @param atsi performance data for the connection
+ * @return GNUNET_OK to keep the connection open,
+ * GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+data_callback (void *cls,
+ struct GNUNET_MESH_Tunnel * tunnel,
+ void **tunnel_ctx,
+ const struct GNUNET_PeerIdentity *sender,
+ const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+{
+ long client = (long) cls;
+
+ switch (client)
+ {
+ case 1L:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "test: Origin client got a response!\n");
+ ok++;
+ break;
+ case 2L:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "test: Destination client got a message \n");
+ ok++;
+ GNUNET_MESH_notify_transmit_ready(incoming_t,
+ GNUNET_NO,
+ 0,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ sender,
+ sizeof(struct GNUNET_MessageHeader),
+ &tmt_rdy,
+ (void *) 1L);
+ break;
+ default:
+ break;
+ }
+ return GNUNET_OK;
+}
+
+
/**
* Handlers, for diverse services
*/
static struct GNUNET_MESH_MessageHandler handlers[] = {
-// {&callback, 1, 0},
+ {&data_callback, 1, sizeof(struct GNUNET_MessageHeader)},
{NULL, 0, 0}
};
"test: Incoming tunnel from %s\n",
GNUNET_i2s(initiator));
ok++;
+ incoming_t = tunnel;
GNUNET_SCHEDULER_cancel (disconnect_task);
disconnect_task = GNUNET_SCHEDULER_add_delayed(SHORT_TIME,
&disconnect_mesh_peers,
return;
}
+
/**
* Method called whenever a tunnel falls apart.
*
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"test: peer %s disconnected\n",
GNUNET_i2s(peer));
- if (memcmp(&d2->id, peer, sizeof(d2->id)))
- ok++;
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"test: peer %s connected\n",
GNUNET_i2s(peer));
+ if (0 == memcmp(&d2->id, peer, sizeof(d2->id)) && (long) cls == 1L)
+ ok++;
+ if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+ {
+ GNUNET_SCHEDULER_cancel (disconnect_task);
+ disconnect_task = GNUNET_SCHEDULER_add_delayed(SHORT_TIME,
+ &disconnect_mesh_peers,
+ NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Sending data unicast...\n");
+ GNUNET_MESH_notify_transmit_ready(t,
+ GNUNET_NO,
+ 0,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &d2->id,
+ sizeof(struct GNUNET_MessageHeader),
+ &tmt_rdy,
+ (void *) 1L);
+ }
return;
}
#endif
h1 = GNUNET_MESH_connect (d1->cfg,
10,
- NULL,
+ (void *) 1L,
NULL,
&tunnel_cleaner,
handlers,
&app);
h2 = GNUNET_MESH_connect (d2->cfg,
10,
- NULL,
+ (void *) 2L,
&incoming_tunnel,
&tunnel_cleaner,
handlers,
"test: connected to mesh service of peer %s\n",
GNUNET_i2s (&d2->id));
#endif
- t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, NULL);
+ t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, (void *) 1L);
test_task =
GNUNET_SCHEDULER_add_delayed(
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 6),
main (int argc, char *argv[])
{
GNUNET_PROGRAM_run (argc, argv, "test_mesh_small_unicast",
- gettext_noop ("Test mesh unicast in a small network."), options,
- &run, NULL);
+ gettext_noop ("Test mesh unicast in a small network."),
+ options, &run, NULL);
#if REMOVE_DIR
GNUNET_DISK_directory_remove ("/tmp/test_mesh_small_unicast");
#endif
if (OK_GOAL != ok)
{
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "test: FAILED! (%d/%d)\n",
+ ok, OK_GOAL);
return 1;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: success\n");
return 0;
}