tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
+/**
+ * Change the tunnel state.
+ *
+ * @param t Tunnel whose ttate to change.
+ * @param state New state.
+ */
+static void
+tunnel_change_state (struct MeshTunnel *t, enum MeshTunnelState state);
+
+
/**
* Notify a tunnel that a connection has broken that affects at least
* some of its peers.
__mesh_divider______________________________________________________________();
+static const char *
+GNUNET_MESH_DEBUG_S2S (enum MeshTunnelState s)
+{
+ static char buf[128];
+
+ switch (s)
+ {
+ /**
+ * Uninitialized status, should never appear in operation.
+ */
+ case MESH_TUNNEL_NEW: return "MESH_TUNNEL_NEW";
+
+ /**
+ * Path to the peer not known yet
+ */
+ case MESH_TUNNEL_SEARCHING: return "MESH_TUNNEL_SEARCHING";
+
+ /**
+ * Request sent, not yet answered.
+ */
+ case MESH_TUNNEL_WAITING: return "MESH_TUNNEL_WAITING";
+
+ /**
+ * Peer connected and ready to accept data
+ */
+ case MESH_TUNNEL_READY: return "MESH_TUNNEL_READY";
+
+ /**
+ * Peer connected previosly but not responding
+ */
+ case MESH_TUNNEL_RECONNECTING: return "MESH_TUNNEL_RECONNECTING";
+
+ default:
+ sprintf (buf, "%u (UNKNOWN STATE)", s);
+ return buf;
+ }
+}
+
+
/******************************************************************************/
/************************ PERIODIC FUNCTIONS ****************************/
/******************************************************************************/
(t->path->length * sizeof (struct GNUNET_PeerIdentity)),
neighbor,
t);
- t->state = MESH_TUNNEL_WAITING;
+ tunnel_change_state (t, MESH_TUNNEL_WAITING);
}
static void
send_path_ack (struct MeshTunnel *t)
{
- struct MeshPeerInfo *peer;
-
- peer = peer_get_short (t->prev_hop);
- t->state = MESH_TUNNEL_WAITING;
+ struct MeshPeerInfo *neighbor;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send path ack\n");
+ neighbor = peer_get_short (t->prev_hop);
queue_add (t,
GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
sizeof (struct GNUNET_MESH_PathACK),
- peer,
+ neighbor,
t);
+ tunnel_change_state (t, MESH_TUNNEL_WAITING);
}
NULL, /* xquery */
0, /* xquery bits */
&dht_get_id_handler, peer);
- t->state = MESH_TUNNEL_SEARCHING;
+ tunnel_change_state (t, MESH_TUNNEL_SEARCHING);
}
else
{
static struct MeshTunnel *
tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
{
+ if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
+ {
+ GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TID %X not a local tid\n", tid);
+ return NULL;
+ }
if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
{
return tunnel_get_incoming (tid);
}
else
{
- GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI);
return GNUNET_CONTAINER_multihashmap32_get (c->own_tunnels, tid);
}
}
}
+/**
+ * Change the tunnel state.
+ *
+ * @param t Tunnel whose ttate to change.
+ * @param state New state.
+ */
+static void
+tunnel_change_state (struct MeshTunnel *t, enum MeshTunnelState state)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Tunnel %s[%X] state was %s\n",
+ GNUNET_i2s (GNUNET_PEER_resolve2 (t->id.oid)), t->id.tid,
+ GNUNET_MESH_DEBUG_S2S (t->state));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Tunnel %s[%X] state is now %s\n",
+ GNUNET_i2s (GNUNET_PEER_resolve2 (t->id.oid)), t->id.tid,
+ GNUNET_MESH_DEBUG_S2S (state));
+ t->state = state;
+}
+
+
+
/**
* Add a client to a tunnel, initializing all needed data structures.
*
t->owner = client;
fc_init (&t->next_fc);
fc_init (&t->prev_fc);
+ t->next_fc.t = t;
+ t->prev_fc.t = t;
t->local_tid = local;
n_tunnels++;
GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"* %s starting poll timeout\n",
GNUNET_i2s (&my_full_id));
- fc->t = t;
fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
&tunnel_poll, fc);
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " nobuffer:%d\n", t->nobuffer);
}
tunnel_reset_timeout (t, GNUNET_YES);
- t->state = MESH_TUNNEL_WAITING;
+ tunnel_change_state (t, MESH_TUNNEL_WAITING);
dest_peer_info =
GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
if (NULL == dest_peer_info)
{
GNUNET_break (0);
}
- t->state = MESH_TUNNEL_READY;
+ tunnel_change_state (t, MESH_TUNNEL_READY);
tunnel_reset_timeout (t, GNUNET_NO);
t->next_fc.last_ack_recv = (NULL == t->client) ? ntohl (msg->ack) : 0;
t->prev_fc.last_ack_sent = ntohl (msg->ack);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
" not for us, retransmitting...\n");
- peer_info = peer_get (&msg->oid);
send_prebuilt_message (message, t->prev_hop, t);
return GNUNET_OK;
}
return GNUNET_OK;
}
if (NULL != c)
- t->state = MESH_TUNNEL_READY;
+ tunnel_change_state (t, MESH_TUNNEL_READY);
tunnel_reset_timeout (t, fwd);
if (NULL != c)
{
fc->last_ack_recv = ack;
peer_unlock_queue (id);
- t->state = MESH_TUNNEL_READY;
+ tunnel_change_state (t, MESH_TUNNEL_READY);
tunnel_send_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK, t->next_hop == id);
hop = fwd ? t->next_hop : t->prev_hop;
if (NULL != c)
- t->state = MESH_TUNNEL_READY;
+ tunnel_change_state (t, MESH_TUNNEL_READY);
tunnel_reset_timeout (t, fwd);
if (NULL != c || 0 == hop || myid == hop)
return GNUNET_OK;
t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " towards %s\n",
GNUNET_i2s (&t_msg->peer));
- /* Sanity check for tunnel numbering */
tid = ntohl (t_msg->tunnel_id);
- if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
/* Sanity check for duplicate tunnel IDs */
if (NULL != tunnel_get_by_local_id (c, tid))
{
/* Retrieve tunnel */
tid = ntohl (tunnel_msg->tunnel_id);
- t = tunnel_get_by_local_id(c, tid);
+ t = tunnel_get_by_local_id (c, tid);
if (NULL == t)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " tunnel %X not found\n", tid);
/* Cleanup after the tunnel */
client_delete_tunnel (c, t);
- if (c == t->client)
+ if (c == t->client && GNUNET_MESH_LOCAL_TUNNEL_ID_SERV >= tid)
{
t->client = NULL;
}
- if (c == t->owner)
+ else if (c == t->owner && GNUNET_MESH_LOCAL_TUNNEL_ID_SERV < tid)
{
peer_info_remove_tunnel (peer_get_short (t->dest), t);
t->owner = NULL;
}
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ " tunnel %X client %p (%p, %p)\n",
+ tid, c, t->owner, t->client);
+ GNUNET_break (0);
+ }
/* The tunnel will be destroyed when the last message is transmitted. */
tunnel_destroy_empty (t);
/* Tunnel exists? */
tid = ntohl (data_msg->tid);
- if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI)
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
t = tunnel_get_by_local_id (c, tid);
if (NULL == t)
{