#include "gnunet_statistics_service.h"
-#include "mesh_enc.h"
-#include "mesh_protocol_enc.h"
+#include "mesh.h"
+#include "mesh_protocol.h"
#include "gnunet-service-mesh_channel.h"
#include "gnunet-service-mesh_local.h"
*/
uint32_t mid;
+ /**
+ * Tunnel Queue.
+ */
+ struct MeshTunnel3Queue *q;
+
/**
* When was this message issued (to calculate ACK delay)
*/
return;
}
- /* Search the message to be retransmitted in the outgoing queue.
- * Check only the queue for the connection that is going to be used,
- * if the message is stuck in some other connection's queue we shouldn't
- * act upon it:
- * - cancelling it and sending the new one doesn't guarantee it's delivery,
- * the old connection could be temporary stalled or the queue happened to
- * be long at time of insertion.
- * - not sending the new one could cause terrible delays the old connection
- * is stalled.
- */
-// FIXME access to queue elements is limited
payload = (struct GNUNET_MESH_Data *) ©[1];
fwd = (rel == ch->root_rel);
-// c = GMT_get_connection (ch->t, fwd);
-// hop = connection_get_hop (c, fwd);
-// for (q = hop->queue_head; NULL != q; q = q->next)
-// {
-// if (ntohs (payload->header.type) == q->type && ch == q->ch)
-// {
-// struct GNUNET_MESH_Data *queued_data = q->cls;
-//
-// if (queued_data->mid == payload->mid)
-// break;
-// }
-// }
/* Message not found in the queue that we are going to use. */
-// if (NULL == q)
-// {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid);
-
- GMCH_send_prebuilt_message (&payload->header, ch, fwd);
- GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
-// }
-// else
-// {
-// LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! ALREADY IN QUEUE %u\n", copy->mid);
-// }
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid);
+
+ GMCH_send_prebuilt_message (&payload->header, ch, fwd, GNUNET_YES);
+ GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
copy->timestamp = GNUNET_TIME_absolute_get();
rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer);
fwd ? "FWD" : "BCK", GMCH_2s (ch));
msg.chid = htonl (ch->gid);
- GMCH_send_prebuilt_message (&msg.header, ch, !fwd);
+ GMCH_send_prebuilt_message (&msg.header, ch, !fwd, GNUNET_NO);
}
GMCH_2s (ch));
msg.chid = htonl (ch->gid);
- GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO);
+ GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, GNUNET_NO);
}
channel_send_ack (ch, !fwd);
}
+static void
+message_sent (void *cls,
+ struct MeshTunnel3 *t,
+ struct MeshTunnel3Queue *q,
+ uint16_t type, size_t size)
+{
+ struct MeshReliableMessage *copy = cls;
+ struct MeshChannelReliability *rel = copy->rel;
+
+ copy->timestamp = GNUNET_TIME_absolute_get ();
+ if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task)
+ {
+ rel->retry_timer =
+ GNUNET_TIME_relative_multiply (rel->expected_delay,
+ MESH_RETRANSMIT_MARGIN);
+ rel->retry_task =
+ GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
+ &channel_retransmit_message,
+ rel);
+ }
+}
+
/**
* Save a copy to retransmit in case it gets lost.
* @param msg Message to copy.
* @param fwd Is this fwd traffic?
*/
-static void
+static struct MeshReliableMessage *
channel_save_copy (struct MeshChannel *ch,
const struct GNUNET_MessageHeader *msg,
int fwd)
mid, GNUNET_MESH_DEBUG_M2S (type));
copy = GNUNET_malloc (sizeof (struct MeshReliableMessage) + size);
copy->mid = mid;
- copy->timestamp = GNUNET_TIME_absolute_get ();
copy->rel = rel;
copy->type = type;
memcpy (©[1], msg, size);
GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy);
- if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task)
- {
- rel->retry_timer =
- GNUNET_TIME_relative_multiply (rel->expected_delay,
- MESH_RETRANSMIT_MARGIN);
- rel->retry_task =
- GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
- &channel_retransmit_message,
- rel);
- }
+
+ return copy;
}
if (NULL != ch->root)
GML_send_channel_destroy (ch->root, ch->lid_root);
else if (0 == ch->lid_root)
- GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO);
+ GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, GNUNET_NO);
if (NULL != ch->dest)
GML_send_channel_destroy (ch->dest, ch->lid_dest);
else if (0 == ch->lid_dest)
- GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES);
-}
-
-
-/**
- * Send data on a channel.
- *
- * If the destination is local, send it to client, otherwise encrypt and
- * send to next hop.
- *
- * @param ch Channel
- * @param msg Message.
- * @param fwd Is this a fwd (root->dest) message?
- */
-void
-GMCH_send_data (struct MeshChannel *ch,
- const struct GNUNET_MESH_Data *msg,
- int fwd)
-{
- if (GMCH_is_terminal (ch, fwd))
- {
- GML_send_data (fwd ? ch->dest : ch->root,
- msg,
- fwd ? ch->lid_dest : ch->lid_root);
- }
- else
- {
- GMT_send_prebuilt_message (&msg->header, ch->t, ch, fwd);
- }
+ GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, GNUNET_NO);
}
"!!! ACK for %u, futures %llX\n",
ack, msg.futures);
- GMCH_send_prebuilt_message (&msg.header, ch, !fwd);
+ GMCH_send_prebuilt_message (&msg.header, ch, !fwd, GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n");
}
GMCH_allow_client (struct MeshChannel *ch, int fwd)
{
struct MeshChannelReliability *rel;
+ unsigned int buffer;
LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n");
if (MESH_CHANNEL_READY != ch->state)
{
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not ready yet!\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n");
return;
}
}
if (NULL != rel->head_sent && 64 <= rel->mid_send - rel->head_sent->mid)
{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " too big mid gap! Wait for ACK.\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n");
return;
}
}
+ if (is_loopback (ch))
+ buffer = GMCH_get_buffer (ch, fwd);
+ else
+ buffer = GMT_get_connections_buffer (ch->t);
+
+ if (0 == buffer)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n");
+ return;
+ }
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer);
send_client_ack (ch, fwd);
}
payload->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_DATA);
payload->chid = htonl (ch->gid);
LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
- if (GNUNET_YES == ch->reliable)
- channel_save_copy (ch, &payload->header, fwd);
- GMCH_send_prebuilt_message (&payload->header, ch, fwd);
+ GMCH_send_prebuilt_message (&payload->header, ch, fwd, GNUNET_NO);
if (is_loopback (ch))
{
- if (GMCH_get_buffer (ch, fwd) > 0);
+ if (GMCH_get_buffer (ch, fwd) > 0)
send_client_ack (ch, fwd);
return GNUNET_OK;
msgcc.port = msg->port;
msgcc.opt = msg->opt;
- GMT_send_prebuilt_message (&msgcc.header, t, ch, GNUNET_YES);
+ GMT_send_prebuilt_message (&msgcc.header, t, ch, GNUNET_YES, NULL, NULL);
}
return GNUNET_OK;
}
* @param message Message to send. Function makes a copy of it.
* @param ch Channel on which this message is transmitted.
* @param fwd Is this a fwd message?
+ * @param retransmission Is this a retransmission? (Don't save a copy)
*/
void
GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- struct MeshChannel *ch, int fwd)
+ struct MeshChannel *ch, int fwd,
+ int retransmission)
{
LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH Send %s %s on channel %s\n",
fwd ? "FWD" : "BCK", GNUNET_MESH_DEBUG_M2S (ntohs (message->type)),
return;
}
- GMT_send_prebuilt_message (message, ch->t, ch, fwd);
+ if (GNUNET_YES == ch->reliable && GNUNET_NO == retransmission
+ && ntohs (message->type) == GNUNET_MESSAGE_TYPE_MESH_DATA)
+ {
+ struct MeshReliableMessage *copy;
+
+ copy = channel_save_copy (ch, message, fwd);
+ copy->q = GMT_send_prebuilt_message (message, ch->t, ch, fwd,
+ &message_sent, copy);
+ }
+ else
+ GMT_send_prebuilt_message (message, ch->t, ch, fwd, NULL, NULL);
}