struct MeshTunnelDelayed *prev;
/**
- * Channel.
+ * Tunnel.
*/
- struct MeshChannel *ch;
+ struct MeshTunnel3 *t;
+
+ /**
+ * Tunnel queue given to the channel to cancel request. Update on send_queued.
+ */
+ struct MeshTunnel3Queue *tq;
/**
* Message to send.
/**
* Connection queue handle, to cancel if necessary.
*/
- struct MeshConnectionQueue *q;
+ struct MeshConnectionQueue *cq;
+
+ /**
+ * Handle in case message hasn't been given to a connection yet.
+ */
+ struct MeshTunnelDelayed *tqd;
/**
* Continuation to call once sent.
extern struct GNUNET_PeerIdentity my_full_id;
+/**
+ * Don't try to recover tunnels if shutting down.
+ */
+extern int shutting_down;
+
+
/**
* Set of all tunnels, in order to trigger a new exchange on rekey.
* Indexed by peer's ID.
/**
- * Send all cached messages that we can, tunnel is online.
+ * Callback called when a queued message is sent.
*
- * @param t Tunnel that holds the messages. Cannot be loopback.
+ * Calculates the average time and connection packet tracking.
+ *
+ * @param cls Closure (TunnelQueue handle).
+ * @param c Connection this message was on.
+ * @param q Connection queue handle (unused).
+ * @param type Type of message sent.
+ * @param fwd Was this a FWD going message?
+ * @param size Size of the message.
*/
static void
-send_queued_data (struct MeshTunnel3 *t)
+message_sent (void *cls,
+ struct MeshConnection *c,
+ struct MeshConnectionQueue *q,
+ uint16_t type, int fwd, size_t size)
{
- struct MeshTunnelDelayed *tq;
- struct MeshTunnelDelayed *next;
- unsigned int room;
+ struct MeshTunnel3Queue *qt = cls;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "GMT_send_queued_data on tunnel %s\n",
- GMT_2s (t));
+ GNUNET_assert (NULL != qt->cont);
+ qt->cont (qt->cont_cls, GMC_get_tunnel (c), qt, type, size);
+ GNUNET_free (qt);
+}
- if (GMT_is_loopback (t))
+
+/**
+ * Delete a queued message: either was sent or the channel was destroyed
+ * before the tunnel's key exchange had a chance to finish.
+ *
+ * @param tq Queue handle.
+ */
+static void
+unqueue_data (struct MeshTunnelDelayed *tq)
+{
+ GNUNET_CONTAINER_DLL_remove (tq->t->tq_head, tq->t->tq_tail, tq);
+ GNUNET_free (tq);
+}
+
+
+/**
+ * Cache a message to be sent once tunnel is online.
+ *
+ * @param t Tunnel to hold the message.
+ * @param msg Message itself (copy will be made).
+ */
+static struct MeshTunnelDelayed *
+queue_data (struct MeshTunnel3 *t, const struct GNUNET_MessageHeader *msg)
+{
+ struct MeshTunnelDelayed *tqd;
+ uint16_t size = ntohs (msg->size);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GMT_2s (t));
+
+ if (GNUNET_YES == is_ready (t))
{
GNUNET_break (0);
- return;
+ return NULL;
}
+ tqd = GNUNET_malloc (sizeof (struct MeshTunnelDelayed) + size);
+
+ tqd->t = t;
+ memcpy (&tqd[1], msg, size);
+ GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tqd);
+ return tqd;
+}
+
+
+
+/**
+ * Sends an already built message on a tunnel, encrypting it and
+ * choosing the best connection.
+ *
+ * @param message Message to send. Function modifies it.
+ * @param t Tunnel on which this message is transmitted.
+ * @param force Force the tunnel to take the message (buffer overfill).
+ * @param cont Continuation to call once message is really sent.
+ * @param cont_cls Closure for @c cont.
+ * @param existing_q In case this a transmission of previously queued data,
+ * this should be TunnelQueue given to the client.
+ * Otherwise, NULL.
+ *
+ * @return Handle to cancel message. NULL if @c cont is NULL.
+ */
+static struct MeshTunnel3Queue *
+send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+ struct MeshTunnel3 *t, int force,
+ GMT_sent cont, void *cont_cls,
+ struct MeshTunnel3Queue *existing_q)
+{
+ struct MeshTunnel3Queue *tq;
+ struct MeshConnection *c;
+ struct GNUNET_MESH_Encrypted *msg;
+ size_t size = ntohs (message->size);
+ char cbuf[sizeof (struct GNUNET_MESH_Encrypted) + size];
+ uint32_t iv;
+ uint16_t type;
+ int fwd;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMT_2s (t));
+
if (GNUNET_NO == is_ready (t))
{
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not ready yet: %s/%s\n",
- estate2s (t->estate), cstate2s (t->cstate));
- return;
+ struct MeshTunnelDelayed *tqd;
+ /* A non null existing_q indicates sending of queued data.
+ * Should only happen after tunnel becomes ready.
+ */
+ GNUNET_assert (NULL == existing_q);
+ tqd = queue_data (t, message);
+ if (NULL == cont)
+ return NULL;
+ tq = GNUNET_new (struct MeshTunnel3Queue);
+ tq->tqd = tqd;
+ tqd->tq = tq;
+ tq->cont = cont;
+ tq->cont_cls = cont_cls;
+ return tq;
}
- room = GMT_get_connections_buffer (t);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " tq head: %p\n", t->tq_head);
- for (tq = t->tq_head; NULL != tq && room > 0; tq = next)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " data on channel %s\n", GMCH_2s (tq->ch));
- next = tq->next;
- room--;
- GNUNET_CONTAINER_DLL_remove (t->tq_head, t->tq_tail, tq);
- GMCH_send_prebuilt_message ((struct GNUNET_MessageHeader *) &tq[1],
- tq->ch, GMCH_is_origin (tq->ch, GNUNET_YES),
- GNUNET_NO);
+ GNUNET_assert (GNUNET_NO == GMT_is_loopback (t));
- GNUNET_free (tq);
+ iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
+ msg = (struct GNUNET_MESH_Encrypted *) cbuf;
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED);
+ msg->iv = iv;
+ GNUNET_assert (t_encrypt (t, &msg[1], message, size, iv) == size);
+ msg->header.size = htons (sizeof (struct GNUNET_MESH_Encrypted) + size);
+ c = tunnel_get_connection (t);
+ if (NULL == c)
+ {
+ if (GNUNET_YES == t->destroy || MESH_TUNNEL3_SEARCHING != t->cstate)
+ {
+ GNUNET_break (0);
+ GMT_debug (t);
+ }
+ return NULL;
}
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "GMT_send_queued_data end\n",
- GMP_2s (t->peer));
-}
+ type = ntohs (message->type);
+ switch (type)
+ {
+ case GNUNET_MESSAGE_TYPE_MESH_DATA:
+ case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK:
+ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
+ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
+ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK:
+ msg->cid = *GMC_get_id (c);
+ msg->ttl = htonl (default_ttl);
+ break;
+ default:
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n",
+ GM_m2s (type));
+ GNUNET_break (0);
+ }
+
+ fwd = GMC_is_origin (c, GNUNET_YES);
+ if (NULL == cont)
+ {
+ (void) GMC_send_prebuilt_message (&msg->header, c, fwd, force, NULL, NULL);
+ return NULL;
+ }
+ if (NULL == existing_q)
+ {
+ tq = GNUNET_new (struct MeshTunnel3Queue); /* FIXME valgrind: leak*/
+ }
+ else
+ {
+ tq = existing_q;
+ tq->tqd = NULL;
+ }
+ tq->cq = GMC_send_prebuilt_message (&msg->header, c, fwd, force,
+ &message_sent, tq);
+ tq->cont = cont;
+ tq->cont_cls = cont_cls;
+ return tq;
+}
/**
- * Cache a message to be sent once tunnel is online.
+ * Send all cached messages that we can, tunnel is online.
*
- * @param t Tunnel to hold the message.
- * @param ch Channel the message is about.
- * @param msg Message itself (copy will be made).
+ * @param t Tunnel that holds the messages. Cannot be loopback.
*/
static void
-queue_data (struct MeshTunnel3 *t,
- struct MeshChannel *ch,
- const struct GNUNET_MessageHeader *msg)
+send_queued_data (struct MeshTunnel3 *t)
{
- struct MeshTunnelDelayed *tq;
- uint16_t size = ntohs (msg->size);
+ struct MeshTunnelDelayed *tqd;
+ struct MeshTunnelDelayed *next;
+ unsigned int room;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GMT_2s (t));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "GMT_send_queued_data on tunnel %s\n",
+ GMT_2s (t));
- if (GNUNET_YES == is_ready (t))
+ if (GMT_is_loopback (t))
{
GNUNET_break (0);
return;
}
- tq = GNUNET_malloc (sizeof (struct MeshTunnelDelayed) + size);
+ if (GNUNET_NO == is_ready (t))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " not ready yet: %s/%s\n",
+ estate2s (t->estate), cstate2s (t->cstate));
+ return;
+ }
- tq->ch = ch;
- memcpy (&tq[1], msg, size);
- GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tq);
+ room = GMT_get_connections_buffer (t);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " tq head: %p\n", t->tq_head);
+ for (tqd = t->tq_head; NULL != tqd && room > 0; tqd = next)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " sending queued data\n");
+ next = tqd->next;
+ room--;
+ send_prebuilt_message ((struct GNUNET_MessageHeader *) &tqd[1],
+ tqd->t, GNUNET_YES,
+ NULL != tqd->tq ? tqd->tq->cont : NULL,
+ NULL != tqd->tq ? tqd->tq->cont_cls : NULL,
+ tqd->tq);
+ unqueue_data (tqd);
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_send_queued_data end\n", GMP_2s (t->peer));
}
-
/**
* Sends key exchange message on a tunnel, choosing the best connection.
* Should not be called on loopback tunnels.
/* Must have a connection. */
if (NULL == t->connection_head)
{
- GNUNET_break (0);
+ GNUNET_break (MESH_TUNNEL3_SEARCHING == t->cstate);
+ GMT_debug (t);
return;
}
c = tunnel_get_connection (t);
if (NULL == c)
{
- GNUNET_break (GNUNET_YES == t->destroy);
+ GNUNET_break (GNUNET_YES == t->destroy || MESH_TUNNEL3_READY != t->cstate);
+ GMT_debug (t);
return;
}
type = ntohs (message->type);
break;
default:
LOG (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n",
- GNUNET_MESH_DEBUG_M2S (type));
+ GM_m2s (type));
GNUNET_break (0);
}
fwd = GMC_is_origin (t->connection_head->c, GNUNET_YES);
/* TODO save handle and cancel in case of a unneeded retransmission */
- GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
+ GMC_send_prebuilt_message (&msg->header, c, fwd, GNUNET_YES, NULL, NULL);
}
t->rekey_task = GNUNET_SCHEDULER_NO_TASK;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Re-key Tunnel\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Re-key Tunnel %s\n", GMT_2s (t));
if (NULL != tc && 0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
return;
return;
}
LOG (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n",
- GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
+ GM_m2s (ntohs (msg[1].header.type)));
/* Check channel */
ch = GMT_get_channel (t, ntohl (msg->chid));
type = ntohs (msgh->type);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Got a %s message!\n",
- GNUNET_MESH_DEBUG_M2S (type));
+ GM_m2s (type));
switch (type)
{
* @param cstate New connection state.
*/
void
-GMT_change_cstate (struct MeshTunnel3* t, enum MeshTunnel3CState state)
+GMT_change_cstate (struct MeshTunnel3* t, enum MeshTunnel3CState cstate)
{
if (NULL == t)
return;
GMP_2s (t->peer), cstate2s (t->cstate));
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Tunnel %s cstate is now %s\n",
- GMP_2s (t->peer), cstate2s (state));
+ GMP_2s (t->peer), cstate2s (cstate));
if (myid != GMP_get_short_id (t->peer) &&
MESH_TUNNEL3_READY != t->cstate &&
- MESH_TUNNEL3_READY == state)
+ MESH_TUNNEL3_READY == cstate)
{
- t->cstate = state;
+ t->cstate = cstate;
if (MESH_TUNNEL3_KEY_OK == t->estate)
{
LOG (GNUNET_ERROR_TYPE_DEBUG, " triggered send queued data\n");
rekey_tunnel (t, NULL);
}
}
- t->cstate = state;
+ t->cstate = cstate;
- if (MESH_TUNNEL3_READY == state && 3 <= GMT_count_connections (t))
+ if (MESH_TUNNEL3_READY == cstate && 3 <= GMT_count_connections (t))
{
GMP_stop_search (t->peer);
}
{
struct MeshTConnection *aux;
+ GNUNET_assert (NULL != c);
+
for (aux = t->connection_head; aux != NULL; aux = aux->next)
if (aux->c == c)
return;
}
+/**
+ * Mark a path as no longer valid for this tunnel: has been tried and failed.
+ *
+ * @param t Tunnel to update.
+ * @param path Invalid path to remove. Is destroyed after removal.
+ */
+void
+GMT_remove_path (struct MeshTunnel3 *t, struct MeshPeerPath *path)
+{
+ GMP_remove_path (t->peer, path);
+}
+
+
/**
* Remove a connection from a tunnel.
*
* @param c Connection.
*/
void
-GMT_remove_connection (struct MeshTunnel3 *t, struct MeshConnection *c)
+GMT_remove_connection (struct MeshTunnel3 *t,
+ struct MeshConnection *c)
{
struct MeshTConnection *aux;
+ struct MeshTConnection *next;
- for (aux = t->connection_head; aux != NULL; aux = aux->next)
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing connection %s from tunnel %s\n",
+ GMC_2s (c), GMT_2s (t));
+ for (aux = t->connection_head; aux != NULL; aux = next)
+ {
+ next = aux->next;
if (aux->c == c)
{
GNUNET_CONTAINER_DLL_remove (t->connection_head, t->connection_tail, aux);
GNUNET_free (aux);
- return;
}
+ }
+
+ /* Start new connections if needed */
+ if (NULL == t->connection_head
+ && GNUNET_NO == t->destroy
+ && GNUNET_NO == shutting_down)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " no more connections\n");
+ GMP_connect (t->peer);
+ t->cstate = MESH_TUNNEL3_SEARCHING;
+ return;
+ }
+
+ /* If not marked as ready, no change is needed */
+ if (MESH_TUNNEL3_READY != t->cstate)
+ return;
+
+ /* Check if any connection is ready to maintaing cstate */
+ for (aux = t->connection_head; aux != NULL; aux = aux->next)
+ if (MESH_CONNECTION_READY == GMC_get_state (aux->c))
+ return;
+
+ t->cstate = MESH_TUNNEL3_WAITING;
}
aux->ch = ch;
LOG (GNUNET_ERROR_TYPE_DEBUG, " adding %p to %p\n", aux, t->channel_head);
GNUNET_CONTAINER_DLL_insert_tail (t->channel_head, t->channel_tail, aux);
+
+ if (GNUNET_YES == t->destroy)
+ {
+ t->destroy = GNUNET_NO;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " undo destroy!\n");
+ }
}
GMC_send_destroy (iter->c);
}
+ if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task)
+ {
+ t->estate = MESH_TUNNEL3_KEY_UNINITIALIZED;
+ GNUNET_SCHEDULER_cancel (t->rekey_task);
+ t->rekey_task = GNUNET_SCHEDULER_NO_TASK;
+ }
t->cstate = MESH_TUNNEL3_NEW;
t->destroy = GNUNET_YES;
}
if (NULL == t)
return;
+ t->destroy = 2;
+
LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s\n", GMP_2s (t->peer));
GNUNET_break (GNUNET_YES ==
}
if (own_pos > p->length - 1)
{
- GNUNET_break (0);
+ GNUNET_break_op (0);
return NULL;
}
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE, &cid);
c = GMC_new (&cid, t, p, own_pos);
+ if (NULL == c)
+ {
+ /* Path was flawed */
+ return NULL;
+ }
GMT_add_connection (t, c);
return c;
}
struct MeshTConnection *iter;
unsigned int buffer;
- iter = t->connection_head;
buffer = 0;
- while (NULL != iter)
+ for (iter = t->connection_head; NULL != iter; iter = iter->next)
{
if (GMC_get_state (iter->c) != MESH_CONNECTION_READY)
{
- iter = iter->next;
continue;
}
-
buffer += get_connection_buffer (iter);
- iter = iter->next;
}
return buffer;
GMT_get_next_chid (struct MeshTunnel3 *t)
{
MESH_ChannelNumber chid;
+ MESH_ChannelNumber mask;
+ int result;
+
+ /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID.
+ * If our ID is bigger or loopback tunnel, start at 0, bit 30 = 0
+ * If peer's ID is bigger, start at 0x4... bit 30 = 1
+ */
+ result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GMP_get_id (t->peer));
+ if (0 > result)
+ mask = 0x4000000;
+ else
+ mask = 0x0;
while (NULL != GMT_get_channel (t, t->next_chid))
{
LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", t->next_chid);
t->next_chid = (t->next_chid + 1) & ~GNUNET_MESH_LOCAL_CHANNEL_ID_CLI;
+ t->next_chid |= mask;
}
chid = t->next_chid;
t->next_chid = (t->next_chid + 1) & ~GNUNET_MESH_LOCAL_CHANNEL_ID_CLI;
+ t->next_chid |= mask;
return chid;
}
}
-/**
- * Callback called when a queued message is sent.
- *
- * Calculates the average time and connection packet tracking.
- *
- * @param cls Closure (TunnelQueue handle).
- * @param c Connection this message was on.
- * @param type Type of message sent.
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- */
-static void
-message_sent (void *cls,
- struct MeshConnection *c,
- struct MeshConnectionQueue *q,
- uint16_t type, int fwd, size_t size)
-{
- struct MeshTunnel3Queue *qt = cls;
-
- GNUNET_assert (NULL != qt->cont);
- qt->cont (qt->cont_cls, GMC_get_tunnel (c), qt, type, size);
- GNUNET_free (qt);
-}
-
-
/**
* Cancel a previously sent message while it's in the queue.
*
void
GMT_cancel (struct MeshTunnel3Queue *q)
{
- GMC_cancel (q->q);
- /* message_sent() will be called and free q */
+ if (NULL != q->cq)
+ {
+ GMC_cancel (q->cq);
+ /* message_sent() will be called and free q */
+ }
+ else if (NULL != q->tqd)
+ {
+ unqueue_data (q->tqd);
+ }
+ else
+ {
+ GNUNET_break (0);
+ }
}
*
* @param message Message to send. Function modifies it.
* @param t Tunnel on which this message is transmitted.
- * @param ch Channel on which this message is transmitted.
- * @param fwd Is this a fwd message on @c ch?
+ * @param force Force the tunnel to take the message (buffer overfill).
* @param cont Continuation to call once message is really sent.
* @param cont_cls Closure for @c cont.
*
*/
struct MeshTunnel3Queue *
GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- struct MeshTunnel3 *t,
- struct MeshChannel *ch, int fwd,
+ struct MeshTunnel3 *t, int force,
GMT_sent cont, void *cont_cls)
{
- struct MeshTunnel3Queue *q;
- struct MeshConnection *c;
- struct GNUNET_MESH_Encrypted *msg;
- size_t size = ntohs (message->size);
- size_t encrypted_size;
- char cbuf[sizeof (struct GNUNET_MESH_Encrypted) + size];
- uint32_t iv;
- uint16_t type;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMT_2s (t));
-
- if (GNUNET_NO == is_ready (t))
- {
- queue_data (t, ch, message);
- /* FIXME */
- return NULL;
- }
-
- if (GMT_is_loopback (t))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback!\n");
- handle_decrypted (t, message, fwd);
- /* FIXME: call cont? */
- return NULL; /* Already delivered, cannot cancel */
- }
-
- iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
- msg = (struct GNUNET_MESH_Encrypted *) cbuf;
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED);
- msg->iv = iv;
- encrypted_size = t_encrypt (t, &msg[1], message, size, iv);
- msg->header.size = htons (sizeof (struct GNUNET_MESH_Encrypted) + encrypted_size);
- c = tunnel_get_connection (t);
- if (NULL == c)
- {
- GNUNET_break (GNUNET_YES == t->destroy);
- return NULL;
- }
- type = ntohs (message->type);
- switch (type)
- {
- case GNUNET_MESSAGE_TYPE_MESH_DATA:
- case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK:
- case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
- case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
- case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK:
- msg->cid = *GMC_get_id (c);
- msg->ttl = htonl (default_ttl);
- break;
- default:
- LOG (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n",
- GNUNET_MESH_DEBUG_M2S (type));
- GNUNET_break (0);
- }
-
- fwd = GMC_is_origin (c, GNUNET_YES);
-
- if (NULL == cont)
- {
- (void) GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
- return NULL;
- }
- q = GNUNET_new (struct MeshTunnel3Queue); /* FIXME valgrind: leak*/
- q->q = GMC_send_prebuilt_message (&msg->header, c, fwd, &message_sent, q);
- q->cont = cont;
- q->cont_cls = cont_cls;
-
- return q;
+ return send_prebuilt_message (message, t, force, cont, cont_cls, NULL);
}
+
/**
* Is the tunnel directed towards the local peer?
*
const struct MeshPeerPath *path)
{
struct MeshTConnection *iter;
+ const struct MeshPeerPath *aux;
unsigned int overlap;
unsigned int i;
unsigned int j;
{
for (iter = t->connection_head; NULL != iter; iter = iter->next)
{
- for (j = 0; j < GMC_get_path (iter->c)->length; j++)
+ aux = GMC_get_path (iter->c);
+ if (NULL == aux)
+ continue;
+
+ for (j = 0; j < aux->length; j++)
{
- if (path->peers[i] == GMC_get_path (iter->c)->peers[j])
+ if (path->peers[i] == aux->peers[j])
{
overlap++;
break;
return GMP_2s (t->peer);
}
+
+
+/**
+ * Log all possible info about the tunnel state.
+ *
+ * @param t Tunnel to debug.
+ */
+void
+GMT_debug (const struct MeshTunnel3 *t)
+{
+ struct MeshTChannel *iterch;
+ struct MeshTConnection *iterc;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "DEBUG %s\n", GMT_2s (t));
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate %s, estate %s\n",
+ cstate2s (t->cstate), estate2s (t->estate));
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " channels:\n");
+ for (iterch = t->channel_head; NULL != iterch; iterch = iterch->next)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " - %s\n", GMCH_2s (iterch->ch));
+ }
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " connections:\n");
+ for (iterc = t->connection_head; NULL != iterc; iterc = iterc->next)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " - %s\n", GMC_2s (iterc->c));
+ }
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "DEBUG END\n");
+}