X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Fmesh_api.c;h=0ff46f01c6be553b397a879d01596fda7b5a11b7;hb=e43078b68951ad8a3daa3a193473e9c321549e1d;hp=186961e6cac73e907ce4cfa821f1c703fbf6dbf3;hpb=0e44af8a33393dec3ec7ca13b38bacfa953d5d93;p=oweals%2Fgnunet.git diff --git a/src/mesh/mesh_api.c b/src/mesh/mesh_api.c index 186961e6c..0ff46f01c 100644 --- a/src/mesh/mesh_api.c +++ b/src/mesh/mesh_api.c @@ -19,28 +19,15 @@ * @file mesh/mesh_api.c * @brief mesh api: client implementation of new mesh service * @author Bartlomiej Polot - * - * STRUCTURE: - * - DATA STRUCTURES - * - DECLARATIONS - * - AUXILIARY FUNCTIONS - * - RECEIVE HANDLERS - * - SEND FUNCTIONS - * - API CALL DEFINITIONS - * - * 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" #define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__) -#define DEBUG_ACK GNUNET_YES /******************************************************************************/ /************************ DATA STRUCTURES ****************************/ @@ -63,9 +50,9 @@ struct GNUNET_MESH_TransmitHandle struct GNUNET_MESH_TransmitHandle *prev; /** - * Tunnel this message is sent on / for (may be NULL for control messages). + * Channel this message is sent on / for (may be NULL for control messages). */ - struct GNUNET_MESH_Tunnel *tunnel; + struct GNUNET_MESH_Channel *channel; /** * Callback to obtain the message to transmit, or NULL if we @@ -112,7 +99,7 @@ struct GNUNET_MESH_Handle struct GNUNET_CLIENT_Connection *client; /** - * Set of handlers used for processing incoming messages in the tunnels + * Set of handlers used for processing incoming messages in the channels */ const struct GNUNET_MESH_MessageHandler *message_handlers; @@ -132,24 +119,24 @@ struct GNUNET_MESH_Handle unsigned int n_ports; /** - * Double linked list of the tunnels this client is connected to, head. + * Double linked list of the channels this client is connected to, head. */ - struct GNUNET_MESH_Tunnel *tunnels_head; + struct GNUNET_MESH_Channel *channels_head; /** - * Double linked list of the tunnels this client is connected to, tail. + * Double linked list of the channels this client is connected to, tail. */ - struct GNUNET_MESH_Tunnel *tunnels_tail; + struct GNUNET_MESH_Channel *channels_tail; /** - * Callback for inbound tunnel creation + * Callback for inbound channel creation */ - GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel; + GNUNET_MESH_InboundChannelNotificationHandler *new_channel; /** - * Callback for inbound tunnel disconnection + * Callback for inbound channel disconnection */ - GNUNET_MESH_TunnelEndHandler *cleaner; + GNUNET_MESH_ChannelEndHandler *cleaner; /** * Handle to cancel pending transmissions in case of disconnection @@ -172,9 +159,9 @@ struct GNUNET_MESH_Handle struct GNUNET_MESH_TransmitHandle *th_tail; /** - * tid of the next tunnel to create (to avoid reusing IDs often) + * chid of the next channel to create (to avoid reusing IDs often) */ - MESH_TunnelNumber next_tid; + MESH_ChannelNumber next_chid; /** * Have we started the task to receive messages from the service @@ -191,12 +178,42 @@ struct GNUNET_MESH_Handle * Time to the next reconnect in case one reconnect fails */ struct GNUNET_TIME_Relative reconnect_time; - + /** * Task for trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; + /** + * Monitor callback + */ + GNUNET_MESH_ChannelsCB channels_cb; + + /** + * Monitor callback closure. + */ + void *channels_cls; + + /** + * Channel callback. + */ + GNUNET_MESH_ChannelCB channel_cb; + + /** + * Channel callback closure. + */ + void *channel_cls; + + /** + * Monitor callback + */ + GNUNET_MESH_PeersCB peers_cb; + + /** + * Monitor callback closure. + */ + void *peers_cls; + /** * Monitor callback */ @@ -216,11 +233,6 @@ struct GNUNET_MESH_Handle * Tunnel callback closure. */ void *tunnel_cls; - -#if DEBUG_ACK - unsigned int acks_sent; - unsigned int acks_recv; -#endif }; @@ -235,43 +247,37 @@ struct GNUNET_MESH_Peer GNUNET_PEER_Id id; /** - * Tunnel this peer belongs to - */ - struct GNUNET_MESH_Tunnel *t; - - /** - * Flag indicating whether service has informed about its connection + * Channel this peer belongs to */ - int connected; - + struct GNUNET_MESH_Channel *t; }; /** - * Opaque handle to a tunnel. + * Opaque handle to a channel. */ -struct GNUNET_MESH_Tunnel +struct GNUNET_MESH_Channel { /** * DLL next */ - struct GNUNET_MESH_Tunnel *next; + struct GNUNET_MESH_Channel *next; /** * DLL prev */ - struct GNUNET_MESH_Tunnel *prev; + struct GNUNET_MESH_Channel *prev; /** - * Handle to the mesh this tunnel belongs to + * Handle to the mesh this channel belongs to */ struct GNUNET_MESH_Handle *mesh; /** - * Local ID of the tunnel + * Local ID of the channel */ - MESH_TunnelNumber tid; + MESH_ChannelNumber chid; /** * Port number. @@ -279,7 +285,7 @@ struct GNUNET_MESH_Tunnel uint32_t port; /** - * Other end of the tunnel. + * Other end of the channel. */ GNUNET_PEER_Id peer; @@ -289,19 +295,14 @@ struct GNUNET_MESH_Tunnel void *ctx; /** - * Size of packet queued in this tunnel + * Size of packet queued in this channel */ unsigned int packet_size; /** - * Is the tunnel allowed to buffer? - */ - int buffering; - - /** - * Is the tunnel allowed to buffer? + * Channel options: reliability, etc. */ - int reliable; + enum GNUNET_MESH_ChannelOption options; /** * Are we allowed to send to the service? @@ -323,9 +324,9 @@ struct MeshMQState struct GNUNET_MESH_TransmitHandle *th; /** - * Tunnel to send the data over. + * Channel to send the data over. */ - struct GNUNET_MESH_Tunnel *tunnel; + struct GNUNET_MESH_Channel *channel; }; @@ -368,9 +369,9 @@ th_is_payload (struct GNUNET_MESH_TransmitHandle *th) /** * 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. */ @@ -378,17 +379,17 @@ static size_t message_ready_size (struct GNUNET_MESH_Handle *h) { struct GNUNET_MESH_TransmitHandle *th; - struct GNUNET_MESH_Tunnel *t; + struct GNUNET_MESH_Channel *ch; for (th = h->th_head; NULL != th; th = th->next) { - t = th->tunnel; + ch = th->channel; if (GNUNET_NO == th_is_payload (th)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "# message internal\n"); return th->size; } - if (GNUNET_YES == t->allow_send) + if (GNUNET_YES == ch->allow_send) { LOG (GNUNET_ERROR_TYPE_DEBUG, "# message payload ok\n"); return th->size; @@ -399,110 +400,117 @@ message_ready_size (struct GNUNET_MESH_Handle *h) /** - * Get the tunnel handler for the tunnel specified by id from the given handle + * Get the channel handler for the channel specified by id from the given handle * @param h Mesh handle - * @param tid ID of the wanted tunnel - * @return handle to the required tunnel or NULL if not found + * @param chid ID of the wanted channel + * @return handle to the required channel or NULL if not found */ -static struct GNUNET_MESH_Tunnel * -retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid) +static struct GNUNET_MESH_Channel * +retrieve_channel (struct GNUNET_MESH_Handle *h, MESH_ChannelNumber chid) { - struct GNUNET_MESH_Tunnel *t; + struct GNUNET_MESH_Channel *ch; - t = h->tunnels_head; - while (t != NULL) + ch = h->channels_head; + while (ch != NULL) { - if (t->tid == tid) - return t; - t = t->next; + if (ch->chid == chid) + return ch; + ch = ch->next; } return NULL; } /** - * Create a new tunnel and insert it in the tunnel list of the mesh handle + * Create a new channel and insert it in the channel list of the mesh handle + * * @param h Mesh handle - * @param tid desired tid of the tunnel, 0 to assign one automatically - * @return handle to the created tunnel + * @param chid Desired chid of the channel, 0 to assign one automatically. + * + * @return Handle to the created channel. */ -static struct GNUNET_MESH_Tunnel * -create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid) +static struct GNUNET_MESH_Channel * +create_channel (struct GNUNET_MESH_Handle *h, MESH_ChannelNumber chid) { - struct GNUNET_MESH_Tunnel *t; + struct GNUNET_MESH_Channel *ch; - t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel)); - GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t); - t->mesh = h; - if (0 == tid) + ch = GNUNET_new (struct GNUNET_MESH_Channel); + GNUNET_CONTAINER_DLL_insert (h->channels_head, h->channels_tail, ch); + ch->mesh = h; + if (0 == chid) { - t->tid = h->next_tid; - while (NULL != retrieve_tunnel (h, h->next_tid)) + ch->chid = h->next_chid; + while (NULL != retrieve_channel (h, h->next_chid)) { - h->next_tid++; - h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; + h->next_chid++; + h->next_chid &= ~GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; + h->next_chid |= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI; } } else { - t->tid = tid; + ch->chid = chid; } - t->allow_send = GNUNET_NO; - t->buffering = GNUNET_YES; - return t; + ch->allow_send = GNUNET_NO; + return ch; } /** - * Destroy the specified tunnel. + * Destroy the specified channel. * - Destroys all peers, calling the disconnect callback on each if needed - * - Cancels all outgoing traffic for that tunnel, calling respective notifys - * - Calls cleaner if tunnel was inbound + * - Cancels all outgoing traffic for that channel, calling respective notifys + * - Calls cleaner if channel was inbound * - Frees all memory used * - * @param t Pointer to the tunnel. + * @param ch Pointer to the channel. * @param call_cleaner Whether to call the cleaner handler. * - * @return Handle to the required tunnel or NULL if not found. + * @return Handle to the required channel or NULL if not found. */ static void -destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner) +destroy_channel (struct GNUNET_MESH_Channel *ch, int call_cleaner) { struct GNUNET_MESH_Handle *h; struct GNUNET_MESH_TransmitHandle *th; struct GNUNET_MESH_TransmitHandle *next; - LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid); + LOG (GNUNET_ERROR_TYPE_DEBUG, " destroy_channel %X\n", ch->chid); - if (NULL == t) + if (NULL == ch) { GNUNET_break (0); return; } - h = t->mesh; + h = ch->mesh; - GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t); + GNUNET_CONTAINER_DLL_remove (h->channels_head, h->channels_tail, ch); - /* signal tunnel destruction */ - if ( (NULL != h->cleaner) && (0 != t->peer) && (GNUNET_YES == call_cleaner) ) - h->cleaner (h->cls, t, t->ctx); + /* signal channel destruction */ + if ( (NULL != h->cleaner) && (0 != ch->peer) && (GNUNET_YES == call_cleaner) ) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cleaner\n"); + h->cleaner (h->cls, ch, ch->ctx); + } /* check that clients did not leave messages behind in the queue */ for (th = h->th_head; NULL != th; th = next) { next = th->next; - if (th->tunnel != t) + if (th->channel != ch) continue; /* Clients should have aborted their requests already. - * Management traffic should be ok, as clients can't cancel that */ - GNUNET_break (GNUNET_NO == th_is_payload(th)); + * Management traffic should be ok, as clients can't cancel that. + * If the service crashed and we are reconnecting, it's ok. + */ + GNUNET_break (GNUNET_NO == th_is_payload (th) + || GNUNET_NO == h->in_receive); GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); /* 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 */ @@ -513,16 +521,16 @@ destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner) h->th = NULL; } - if (0 != t->peer) - GNUNET_PEER_change_rc (t->peer, -1); - GNUNET_free (t); + if (0 != ch->peer) + GNUNET_PEER_change_rc (ch->peer, -1); + GNUNET_free (ch); return; } /** * Notify client that the transmission has timed out - * + * * @param cls closure * @param tc task context */ @@ -532,9 +540,9 @@ timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct GNUNET_MESH_TransmitHandle *th = cls; struct GNUNET_MESH_Handle *mesh; - mesh = th->tunnel->mesh; + mesh = th->channel->mesh; GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th); - th->tunnel->packet_size = 0; + th->channel->packet_size = 0; if (GNUNET_YES == th_is_payload (th)) th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); @@ -559,7 +567,7 @@ add_to_queue (struct GNUNET_MESH_Handle *h, 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 @@ -574,34 +582,30 @@ add_to_queue (struct GNUNET_MESH_Handle *h, * * @param h mesh handle * @param msg message to transmit - * @param tunnel tunnel this send is related to (NULL if N/A) + * @param channel channel this send is related to (NULL if N/A) */ static void send_packet (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *msg, - struct GNUNET_MESH_Tunnel *tunnel); + struct GNUNET_MESH_Channel *channel); /** - * Send an ack on the tunnel to confirm the processing of a message. - * - * @param t Tunnel on which to send the ACK. + * Send an ack on the channel to confirm the processing of a message. + * + * @param ch Channel on which to send the ACK. */ static void -send_ack (struct GNUNET_MESH_Tunnel *t) +send_ack (struct GNUNET_MESH_Channel *ch) { struct GNUNET_MESH_LocalAck msg; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on tunnel %X\n", t->tid); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on channel %X\n", ch->chid); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); msg.header.size = htons (sizeof (msg)); - msg.tunnel_id = htonl (t->tid); - -#if DEBUG_ACK - t->mesh->acks_sent++; -#endif + msg.channel_id = htonl (ch->chid); - send_packet (t->mesh, &msg.header, t); + send_packet (ch->mesh, &msg.header, ch); return; } @@ -667,8 +671,6 @@ send_connect (struct GNUNET_MESH_Handle *h) static int do_reconnect (struct GNUNET_MESH_Handle *h) { - struct GNUNET_MESH_Tunnel *t; - LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); @@ -696,10 +698,9 @@ do_reconnect (struct GNUNET_MESH_Handle *h) GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, GNUNET_TIME_relative_multiply (h->reconnect_time, 2)); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Next retry in %s\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, "Next retry in %s\n", GNUNET_STRINGS_relative_time_to_string (h->reconnect_time, - GNUNET_NO)); + GNUNET_NO)); GNUNET_break (0); return GNUNET_NO; } @@ -708,37 +709,6 @@ do_reconnect (struct GNUNET_MESH_Handle *h) h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; } send_connect (h); - /* Rebuild all tunnels */ - for (t = h->tunnels_head; NULL != t; t = t->next) - { - struct GNUNET_MESH_TunnelMessage tmsg; - uint32_t options; - - if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - /* Tunnel was created by service (incoming tunnel) */ - /* TODO: Notify service of missing tunnel, to request - * creator to recreate path (find a path to him via DHT?) - */ - continue; - } - t->allow_send = GNUNET_NO; - tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); - tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - tmsg.tunnel_id = htonl (t->tid); - tmsg.port = htonl (t->port); - GNUNET_PEER_resolve (t->peer, &tmsg.peer); - - options = 0; - if (GNUNET_NO == t->buffering) - options |= GNUNET_MESH_OPTION_NOBUFFER; - - if (GNUNET_YES == t->reliable) - options |= GNUNET_MESH_OPTION_RELIABLE; - - tmsg.opt = htonl (options); - send_packet (h, &tmsg.header, t); - } return GNUNET_YES; } @@ -771,8 +741,17 @@ reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void reconnect (struct GNUNET_MESH_Handle *h) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n"); + struct GNUNET_MESH_Channel *ch; + struct GNUNET_MESH_Channel *next; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Requested RECONNECT, destroying all channels\n"); h->in_receive = GNUNET_NO; + for (ch = h->channels_head; NULL != ch; ch = next) + { + next = ch->next; + destroy_channel (ch, GNUNET_YES); + } if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task) h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, &reconnect_cbk, h); @@ -784,54 +763,54 @@ reconnect (struct GNUNET_MESH_Handle *h) /******************************************************************************/ /** - * Process the new tunnel notification and add it to the tunnels in the handle + * Process the new channel notification and add it to the channels in the handle * * @param h The mesh handle - * @param msg A message with the details of the new incoming tunnel + * @param msg A message with the details of the new incoming channel */ static void -process_tunnel_created (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MESH_TunnelMessage *msg) +process_channel_created (struct GNUNET_MESH_Handle *h, + const struct GNUNET_MESH_ChannelMessage *msg) { - struct GNUNET_MESH_Tunnel *t; - MESH_TunnelNumber tid; + struct GNUNET_MESH_Channel *ch; + MESH_ChannelNumber chid; + uint32_t port; - tid = ntohl (msg->tunnel_id); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid); - if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) + chid = ntohl (msg->channel_id); + port = ntohl (msg->port); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X:%u\n", chid, port); + if (chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) { GNUNET_break (0); return; } - if (NULL != h->new_tunnel) + if (NULL != h->new_channel) { - t = create_tunnel (h, tid); - t->allow_send = GNUNET_NO; - t->peer = GNUNET_PEER_intern (&msg->peer); - t->mesh = h; - t->tid = tid; - t->port = ntohl (msg->port); - if (0 != (msg->opt & GNUNET_MESH_OPTION_NOBUFFER)) - t->buffering = GNUNET_NO; - else - t->buffering = GNUNET_YES; - if (0 != (msg->opt & GNUNET_MESH_OPTION_RELIABLE)) - t->reliable = GNUNET_YES; - else - t->reliable = GNUNET_NO; - LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t); - t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port); + void *ctx; + + ch = create_channel (h, chid); + ch->allow_send = GNUNET_NO; + ch->peer = GNUNET_PEER_intern (&msg->peer); + ch->mesh = h; + ch->chid = chid; + ch->port = port; + ch->options = ntohl (msg->opt); + + LOG (GNUNET_ERROR_TYPE_DEBUG, " created channel %p\n", ch); + ctx = h->new_channel (h->cls, ch, &msg->peer, ch->port, ch->options); + if (NULL != ctx) + ch->ctx = ctx; LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n"); } else { - struct GNUNET_MESH_TunnelMessage d_msg; + struct GNUNET_MESH_ChannelMessage d_msg; - LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming channels\n"); - d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); - d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - d_msg.tunnel_id = msg->tunnel_id; + d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY); + d_msg.header.size = htons (sizeof (struct GNUNET_MESH_ChannelMessage)); + d_msg.channel_id = msg->channel_id; memset (&d_msg.peer, 0, sizeof (struct GNUNET_PeerIdentity)); d_msg.port = 0; d_msg.opt = 0; @@ -843,28 +822,29 @@ process_tunnel_created (struct GNUNET_MESH_Handle *h, /** - * Process the tunnel destroy notification and free associated resources + * Process the channel destroy notification and free associated resources * * @param h The mesh handle - * @param msg A message with the details of the tunnel being destroyed + * @param msg A message with the details of the channel being destroyed */ static void -process_tunnel_destroy (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MESH_TunnelMessage *msg) +process_channel_destroy (struct GNUNET_MESH_Handle *h, + const struct GNUNET_MESH_ChannelMessage *msg) { - struct GNUNET_MESH_Tunnel *t; - MESH_TunnelNumber tid; + struct GNUNET_MESH_Channel *ch; + MESH_ChannelNumber chid; - tid = ntohl (msg->tunnel_id); - t = retrieve_tunnel (h, tid); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel Destroy received from service\n"); + chid = ntohl (msg->channel_id); + ch = retrieve_channel (h, chid); - if (NULL == t) + if (NULL == ch) { + LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X unknown\n", chid); return; } - LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid); - destroy_tunnel (t, GNUNET_YES); - return; + LOG (GNUNET_ERROR_TYPE_DEBUG, " destroying channel %X\n", ch->chid); + destroy_channel (ch, GNUNET_YES); } @@ -880,47 +860,51 @@ process_incoming_data (struct GNUNET_MESH_Handle *h, { 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; + struct GNUNET_MESH_Channel *ch; + size_t size; unsigned int i; uint16_t type; LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n"); - dmsg = (struct GNUNET_MESH_LocalData *) message; - - t = retrieve_tunnel (h, ntohl (dmsg->tid)); + ch = retrieve_channel (h, ntohl (dmsg->id)); 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) + LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on channel %s [%X]\n", + GM_f2s (ch->chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV), + GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), ntohl (dmsg->id)); + + size = ntohs (message->size); + LOG (GNUNET_ERROR_TYPE_DEBUG, " %u bytes\n", size); + + if (NULL == ch) { - /* Tunnel was ignored/destroyed, probably service didn't get it yet */ + /* Channel was ignored/destroyed, probably service didn't get it yet */ LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n"); return; } type = ntohs (payload->type); + size = ntohs (payload->size); + LOG (GNUNET_ERROR_TYPE_DEBUG, " payload type %s\n", GM_m2s (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 != - handler->callback (h->cls, t, &t->ctx, payload)) + handler->callback (h->cls, ch, &ch->ctx, payload)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n"); - GNUNET_MESH_tunnel_destroy (t); + GNUNET_MESH_channel_destroy (ch); return; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "callback completed successfully\n"); + return; } } } @@ -930,7 +914,7 @@ process_incoming_data (struct GNUNET_MESH_Handle *h, /** * Process a local ACK message, enabling the client to send * more data to the service. - * + * * @param h Mesh handle. * @param message Message itself. */ @@ -939,33 +923,118 @@ process_ack (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalAck *msg; - struct GNUNET_MESH_Tunnel *t; - MESH_TunnelNumber tid; + struct GNUNET_MESH_Channel *ch; + MESH_ChannelNumber chid; LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n"); - h->acks_recv++; msg = (struct GNUNET_MESH_LocalAck *) message; - tid = ntohl (msg->tunnel_id); - t = retrieve_tunnel (h, tid); - if (NULL == t) + chid = ntohl (msg->channel_id); + ch = retrieve_channel (h, chid); + if (NULL == ch) { - LOG (GNUNET_ERROR_TYPE_WARNING, "ACK on unknown tunnel %X\n", tid); + LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK on unknown channel %X\n", chid); return; } - LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X!\n", t->tid); - t->allow_send = GNUNET_YES; - if (NULL == h->th && 0 < t->packet_size) + LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X!\n", ch->chid); + ch->allow_send = GNUNET_YES; + if (NULL == h->th && 0 < ch->packet_size) { LOG (GNUNET_ERROR_TYPE_DEBUG, " tmt rdy was NULL, requesting!\n"); - h->th = - GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size, - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, &send_callback, h); + h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ch->packet_size, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, &send_callback, h); } } -/** +/* + * Process a local reply about info on all channels, pass info to the user. + * + * @param h Mesh handle. + * @param message Message itself. + */ +// static void +// process_get_channels (struct GNUNET_MESH_Handle *h, +// const struct GNUNET_MessageHeader *message) +// { +// struct GNUNET_MESH_LocalInfo *msg; +// +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Channels messasge received\n"); +// +// if (NULL == h->channels_cb) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); +// return; +// } +// +// msg = (struct GNUNET_MESH_LocalInfo *) message; +// if (ntohs (message->size) != +// (sizeof (struct GNUNET_MESH_LocalInfo) + +// sizeof (struct GNUNET_PeerIdentity))) +// { +// GNUNET_break_op (0); +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Get channels message: size %hu - expected %u\n", +// ntohs (message->size), +// sizeof (struct GNUNET_MESH_LocalInfo)); +// return; +// } +// h->channels_cb (h->channels_cls, +// ntohl (msg->channel_id), +// &msg->owner, +// &msg->destination); +// } + + + +/* + * Process a local monitor_channel reply, pass info to the user. + * + * @param h Mesh handle. + * @param message Message itself. + */ +// static void +// process_show_channel (struct GNUNET_MESH_Handle *h, +// const struct GNUNET_MessageHeader *message) +// { +// struct GNUNET_MESH_LocalInfo *msg; +// size_t esize; +// +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Channel messasge received\n"); +// +// if (NULL == h->channel_cb) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); +// return; +// } +// +// /* Verify message sanity */ +// msg = (struct GNUNET_MESH_LocalInfo *) message; +// esize = sizeof (struct GNUNET_MESH_LocalInfo); +// if (ntohs (message->size) != esize) +// { +// GNUNET_break_op (0); +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Show channel message: size %hu - expected %u\n", +// ntohs (message->size), +// esize); +// +// h->channel_cb (h->channel_cls, NULL, NULL); +// h->channel_cb = NULL; +// h->channel_cls = NULL; +// +// return; +// } +// +// h->channel_cb (h->channel_cls, +// &msg->destination, +// &msg->owner); +// } + + + + +/* * Process a local reply about info on all tunnels, pass info to the user. * * @param h Mesh handle. @@ -975,80 +1044,96 @@ static void process_get_tunnels (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { - struct GNUNET_MESH_LocalMonitor *msg; + struct GNUNET_MESH_LocalInfoTunnel *msg; + uint16_t size; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnels messasge received\n"); if (NULL == h->tunnels_cb) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); return; } - msg = (struct GNUNET_MESH_LocalMonitor *) message; - if (ntohs (message->size) != - (sizeof (struct GNUNET_MESH_LocalMonitor) + - sizeof (struct GNUNET_PeerIdentity))) + size = ntohs (message->size); + if (sizeof (struct GNUNET_MESH_LocalInfoTunnel) > size) { - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Get tunnels message: size %hu - expected %u\n", - ntohs (message->size), - sizeof (struct GNUNET_MESH_LocalMonitor)); + h->tunnels_cb (h->tunnel_cls, NULL, 0, 0, 0, 0); + h->tunnels_cb = NULL; + h->tunnels_cls = NULL; return; } - h->tunnels_cb (h->tunnels_cls, - ntohl (msg->tunnel_id), - &msg->owner, - &msg->destination); + + msg = (struct GNUNET_MESH_LocalInfoTunnel *) message; + h->tunnels_cb (h->tunnel_cls, + &msg->destination, + ntohl (msg->channels), + ntohl (msg->connections), + ntohs (msg->estate), + ntohs (msg->cstate)); + } -/** - * Process a local monitor_tunnel reply, pass info to the user. +/* + * Process a local monitor_channel reply, pass info to the user. * * @param h Mesh handle. * @param message Message itself. */ static void -process_show_tunnel (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MessageHeader *message) +process_get_tunnel (struct GNUNET_MESH_Handle *h, + const struct GNUNET_MessageHeader *message) { - struct GNUNET_MESH_LocalMonitor *msg; + struct GNUNET_MESH_LocalInfoTunnel *msg; size_t esize; + size_t msize; + unsigned int ch_n; + unsigned int c_n; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n"); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n"); if (NULL == h->tunnel_cb) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); return; } /* Verify message sanity */ - msg = (struct GNUNET_MESH_LocalMonitor *) message; - esize = sizeof (struct GNUNET_MESH_LocalMonitor); - if (ntohs (message->size) != esize) + msg = (struct GNUNET_MESH_LocalInfoTunnel *) message; + msize = ntohs (message->size); + esize = sizeof (struct GNUNET_MESH_LocalInfoTunnel); + if (esize > msize) { GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Show tunnel message: size %hu - expected %u\n", - ntohs (message->size), - esize); - - h->tunnel_cb (h->tunnel_cls, NULL, NULL); - h->tunnel_cb = NULL; - h->tunnel_cls = NULL; - - return; + h->tunnel_cb (h->tunnel_cls, NULL, 0, 0, 0, 0); + goto clean_cls; + } + ch_n = ntohl (msg->channels); + c_n = ntohl (msg->connections); + esize += ch_n * sizeof (MESH_ChannelNumber); + esize += c_n * sizeof (struct GNUNET_HashCode); + if (msize != esize) + { + GNUNET_break_op (0); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n", + msize, esize, ch_n, c_n); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n", + sizeof (struct GNUNET_MESH_LocalInfoTunnel), + sizeof (MESH_ChannelNumber), sizeof (struct GNUNET_HashCode)); + h->tunnel_cb (h->tunnel_cls, NULL, 0, 0, 0, 0); + goto clean_cls; } - h->tunnel_cb (h->tunnel_cls, - &msg->destination, - &msg->owner); -} + /* Call Callback with tunnel info. */ + h->tunnel_cb (h->tunnel_cls, &msg->destination, + ch_n, c_n, + ntohs (msg->estate), ntohs (msg->cstate)); +clean_cls: + h->tunnel_cb = NULL; + h->tunnel_cls = NULL; +} /** * Function to process all messages received from the service @@ -1060,46 +1145,56 @@ static void 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)) + GM_m2s (type)); + switch (type) { - /* Notify of a new incoming tunnel */ - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE: - process_tunnel_created (h, (struct GNUNET_MESH_TunnelMessage *) msg); + /* Notify of a new incoming channel */ + case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: + process_channel_created (h, (struct GNUNET_MESH_ChannelMessage *) msg); break; - /* Notify of a tunnel disconnection */ - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY: - process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg); + /* Notify of a channel disconnection */ + case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: /* TODO separate(gid problem)*/ + case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK: + process_channel_destroy (h, (struct GNUNET_MESH_ChannelMessage *) msg); break; - /* Notify of a new data packet in the tunnel */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA: process_incoming_data (h, msg); break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: process_ack (h, msg); break; +// case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNELS: +// process_get_channels (h, msg); +// break; +// case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL: +// process_show_channel (h, msg); +// break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS: process_get_tunnels (h, msg); break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL: - process_show_tunnel (h, msg); + process_get_tunnel (h, msg); break; +// case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL: +// process_show_channel (h, msg); +// break; default: /* We shouldn't get any other packages, log and ignore */ LOG (GNUNET_ERROR_TYPE_WARNING, "unsolicited message form service (type %s)\n", - GNUNET_MESH_DEBUG_M2S (ntohs (msg->type))); + GM_m2s (ntohs (msg->type))); } LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n"); if (GNUNET_YES == h->in_receive) @@ -1135,7 +1230,7 @@ send_callback (void *cls, size_t size, void *buf) struct GNUNET_MESH_Handle *h = cls; struct GNUNET_MESH_TransmitHandle *th; struct GNUNET_MESH_TransmitHandle *next; - struct GNUNET_MESH_Tunnel *t; + struct GNUNET_MESH_Channel *ch; char *cbuf = buf; size_t tsize; size_t psize; @@ -1155,21 +1250,20 @@ send_callback (void *cls, size_t size, void *buf) nsize = message_ready_size (h); while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize)) { - t = th->tunnel; + ch = th->channel; if (GNUNET_YES == th_is_payload (th)) { struct GNUNET_MESH_LocalData *dmsg; struct GNUNET_MessageHeader *mh; LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload\n"); - if (GNUNET_NO == t->allow_send) + if (GNUNET_NO == ch->allow_send) { - /* This tunnel is not ready to transmit yet, try next message */ + /* This channel is not ready to transmit yet, try next message */ next = th->next; continue; } - t->packet_size = 0; - t->allow_send = GNUNET_NO; + ch->packet_size = 0; GNUNET_assert (size >= th->size); dmsg = (struct GNUNET_MESH_LocalData *) cbuf; mh = (struct GNUNET_MessageHeader *) &dmsg[1]; @@ -1181,19 +1275,25 @@ send_callback (void *cls, size_t size, void *buf) psize += sizeof (struct GNUNET_MESH_LocalData); GNUNET_assert (size >= psize); dmsg->header.size = htons (psize); - dmsg->tid = htonl (t->tid); + dmsg->id = htonl (ch->chid); + dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload type %s\n", + GM_m2s (ntohs (mh->type))); + ch->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", - GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# mesh internal traffic, type %s\n", + GM_m2s (ntohs (mh->type))); memcpy (cbuf, &th[1], th->size); psize = th->size; } @@ -1241,26 +1341,26 @@ send_callback (void *cls, size_t size, void *buf) * 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) + * @param channel channel this send is related to (NULL if N/A) */ static void send_packet (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *msg, - struct GNUNET_MESH_Tunnel *tunnel) + struct GNUNET_MESH_Channel *channel) { struct GNUNET_MESH_TransmitHandle *th; size_t msize; LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n", - GNUNET_MESH_DEBUG_M2S(ntohs(msg->type))); + GM_m2s(ntohs(msg->type))); msize = ntohs (msg->size); th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize); th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; th->size = msize; - th->tunnel = tunnel; + th->channel = channel; memcpy (&th[1], msg, msize); add_to_queue (h, th); LOG (GNUNET_ERROR_TYPE_DEBUG, " queued\n"); @@ -1280,18 +1380,18 @@ send_packet (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Handle * GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, - GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, - GNUNET_MESH_TunnelEndHandler cleaner, + GNUNET_MESH_InboundChannelNotificationHandler new_channel, + GNUNET_MESH_ChannelEndHandler cleaner, const struct GNUNET_MESH_MessageHandler *handlers, const uint32_t *ports) { struct GNUNET_MESH_Handle *h; LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n"); - h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle)); + h = GNUNET_new (struct GNUNET_MESH_Handle); LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h); h->cfg = cfg; - h->new_tunnel = new_tunnel; + h->new_channel = new_channel; h->cleaner = cleaner; h->client = GNUNET_CLIENT_connect ("mesh", cfg); if (h->client == NULL) @@ -1303,10 +1403,22 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, h->cls = cls; h->message_handlers = handlers; h->ports = ports; - h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; + h->next_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_CLI; h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != ports && ports[0] != 0 && NULL == new_channel) + { + GNUNET_break (0); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "no new channel handler given, ports parameter is useless!!\n"); + } + if ((NULL == ports || ports[0] == 0) && NULL != new_channel) + { + GNUNET_break (0); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "no ports given, new channel handler will never be called!!\n"); + } /* count handlers */ for (h->n_handlers = 0; handlers && handlers[h->n_handlers].type; @@ -1323,28 +1435,23 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, void GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) { - struct GNUNET_MESH_Tunnel *t; - struct GNUNET_MESH_Tunnel *aux; + struct GNUNET_MESH_Channel *ch; + struct GNUNET_MESH_Channel *aux; struct GNUNET_MESH_TransmitHandle *th; LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n"); -#if DEBUG_ACK - LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent); - LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv); -#endif - - t = handle->tunnels_head; - while (NULL != t) + ch = handle->channels_head; + while (NULL != ch) { - aux = t->next; - if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) + aux = ch->next; + if (ch->chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) { GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid); + LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X not destroyed\n", ch->chid); } - destroy_tunnel (t, GNUNET_YES); - t = aux; + destroy_channel (ch, GNUNET_YES); + ch = aux; } while ( (th = handle->th_head) != NULL) { @@ -1358,9 +1465,12 @@ GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) switch (ntohs(msg->type)) { case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT: - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY: - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS: + case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: + case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: + case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNELS: + case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL: + case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS: break; default: GNUNET_break (0); @@ -1392,65 +1502,63 @@ GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) /** - * Create a new tunnel (we're initiator and will be allowed to add/remove peers - * and to broadcast). + * Create a new channel towards a remote peer. + * + * If the destination port is not open by any peer or the destination peer + * does not accept the channel, #GNUNET_MESH_ChannelEndHandler will be called + * for this channel. * * @param h mesh handle - * @param tunnel_ctx client's tunnel context to associate with the tunnel - * @param peer peer identity the tunnel should go to + * @param channel_ctx client's channel context to associate with the channel + * @param peer peer identity the channel should go to * @param port Port number. - * @param buffer Flag for buffering on relay nodes. - * @param reliable Flag for end-to-end reliability. + * @param options MeshOption flag field, with all desired option bits set to 1. * - * @return handle to the tunnel + * @return handle to the channel */ -struct GNUNET_MESH_Tunnel * -GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, - void *tunnel_ctx, - const struct GNUNET_PeerIdentity *peer, - uint32_t port, - int buffer, - int reliable) +struct GNUNET_MESH_Channel * +GNUNET_MESH_channel_create (struct GNUNET_MESH_Handle *h, + void *channel_ctx, + const struct GNUNET_PeerIdentity *peer, + uint32_t port, + enum GNUNET_MESH_ChannelOption options) { - struct GNUNET_MESH_Tunnel *t; - struct GNUNET_MESH_TunnelMessage msg; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n"); - 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); - 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); + struct GNUNET_MESH_Channel *ch; + struct GNUNET_MESH_ChannelMessage msg; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Creating new channel to %s:%u\n", + GNUNET_i2s (peer), port); + ch = create_channel (h, 0); + LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", ch); + LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", ch->chid); + ch->ctx = channel_ctx; + ch->peer = GNUNET_PEER_intern (peer); + msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE); + msg.header.size = htons (sizeof (struct GNUNET_MESH_ChannelMessage)); + msg.channel_id = htonl (ch->chid); msg.port = htonl (port); msg.peer = *peer; - msg.opt = 0; - if (GNUNET_YES == reliable) - msg.opt |= GNUNET_MESH_OPTION_RELIABLE; - if (GNUNET_NO == buffer) - msg.opt |= GNUNET_MESH_OPTION_NOBUFFER; - msg.opt = htonl (msg.opt); - t->allow_send = 0; - send_packet (h, &msg.header, t); - return t; + msg.opt = htonl (options); + ch->allow_send = 0; + send_packet (h, &msg.header, ch); + return ch; } void -GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel) +GNUNET_MESH_channel_destroy (struct GNUNET_MESH_Channel *channel) { struct GNUNET_MESH_Handle *h; - struct GNUNET_MESH_TunnelMessage msg; + struct GNUNET_MESH_ChannelMessage msg; struct GNUNET_MESH_TransmitHandle *th; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n"); - h = tunnel->mesh; + LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying channel\n"); + h = channel->mesh; - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); - msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - msg.tunnel_id = htonl (tunnel->tid); + msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY); + msg.header.size = htons (sizeof (struct GNUNET_MESH_ChannelMessage)); + msg.channel_id = htonl (channel->chid); memset (&msg.peer, 0, sizeof (struct GNUNET_PeerIdentity)); msg.port = 0; msg.opt = 0; @@ -1458,7 +1566,7 @@ GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel) while (th != NULL) { struct GNUNET_MESH_TransmitHandle *aux; - if (th->tunnel == tunnel) + if (th->channel == channel) { aux = th->next; /* FIXME call the handler? */ @@ -1472,40 +1580,51 @@ GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel) th = th->next; } - destroy_tunnel (tunnel, GNUNET_YES); + destroy_channel (channel, GNUNET_YES); send_packet (h, &msg.header, NULL); } /** - * Get information about a tunnel. - * - * The existing end callback for the tunnel will be called immediately. - * Any pending outgoing messages will be sent but no incoming messages will be - * accepted and no data callbacks will be called. + * Get information about a channel. + * + * @param channel Channel handle. + * @param option Query (GNUNET_MESH_OPTION_*). + * @param ... dependant on option, currently not used * - * @param tunnel Tunnel handle. - * - * @return Allocated, {0, NULL} terminated set of tunnel properties. + * @return Union with an answer to the query. */ -struct MeshTunnelInfo * -GNUNET_MESH_tunnel_get_info (struct GNUNET_MESH_Tunnel *tunnel) +const union GNUNET_MESH_ChannelInfo * +GNUNET_MESH_channel_get_info (struct GNUNET_MESH_Channel *channel, + enum GNUNET_MESH_ChannelOption option, ...) { - struct MeshTunnelInfo *ret; + static int bool_flag; + const union GNUNET_MESH_ChannelInfo *ret; - ret = GNUNET_malloc (sizeof (struct MeshTunnelInfo) * 3); - ret[0].prop = GNUNET_MESH_OPTION_NOBUFFER; - ret[0].value = &tunnel->buffering; // FIXME return ¬buffering ("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: + case GNUNET_MESH_OPTION_RELIABLE: + case GNUNET_MESH_OPTION_OOORDER: + if (0 != (option & channel->options)) + bool_flag = GNUNET_YES; + else + bool_flag = GNUNET_NO; + ret = (const union GNUNET_MESH_ChannelInfo *) &bool_flag; + break; + case GNUNET_MESH_OPTION_PEER: + ret = (const union GNUNET_MESH_ChannelInfo *) GNUNET_PEER_resolve2 (channel->peer); + break; + default: + GNUNET_break (0); + return NULL; + } return ret; } struct GNUNET_MESH_TransmitHandle * -GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, +GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Channel *channel, int cork, struct GNUNET_TIME_Relative maxdelay, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, @@ -1513,36 +1632,36 @@ GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, { struct GNUNET_MESH_TransmitHandle *th; - GNUNET_assert (NULL != tunnel); + GNUNET_assert (NULL != channel); LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tunnel->tid); - LOG (GNUNET_ERROR_TYPE_DEBUG, " allow_send %d\n", tunnel->allow_send); - if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) + LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", channel->chid); + LOG (GNUNET_ERROR_TYPE_DEBUG, " allow_send %d\n", channel->allow_send); + if (channel->chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n"); else LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size); GNUNET_assert (NULL != notify); - GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed - th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle)); - th->tunnel = tunnel; + GNUNET_assert (0 == channel->packet_size); // Only one data packet allowed + th = GNUNET_new (struct GNUNET_MESH_TransmitHandle); + th->channel = channel; th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); th->size = notify_size + sizeof (struct GNUNET_MESH_LocalData); - tunnel->packet_size = th->size; + channel->packet_size = th->size; LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size); th->notify = notify; th->notify_cls = notify_cls; - add_to_queue (tunnel->mesh, th); - if (NULL != tunnel->mesh->th) + add_to_queue (channel->mesh, th); + if (NULL != channel->mesh->th) return th; - if (GNUNET_NO == tunnel->allow_send) + if (GNUNET_NO == channel->allow_send) return th; LOG (GNUNET_ERROR_TYPE_DEBUG, " call client notify tmt rdy\n"); - tunnel->mesh->th = - GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size, + channel->mesh->th = + GNUNET_CLIENT_notify_transmit_ready (channel->mesh->client, th->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_callback, - tunnel->mesh); + channel->mesh); LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n"); return th; } @@ -1553,8 +1672,8 @@ GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th) { struct GNUNET_MESH_Handle *mesh; - th->tunnel->packet_size = 0; - mesh = th->tunnel->mesh; + th->channel->packet_size = 0; + mesh = th->channel->mesh; if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (th->timeout_task); GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th); @@ -1567,17 +1686,100 @@ GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th) } } + +void +GNUNET_MESH_receive_done (struct GNUNET_MESH_Channel *channel) +{ + send_ack (channel); +} + + +static void +send_info_request (struct GNUNET_MESH_Handle *h, uint16_t type) +{ + struct GNUNET_MessageHeader msg; + + msg.size = htons (sizeof (msg)); + msg.type = htons (type); + send_packet (h, &msg, NULL); +} + +/** + * Request information about the running mesh peer. + * The callback will be called for every channel known to the service, + * listing all active peers that blong to the channel. + * + * If called again on the same handle, it will overwrite the previous + * callback and cls. To retrieve the cls, monitor_cancel must be + * called first. + * + * WARNING: unstable API, likely to change in the future! + * + * @param h Handle to the mesh peer. + * @param callback Function to call with the requested data. + * @param callback_cls Closure for @c callback. + */ +void +GNUNET_MESH_get_channels (struct GNUNET_MESH_Handle *h, + GNUNET_MESH_ChannelsCB callback, + void *callback_cls) +{ + send_info_request (h, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNELS); + h->channels_cb = callback; + h->channels_cls = callback_cls; +} + + +/** + * Cancel a monitor request. The monitor callback will not be called. + * + * WARNING: unstable API, likely to change in the future! + * + * @param h Mesh handle. + * + * @return Closure given to GNUNET_MESH_monitor, if any. + */ +void * +GNUNET_MESH_get_channels_cancel (struct GNUNET_MESH_Handle *h) +{ + void *cls; + + cls = h->channels_cls; + h->channels_cb = NULL; + h->channels_cls = NULL; + return cls; +} + + +/** + * Request information about the running mesh peer. + * The callback will be called for every peer known to the service. + * + * If called again on the same handle, it will overwrite the previous + * callback and cls. To retrieve the cls, monitor_cancel must be + * called first. + * + * WARNING: unstable API, likely to change in the future! + * + * @param h Handle to the mesh peer. + * @param callback Function to call with the requested data. + * @param callback_cls Closure for @c callback. + */ void -GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel) +GNUNET_MESH_get_peers (struct GNUNET_MESH_Handle *h, + GNUNET_MESH_PeersCB callback, + void *callback_cls) { - send_ack (tunnel); + send_info_request (h, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS); + h->peers_cb = callback; + h->peers_cls = callback_cls; } + /** * Request information about the running mesh peer. - * The callback will be called for every tunnel known to the service, - * listing all active peers that blong to the tunnel. + * The callback will be called for every tunnel known to the service. * * If called again on the same handle, it will overwrite the previous * callback and cls. To retrieve the cls, monitor_cancel must be @@ -1594,15 +1796,9 @@ GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h, GNUNET_MESH_TunnelsCB callback, void *callback_cls) { - struct GNUNET_MessageHeader msg; - - msg.size = htons (sizeof (msg)); - msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); - send_packet (h, &msg, NULL); + send_info_request (h, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); h->tunnels_cb = callback; h->tunnels_cls = callback_cls; - - return; } @@ -1618,44 +1814,77 @@ GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h) { void *cls; - cls = h->tunnels_cls; h->tunnels_cb = NULL; + cls = h->tunnels_cls; h->tunnels_cls = NULL; + return cls; } + /** - * Request information about a specific tunnel of the running mesh peer. + * Request information about the running mesh peer. + * The callback will be called for every channel known to the service, + * listing all active peers that blong to the channel. + * + * If called again on the same handle, it will overwrite the previous + * callback and cls. To retrieve the cls, monitor_cancel must be + * called first. * * WARNING: unstable API, likely to change in the future! - * FIXME Add destination option. * * @param h Handle to the mesh peer. - * @param initiator ID of the owner of the tunnel. - * @param tunnel_number Tunnel number. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. */ void -GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h, - struct GNUNET_PeerIdentity *initiator, - unsigned int tunnel_number, - GNUNET_MESH_TunnelCB callback, - void *callback_cls) +GNUNET_MESH_get_tunnel (struct GNUNET_MESH_Handle *h, + const struct GNUNET_PeerIdentity *id, + GNUNET_MESH_TunnelCB callback, + void *callback_cls) { - struct GNUNET_MESH_LocalMonitor msg; + struct GNUNET_MESH_LocalInfo msg; + memset (&msg, 0, sizeof (msg)); msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL); - msg.owner = *initiator; - msg.tunnel_id = htonl (tunnel_number); - msg.reserved = 0; + msg.peer = *id; send_packet (h, &msg.header, NULL); h->tunnel_cb = callback; h->tunnel_cls = callback_cls; +} - return; + +/** + * Request information about a specific channel of the running mesh peer. + * + * WARNING: unstable API, likely to change in the future! + * FIXME Add destination option. + * + * @param h Handle to the mesh peer. + * @param initiator ID of the owner of the channel. + * @param channel_number Channel number. + * @param callback Function to call with the requested data. + * @param callback_cls Closure for @c callback. + */ +void +GNUNET_MESH_show_channel (struct GNUNET_MESH_Handle *h, + struct GNUNET_PeerIdentity *initiator, + unsigned int channel_number, + GNUNET_MESH_ChannelCB callback, + void *callback_cls) +{ + struct GNUNET_MESH_LocalInfo msg; + + msg.header.size = htons (sizeof (msg)); + msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL); + msg.peer = *initiator; + msg.channel_id = htonl (channel_number); +// msg.reserved = 0; + send_packet (h, &msg.header, NULL); + h->channel_cb = callback; + h->channel_cls = callback_cls; } @@ -1674,7 +1903,7 @@ static size_t 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; @@ -1708,12 +1937,11 @@ mesh_mq_send_impl (struct GNUNET_MQ_Handle *mq, struct MeshMQState *state = impl_state; GNUNET_assert (NULL == state->th); - GNUNET_MQ_impl_send_commit (mq); state->th = - GNUNET_MESH_notify_transmit_ready (state->tunnel, + GNUNET_MESH_notify_transmit_ready (state->channel, /* FIXME: add option for corking */ GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_TIME_UNIT_FOREVER_REL, ntohs (msg->size), mesh_mq_ntr, mq); @@ -1725,7 +1953,7 @@ mesh_mq_send_impl (struct GNUNET_MQ_Handle *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 */ @@ -1742,21 +1970,21 @@ mesh_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) /** - * Create a message queue for a mesh tunnel. + * Create a message queue for a mesh channel. * The message queue can only be used to transmit messages, * not to receive them. * - * @param tunnel the tunnel to create the message qeue for - * @return a message queue to messages over the tunnel + * @param channel the channel to create the message qeue for + * @return a message queue to messages over the channel */ struct GNUNET_MQ_Handle * -GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel) +GNUNET_MESH_mq_create (struct GNUNET_MESH_Channel *channel) { struct GNUNET_MQ_Handle *mq; struct MeshMQState *state; state = GNUNET_new (struct MeshMQState); - state->tunnel = tunnel; + state->channel = channel; mq = GNUNET_MQ_queue_for_callbacks (mesh_mq_send_impl, mesh_mq_destroy_impl,