/** Tunnel it belongs to. */
struct MeshTunnel *t;
- /** In case of a multicast, task to allow a client to send more data if
- * some neighbor is too slow. */
- GNUNET_SCHEDULER_TaskIdentifier *task;
-
/** How many remaining neighbors we need to send this to. */
- unsigned int *reference_counter;
+ unsigned int reference_counter;
/** Size of the data. */
size_t data_len;
}
#endif
+unsigned int debug_fwd_ack;
+unsigned int debug_bck_ack;
+
#endif
/******************************************************************************/
block.id = my_full_id;
c = GNUNET_CONTAINER_multihashmap_get (applications, key);
+ GNUNET_assert(NULL != c);
block.type = (long) GNUNET_CONTAINER_multihashmap_get (c->apps, key);
if (0 == block.type)
{
static void
data_descriptor_decrement_rc (struct MeshData *mesh_data)
{
- /* Make sure it's a multicast packet */
- GNUNET_assert (NULL != mesh_data->reference_counter);
-
- if (0 == --(*(mesh_data->reference_counter)))
+ if (0 == --(mesh_data->reference_counter))
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last copy!\n");
- if (NULL != mesh_data->task)
- {
- if (GNUNET_SCHEDULER_NO_TASK != *(mesh_data->task))
- {
- GNUNET_SCHEDULER_cancel (*(mesh_data->task));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " notifying client...\n");
- GNUNET_SERVER_receive_done (mesh_data->t->owner->handle, GNUNET_OK);
- }
- GNUNET_free (mesh_data->task);
- }
- GNUNET_free (mesh_data->reference_counter);
GNUNET_free (mesh_data->data);
GNUNET_free (mesh_data);
}
}
-/**
- * Allow a client to send more data after transmitting a multicast message
- * which some neighbor has not yet accepted altough a reasonable time has
- * passed.
- *
- * @param cls Closure (DataDescriptor containing the task identifier)
- * @param tc Task Context
- *
- * FIXME reference counter cshould be just int
- */
-static void
-client_allow_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct MeshData *mdata = cls;
-
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
- GNUNET_assert (NULL != mdata->reference_counter);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "CLIENT ALLOW SEND DESPITE %u COPIES PENDING\n",
- *(mdata->reference_counter));
- *(mdata->task) = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SERVER_receive_done (mdata->t->owner->handle, GNUNET_OK);
-}
-
-
/**
* Check whether client wants traffic from a tunnel.
*
m->ttl = htonl (ntohl (m->ttl) - 1);
}
info->mesh_data->data_len = size;
- info->mesh_data->reference_counter = GNUNET_malloc (sizeof (unsigned int));
- *info->mesh_data->reference_counter = 1;
+ info->mesh_data->reference_counter = 1;
neighbor = peer_info_get (peer);
for (p = neighbor->path_head; NULL != p; p = p->next)
{
queue_destroy(cinfo->send_buffer[i], GNUNET_YES);
else
GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u %u\n", c, cinfo->send_buffer_n);
}
GNUNET_free_non_null (cinfo->send_buffer);
GNUNET_free (cinfo);
info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
info->mesh_data = mdata;
- (*(mdata->reference_counter)) ++;
+ (mdata->reference_counter) ++;
info->destination = neighbor_id;
GNUNET_PEER_resolve (neighbor_id, &neighbor);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending to %s...\n",
*
* @param t Tunnel in which to send the data.
* @param msg Message to be sent.
- * @param internal Has the service generated this message?
+ * @param internal DEPRECATED Has the service generated this message?
+ *
+ * FIXME remove internal if no use comes up
*/
static void
tunnel_send_multicast (struct MeshTunnel *t,
mdata = GNUNET_malloc (sizeof (struct MeshData));
mdata->data_len = ntohs (msg->size);
- mdata->reference_counter = GNUNET_malloc (sizeof (unsigned int));
mdata->t = t;
mdata->data = GNUNET_malloc (mdata->data_len);
memcpy (mdata->data, msg, mdata->data_len);
{
struct GNUNET_MESH_Multicast *mcast;
+ mcast = (struct GNUNET_MESH_Multicast *) mdata->data;
if (t->fwd_queue_n >= t->fwd_queue_max)
{
GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " queue full!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " queue full!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ " message from %s!\n",
+ GNUNET_i2s(&mcast->oid));
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ " message at %s!\n",
+ GNUNET_i2s(&my_full_id));
GNUNET_free (mdata->data);
- GNUNET_free (mdata->reference_counter);
GNUNET_free (mdata);
return;
}
t->fwd_queue_n++;
- mcast = (struct GNUNET_MESH_Multicast *) mdata->data;
mcast->ttl = htonl (ntohl (mcast->ttl) - 1);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " data packet, ttl: %u\n",
ntohl (mcast->ttl));
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not a data packet, no ttl\n");
}
- if (NULL != t->owner &&
- GNUNET_YES != t->owner->shutting_down &&
- GNUNET_NO == internal)
- {
- mdata->task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier));
- (*(mdata->task)) =
- GNUNET_SCHEDULER_add_delayed (unacknowledged_wait_time, &client_allow_send,
- mdata);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout task %u\n",
- *(mdata->task));
- }
tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata);
- if (*(mdata->reference_counter) == 0)
+ if (mdata->reference_counter == 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
" no one to send data to\n");
GNUNET_free (mdata->data);
- GNUNET_free (mdata->reference_counter);
- if (NULL != mdata->task)
- {
- GNUNET_SCHEDULER_cancel(*(mdata->task));
- GNUNET_free (mdata->task);
- GNUNET_SERVER_receive_done (t->owner->handle, GNUNET_OK);
- }
GNUNET_free (mdata);
t->fwd_queue_n--;
}
*
* @param t Tunnel.
*
- * @return Maximum PID allowed (uint32 MAX), -1 if node has no children.
+ * @return Maximum PID allowed (uint32 MAX), -1LL if node has no children.
*/
static int64_t
tunnel_get_children_fwd_ack (struct MeshTunnel *t)
* @param t Tunnel on which to look.
*
* @return Corresponding ACK value (max uint32_t).
- * If no clients are suscribed, -1.
+ * If no clients are suscribed, -1LL.
*/
static int64_t
tunnel_get_clients_fwd_ack (struct MeshTunnel *t)
return -1LL;
}
- for (ack = -1, i = 0; i < t->nclients; i++)
+ for (ack = -1LL, i = 0; i < t->nclients; i++)
{
- if (-1 == ack ||
+ if (-1LL == ack ||
(GNUNET_YES == t->speed_min &&
GNUNET_YES == GMC_is_pid_bigger (ack, t->clients_fc[i].fwd_ack)) ||
(GNUNET_NO == t->speed_min &&
static uint32_t
tunnel_get_fwd_ack (struct MeshTunnel *t)
{
+ uint32_t ack;
uint32_t count;
uint32_t buffer_free;
int64_t child_ack;
int64_t client_ack;
- uint32_t ack;
count = t->fwd_pid - t->skip;
buffer_free = t->fwd_queue_max - t->fwd_queue_n;
ack = count + buffer_free; // Might overflow 32 bits, it's ok!
child_ack = tunnel_get_children_fwd_ack (t);
client_ack = tunnel_get_clients_fwd_ack (t);
- if (-1 == child_ack)
+ if (-1LL == child_ack)
{
// Node has no children, child_ack AND core buffer are irrelevant.
- GNUNET_break (-1 != client_ack); // No children AND no clients? Not good!
+ GNUNET_break (-1LL != client_ack); // No children AND no clients? Not good!
return (uint32_t) client_ack;
}
-
+ if (-1LL == client_ack)
+ {
+ client_ack = ack;
+ }
if (GNUNET_YES == t->speed_min)
{
ack = GMC_min_pid ((uint32_t) child_ack, ack);
}
if (GNUNET_YES == t->nobuffer && GMC_is_pid_bigger(ack, t->fwd_pid))
ack = t->fwd_pid + 1; // Might overflow 32 bits, it's ok!
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "c %u, bf %u, ch %u, cl %u, ACK: %u\n",
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "c %u, bf %u, ch %lld, cl %lld, ACK: %u\n",
count, buffer_free, child_ack, client_ack, ack);
return ack;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, nobuffer\n");
return;
}
- if (t->fwd_queue_max > t->fwd_queue_n * 2 &&
- GMC_is_pid_bigger(t->last_fwd_ack, t->fwd_pid))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- " t->qmax: %u, t->qn: %u\n",
- t->fwd_queue_max, t->fwd_queue_n);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- " t->pid: %u, t->ack: %u\n",
- t->fwd_pid, t->last_fwd_ack);
- return;
- }
break;
case GNUNET_MESSAGE_TYPE_MESH_ACK:
case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
GNUNET_break (0);
}
+ /* Check if we need no retransmit the ACK */
+ if (t->fwd_queue_max > t->fwd_queue_n * 2 &&
+ GMC_is_pid_bigger(t->last_fwd_ack, t->fwd_pid))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " t->qmax: %u, t->qn: %u\n",
+ t->fwd_queue_max, t->fwd_queue_n);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " t->pid: %u, t->ack: %u\n",
+ t->fwd_pid, t->last_fwd_ack);
+ return;
+ }
+
/* Ok, ACK might be necessary, what PID to ACK? */
ack = tunnel_get_fwd_ack (t);
t->last_fwd_ack = ack;
GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id);
send_ack (t, &id, ack);
+ debug_fwd_ack++;
}
next = pq->next;
if (pq->tunnel == t)
{
+ if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST == pq->type ||
+ GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type ||
+ GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type)
+ {
+ // Should have been removed on destroy children
+ GNUNET_break (0);
+ }
queue_destroy (pq, GNUNET_YES);
}
}
if (NULL == t)
return GNUNET_OK;
- tree_iterate_children (t->tree, &tunnel_cancel_queues, t);
-
r = GNUNET_OK;
c = t->owner;
#if MESH_DEBUG
t);
GNUNET_CONTAINER_multihashmap_destroy (t->children_fc);
+ tree_iterate_children (t->tree, &tunnel_cancel_queues, t);
+
tree_destroy (t->tree);
if (NULL != t->regex_ctx)
msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
msg->tid = ntohl (t->id.tid);
+ opt = 0;
if (GNUNET_YES == t->speed_min)
- opt = MESH_TUNNEL_OPT_SPEED_MIN;
+ opt |= MESH_TUNNEL_OPT_SPEED_MIN;
if (GNUNET_YES == t->nobuffer)
opt |= MESH_TUNNEL_OPT_NOBUFFER;
msg->opt = htonl(opt);
break;
default:
GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type unknown!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ " type %u unknown!\n",
+ queue->type);
}
GNUNET_free_non_null (queue->cls);
}
break;
case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* multicast\n");
+ {
+ struct MeshTransmissionDescriptor *info = queue->cls;
+ if (info->mesh_data->reference_counter == 1)
+ t->fwd_queue_n--;
+ // FIXME fc (t->fwd_queue_n--)
+ }
data_size = send_core_data_multicast(queue->cls, size, buf);
- // FIXME fc substract when? depending on the tunnel conf.
- // t->fwd_queue_n--;
tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
break;
case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
queue->type);
data_size = 0;
}
-
- cinfo = tunnel_get_neighbor_fc(t, &dst_id);
- GNUNET_break(cinfo->send_buffer[cinfo->send_buffer_start] == queue);
- GNUNET_break(cinfo->send_buffer_n > 0);
- cinfo->send_buffer[cinfo->send_buffer_start] = NULL;
- cinfo->send_buffer_n--;
- cinfo->send_buffer_start++;
- cinfo->send_buffer_start %= t->fwd_queue_max;
+ switch (queue->type)
+ {
+ case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+ case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+ case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
+ cinfo = tunnel_get_neighbor_fc(t, &dst_id);
+ if (cinfo->send_buffer[cinfo->send_buffer_start] != queue)
+ {
+ GNUNET_break(0);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "at pos %u (%p) != %p\n",
+ cinfo->send_buffer_start,
+ cinfo->send_buffer[cinfo->send_buffer_start],
+ queue);
+ }
+ GNUNET_break(cinfo->send_buffer_n > 0);
+ cinfo->send_buffer[cinfo->send_buffer_start] = NULL;
+ cinfo->send_buffer_n--;
+ cinfo->send_buffer_start++;
+ cinfo->send_buffer_start %= t->fwd_queue_max;
+ break;
+ default:
+ break;
+ }
/* Free queue, but cls was freed by send_core_* */
queue_destroy (queue, GNUNET_NO);
}
/* If more data in queue, send next */
- if (NULL != peer->queue_head)
+ queue = queue_get_next(peer);
+ if (NULL != queue)
{
struct GNUNET_PeerIdentity id;
0,
GNUNET_TIME_UNIT_FOREVER_REL,
&id,
- peer->queue_head->size,
+ queue->size,
&queue_send,
peer);
}
+ else
+ {
+ if (NULL != peer->queue_head)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "********* %s stalled\n",
+ GNUNET_i2s(&my_full_id));
+ }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* return %d\n", data_size);
return data_size;
}
GNUNET_YES : GNUNET_NO;
t->nobuffer = (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER)) ?
GNUNET_YES : GNUNET_NO;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " speed_min: %d, nobuffer:%d\n",
+ t->speed_min, t->nobuffer);
if (GNUNET_YES == t->nobuffer)
{
{
struct MeshTunnelChildInfo *cinfo;
+ debug_bck_ack++;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
cinfo = tunnel_get_neighbor_fc (t, peer);
cinfo->fwd_ack = ack;
handle_mesh_data_multicast (client, &my_full_id, ©->header, NULL, 0);
}
- /* receive done gets called when last copy is sent to a neighbor */
+ GNUNET_SERVER_receive_done (t->owner->handle, GNUNET_OK);
return;
}
INTERVAL_SHOW;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Mesh for peer [%s] FWD ACKs %u, BCK ACKs %u\n",
+ GNUNET_i2s(&my_full_id), debug_fwd_ack, debug_bck_ack);
+
+
return ret;
}