#define LOG(level, ...) GNUNET_log_from(level,"mesh-tun",__VA_ARGS__)
+#define START_FUNCTION LOG(GNUNET_ERROR_TYPE_DEBUG, "%s start\n", __FUNCTION__)
+#define END_FUNCTION LOG(GNUNET_ERROR_TYPE_DEBUG, "%s end\n", __FUNCTION__)
+
/******************************************************************************/
/******************************** STRUCTS **********************************/
/**
* State of the tunnel.
*/
- enum MeshTunnelState state;
+ enum MeshTunnel3State state;
/**
* Local peer ephemeral private key
*/
- struct GNUNET_CRYPTO_EccPrivateKey *my_eph_key;
+ struct GNUNET_CRYPTO_EddsaPrivateKey *my_eph_key;
/**
* Local peer ephemeral public key
*/
- struct GNUNET_CRYPTO_EccPublicSignKey *my_eph;
+ struct GNUNET_CRYPTO_EddsaPublicKey *my_eph;
/**
* Remote peer's public key.
*/
- struct GNUNET_CRYPTO_EccPublicSignKey *peers_eph;
+ struct GNUNET_CRYPTO_EddsaPublicKey *peers_eph;
/**
* Encryption ("our") key.
*/
MESH_ChannelNumber next_chid;
- /**
- * Channel ID for the next incoming channel.
- */
- MESH_ChannelNumber next_local_chid;
-
/**
* Pending message count.
*/
extern struct GNUNET_STATISTICS_Handle *stats;
/**
- * Default TTL for payload packets.
+ * Local peer own ID (memory efficient handle).
*/
-static unsigned long long default_ttl;
+extern GNUNET_PEER_Id myid;
/**
- * Local peer own ID (memory efficient handle).
+ * Local peer own ID (full value).
*/
-static GNUNET_PEER_Id my_short_id;
+extern struct GNUNET_PeerIdentity my_full_id;
/**
- * Local peer own ID (full value).
+ * Default TTL for payload packets.
*/
-const static struct GNUNET_PeerIdentity *my_full_id;
+static unsigned long long default_ttl;
/**
* Own private key.
*/
-const static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key;
+const static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
/******************************************************************************/
* @return String representation.
*/
static const char *
-GMT_state2s (enum MeshTunnelState s)
+GMT_state2s (enum MeshTunnel3State s)
{
static char buf[128];
switch (s)
{
- case MESH_TUNNEL_NEW:
- return "MESH_TUNNEL_NEW";
- case MESH_TUNNEL_SEARCHING:
- return "MESH_TUNNEL_SEARCHING";
- case MESH_TUNNEL_WAITING:
- return "MESH_TUNNEL_WAITING";
- case MESH_TUNNEL_READY:
- return "MESH_TUNNEL_READY";
- case MESH_TUNNEL_RECONNECTING:
- return "MESH_TUNNEL_RECONNECTING";
+ case MESH_TUNNEL3_NEW:
+ return "MESH_TUNNEL3_NEW";
+ case MESH_TUNNEL3_SEARCHING:
+ return "MESH_TUNNEL3_SEARCHING";
+ case MESH_TUNNEL3_WAITING:
+ return "MESH_TUNNEL3_WAITING";
+ case MESH_TUNNEL3_READY:
+ return "MESH_TUNNEL3_READY";
+ case MESH_TUNNEL3_RECONNECTING:
+ return "MESH_TUNNEL3_RECONNECTING";
default:
sprintf (buf, "%u (UNKNOWN STATE)", s);
}
}
-
-/**
- * Search for a channel by global ID using full PeerIdentities.
- *
- * @param t Tunnel containing the channel.
- * @param chid Public channel number.
- *
- * @return channel handler, NULL if doesn't exist
- */
-static struct MeshChannel *
-get_channel (struct MeshTunnel3 *t, MESH_ChannelNumber chid)
-{
- struct MeshTChannel *iter;
-
- if (NULL == t)
- return NULL;
-
- for (iter = t->channel_head; NULL != iter; iter = iter->next)
- {
- if (GMCH_get_id (iter->ch) == chid)
- break;
- }
-
- return NULL == iter ? NULL : iter->ch;
-}
-
-
/**
* Pick a connection on which send the next data message.
*
/**
- * Send all cached messages that we can, tunnel is online.
+ * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+ * Encrypt data with the tunnel key.
*
- * @param t Tunnel that holds the messages.
- * @param fwd Is this fwd?
+ * @param t Tunnel whose key to use.
+ * @param dst Destination for the GMT_encrypted data.
+ * @param src Source of the plaintext.
+ * @param size Size of the plaintext.
+ * @param iv Initialization Vector to use.
+ * @param fwd Is this a fwd message?
*/
static void
-tunnel_send_queued_data (struct MeshTunnel3 *t, int fwd)
+GMT_encrypt (struct MeshTunnel3 *t,
+ void *dst, const void *src,
+ size_t size, uint64_t iv, int fwd)
{
- struct MeshTunnelQueue *tq;
- struct MeshTunnelQueue *next;
- unsigned int room;
+ memcpy (dst, src, size);
+}
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "tunnel_send_queued_data on tunnel %s\n",
- GMP_2s (t->peer));
- room = GMT_get_buffer (t, fwd);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room);
- for (tq = t->tq_head; NULL != tq && room > 0; tq = next)
- {
- 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, fwd);
- GNUNET_free (tq);
- }
+/**
+ * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+ * Decrypt data with the tunnel key.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination for the plaintext.
+ * @param src Source of the GMT_encrypted data.
+ * @param size Size of the GMT_encrypted data.
+ * @param iv Initialization Vector to use.
+ * @param fwd Is this a fwd message?
+ */
+static void
+GMT_decrypt (struct MeshTunnel3 *t,
+ void *dst, const void *src,
+ size_t size, uint64_t iv, int fwd)
+{
+ memcpy (dst, src, size);
}
+
void
handle_data (struct MeshTunnel3 *t,
const struct GNUNET_MESH_Data *msg,
GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
/* Check channel */
- ch = get_channel (t, ntohl (msg->chid));
+ ch = GMT_get_channel (t, ntohl (msg->chid));
if (NULL == ch)
{
GNUNET_STATISTICS_update (stats, "# data on unknown channel",
return;
}
- GMT_change_state (t, MESH_TUNNEL_READY);
+ GMT_change_state (t, MESH_TUNNEL3_READY);
GMCH_handle_data (ch, msg, fwd);
}
}
/* Check channel */
- ch = get_channel (t, ntohl (msg->chid));
+ ch = GMT_get_channel (t, ntohl (msg->chid));
if (NULL == ch)
{
GNUNET_STATISTICS_update (stats, "# data ack on unknown channel",
const struct GNUNET_MESH_ChannelCreate *msg,
int fwd)
{
+ ;
+
struct MeshTChannel *tch;
struct MeshChannel *ch;
size_t size;
}
/* Check channel */
- ch = get_channel (t, ntohl (msg->chid));
+ ch = GMT_get_channel (t, ntohl (msg->chid));
if (NULL != ch)
{
/* Probably a retransmission, safe to ignore */
}
else
{
- ch = GMCH_handle_create (msg, fwd);
+ ch = GMCH_handle_create (t, msg, fwd);
}
tch = GNUNET_new (struct MeshTChannel);
tch->ch = ch;
GNUNET_CONTAINER_DLL_insert (t->channel_head, t->channel_tail, tch);
+
+ ;
}
void
}
/* Check channel */
- ch = get_channel (t, ntohl (msg->chid));
+ ch = GMT_get_channel (t, ntohl (msg->chid));
if (NULL == ch)
{
GNUNET_STATISTICS_update (stats, "# channel ack on unknown channel",
}
/* Check channel */
- ch = get_channel (t, ntohl (msg->chid));
+ ch = GMT_get_channel (t, ntohl (msg->chid));
if (NULL == ch)
{
/* Probably a retransmission, safe to ignore */
GMCH_handle_destroy (ch, msg, fwd);
}
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
/**
* Demultiplex by message type and call appropriate handler for a message
* @param msgh Message header.
* @param fwd Is this message fwd?
*/
-void
-GMT_handle_decrypted (struct MeshTunnel3 *t,
- const struct GNUNET_MessageHeader *msgh,
- int fwd)
+static void
+handle_decrypted (struct MeshTunnel3 *t,
+ const struct GNUNET_MessageHeader *msgh,
+ int fwd)
{
uint16_t type;
}
}
+/******************************************************************************/
+/******************************** API ***********************************/
+/******************************************************************************/
+
+
+/**
+ * Decrypt and demultiplex by message type. Call appropriate handler
+ * for every message.
+ *
+ * @param t Tunnel this message came on.
+ * @param msg Encrypted message.
+ * @param fwd Is this message fwd?
+ */
+void
+GMT_handle_encrypted (struct MeshTunnel3 *t,
+ const struct GNUNET_MESH_Encrypted *msg,
+ int fwd)
+{
+ size_t size = ntohs (msg->header.size);
+ size_t payload_size = size - sizeof (struct GNUNET_MESH_Encrypted);
+ char cbuf[payload_size];
+ struct GNUNET_MessageHeader *msgh;
+ unsigned int off;
+
+ GMT_decrypt (t, cbuf, &msg[1], payload_size, msg->iv, fwd);
+ off = 0;
+ while (off < payload_size)
+ {
+ msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
+ handle_decrypted (t, msgh, fwd);
+ off += ntohs (msgh->size);
+ }
+}
+
/**
* Cache a message to be sent once tunnel is online.
memcpy (&tq[1], msg, size);
GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tq);
- if (MESH_TUNNEL_READY == t->state)
- tunnel_send_queued_data (t, fwd);
+ if (MESH_TUNNEL3_READY == t->state)
+ GMT_send_queued_data (t, fwd);
+}
+
+
+/**
+ * Send all cached messages that we can, tunnel is online.
+ *
+ * @param t Tunnel that holds the messages.
+ * @param fwd Is this fwd?
+ */
+void
+GMT_send_queued_data (struct MeshTunnel3 *t, int fwd)
+{
+ struct MeshTunnelQueue *tq;
+ struct MeshTunnelQueue *next;
+ unsigned int room;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "GMT_send_queued_data on tunnel %s\n",
+ GMT_2s (t));
+ room = GMT_get_buffer (t, fwd);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room);
+ 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, fwd);
+
+ GNUNET_free (tq);
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "GMT_send_queued_data end\n",
+ GMP_2s (t->peer));
}
*/
void
GMT_init (const struct GNUNET_CONFIGURATION_Handle *c,
- const struct GNUNET_PeerIdentity *id,
- const struct GNUNET_CRYPTO_EccPrivateKey *key)
+ const struct GNUNET_CRYPTO_EddsaPrivateKey *key)
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL",
&default_ttl))
"MESH", "DEFAULT_TTL", "USING DEFAULT");
default_ttl = 64;
}
- my_full_id = id;
my_private_key = key;
- my_short_id = GNUNET_PEER_intern (my_full_id);
}
void
GMT_shutdown (void)
{
- GNUNET_PEER_change_rc (my_short_id, -1);
}
/**
* Create a tunnel.
+ *
+ * @param destination Peer this tunnel is towards.
*/
struct MeshTunnel3 *
-GMT_new (void)
+GMT_new (struct MeshPeer *destination)
{
struct MeshTunnel3 *t;
t = GNUNET_new (struct MeshTunnel3);
t->next_chid = 0;
- t->next_local_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
+ t->peer = destination;
// if (GNUNET_OK !=
// GNUNET_CONTAINER_multihashmap_put (tunnels, tid, t,
// GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
}
-
/**
* Change the tunnel state.
*
* @param state New state.
*/
void
-GMT_change_state (struct MeshTunnel3* t, enum MeshTunnelState state)
+GMT_change_state (struct MeshTunnel3* t, enum MeshTunnel3State state)
{
if (NULL == t)
return;
GMP_2s (t->peer),
GMT_state2s (state));
t->state = state;
+ if (MESH_TUNNEL3_READY == state && 3 <= GMT_count_connections (t))
+ {
+ GMP_stop_search (t->peer);
+ }
}
}
+/**
+ * Add a channel to a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel.
+ */
+void
+GMT_add_channel (struct MeshTunnel3 *t, struct MeshChannel *ch)
+{
+ struct MeshTChannel *aux;
+
+ for (aux = t->channel_head; aux != NULL; aux = aux->next)
+ if (aux->ch == ch)
+ return;
+
+ aux = GNUNET_new (struct MeshTChannel);
+ aux->ch = ch;
+ GNUNET_CONTAINER_DLL_insert_tail (t->channel_head, t->channel_tail, aux);
+}
+
+
+/**
+ * Remove a channel from a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel.
+ */
+void
+GMT_remove_channel (struct MeshTunnel3 *t, struct MeshChannel *ch)
+{
+ struct MeshTChannel *aux;
+
+ for (aux = t->channel_head; aux != NULL; aux = aux->next)
+ if (aux->ch == ch)
+ {
+ GNUNET_CONTAINER_DLL_remove (t->channel_head, t->channel_tail, aux);
+ GNUNET_free (aux);
+ return;
+ }
+}
+
+
+/**
+ * Search for a channel by global ID.
+ *
+ * @param t Tunnel containing the channel.
+ * @param chid Public channel number.
+ *
+ * @return channel handler, NULL if doesn't exist
+ */
+struct MeshChannel *
+GMT_get_channel (struct MeshTunnel3 *t, MESH_ChannelNumber chid)
+{
+ struct MeshTChannel *iter;
+
+ if (NULL == t)
+ return NULL;
+
+ for (iter = t->channel_head; NULL != iter; iter = iter->next)
+ {
+ if (GMCH_get_id (iter->ch) == chid)
+ break;
+ }
+
+ return NULL == iter ? NULL : iter->ch;
+}
+
+
/**
* Tunnel is empty: destroy it.
*
}
-/**
- * Notifies a tunnel that a connection has broken that affects at least
- * some of its peers. Sends a notification towards the root of the tree.
- * In case the peer is the owner of the tree, notifies the client that owns
- * the tunnel and tries to reconnect.
- *
- * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
- *
- * @param t Tunnel affected.
- * @param p1 Peer that got disconnected from p2.
- * @param p2 Peer that got disconnected from p1.
- *
- * @return Short ID of the peer disconnected (either p1 or p2).
- * 0 if the tunnel remained unaffected.
- */
-GNUNET_PEER_Id
-GMT_notify_connection_broken (struct MeshTunnel3* t,
- GNUNET_PEER_Id p1, GNUNET_PEER_Id p2)
-{
-// if (myid != p1 && myid != p2) FIXME
-// {
-// return;
-// }
-//
-// if (tree_get_predecessor (t->tree) != 0)
-// {
-// /* We are the peer still connected, notify owner of the disconnection. */
-// struct GNUNET_MESH_PathBroken msg;
-// struct GNUNET_PeerIdentity neighbor;
-//
-// msg.header.size = htons (sizeof (msg));
-// msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
-// GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-// msg.tid = htonl (t->id.tid);
-// msg.peer1 = my_full_id;
-// GNUNET_PEER_resolve (pid, &msg.peer2);
-// GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
-// send_prebuilt_message (&msg.header, &neighbor, t);
-// }
- return 0;
-}
-
/**
* @brief Use the given path for the tunnel.
* Update the next and prev hops (and RCs).
for (own_pos = 0; own_pos < p->length; own_pos++)
{
- if (p->peers[own_pos] == my_short_id)
+ if (p->peers[own_pos] == myid)
break;
}
if (own_pos > p->length - 1)
}
-/**
- * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
- * Encrypt data with the tunnel key.
- *
- * @param t Tunnel whose key to use.
- * @param dst Destination for the encrypted data.
- * @param src Source of the plaintext.
- * @param size Size of the plaintext.
- * @param iv Initialization Vector to use.
- * @param fwd Is this a fwd message?
- */
-void
-GMT_encrypt (struct MeshTunnel3 *t,
- void *dst, const void *src,
- size_t size, uint64_t iv, int fwd)
-{
- memcpy (dst, src, size);
-}
-
-
-/**
- * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
- * Decrypt data with the tunnel key.
- *
- * @param t Tunnel whose key to use.
- * @param dst Destination for the plaintext.
- * @param src Source of the encrypted data.
- * @param size Size of the encrypted data.
- * @param iv Initialization Vector to use.
- * @param fwd Is this a fwd message?
- */
-void
-GMT_decrypt (struct MeshTunnel3 *t,
- void *dst, const void *src,
- size_t size, uint64_t iv, int fwd)
-{
- memcpy (dst, src, size);
-}
-
-
/**
* Count established (ready) connections of a tunnel.
*
for (count = 0, iter = t->channel_head;
NULL != iter;
- iter = iter->next, count++);
+ iter = iter->next, count++) /* skip */;
return count;
}
+/**
+ * Get the state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's state.
+ */
+enum MeshTunnel3State
+GMT_get_state (struct MeshTunnel3 *t)
+{
+ if (NULL == t)
+ return (enum MeshTunnel3State) -1;
+ return t->state;
+}
+
/**
* Get the total buffer space for a tunnel.
*
+ * If terminal, use the biggest channel buffer (or 64) if no channel exists.
+ * If not terminal, use the sum of all connection buffers.
+ *
* @param t Tunnel.
* @param fwd Is this for FWD traffic?
*
- * @return Buffer space offered by all connections in the tunnel.
+ * @return Buffer space offered by all entities (c/ch) in the tunnel.
*/
unsigned int
GMT_get_buffer (struct MeshTunnel3 *t, int fwd)
unsigned int ch_buf;
if (NULL == t->channel_head)
+ {
+ /* Probably getting buffer for a channel create/handshake. */
return 64;
+ }
for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = iter_ch->next)
{
return buffer;
}
+
+/**
+ * Get the tunnel's destination.
+ *
+ * @param t Tunnel.
+ *
+ * @return ID of the destination peer.
+ */
+const struct GNUNET_PeerIdentity *
+GMT_get_destination (struct MeshTunnel3 *t)
+{
+ return GMP_get_id (t->peer);
+}
+
+
+/**
+ * Get the tunnel's next free global channel ID.
+ *
+ * @param t Tunnel.
+ *
+ * @return GID of a channel free to use.
+ */
+MESH_ChannelNumber
+GMT_get_next_chid (struct MeshTunnel3 *t)
+{
+ MESH_ChannelNumber chid;
+
+ 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;
+ }
+ chid = t->next_chid;
+ t->next_chid = (t->next_chid + 1) & ~GNUNET_MESH_LOCAL_CHANNEL_ID_CLI;
+
+ return chid;
+}
+
+
/**
- * Sends an already built message on a tunnel, choosing the best connection.
+ * Send ACK on one or more channels due to buffer in connections.
+ *
+ * @param t Channel which has some free buffer space.
+ * @param fwd Is this for FWD traffic? (ACK goes to root)
+ */
+void
+GMT_unchoke_channels (struct MeshTunnel3 *t, int fwd)
+{
+ struct MeshTChannel *iter;
+ unsigned int buffer;
+ unsigned int channels = GMT_count_channels (t);
+ unsigned int choked_n;
+ struct MeshChannel *choked[channels];
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_unchoke_channels on %s\n", GMT_2s (t));
+
+ if (NULL == t)
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ /* Get buffer space */
+ buffer = GMT_get_buffer (t, fwd);
+ if (0 == buffer)
+ {
+ return;
+ }
+
+ /* Count and remember choked channels */
+ choked_n = 0;
+ for (iter = t->channel_head; NULL != iter; iter = iter->next)
+ {
+ if (GNUNET_NO == GMCH_get_allowed (iter->ch, fwd))
+ {
+ choked[choked_n++] = iter->ch;
+ }
+ }
+
+ /* Unchoke random channels */
+ while (0 < buffer && 0 < choked_n)
+ {
+ unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ choked_n);
+ GMCH_allow_client (choked[r], fwd);
+ choked_n--;
+ buffer--;
+ choked[r] = choked[choked_n];
+ }
+}
+
+
+/**
+ * Send ACK on one or more connections due to buffer space to the client.
+ *
+ * Iterates all connections of the tunnel and sends ACKs appropriately.
+ *
+ * @param t Tunnel.
+ * @param fwd Is this in for FWD traffic? (ACK goes dest->root)
+ */
+void
+GMT_send_acks (struct MeshTunnel3 *t, int fwd)
+{
+ struct MeshTConnection *iter;
+ uint32_t allowed;
+ uint32_t to_allow;
+ uint32_t allow_per_connection;
+ unsigned int cs;
+ unsigned int buffer;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Tunnel send %s ACKs on %s\n",
+ fwd ? "FWD" : "BCK", GMT_2s (t));
+
+ if (NULL == t)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (NULL == t->channel_head ||
+ GNUNET_NO == GMCH_is_origin (t->channel_head->ch, !fwd))
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ buffer = GMT_get_buffer (t, fwd);
+
+ /* Count connections, how many messages are already allowed */
+ cs = GMT_count_connections (t);
+ for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
+ {
+ allowed += GMC_get_allowed (iter->c, fwd);
+ }
+
+ /* Make sure there is no overflow */
+ if (allowed > buffer)
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ /* Authorize connections to send more data */
+ to_allow = buffer; /* - allowed; */
+
+ for (iter = t->connection_head; NULL != iter && to_allow > 0; iter = iter->next)
+ {
+ allow_per_connection = to_allow/cs;
+ to_allow -= allow_per_connection;
+ cs--;
+ if (GMC_get_allowed (iter->c, fwd) > 64 / 3)
+ {
+ continue;
+ }
+ GMC_allow (iter->c, buffer, fwd);
+ }
+
+ GNUNET_break (to_allow == 0);
+}
+
+
+/**
+ * Sends an already built message on a tunnel, GMT_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 fwd Is this a fwd message?
*/
void
-GMT_send_prebuilt_message (struct GNUNET_MESH_Encrypted *msg,
+GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
struct MeshTunnel3 *t,
struct MeshChannel *ch,
int fwd)
{
struct MeshConnection *c;
+ struct GNUNET_MESH_Encrypted *msg;
+ size_t size = ntohs (message->size);
+ char *cbuf[sizeof (struct GNUNET_MESH_Encrypted) + size];
+ uint64_t iv;
uint16_t type;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Send on Tunnel %s\n", GMP_2s (t->peer));
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMP_2s (t->peer));
+
+ iv = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+ msg = (struct GNUNET_MESH_Encrypted *) cbuf;
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED);
+ msg->header.size = htons (sizeof (struct GNUNET_MESH_Encrypted) + size);
+ msg->iv = GNUNET_htonll (iv);
+ GMT_encrypt (t, &msg[1], message, size, iv, fwd);
c = tunnel_get_connection (t, fwd);
if (NULL == c)
{
GNUNET_break (GNUNET_YES == t->destroy);
return;
}
- type = ntohs (msg->header.type);
+ type = ntohs (message->type);
switch (type)
{
- case GNUNET_MESSAGE_TYPE_MESH_FWD:
- case GNUNET_MESSAGE_TYPE_MESH_BCK:
+ case GNUNET_MESSAGE_TYPE_MESH_DATA:
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;
}
msg->reserved = 0;
+ t->pending_messages++;
GMC_send_prebuilt_message (&msg->header, c, ch, fwd);
}
+
+/**
+ * Is the tunnel directed towards the local peer?
+ *
+ * @param t Tunnel.
+ *
+ * @return GNUNET_YES if it is loopback.
+ */
+int
+GMT_is_loopback (const struct MeshTunnel3 *t)
+{
+ return (myid == GMP_get_short_id(t->peer));
+}
+
+
+/**
+ * Is the tunnel using this path already?
+ *
+ * @param t Tunnel.
+ * @param p Path.
+ *
+ * @return GNUNET_YES a connection uses this path.
+ */
+int
+GMT_is_path_used (const struct MeshTunnel3 *t, const struct MeshPeerPath *p)
+{
+ struct MeshTConnection *iter;
+
+ for (iter = t->connection_head; NULL != iter; iter = iter->next)
+ if (GMC_get_path (iter->c) == p)
+ return GNUNET_YES;
+
+ return GNUNET_NO;
+}
+
+
+/**
+ * Get a cost of a path for a tunnel considering existing connections.
+ *
+ * @param t Tunnel.
+ * @param path Candidate path.
+ *
+ * @return Cost of the path (path length + number of overlapping nodes)
+ */
+unsigned int
+GMT_get_path_cost (const struct MeshTunnel3 *t,
+ const struct MeshPeerPath *path)
+{
+ struct MeshTConnection *iter;
+ unsigned int overlap;
+ unsigned int i;
+ unsigned int j;
+
+ if (NULL == path)
+ return 0;
+
+ overlap = 0;
+ GNUNET_assert (NULL != t);
+
+ for (i = 0; i < path->length; i++)
+ {
+ for (iter = t->connection_head; NULL != iter; iter = iter->next)
+ {
+ for (j = 0; j < GMC_get_path (iter->c)->length; j++)
+ {
+ if (path->peers[i] == GMC_get_path (iter->c)->peers[j])
+ {
+ overlap++;
+ break;
+ }
+ }
+ }
+ }
+ return (path->length + overlap) * (path->score * -1);
+}
+
+
+/**
+ * Get the static string for the peer this tunnel is directed.
+ *
+ * @param t Tunnel.
+ *
+ * @return Static string the destination peer's ID.
+ */
+const char *
+GMT_2s (const struct MeshTunnel3 *t)
+{
+ return GMP_2s (t->peer);
+}
\ No newline at end of file