}
+/**
+ * Notify the root that the destination rejected the channel.
+ *
+ * @param ch Rejected channel.
+ */
+static void
+send_client_nack (struct MeshChannel *ch)
+{
+ if (NULL == ch->root)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GML_send_nack (ch->root, ch->lid_root);
+}
+
+
/**
* Destroy all reliable messages queued for a channel,
* during a channel destruction.
}
+/**
+ * Notify that a channel create didn't succeed.
+ *
+ * @param ch The channel to reject.
+ */
+static void
+channel_send_nack (struct MeshChannel *ch)
+{
+ struct GNUNET_MESH_ChannelManage msg;
+
+ msg.header.size = htons (sizeof (msg));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ " sending channel NACK for channel %s\n",
+ GMCH_2s (ch));
+
+ msg.chid = htonl (ch->gid);
+ GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO);
+}
+
+
/**
* Channel was ACK'd by remote peer, mark as ready and cancel retransmission.
*
GNUNET_YES : GNUNET_NO;
}
+static int
+is_loopback (const struct MeshChannel *ch)
+{
+ if (NULL != ch->t)
+ return GMT_is_loopback (ch->t);
+
+ return (NULL != ch->root && NULL != ch->dest);
+}
+
/**
* Handle a loopback message: call the appropriate handler for the message type.
case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
GMCH_handle_create (ch->t,
- (struct GNUNET_MESH_ChannelCreate *) msgh,
- fwd);
+ (struct GNUNET_MESH_ChannelCreate *) msgh);
break;
case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK:
fwd);
break;
+ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK:
+ GMCH_handle_nack (ch);
+ break;
+
case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
GMCH_handle_destroy (ch,
(struct GNUNET_MESH_ChannelManage *) msgh,
* @param ch Channel.
* @param fwd Is query about FWD traffic? (Request root status).
*
- * @return GNUNET_YES if client is allowed to send us data.
+ * @return #GNUNET_YES if client is allowed to send us data.
*/
int
GMCH_get_allowed (struct MeshChannel *ch, int fwd)
* @param ch Channel.
* @param fwd Is this for fwd traffic?
*
- * @return GNUNET_YES in case it is.
+ * @return #GNUNET_YES in case it is.
*/
int
GMCH_is_origin (struct MeshChannel *ch, int fwd)
* @param ch Channel.
* @param fwd Is this for fwd traffic?
*
- * @return GNUNET_YES in case it is.
+ * @return #GNUNET_YES in case it is.
*/
int
GMCH_is_terminal (struct MeshChannel *ch, int fwd)
* Mark client as ready and send him any buffered data we could have for him.
*
* @param ch Channel.
- * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by root and go BCK)
+ * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK)
*/
void
GMCH_handle_local_ack (struct MeshChannel *ch, int fwd)
rel->client_ready = GNUNET_YES;
send_client_buffered_data (ch, c, fwd);
- GMT_send_acks (ch->t, fwd);
+ if (is_loopback (ch))
+ {
+ unsigned int buffer;
+
+ buffer = GMCH_get_buffer (ch, fwd);
+ if (0 < buffer)
+ GMCH_allow_client (ch, fwd);
+
+ return;
+ }
+ GMT_send_connection_acks (ch->t);
}
channel_save_copy (ch, &payload->header, fwd);
GMCH_send_prebuilt_message (&payload->header, ch, fwd);
- if (GMT_get_buffer (ch->t, fwd) > 0)
+ if (is_loopback (ch))
+ {
+ if (GMCH_get_buffer (ch, fwd) > 0);
+ send_client_ack (ch, fwd);
+
+ return GNUNET_OK;
+ }
+
+ if (GMT_get_connections_buffer (ch->t) > 0)
{
send_client_ack (ch, fwd);
}
return GNUNET_OK;
}
+
/**
* Handler for mesh network payload traffic.
*
* @param ch Channel for the message.
* @param msg Unencryted data message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
+ * @param fwd Is this message fwd? This only is meaningful in loopback channels.
+ * #GNUNET_YES if message is FWD on the respective channel (loopback)
+ * #GNUNET_NO if message is BCK on the respective channel (loopback)
+ * #GNUNET_SYSERR if message on a one-ended channel (remote)
*/
void
GMCH_handle_data (struct MeshChannel *ch,
struct MeshClient *c;
uint32_t mid;
+ /* If this is a remote (non-loopback) channel, find 'fwd'. */
+ if (GNUNET_SYSERR == fwd)
+ {
+ if (is_loopback (ch))
+ {
+ /* It is a loopback channel after all... */
+ GNUNET_break (0);
+ return;
+ }
+ fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
+ }
+
/* Initialize FWD/BCK data */
c = fwd ? ch->dest : ch->root;
rel = fwd ? ch->dest_rel : ch->root_rel;
*
* @param ch Channel on which we got this message.
* @param msg Data message.
- * @param fwd Is this a fwd ACK? (dest->orig)
+ * @param fwd Is this message fwd? This only is meaningful in loopback channels.
+ * #GNUNET_YES if message is FWD on the respective channel (loopback)
+ * #GNUNET_NO if message is BCK on the respective channel (loopback)
+ * #GNUNET_SYSERR if message on a one-ended channel (remote)
*/
void
GMCH_handle_data_ack (struct MeshChannel *ch,
uint32_t ack;
int work;
+ /* If this is a remote (non-loopback) channel, find 'fwd'. */
+ if (GNUNET_SYSERR == fwd)
+ {
+ if (is_loopback (ch))
+ {
+ /* It is a loopback channel after all... */
+ GNUNET_break (0);
+ return;
+ }
+ fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
+ }
+
ack = ntohl (msg->mid);
LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! %s ACK %u\n",
- (GNUNET_YES == fwd) ? "FWD" : "BCK", ack);
+ (GNUNET_YES == fwd) ? "FWD" : "BCK", ack);
if (GNUNET_YES == fwd)
{
/**
* Handler for channel create messages.
*
+ * Does not have fwd parameter because it's always 'FWD': channel is incoming.
+ *
* @param t Tunnel this channel will be in.
- * @param msg Message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
+ * @param msg Channel crate message.
*/
struct MeshChannel *
GMCH_handle_create (struct MeshTunnel3 *t,
- const struct GNUNET_MESH_ChannelCreate *msg,
- int fwd)
+ const struct GNUNET_MESH_ChannelCreate *msg)
{
MESH_ChannelNumber chid;
struct MeshChannel *ch;
{
/* TODO send reject */
LOG (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n");
- channel_destroy (ch);
+ if (is_loopback (ch))
+ {
+ channel_send_nack (ch);
+ }
+ else
+ {
+ channel_send_nack (ch);
+ channel_destroy (ch);
+ }
return NULL;
}
else
LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Not Reliable\n");
GMCH_send_create (ch);
- channel_send_ack (ch, fwd);
+ channel_send_ack (ch, GNUNET_YES);
return ch;
}
+/**
+ * Handler for channel NACK messages.
+ *
+ * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter.
+ *
+ * @param ch Channel.
+ */
+void
+GMCH_handle_nack (struct MeshChannel *ch)
+{
+ send_client_nack (ch);
+ channel_destroy (ch);
+}
+
+
/**
* Handler for channel ack messages.
*
* @param ch Channel.
* @param msg Message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
+ * @param fwd Is this message fwd? This only is meaningful in loopback channels.
+ * #GNUNET_YES if message is FWD on the respective channel (loopback)
+ * #GNUNET_NO if message is BCK on the respective channel (loopback)
+ * #GNUNET_SYSERR if message on a one-ended channel (remote)
*/
void
GMCH_handle_ack (struct MeshChannel *ch,
const struct GNUNET_MESH_ChannelManage *msg,
int fwd)
{
+ /* If this is a remote (non-loopback) channel, find 'fwd'. */
+ if (GNUNET_SYSERR == fwd)
+ {
+ if (is_loopback (ch))
+ {
+ /* It is a loopback channel after all... */
+ GNUNET_break (0);
+ return;
+ }
+ fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
+ }
+
channel_confirm (ch, !fwd);
}
*
* @param ch Channel to be destroyed of.
* @param msg Message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
+ * @param fwd Is this message fwd? This only is meaningful in loopback channels.
+ * #GNUNET_YES if message is FWD on the respective channel (loopback)
+ * #GNUNET_NO if message is BCK on the respective channel (loopback)
+ * #GNUNET_SYSERR if message on a one-ended channel (remote)
*/
void
GMCH_handle_destroy (struct MeshChannel *ch,
{
struct MeshTunnel3 *t;
+ /* If this is a remote (non-loopback) channel, find 'fwd'. */
+ if (GNUNET_SYSERR == fwd)
+ {
+ if (is_loopback (ch))
+ {
+ /* It is a loopback channel after all... */
+ GNUNET_break (0);
+ return;
+ }
+ fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
+ }
+
GMCH_debug (ch);
if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) )
{