#include "gnunet_util_lib.h"
#include "gnunet_core_service.h"
+#include "gnunet_statistics_service.h"
#include "mesh_protocol_enc.h"
#include "gnunet-service-mesh_dht.h"
#include "gnunet-service-mesh_connection.h"
#include "gnunet-service-mesh_local.h"
+#include "gnunet-service-mesh_tunnel.h"
#include "mesh_path.h"
+#define LOG(level, ...) GNUNET_log_from (level,"mesh-p2p",__VA_ARGS__)
+
/******************************************************************************/
/******************************** STRUCTS **********************************/
/******************************************************************************/
+/**
+ * Struct containing info about a queued transmission to this peer
+ */
+struct MeshPeerQueue
+{
+ /**
+ * DLL next
+ */
+ struct MeshPeerQueue *next;
+
+ /**
+ * DLL previous
+ */
+ struct MeshPeerQueue *prev;
+
+ /**
+ * Peer this transmission is directed to.
+ */
+ struct MeshPeer *peer;
+
+ /**
+ * Connection this message belongs to.
+ */
+ struct MeshConnection *c;
+
+ /**
+ * Is FWD in c?
+ */
+ int fwd;
+
+ /**
+ * Channel this message belongs to, if known.
+ */
+ struct MeshChannel *ch;
+
+ /**
+ * Pointer to info stucture used as cls.
+ */
+ void *cls;
+
+ /**
+ * Type of message
+ */
+ uint16_t type;
+
+ /**
+ * Size of the message
+ */
+ size_t size;
+
+ /**
+ * Set when this message starts waiting for CORE.
+ */
+ struct GNUNET_TIME_Absolute start_waiting;
+
+ /**
+ * Function to call on sending.
+ */
+ GMP_sent callback;
+
+ /**
+ * Closure for callback.
+ */
+ void *callback_cls;
+};
+
/**
* Struct containing all information regarding a given peer
*/
/******************************* GLOBALS ***********************************/
/******************************************************************************/
+/**
+ * Global handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
/**
* Peers known, indexed by PeerIdentity (MeshPeer).
*/
{
struct MeshPeer *aux;
struct MeshPeerPath *copy;
-
+
aux = peer_get_short (p->peers[i]);
copy = path_duplicate (p);
copy->length = i + 1;
}
if (0 < drop_percent &&
- GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent)
+ GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent)
{
LOG (GNUNET_ERROR_TYPE_WARNING,
"Dropping message of type %s\n",
data_size = 0;
}
+ if (NULL != queue->callback)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "* Calling callback\n");
+ queue->callback (queue->callback_cls,
+ queue->c,
+ GNUNET_TIME_absolute_get_duration (queue->start_waiting));
+ }
+
/* Free queue, but cls was freed by send_core_* */
ch = queue->ch;
- queue_destroy (queue, GNUNET_NO);
+ GMP_queue_destroy (queue, GNUNET_NO);
/* Send ACK if needed, after accounting for sent ID in fc->queue_n */
switch (type)
queue->size,
&queue_send,
peer);
+ queue->start_waiting = GNUNET_TIME_absolute_get ();
}
else
{
* @param c Connection this message belongs to (cannot be NULL).
* @param ch Channel this message belongs to, if applicable (otherwise NULL).
* @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
+ * @param callback Function to be called once CORE has taken the message.
+ * @param callback_cls Closure for @c callback.
*/
void
-GMP_queue_add (void *cls, uint16_t type, size_t size,
+GMP_queue_add (void *cls, uint16_t type, size_t size,
struct MeshConnection *c,
struct MeshChannel *ch,
- int fwd)
+ int fwd,
+ GMP_sent callback, void *callback_cls)
{
struct MeshPeerQueue *queue;
struct MeshFlowControl *fc;
queue->c = c;
queue->ch = ch;
queue->fwd = fwd;
+ queue->callback = callback;
+ queue->callback_cls = callback_cls;
if (100 <= priority)
{
struct MeshPeerQueue *copy;
if (copy->type == type && copy->c == c && copy->fwd == fwd)
{
/* Example: also a FWD ACK for connection XYZ */
- queue_destroy (copy, GNUNET_YES);
+ GMP_queue_destroy (copy, GNUNET_YES);
}
}
GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue);
size,
&queue_send,
peer);
+ queue->start_waiting = GNUNET_TIME_absolute_get ();
}
else
{
GMP_shutdown (void)
{
GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL);
+
+ if (core_handle != NULL)
+ {
+ GNUNET_CORE_disconnect (core_handle);
+ core_handle = NULL;
+ }
}
{
GMD_search_stop (peer->search_h);
peer->search_h = NULL;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " Stopping DHT GET for peer %s\n", peer2s (peer));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ " Stopping DHT GET for peer %s\n",
+ GMP_2s (peer));
}
if (NULL == peer->search_h)
" Starting DHT GET for peer %s\n", peer2s (peer));
peer->search_h = GMD_search (id, &search_handler, peer);
if (MESH_TUNNEL_NEW == t->state)
- tunnel_change_state (t, MESH_TUNNEL_SEARCHING);
+ GMT_change_state (t, MESH_TUNNEL_SEARCHING);
}
}
+
+/**
+ * Set tunnel.
+ *
+ * @param peer Peer.
+ * @param t Tunnel.
+ */
+void
+GMP_set_tunnel (struct MeshPeer *peer, struct MeshTunnel2 *t)
+{
+ peer->tunnel = t;
+}
+
+
+/**
+ * Chech whether there is a direct (core level) connection to peer.
+ *
+ * @param peer Peer to check.
+ *
+ * @return GNUNET_YES if there is a direct connection.
+ */
+int
+GMP_is_neighbor (const struct MeshPeer *peer)
+{
+ struct MeshPeerPath *path;
+
+ if (NULL == peer->connections)
+ return GNUNET_NO;
+
+ for (path = peer->path_head; NULL != path; path = path->next)
+ {
+ if (3 > path->length)
+ return GNUNET_YES;
+ }
+
+ GNUNET_break (0); /* Is not a neighbor but connections is not NULL */
+ return GNUNET_NO;
+}
+
+
+/**
+ * Add a connection to a neighboring peer.
+ *
+ * Store that the peer is the first hop of the connection in one
+ * direction and that on peer disconnect the connection must be
+ * notified and destroyed, for it will no longer be valid.
+ *
+ * @param peer Peer to add connection to.
+ * @param c Connection to add.
+ *
+ * @return GNUNET_OK on success.
+ */
+int
+GMP_add_connection (struct MeshPeer *peer,
+ const struct MeshConnection *c)
+{
+ if (NULL == peer->connections)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_CONTAINER_multihashmap_put (peer->connections,
+ GMC_get_id (c),
+ c,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+}
+
+
+int
+GMP_remove_connection (struct MeshPeer *peer,
+ const struct MeshConnection *c)
+{
+ if (NULL == peer || NULL == peer->connections)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_CONTAINER_multihashmap_remove (peer->connections,
+ GMC_get_id (c),
+ c);
+}
+
+/**
+ * Get the Full ID of a peer.
+ *
+ * @param peer Peer to get from.
+ *
+ * @return Full ID of peer.
+ */
+struct GNUNET_PeerIdentity *
+GMP_get_id (const struct MeshPeer *peer)
+{
+ return GNUNET_PEER_resolve2 (peer->id);
+}
+
+
+/**
+ * Get the Short ID of a peer.
+ *
+ * @param peer Peer to get from.
+ *
+ * @return Short ID of peer.
+ */
+GNUNET_PEER_Id
+GMP_get_short_id (const struct MeshPeer *peer)
+{
+ return peer->id;
+}
+
+
/**
* Get the static string for a peer ID.
*