aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2013-10-18 02:23:43 +0000
committerBart Polot <bart@net.in.tum.de>2013-10-18 02:23:43 +0000
commit28653a4922fd5a2d8fb7f72d799c9e79a2400abe (patch)
tree6512c6305a85783ff40fef1b4a405084a44cc98a /src
parentb77d61f1ee16dca21c147e09623abe9c121667b7 (diff)
downloadgnunet-28653a4922fd5a2d8fb7f72d799c9e79a2400abe.tar.gz
gnunet-28653a4922fd5a2d8fb7f72d799c9e79a2400abe.zip
- flow control changes and fixes
Diffstat (limited to 'src')
-rw-r--r--src/mesh/gnunet-service-mesh_channel.c48
-rw-r--r--src/mesh/gnunet-service-mesh_channel.h22
-rw-r--r--src/mesh/gnunet-service-mesh_connection.c253
-rw-r--r--src/mesh/gnunet-service-mesh_connection.h11
-rw-r--r--src/mesh/gnunet-service-mesh_local.c4
-rw-r--r--src/mesh/gnunet-service-mesh_tunnel.c71
-rw-r--r--src/mesh/gnunet-service-mesh_tunnel.h13
7 files changed, 293 insertions, 129 deletions
diff --git a/src/mesh/gnunet-service-mesh_channel.c b/src/mesh/gnunet-service-mesh_channel.c
index b02da1aba..519dda89d 100644
--- a/src/mesh/gnunet-service-mesh_channel.c
+++ b/src/mesh/gnunet-service-mesh_channel.c
@@ -143,6 +143,11 @@ struct MeshChannelReliability
143 */ 143 */
144 int client_ready; 144 int client_ready;
145 145
146 /**
147 * Can the client send data to us?
148 */
149 int client_allowed;
150
146 /** 151 /**
147 * Task to resend/poll in case no ACK is received. 152 * Task to resend/poll in case no ACK is received.
148 */ 153 */
@@ -465,6 +470,13 @@ send_client_ack (struct MeshChannel *ch, int fwd)
465 return; 470 return;
466 } 471 }
467 472
473 if (GNUNET_YES == rel->client_allowed)
474 {
475 LOG (GNUNET_ERROR_TYPE_DEBUG, " already allowed\n");
476 return;
477 }
478 rel->client_allowed = GNUNET_YES;
479
468 GML_send_ack (fwd ? ch->root : ch->dest, fwd ? ch->lid_root : ch->lid_dest); 480 GML_send_ack (fwd ? ch->root : ch->dest, fwd ? ch->lid_root : ch->lid_dest);
469} 481}
470 482
@@ -997,6 +1009,25 @@ GMCH_get_buffer (struct MeshChannel *ch, int fwd)
997 1009
998 1010
999/** 1011/**
1012 * Get flow control status of end point: is client allow to send?
1013 *
1014 * @param ch Channel.
1015 * @param fwd Is query about FWD traffic? (Request root status).
1016 *
1017 * @return GNUNET_YES if client is allowed to send us data.
1018 */
1019int
1020GMCH_get_allowed (struct MeshChannel *ch, int fwd)
1021{
1022 struct MeshChannelReliability *rel;
1023
1024 rel = fwd ? ch->root_rel : ch->dest_rel;
1025
1026 return rel->client_allowed;
1027}
1028
1029
1030/**
1000 * Is the root client for this channel on this peer? 1031 * Is the root client for this channel on this peer?
1001 * 1032 *
1002 * @param ch Channel. 1033 * @param ch Channel.
@@ -1152,6 +1183,19 @@ GMCH_send_data_ack (struct MeshChannel *ch, int fwd)
1152 1183
1153 1184
1154/** 1185/**
1186 * Allow a client to send us more data, in case it was choked.
1187 *
1188 * @param ch Channel.
1189 * @param fwd Is this about FWD traffic? (Root client).
1190 */
1191void
1192GMCH_allow_client (struct MeshChannel *ch, int fwd)
1193{
1194 send_client_ack (ch, fwd);
1195}
1196
1197
1198/**
1155 * Log channel info. 1199 * Log channel info.
1156 * 1200 *
1157 * @param ch Channel. 1201 * @param ch Channel.
@@ -1206,7 +1250,7 @@ GMCH_handle_local_ack (struct MeshChannel *ch, int fwd)
1206 1250
1207 rel->client_ready = GNUNET_YES; 1251 rel->client_ready = GNUNET_YES;
1208 send_client_buffered_data (ch, c, fwd); 1252 send_client_buffered_data (ch, c, fwd);
1209 GMC_send_ack (NULL, ch, fwd); 1253 GMT_send_acks (ch->t, fwd);
1210} 1254}
1211 1255
1212 1256
@@ -1247,6 +1291,8 @@ GMCH_handle_local_data (struct MeshChannel *ch,
1247 1291
1248 rel = fwd ? ch->root_rel : ch->dest_rel; 1292 rel = fwd ? ch->root_rel : ch->dest_rel;
1249 1293
1294 rel->client_allowed = GNUNET_NO;
1295
1250 /* Ok, everything is correct, send the message. */ 1296 /* Ok, everything is correct, send the message. */
1251 payload = (struct GNUNET_MESH_Data *) cbuf; 1297 payload = (struct GNUNET_MESH_Data *) cbuf;
1252 payload->mid = htonl (rel->mid_send); 1298 payload->mid = htonl (rel->mid_send);
diff --git a/src/mesh/gnunet-service-mesh_channel.h b/src/mesh/gnunet-service-mesh_channel.h
index 82d85e5be..13bef4799 100644
--- a/src/mesh/gnunet-service-mesh_channel.h
+++ b/src/mesh/gnunet-service-mesh_channel.h
@@ -84,6 +84,19 @@ GMCH_get_tunnel (const struct MeshChannel *ch);
84unsigned int 84unsigned int
85GMCH_get_buffer (struct MeshChannel *ch, int fwd); 85GMCH_get_buffer (struct MeshChannel *ch, int fwd);
86 86
87
88/**
89 * Get flow control status of end point: is client allow to send?
90 *
91 * @param ch Channel.
92 * @param fwd Is query about FWD traffic? (Request root status).
93 *
94 * @return GNUNET_YES if client is allowed to send us data.
95 */
96int
97GMCH_get_allowed (struct MeshChannel *ch, int fwd);
98
99
87/** 100/**
88 * Is the root client for this channel on this peer? 101 * Is the root client for this channel on this peer?
89 * 102 *
@@ -149,6 +162,15 @@ void
149GMCH_send_destroy (struct MeshChannel *ch); 162GMCH_send_destroy (struct MeshChannel *ch);
150 163
151/** 164/**
165 * Allow a client to send us more data, in case it was choked.
166 *
167 * @param ch Channel.
168 * @param fwd Is this about FWD traffic? (Root client).
169 */
170void
171GMCH_allow_client (struct MeshChannel *ch, int fwd);
172
173/**
152 * Log channel info. 174 * Log channel info.
153 * 175 *
154 * @param ch Channel. 176 * @param ch Channel.
diff --git a/src/mesh/gnunet-service-mesh_connection.c b/src/mesh/gnunet-service-mesh_connection.c
index 7ce26082a..64174f3f5 100644
--- a/src/mesh/gnunet-service-mesh_connection.c
+++ b/src/mesh/gnunet-service-mesh_connection.c
@@ -269,7 +269,7 @@ connection_debug (struct MeshConnection *c)
269 return; 269 return;
270 } 270 }
271 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n", 271 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
272 peer2s (c->t->peer), GNUNET_h2s (&c->id)); 272 peer2s (c->t->peer), GMC_2s (c));
273 LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n", 273 LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
274 c->state, c->pending_messages); 274 c->state, c->pending_messages);
275 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); 275 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
@@ -343,15 +343,86 @@ connection_change_state (struct MeshConnection* c,
343{ 343{
344 LOG (GNUNET_ERROR_TYPE_DEBUG, 344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "Connection %s state was %s\n", 345 "Connection %s state was %s\n",
346 GNUNET_h2s (&c->id), GMC_state2s (c->state)); 346 GMC_2s (c), GMC_state2s (c->state));
347 LOG (GNUNET_ERROR_TYPE_DEBUG, 347 LOG (GNUNET_ERROR_TYPE_DEBUG,
348 "Connection %s state is now %s\n", 348 "Connection %s state is now %s\n",
349 GNUNET_h2s (&c->id), GMC_state2s (state)); 349 GMC_2s (c), GMC_state2s (state));
350 c->state = state; 350 c->state = state;
351} 351}
352 352
353 353
354/** 354/**
355 * Send an ACK on the connection, informing the predecessor about
356 * the available buffer space. Should not be called in case the peer
357 * is origin (no predecessor).
358 *
359 * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
360 * the ACK itself goes "back" (dest->root).
361 *
362 * @param c Connection on which to send the ACK.
363 * @param buffer How much space free to advertise?
364 * @param fwd Is this FWD ACK? (Going dest->owner)
365 */
366static void
367send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
368{
369 struct MeshFlowControl *next_fc;
370 struct MeshFlowControl *prev_fc;
371 struct GNUNET_MESH_ACK msg;
372 uint32_t ack;
373 int delta;
374
375 /* If origin, there is no connection to send ACKs. Wrong function! */
376 if (GMC_is_origin (c, fwd))
377 {
378 GNUNET_break (0);
379 return;
380 }
381
382 next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
383 prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
384
385 LOG (GNUNET_ERROR_TYPE_DEBUG,
386 "connection send %s ack on %s\n",
387 fwd ? "FWD" : "BCK", GMC_2s (c));
388
389 /* Check if we need to transmit the ACK */
390 delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv;
391 if (3 < delta && buffer < delta)
392 {
393 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
394 LOG (GNUNET_ERROR_TYPE_DEBUG,
395 " last pid recv: %u, last ack sent: %u\n",
396 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
397 return;
398 }
399
400 /* Ok, ACK might be necessary, what PID to ACK? */
401 ack = prev_fc->last_pid_recv + buffer;
402 LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
403 LOG (GNUNET_ERROR_TYPE_DEBUG,
404 " last pid %u, last ack %u, qmax %u, q %u\n",
405 prev_fc->last_pid_recv, prev_fc->last_ack_sent,
406 next_fc->queue_max, next_fc->queue_n);
407 if (ack == prev_fc->last_ack_sent)
408 {
409 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
410 return;
411 }
412
413 prev_fc->last_ack_sent = ack;
414
415 /* Build ACK message and send on connection */
416 msg.header.size = htons (sizeof (msg));
417 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
418 msg.ack = htonl (ack);
419 msg.cid = c->id;
420
421 GMC_send_prebuilt_message (&msg.header, c, NULL, !fwd);
422}
423
424
425/**
355 * Callback called when a queued message is sent. 426 * Callback called when a queued message is sent.
356 * 427 *
357 * Calculates the average time and connection packet tracking. 428 * Calculates the average time and connection packet tracking.
@@ -374,8 +445,8 @@ message_sent (void *cls,
374 double usecsperbyte; 445 double usecsperbyte;
375 446
376 fc = fwd ? &c->fwd_fc : &c->bck_fc; 447 fc = fwd ? &c->fwd_fc : &c->bck_fc;
448 LOG (GNUNET_ERROR_TYPE_DEBUG, "! sent %s\n", GNUNET_MESH_DEBUG_M2S (type));
377 LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n); 449 LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n);
378 fc->queue_n--;
379 c->pending_messages--; 450 c->pending_messages--;
380 if (GNUNET_YES == c->destroy && 0 == c->pending_messages) 451 if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
381 { 452 {
@@ -387,17 +458,20 @@ message_sent (void *cls,
387 { 458 {
388 case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED: 459 case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED:
389 fc->last_pid_sent++; 460 fc->last_pid_sent++;
390 LOG (GNUNET_ERROR_TYPE_DEBUG, "! accounting pid %u\n", fc->last_pid_sent); 461 fc->queue_n--;
391// send_ack (c, ch, fwd); 462 LOG (GNUNET_ERROR_TYPE_DEBUG,
463 "! accounting pid %u\n",
464 fc->last_pid_sent);
465 GMC_send_ack (c, fwd);
392 break; 466 break;
393 default: 467 default:
394 break; 468 break;
395 } 469 }
470 LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n");
396 471
397 if (NULL == c->perf) 472 if (NULL == c->perf)
398 return; /* Only endpoints are interested in timing. */ 473 return; /* Only endpoints are interested in timing. */
399 474
400 LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n");
401 p = c->perf; 475 p = c->perf;
402 usecsperbyte = ((double) wait.rel_value_us) / size; 476 usecsperbyte = ((double) wait.rel_value_us) / size;
403 if (p->size == AVG_MSGS) 477 if (p->size == AVG_MSGS)
@@ -516,69 +590,6 @@ is_fwd (const struct MeshConnection *c,
516} 590}
517 591
518 592
519
520/**
521 * Send an ACK informing the predecessor about the available buffer space.
522 *
523 * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
524 * the ACK itself goes "back" (dest->root).
525 *
526 * @param c Connection on which to send the ACK.
527 * @param buffer How much space free to advertise?
528 * @param fwd Is this FWD ACK? (Going dest->owner)
529 */
530static void
531send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
532{
533 struct MeshFlowControl *next_fc;
534 struct MeshFlowControl *prev_fc;
535 struct GNUNET_MESH_ACK msg;
536 uint32_t ack;
537 int delta;
538
539 next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
540 prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
541
542 LOG (GNUNET_ERROR_TYPE_DEBUG,
543 "connection send %s ack on %s\n",
544 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
545
546 /* Check if we need to transmit the ACK */
547 delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv;
548 if (3 < delta && buffer < delta)
549 {
550 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
551 LOG (GNUNET_ERROR_TYPE_DEBUG,
552 " last pid recv: %u, last ack sent: %u\n",
553 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
554 return;
555 }
556
557 /* Ok, ACK might be necessary, what PID to ACK? */
558 ack = prev_fc->last_pid_recv + buffer;
559 LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
560 LOG (GNUNET_ERROR_TYPE_DEBUG,
561 " last pid %u, last ack %u, qmax %u, q %u\n",
562 prev_fc->last_pid_recv, prev_fc->last_ack_sent,
563 next_fc->queue_max, next_fc->queue_n);
564 if (ack == prev_fc->last_ack_sent)
565 {
566 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
567 return;
568 }
569
570 prev_fc->last_ack_sent = ack;
571
572 /* Build ACK message and send on connection */
573 msg.header.size = htons (sizeof (msg));
574 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
575 msg.ack = htonl (ack);
576 msg.cid = c->id;
577
578 GMC_send_prebuilt_message (&msg.header, c, NULL, !fwd);
579}
580
581
582/** 593/**
583 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE 594 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
584 * or a first CONNECTION_ACK directed to us. 595 * or a first CONNECTION_ACK directed to us.
@@ -590,7 +601,6 @@ send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
590static void 601static void
591send_connection_ack (struct MeshConnection *connection, int fwd) 602send_connection_ack (struct MeshConnection *connection, int fwd)
592{ 603{
593 struct MeshFlowControl *fc;
594 struct MeshTunnel3 *t; 604 struct MeshTunnel3 *t;
595 605
596 t = connection->t; 606 t = connection->t;
@@ -604,8 +614,6 @@ send_connection_ack (struct MeshConnection *connection, int fwd)
604 GMT_change_state (t, MESH_TUNNEL3_WAITING); 614 GMT_change_state (t, MESH_TUNNEL3_WAITING);
605 if (MESH_CONNECTION_READY != connection->state) 615 if (MESH_CONNECTION_READY != connection->state)
606 connection_change_state (connection, MESH_CONNECTION_SENT); 616 connection_change_state (connection, MESH_CONNECTION_SENT);
607 fc = fwd ? &connection->fwd_fc : &connection->bck_fc;
608 fc->queue_n++;
609} 617}
610 618
611 619
@@ -653,8 +661,8 @@ connection_keepalive (struct MeshConnection *c, int fwd)
653 GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE; 661 GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
654 662
655 LOG (GNUNET_ERROR_TYPE_DEBUG, 663 LOG (GNUNET_ERROR_TYPE_DEBUG,
656 "sending %s keepalive for connection %s[%d]\n", 664 "sending %s keepalive for connection %s]\n",
657 fwd ? "FWD" : "BCK", GMT_2s (c->t), c->id); 665 fwd ? "FWD" : "BCK", GMC_2s (c));
658 666
659 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf; 667 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
660 msg->header.size = htons (size); 668 msg->header.size = htons (size);
@@ -763,7 +771,7 @@ connection_unlock_queue (struct MeshConnection *c, int fwd)
763 771
764 LOG (GNUNET_ERROR_TYPE_DEBUG, 772 LOG (GNUNET_ERROR_TYPE_DEBUG,
765 "connection_unlock_queue %s on %s\n", 773 "connection_unlock_queue %s on %s\n",
766 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id)); 774 fwd ? "FWD" : "BCK", GMC_2s (c));
767 775
768 if (GMC_is_terminal (c, fwd)) 776 if (GMC_is_terminal (c, fwd))
769 { 777 {
@@ -829,8 +837,7 @@ connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
829 837
830 c = fc->c; 838 c = fc->c;
831 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n"); 839 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
832 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n", 840 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%s]\n", GMC_2s (c));
833 GNUNET_h2s (&c->id));
834 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** %s\n", 841 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** %s\n",
835 fc == &c->fwd_fc ? "FWD" : "BCK"); 842 fc == &c->fwd_fc ? "FWD" : "BCK");
836 843
@@ -1440,7 +1447,7 @@ handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1440 } 1447 }
1441 fc->last_pid_recv = pid; 1448 fc->last_pid_recv = pid;
1442 GMT_handle_encrypted (c->t, msg, fwd); 1449 GMT_handle_encrypted (c->t, msg, fwd);
1443 GMC_send_ack (c, NULL, fwd); 1450 GMC_send_ack (c, fwd);
1444 return GNUNET_OK; 1451 return GNUNET_OK;
1445 } 1452 }
1446 1453
@@ -1452,7 +1459,7 @@ handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1452 { 1459 {
1453 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO); 1460 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1454 LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n"); 1461 LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1455 GMC_send_ack (c, NULL, fwd); 1462 GMC_send_ack (c, fwd);
1456 return GNUNET_OK; 1463 return GNUNET_OK;
1457 } 1464 }
1458 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); 1465 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
@@ -1623,7 +1630,7 @@ GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1623 pid, fc->last_pid_recv); 1630 pid, fc->last_pid_recv);
1624 fc->last_pid_recv = pid; 1631 fc->last_pid_recv = pid;
1625 fwd = fc == &c->fwd_fc; 1632 fwd = fc == &c->fwd_fc;
1626 GMC_send_ack (c, NULL, fwd); 1633 GMC_send_ack (c, fwd);
1627 1634
1628 return GNUNET_OK; 1635 return GNUNET_OK;
1629} 1636}
@@ -1690,25 +1697,28 @@ GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1690 * the direction and the position of the peer. 1697 * the direction and the position of the peer.
1691 * 1698 *
1692 * @param c Which connection to send the hop-by-hop ACK. 1699 * @param c Which connection to send the hop-by-hop ACK.
1693 * @param ch Channel, if any.
1694 * @param fwd Is this a fwd ACK? (will go dest->root) 1700 * @param fwd Is this a fwd ACK? (will go dest->root)
1695 */ 1701 */
1696void 1702void
1697GMC_send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd) 1703GMC_send_ack (struct MeshConnection *c, int fwd)
1698{ 1704{
1699 unsigned int buffer; 1705 unsigned int buffer;
1700 1706
1701 LOG (GNUNET_ERROR_TYPE_DEBUG, 1707 LOG (GNUNET_ERROR_TYPE_DEBUG,
1702 "send ack %s on %p %p\n", 1708 "GMC send %s ACK on %s\n",
1703 fwd ? "FWD" : "BCK", c, ch); 1709 fwd ? "FWD" : "BCK", GMC_2s (c));
1704 1710
1705 /* Get available bufffer space */ 1711 if (NULL == c)
1706 if (NULL == c || GMC_is_terminal (c, fwd)) 1712 {
1713 GNUNET_break (0);
1714 return;
1715 }
1716
1717 /* Get available buffer space */
1718 if (GMC_is_terminal (c, fwd))
1707 { 1719 {
1708 struct MeshTunnel3 *t; 1720 LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all channels\n");
1709 LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all connections\n"); 1721 buffer = GMT_get_buffer (c->t, fwd);
1710 t = (NULL == c) ? GMCH_get_tunnel (ch) : GMC_get_tunnel (c);
1711 buffer = GMT_get_buffer (t, fwd);
1712 } 1722 }
1713 else 1723 else
1714 { 1724 {
@@ -1718,23 +1728,16 @@ GMC_send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1718 LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer); 1728 LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
1719 1729
1720 /* Send available buffer space */ 1730 /* Send available buffer space */
1721 if ( (NULL != ch && GMCH_is_origin (ch, fwd)) || 1731 if (GMC_is_origin (c, fwd))
1722 (NULL != c && GMC_is_origin (c, fwd)) )
1723 { 1732 {
1724 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n"); 1733 GNUNET_assert (NULL != c->t);
1734 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channels...\n");
1725 if (0 < buffer) 1735 if (0 < buffer)
1726 { 1736 {
1727 GNUNET_assert (NULL != ch);
1728 LOG (GNUNET_ERROR_TYPE_DEBUG, " really sending!\n"); 1737 LOG (GNUNET_ERROR_TYPE_DEBUG, " really sending!\n");
1729 GMCH_send_data_ack (ch, fwd); 1738 GMT_unchoke_channels (c->t, fwd);
1730 } 1739 }
1731 } 1740 }
1732 else if (NULL == c)
1733 {
1734 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on all connections\n");
1735 GNUNET_assert (NULL != ch);
1736 GMT_send_acks (GMCH_get_tunnel (ch), buffer, fwd);
1737 }
1738 else 1741 else
1739 { 1742 {
1740 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n"); 1743 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
@@ -1838,8 +1841,7 @@ GMC_destroy (struct MeshConnection *c)
1838 if (NULL == c) 1841 if (NULL == c)
1839 return; 1842 return;
1840 1843
1841 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", 1844 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", GMC_2s (c));
1842 GNUNET_h2s (&c->id));
1843 1845
1844 /* Cancel all traffic */ 1846 /* Cancel all traffic */
1845 connection_cancel_queues (c, GNUNET_YES); 1847 connection_cancel_queues (c, GNUNET_YES);
@@ -2106,8 +2108,9 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2106 memcpy (data, message, size); 2108 memcpy (data, message, size);
2107 type = ntohs (message->type); 2109 type = ntohs (message->type);
2108 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n", 2110 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
2109 GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id)); 2111 GNUNET_MESH_DEBUG_M2S (type), size, GMC_2s (c));
2110 2112
2113 fc = fwd ? &c->fwd_fc : &c->bck_fc;
2111 droppable = GNUNET_YES; 2114 droppable = GNUNET_YES;
2112 switch (type) 2115 switch (type)
2113 { 2116 {
@@ -2129,7 +2132,15 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2129 emsg->cid = c->id; 2132 emsg->cid = c->id;
2130 emsg->ttl = htonl (ttl - 1); 2133 emsg->ttl = htonl (ttl - 1);
2131 emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++); 2134 emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
2132 LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid)); 2135 LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u\n", fc, fc->queue_n);
2136 fc->queue_n++;
2137 LOG (GNUNET_ERROR_TYPE_DEBUG, "pid %u\n", ntohl (emsg->pid));
2138 LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid %u\n", fc->last_pid_sent);
2139 LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", fc->last_ack_recv);
2140 if (GMC_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
2141 {
2142 GMC_start_poll (c, fwd);
2143 }
2133 break; 2144 break;
2134 2145
2135 case GNUNET_MESSAGE_TYPE_MESH_ACK: 2146 case GNUNET_MESSAGE_TYPE_MESH_ACK:
@@ -2167,7 +2178,6 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2167 GNUNET_break (0); 2178 GNUNET_break (0);
2168 } 2179 }
2169 2180
2170 fc = fwd ? &c->fwd_fc : &c->bck_fc;
2171 if (fc->queue_n >= fc->queue_max && droppable) 2181 if (fc->queue_n >= fc->queue_max && droppable)
2172 { 2182 {
2173 GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)", 2183 GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
@@ -2179,14 +2189,6 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2179 return; /* Drop this message */ 2189 return; /* Drop this message */
2180 } 2190 }
2181 2191
2182 LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid %u\n", fc->last_pid_sent);
2183 LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", fc->last_ack_recv);
2184 LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u\n", fc, fc->queue_n);
2185 if (GMC_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
2186 {
2187 GMC_start_poll (c, fwd);
2188 }
2189 fc->queue_n++;
2190 c->pending_messages++; 2192 c->pending_messages++;
2191 2193
2192 GMP_queue_add (get_hop (c, fwd), data, type, size, c, ch, fwd, 2194 GMP_queue_add (get_hop (c, fwd), data, type, size, c, ch, fwd,
@@ -2218,7 +2220,6 @@ GMC_send_create (struct MeshConnection *connection)
2218 GMT_change_state (connection->t, MESH_TUNNEL3_WAITING); 2220 GMT_change_state (connection->t, MESH_TUNNEL3_WAITING);
2219 if (MESH_CONNECTION_NEW == connection->state) 2221 if (MESH_CONNECTION_NEW == connection->state)
2220 connection_change_state (connection, MESH_CONNECTION_SENT); 2222 connection_change_state (connection, MESH_CONNECTION_SENT);
2221 connection->fwd_fc.queue_n++;
2222} 2223}
2223 2224
2224 2225
@@ -2244,7 +2245,7 @@ GMC_send_destroy (struct MeshConnection *c)
2244 msg.cid = c->id; 2245 msg.cid = c->id;
2245 LOG (GNUNET_ERROR_TYPE_DEBUG, 2246 LOG (GNUNET_ERROR_TYPE_DEBUG,
2246 " sending connection destroy for connection %s\n", 2247 " sending connection destroy for connection %s\n",
2247 GNUNET_h2s (&c->id)); 2248 GMC_2s (c));
2248 2249
2249 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES)) 2250 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
2250 GMC_send_prebuilt_message (&msg.header, c, NULL, GNUNET_YES); 2251 GMC_send_prebuilt_message (&msg.header, c, NULL, GNUNET_YES);
@@ -2299,4 +2300,22 @@ GMC_stop_poll (struct MeshConnection *c, int fwd)
2299 GNUNET_SCHEDULER_cancel (fc->poll_task); 2300 GNUNET_SCHEDULER_cancel (fc->poll_task);
2300 fc->poll_task = GNUNET_SCHEDULER_NO_TASK; 2301 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
2301 } 2302 }
2303}
2304
2305/**
2306 * Get a (static) string for a connection.
2307 *
2308 * @param c Connection.
2309 */
2310const char *
2311GMC_2s (struct MeshConnection *c)
2312{
2313 if (NULL != c->t)
2314 {
2315 static char buf[128];
2316
2317 sprintf (buf, "%s (->%s)", GNUNET_h2s (&c->id), GMT_2s (c->t));
2318 return buf;
2319 }
2320 return GNUNET_h2s (&c->id);
2302} \ No newline at end of file 2321} \ No newline at end of file
diff --git a/src/mesh/gnunet-service-mesh_connection.h b/src/mesh/gnunet-service-mesh_connection.h
index 3fecf3b63..816d93f45 100644
--- a/src/mesh/gnunet-service-mesh_connection.h
+++ b/src/mesh/gnunet-service-mesh_connection.h
@@ -197,11 +197,10 @@ GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
197 * the direction and the position of the peer. 197 * the direction and the position of the peer.
198 * 198 *
199 * @param c Which connection to send the hop-by-hop ACK. 199 * @param c Which connection to send the hop-by-hop ACK.
200 * @param ch Channel, if any.
201 * @param fwd Is this a fwd ACK? (will go dest->root) 200 * @param fwd Is this a fwd ACK? (will go dest->root)
202 */ 201 */
203void 202void
204GMC_send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd); 203GMC_send_ack (struct MeshConnection *c, int fwd);
205 204
206/** 205/**
207 * Initialize the connections subsystem 206 * Initialize the connections subsystem
@@ -451,6 +450,14 @@ GMC_start_poll (struct MeshConnection *c, int fwd);
451void 450void
452GMC_stop_poll (struct MeshConnection *c, int fwd); 451GMC_stop_poll (struct MeshConnection *c, int fwd);
453 452
453/**
454 * Get a (static) string for a connection.
455 *
456 * @param c Connection.
457 */
458const char *
459GMC_2s (struct MeshConnection *c);
460
454#if 0 /* keep Emacsens' auto-indent happy */ 461#if 0 /* keep Emacsens' auto-indent happy */
455{ 462{
456#endif 463#endif
diff --git a/src/mesh/gnunet-service-mesh_local.c b/src/mesh/gnunet-service-mesh_local.c
index 67d4690e5..9b868124a 100644
--- a/src/mesh/gnunet-service-mesh_local.c
+++ b/src/mesh/gnunet-service-mesh_local.c
@@ -555,8 +555,8 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
555 return; 555 return;
556 } 556 }
557 557
558 /* If client is root, the ACK is going FWD, therefore this is "BCK". */ 558 /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */
559 /* If client is dest, the ACK is going BCK, therefore this is "FWD" */ 559 /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */
560 fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; 560 fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
561 561
562 GMCH_handle_local_ack (ch, fwd); 562 GMCH_handle_local_ack (ch, fwd);
diff --git a/src/mesh/gnunet-service-mesh_tunnel.c b/src/mesh/gnunet-service-mesh_tunnel.c
index 89c9a9db1..5b0573d0a 100644
--- a/src/mesh/gnunet-service-mesh_tunnel.c
+++ b/src/mesh/gnunet-service-mesh_tunnel.c
@@ -984,7 +984,7 @@ GMT_count_channels (struct MeshTunnel3 *t)
984 984
985 for (count = 0, iter = t->channel_head; 985 for (count = 0, iter = t->channel_head;
986 NULL != iter; 986 NULL != iter;
987 iter = iter->next, count++); 987 iter = iter->next, count++) /* skip */;
988 988
989 return count; 989 return count;
990} 990}
@@ -1008,10 +1008,13 @@ GMT_get_state (struct MeshTunnel3 *t)
1008/** 1008/**
1009 * Get the total buffer space for a tunnel. 1009 * Get the total buffer space for a tunnel.
1010 * 1010 *
1011 * If terminal, use the biggest channel buffer (or 64) if no channel exists.
1012 * If not terminal, use the sum of all connection buffers.
1013 *
1011 * @param t Tunnel. 1014 * @param t Tunnel.
1012 * @param fwd Is this for FWD traffic? 1015 * @param fwd Is this for FWD traffic?
1013 * 1016 *
1014 * @return Buffer space offered by all connections in the tunnel. 1017 * @return Buffer space offered by all entities (c/ch) in the tunnel.
1015 */ 1018 */
1016unsigned int 1019unsigned int
1017GMT_get_buffer (struct MeshTunnel3 *t, int fwd) 1020GMT_get_buffer (struct MeshTunnel3 *t, int fwd)
@@ -1030,7 +1033,7 @@ GMT_get_buffer (struct MeshTunnel3 *t, int fwd)
1030 1033
1031 if (NULL == t->channel_head) 1034 if (NULL == t->channel_head)
1032 { 1035 {
1033 /* Probably getting buffer for a channel create. */ 1036 /* Probably getting buffer for a channel create/handshake. */
1034 return 64; 1037 return 64;
1035 } 1038 }
1036 1039
@@ -1099,24 +1102,78 @@ GMT_get_next_chid (struct MeshTunnel3 *t)
1099 1102
1100 1103
1101/** 1104/**
1105 * Send ACK on one or more channels due to buffer in connections..
1106 *
1107 * @param t Channel which has some free buffer space.
1108 * @param fwd Is this for FWD traffic? (ACK goes to root)
1109 */
1110void
1111GMT_unchoke_channels (struct MeshTunnel3 *t, int fwd)
1112{
1113 struct MeshTChannel *iter;
1114 unsigned int buffer;
1115 unsigned int channels = GMT_count_channels (t);
1116 unsigned int choked_n;
1117 struct MeshChannel *choked[channels];
1118
1119 LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_unchoke_channels on %s\n", GMT_2s (t));
1120
1121 if (NULL == t)
1122 {
1123 GNUNET_break (0);
1124 return;
1125 }
1126
1127 /* Get buffer space */
1128 buffer = GMT_get_buffer (t, fwd);
1129 if (0 == buffer)
1130 {
1131 return;
1132 }
1133
1134 /* Count and remember choked channels */
1135 choked_n = 0;
1136 for (iter = t->channel_head; NULL != iter; iter = iter->next)
1137 {
1138 if (GNUNET_NO == GMCH_get_allowed (iter->ch, fwd))
1139 {
1140 choked[choked_n++] = iter->ch;
1141 }
1142 }
1143
1144 /* Unchoke random channels */
1145 while (0 < buffer && 0 < choked_n)
1146 {
1147 unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1148 choked_n);
1149 GMCH_allow_client (choked[r], fwd);
1150 choked_n--;
1151 buffer--;
1152 choked[r] = choked[choked_n];
1153 }
1154}
1155
1156
1157/**
1102 * Send ACK on one or more connections due to buffer space to the client. 1158 * Send ACK on one or more connections due to buffer space to the client.
1103 * 1159 *
1104 * Iterates all connections of the tunnel and sends ACKs appropriately. 1160 * Iterates all connections of the tunnel and sends ACKs appropriately.
1105 * 1161 *
1106 * @param ch Channel which has some free buffer space. 1162 * @param t Tunnel.
1107 * @param fwd Is this in for FWD traffic? (ACK goes dest->root) 1163 * @param fwd Is this in for FWD traffic? (ACK goes dest->root)
1108 */ 1164 */
1109void 1165void
1110GMT_send_acks (struct MeshTunnel3 *t, unsigned int buffer, int fwd) 1166GMT_send_acks (struct MeshTunnel3 *t, int fwd)
1111{ 1167{
1112 struct MeshTConnection *iter; 1168 struct MeshTConnection *iter;
1113 uint32_t allowed; 1169 uint32_t allowed;
1114 uint32_t to_allow; 1170 uint32_t to_allow;
1115 uint32_t allow_per_connection; 1171 uint32_t allow_per_connection;
1116 unsigned int cs; 1172 unsigned int cs;
1173 unsigned int buffer;
1117 1174
1118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1119 "Tunnel send acks on %s:%X\n", 1176 "Tunnel send %s ACKs on %s\n",
1120 fwd ? "FWD" : "BCK", GMT_2s (t)); 1177 fwd ? "FWD" : "BCK", GMT_2s (t));
1121 1178
1122 if (NULL == t) 1179 if (NULL == t)
@@ -1131,6 +1188,8 @@ GMT_send_acks (struct MeshTunnel3 *t, unsigned int buffer, int fwd)
1131 return; 1188 return;
1132 } 1189 }
1133 1190
1191 buffer = GMT_get_buffer (t, fwd);
1192
1134 /* Count connections, how many messages are already allowed */ 1193 /* Count connections, how many messages are already allowed */
1135 cs = GMT_count_connections (t); 1194 cs = GMT_count_connections (t);
1136 for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next) 1195 for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
diff --git a/src/mesh/gnunet-service-mesh_tunnel.h b/src/mesh/gnunet-service-mesh_tunnel.h
index e15d07988..9e32c5d92 100644
--- a/src/mesh/gnunet-service-mesh_tunnel.h
+++ b/src/mesh/gnunet-service-mesh_tunnel.h
@@ -280,6 +280,8 @@ GMT_get_state (struct MeshTunnel3 *t);
280 280
281/** 281/**
282 * Get the total buffer space for a tunnel. 282 * Get the total buffer space for a tunnel.
283 *
284 * FIXME get a ch parameter in case of loopback tunnels
283 * 285 *
284 * @param t Tunnel. 286 * @param t Tunnel.
285 * @param fwd Is this for FWD traffic? 287 * @param fwd Is this for FWD traffic?
@@ -310,6 +312,15 @@ MESH_ChannelNumber
310GMT_get_next_chid (struct MeshTunnel3 *t); 312GMT_get_next_chid (struct MeshTunnel3 *t);
311 313
312/** 314/**
315 * Send ACK on one or more channels due to buffer in connections..
316 *
317 * @param t Channel which has some free buffer space.
318 * @param fwd Is this for FWD traffic? (ACK goes to root)
319 */
320void
321GMT_unchoke_channels (struct MeshTunnel3 *t, int fwd);
322
323/**
313 * Send ACK on one or more connections due to buffer space to the client. 324 * Send ACK on one or more connections due to buffer space to the client.
314 * 325 *
315 * Iterates all connections of the tunnel and sends ACKs appropriately. 326 * Iterates all connections of the tunnel and sends ACKs appropriately.
@@ -318,7 +329,7 @@ GMT_get_next_chid (struct MeshTunnel3 *t);
318 * @param fwd Is this in for FWD traffic? (ACK goes dest->root) 329 * @param fwd Is this in for FWD traffic? (ACK goes dest->root)
319 */ 330 */
320void 331void
321GMT_send_acks (struct MeshTunnel3 *t, unsigned int buffer, int fwd); 332GMT_send_acks (struct MeshTunnel3 *t, int fwd);
322 333
323/** 334/**
324 * Sends an already built message on a tunnel, encrypting it and 335 * Sends an already built message on a tunnel, encrypting it and