* TODO: add regex to reconnect
*/
#include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_client_lib.h"
#include "gnunet_util_lib.h"
-#include "gnunet_peer_lib.h"
#include "gnunet_mesh_service.h"
#include "mesh.h"
#include "mesh_protocol.h"
* Time to the next reconnect in case one reconnect fails
*/
struct GNUNET_TIME_Relative reconnect_time;
-
+
/**
* Task for trying to reconnect.
*/
*/
struct GNUNET_MESH_Peer
{
- /**
- * ID of the peer in short form
- */
+ /**
+ * ID of the peer in short form
+ */
GNUNET_PEER_Id id;
/**
/**
* Flag indicating whether service has informed about its connection
+ * FIXME-BART: is this flag used? Seems dead right now...
*/
int connected;
*/
GNUNET_PEER_Id peer;
+ struct GNUNET_PeerIdentity pid;
+
/**
* Any data the caller wants to put in here
*/
/**
* Is the tunnel allowed to buffer?
*/
- int buffering;
+ int nobuffer;
/**
- * Is the tunnel allowed to buffer?
+ * Is the tunnel realiable?
*/
int reliable;
+ /**
+ * If reliable, is the tunnel out of order?
+ */
+ int ooorder;
+
/**
* Are we allowed to send to the service?
*/
/**
* Check whether there is any message ready in the queue and find the size.
- *
+ *
* @param h Mesh handle.
- *
+ *
* @return The size of the first ready message in the queue,
* 0 if there is none.
*/
t->tid = tid;
}
t->allow_send = GNUNET_NO;
- t->buffering = GNUNET_YES;
+ t->nobuffer = GNUNET_NO;
return t;
}
struct GNUNET_MESH_TransmitHandle *th;
struct GNUNET_MESH_TransmitHandle *next;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
-
if (NULL == t)
{
GNUNET_break (0);
return;
}
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "destroy_tunnel %X\n",
+ t->tid);
h = t->mesh;
GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
/* clean up request */
if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
GNUNET_SCHEDULER_cancel (th->timeout_task);
- GNUNET_free (th);
+ GNUNET_free (th);
}
/* if there are no more pending requests with mesh service, cancel active request */
/**
* Notify client that the transmission has timed out
- *
+ *
* @param cls closure
* @param tc task context
*/
struct GNUNET_MESH_TransmitHandle *th)
{
GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
- if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
+ if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == th->timeout.abs_value_us)
return;
th->timeout_task =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
/**
* Send an ack on the tunnel to confirm the processing of a message.
- *
+ *
* @param t Tunnel on which to send the ACK.
*/
static void
GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
GNUNET_TIME_relative_multiply
(h->reconnect_time, 2));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
"Next retry in %s\n",
GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
GNUNET_NO));
tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
tmsg.tunnel_id = htonl (t->tid);
tmsg.port = htonl (t->port);
+ t->pid = tmsg.peer;
GNUNET_PEER_resolve (t->peer, &tmsg.peer);
options = 0;
- if (GNUNET_NO == t->buffering)
+ if (GNUNET_YES == t->nobuffer)
options |= GNUNET_MESH_OPTION_NOBUFFER;
if (GNUNET_YES == t->reliable)
{
struct GNUNET_MESH_Tunnel *t;
MESH_TunnelNumber tid;
+ uint32_t port;
tid = ntohl (msg->tunnel_id);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
+ port = ntohl (msg->port);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X:%u\n", tid, port);
if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
{
GNUNET_break (0);
t = create_tunnel (h, tid);
t->allow_send = GNUNET_NO;
t->peer = GNUNET_PEER_intern (&msg->peer);
+ t->pid = msg->peer;
t->mesh = h;
t->tid = tid;
- t->port = ntohl (msg->port);
+ t->port = port;
if (0 != (msg->opt & GNUNET_MESH_OPTION_NOBUFFER))
- t->buffering = GNUNET_NO;
+ t->nobuffer = GNUNET_YES;
else
- t->buffering = GNUNET_YES;
+ t->nobuffer = GNUNET_NO;
if (0 != (msg->opt & GNUNET_MESH_OPTION_RELIABLE))
t->reliable = GNUNET_YES;
else
t->reliable = GNUNET_NO;
+ if (GNUNET_YES == t->reliable &&
+ 0 != (msg->opt & GNUNET_MESH_OPTION_OOORDER))
+ t->ooorder = GNUNET_YES;
+ else
+ t->ooorder = GNUNET_NO;
LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t);
t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port);
LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
struct GNUNET_MESH_Tunnel *t;
MESH_TunnelNumber tid;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel from service\n");
tid = ntohl (msg->tunnel_id);
t = retrieve_tunnel (h, tid);
if (NULL == t)
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X unknown\n", tid);
return;
}
LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
destroy_tunnel (t, GNUNET_YES);
- return;
}
{
const struct GNUNET_MessageHeader *payload;
const struct GNUNET_MESH_MessageHandler *handler;
- const struct GNUNET_PeerIdentity *peer;
- struct GNUNET_PeerIdentity id;
struct GNUNET_MESH_LocalData *dmsg;
struct GNUNET_MESH_Tunnel *t;
unsigned int i;
t = retrieve_tunnel (h, ntohl (dmsg->tid));
payload = (struct GNUNET_MessageHeader *) &dmsg[1];
- GNUNET_PEER_resolve (t->peer, &id);
- peer = &id;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on tunnel %s [%X]\n",
- t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV ? "fwd" : "bck",
- GNUNET_i2s (peer), ntohl (dmsg->tid));
if (NULL == t)
{
/* Tunnel was ignored/destroyed, probably service didn't get it yet */
LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n");
return;
}
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ " %s data on tunnel %s [%X]\n",
+ t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV ? "fwd" : "bck",
+ GNUNET_i2s (GNUNET_PEER_resolve2(t->peer)),
+ ntohl (dmsg->tid));
type = ntohs (payload->type);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " payload type %u\n", type);
for (i = 0; i < h->n_handlers; i++)
{
handler = &h->message_handlers[i];
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ " checking handler for type %u\n",
+ handler->type);
if (handler->type == type)
{
if (GNUNET_OK !=
/**
* Process a local ACK message, enabling the client to send
* more data to the service.
- *
+ *
* @param h Mesh handle.
* @param message Message itself.
*/
msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
{
struct GNUNET_MESH_Handle *h = cls;
+ uint16_t type;
if (msg == NULL)
{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
"Mesh service disconnected, reconnecting\n", h);
reconnect (h);
return;
}
- LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
- GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
+ type = ntohs (msg->type);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
- GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
- switch (ntohs (msg->type))
+ GNUNET_MESH_DEBUG_M2S (type));
+ switch (type)
{
/* Notify of a new incoming tunnel */
case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
continue;
}
t->packet_size = 0;
- t->allow_send = GNUNET_NO;
GNUNET_assert (size >= th->size);
dmsg = (struct GNUNET_MESH_LocalData *) cbuf;
mh = (struct GNUNET_MessageHeader *) &dmsg[1];
GNUNET_assert (size >= psize);
dmsg->header.size = htons (psize);
dmsg->tid = htonl (t->tid);
+ dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload type %s\n",
+ GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
+ t->allow_send = GNUNET_NO;
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "# callback returned size 0, "
+ "application canceled transmission\n");
}
- dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload type %s\n",
- GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-
}
else
{
struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
- LOG (GNUNET_ERROR_TYPE_DEBUG, "# mesh traffic, type %s\n",
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "# mesh internal traffic, type %s\n",
GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
memcpy (cbuf, &th[1], th->size);
psize = th->size;
* Auxiliary function to send an already constructed packet to the service.
* Takes care of creating a new queue element, copying the message and
* calling the tmt_rdy function if necessary.
- *
+ *
* @param h mesh handle
* @param msg message to transmit
* @param tunnel tunnel this send is related to (NULL if N/A)
h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ if (NULL != ports && ports[0] != 0 && NULL == new_tunnel)
+ {
+ GNUNET_break (0);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "no new tunnel handler given, ports parameter is useless!!\n");
+ }
+ if ((NULL == ports || ports[0] == 0) && NULL != new_tunnel)
+ {
+ GNUNET_break (0);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "no ports given, new tunnel handler will never be called!!\n");
+ }
/* count handlers */
for (h->n_handlers = 0;
handlers && handlers[h->n_handlers].type;
* @param tunnel_ctx client's tunnel context to associate with the tunnel
* @param peer peer identity the tunnel should go to
* @param port Port number.
- * @param buffer Flag for buffering on relay nodes.
+ * @param nobuffer Flag for disabling buffering on relay nodes.
* @param reliable Flag for end-to-end reliability.
*
* @return handle to the tunnel
*/
struct GNUNET_MESH_Tunnel *
-GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h,
+GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h,
void *tunnel_ctx,
const struct GNUNET_PeerIdentity *peer,
uint32_t port,
- int buffer,
+ int nobuffer,
int reliable)
{
struct GNUNET_MESH_Tunnel *t;
struct GNUNET_MESH_TunnelMessage msg;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating new tunnel to %s:%u\n",
+ GNUNET_i2s (peer), port);
t = create_tunnel (h, 0);
LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", t);
LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", t->tid);
t->ctx = tunnel_ctx;
t->peer = GNUNET_PEER_intern (peer);
+ t->pid = *peer;
msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
msg.tunnel_id = htonl (t->tid);
msg.opt = 0;
if (GNUNET_YES == reliable)
msg.opt |= GNUNET_MESH_OPTION_RELIABLE;
- if (GNUNET_NO == buffer)
+ if (GNUNET_YES == nobuffer)
msg.opt |= GNUNET_MESH_OPTION_NOBUFFER;
msg.opt = htonl (msg.opt);
t->allow_send = 0;
* Get information about a tunnel.
*
* @param tunnel Tunnel handle.
- *
- * @return Allocated, {0, NULL} terminated set of tunnel properties.
+ * @param option Query (GNUNET_MESH_OPTION_*).
+ * @param ... dependant on option, currently not used
+ *
+ * @return Union with an answer to the query.
*/
-struct MeshTunnelInfo *
-GNUNET_MESH_tunnel_get_info (struct GNUNET_MESH_Tunnel *tunnel)
+const union GNUNET_MESH_TunnelInfo *
+GNUNET_MESH_tunnel_get_info (struct GNUNET_MESH_Tunnel *tunnel,
+ enum MeshTunnelOption option, ...)
{
- struct MeshTunnelInfo *ret;
+ const union GNUNET_MESH_TunnelInfo *ret;
- ret = GNUNET_malloc (sizeof (struct MeshTunnelInfo) * 3);
- ret[0].prop = GNUNET_MESH_OPTION_NOBUFFER;
- ret[0].value = &tunnel->buffering; // FIXME use "nobuffer"
- ret[1].prop = GNUNET_MESH_OPTION_RELIABLE;
- ret[1].value = &tunnel->reliable;
- ret[2].prop = 0;
- ret[2].value = NULL;
+ switch (option)
+ {
+ case GNUNET_MESH_OPTION_NOBUFFER:
+ ret = (const union GNUNET_MESH_TunnelInfo *) &tunnel->nobuffer;
+ break;
+ case GNUNET_MESH_OPTION_RELIABLE:
+ ret = (const union GNUNET_MESH_TunnelInfo *) &tunnel->reliable;
+ break;
+ case GNUNET_MESH_OPTION_OOORDER:
+ ret = (const union GNUNET_MESH_TunnelInfo *) &tunnel->ooorder;
+ break;
+ case GNUNET_MESH_OPTION_PEER:
+ ret = (const union GNUNET_MESH_TunnelInfo *) &tunnel->pid;
+ break;
+ default:
+ GNUNET_break (0);
+ return NULL;
+ }
return ret;
}
mesh_mq_ntr (void *cls, size_t size,
void *buf)
{
- struct GNUNET_MQ_Handle *mq = cls;
+ struct GNUNET_MQ_Handle *mq = cls;
struct MeshMQState *state = GNUNET_MQ_impl_state (mq);
const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq);
uint16_t msize;
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "mesh-mq",
+ "writing message (t: %u, s: %u) to buffer\n",
+ ntohs (msg->type), ntohs (msg->size));
+
state->th = NULL;
if (NULL == buf)
{
GNUNET_assert (NULL == state->th);
GNUNET_MQ_impl_send_commit (mq);
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "mesh-mq",
+ "calling ntr for message (t: %u, s: %u)\n",
+ ntohs (msg->type), ntohs (msg->size));
state->th =
GNUNET_MESH_notify_transmit_ready (state->tunnel,
/* FIXME: add option for corking */
GNUNET_NO,
- GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_TIME_UNIT_FOREVER_REL,
ntohs (msg->size),
mesh_mq_ntr, mq);
* destruction of a message queue.
* Implementations must not free 'mq', but should
* take care of 'impl_state'.
- *
+ *
* @param mq the message queue to destroy
* @param impl_state state of the implementation
*/