GNUnet 0.26.2-114-g7c6b613e3
 
Loading...
Searching...
No Matches
gnunet-service-cadet_channel.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
36#include "gnunet_common.h"
37#include "platform.h"
38#include "cadet.h"
44
45#define LOG(level, ...) GNUNET_log_from (level, "cadet-chn", __VA_ARGS__)
46
50#define CADET_INITIAL_RETRANSMIT_TIME \
51 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
52
57#define TIMEOUT_CLOSED_PORT \
58 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
59
63#define MIN_RTT_DELAY \
64 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 75)
65
76#define MAX_OUT_OF_ORDER_DISTANCE 1024
77
78
105
106
172
173
200
201
244
245
391
392void
395{
396
397 ch->type = message->type;
398
399}
400
401
407int
409 GNUNET_MessageHeader *message)
410{
411
412 if (ch->type == message->type)
413 {
414 ch->type = 0;
415 return GNUNET_YES;
416 }
417 else
418 return GNUNET_NO;
419}
420
421
429const char *
430GCCH_2s (const struct CadetChannel *ch)
431{
432 static char buf[128];
433
434 GNUNET_snprintf (buf,
435 sizeof(buf),
436 "Channel %s:%s ctn:%X(%X/%X)",
437 (GNUNET_YES == ch->is_loopback)
438 ? "loopback"
440 GNUNET_h2s (&ch->port),
441 ch->ctn.cn,
442 (NULL == ch->owner)
443 ? 0
444 : ntohl (ch->owner->ccn.channel_of_client),
445 (NULL == ch->dest)
446 ? 0
447 : ntohl (ch->dest->ccn.channel_of_client));
448 return buf;
449}
450
451
461void
463 const struct GNUNET_HashCode *port,
464 const struct GNUNET_PeerIdentity *listener)
465{
466 struct GNUNET_HashContext *hc;
467
470 GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener));
473 "Calculated port hash %s\n",
474 GNUNET_h2s (h_port));
475}
476
477
487{
488 return ch->ctn;
489}
490
491
497static void
499{
500 struct CadetOutOfOrderMessage *com;
501
502 while (NULL != (com = ccc->head_recv))
503 {
505 ccc->num_recv--;
506 GNUNET_MQ_discard (com->env);
507 GNUNET_free (com);
508 }
509 GNUNET_free (ccc);
510}
511
512
518static void
520{
521 struct CadetReliableMessage *crm;
522
523 while (NULL != (crm = ch->head_sent))
524 {
525 GNUNET_assert (ch == crm->ch);
526 if (NULL != crm->qe)
527 {
528 GCT_send_cancel (crm->qe);
529 crm->qe = NULL;
530 }
531 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
533 GNUNET_free (crm);
534 }
535 if (CADET_CHANNEL_LOOSE == ch->state)
536 {
537 GSC_drop_loose_channel (&ch->h_port, ch);
538 }
539 if (NULL != ch->owner)
540 {
541 free_channel_client (ch->owner);
542 ch->owner = NULL;
543 }
544 if (NULL != ch->dest)
545 {
546 free_channel_client (ch->dest);
547 ch->dest = NULL;
548 }
549 if (NULL != ch->last_control_qe)
550 {
551 GCT_send_cancel (ch->last_control_qe);
552 ch->last_control_qe = NULL;
553 }
554 if (NULL != ch->retry_data_task)
555 {
556 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
557 ch->retry_data_task = NULL;
558 }
559 if (NULL != ch->retry_control_task)
560 {
561 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
562 ch->retry_control_task = NULL;
563 }
564 if (GNUNET_NO == ch->is_loopback)
565 {
566 GCT_remove_channel (ch->t, ch, ch->ctn);
567 ch->t = NULL;
568 }
569 GNUNET_free (ch);
570}
571
572
578static void
579send_channel_open (void *cls);
580
581
590static void
593{
594 struct CadetChannel *ch = cls;
595
596 GNUNET_assert (NULL != ch->last_control_qe);
597 ch->last_control_qe = NULL;
598 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
600 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
601 GCCH_2s (ch),
603 ch->retry_control_task =
605}
606
607
613static void
615{
616 struct CadetChannel *ch = cls;
618
619 ch->retry_control_task = NULL;
621 "Sending CHANNEL_OPEN message for %s\n",
622 GCCH_2s (ch));
623 msgcc.header.size = htons (sizeof(msgcc));
625 // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated "reliable" bit here that was removed.
626 msgcc.opt = 2;
627 msgcc.h_port = ch->h_port;
628 msgcc.ctn = ch->ctn;
630 if (NULL != ch->last_control_qe)
631 GCT_send_cancel (ch->last_control_qe);
632 ch->last_control_qe =
633 GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn);
634 GNUNET_assert (NULL == ch->retry_control_task);
635}
636
637
648void
650{
651 GNUNET_assert (NULL == ch->retry_control_task);
653 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
654 GCCH_2s (ch));
655 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch);
656}
657
658
659struct CadetChannel *
662 struct CadetPeer *destination,
663 const struct GNUNET_HashCode *port,
664 uint32_t options)
665{
666 const struct GNUNET_PeerIdentity *my_identity;
667 struct CadetChannel *ch;
668 struct CadetChannelClient *ccco;
669
672
673 ccco = GNUNET_new (struct CadetChannelClient);
674 ccco->c = owner;
675 ccco->ccn = ccn;
676 ccco->client_ready = GNUNET_YES;
677
678 ch = GNUNET_new (struct CadetChannel);
679 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
680 ch->nobuffer = GNUNET_NO;
681 ch->reliable = GNUNET_YES;
682 ch->out_of_order = GNUNET_NO;
683 ch->max_pending_messages =
684 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
685 ch->owner = ccco;
686 ch->port = *port;
687 GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination));
688 if (0 == GNUNET_memcmp (my_identity, GCP_get_id (destination)))
689 {
690 struct OpenPort *op;
691
692 ch->is_loopback = GNUNET_YES;
694 if (NULL == op)
695 {
696 /* port closed, wait for it to possibly open */
697 ch->state = CADET_CHANNEL_LOOSE;
700 &ch->h_port,
701 ch,
704 "Created loose incoming loopback channel to port %s\n",
705 GNUNET_h2s (&ch->port));
706 }
707 else
708 {
709 GCCH_bind (ch, op->c, &op->port);
710 }
711 }
712 else
713 {
714 ch->t = GCP_get_tunnel (destination, GNUNET_YES);
715 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
716 ch->ctn = GCT_add_channel (ch->t, ch);
717 }
718 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
720 "Created channel to port %s at peer %s for %s using %s\n",
722 GCP_2s (destination),
723 GSC_2s (owner),
724 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
725 return ch;
726}
727
728
735static void
737{
738 struct CadetChannel *ch = cls;
739
740 ch->retry_control_task = NULL;
742 "Closing incoming channel to port %s from peer %s due to timeout\n",
743 GNUNET_h2s (&ch->port),
746}
747
748
749struct CadetChannel *
752 const struct GNUNET_HashCode *h_port,
753 uint32_t options)
754{
755 struct CadetChannel *ch;
756 struct OpenPort *op;
757
758 ch = GNUNET_new (struct CadetChannel);
759 ch->h_port = *h_port;
760 ch->t = t;
761 ch->ctn = ctn;
762 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
763 ch->nobuffer = GNUNET_NO;
764 ch->reliable = GNUNET_YES;
765 ch->out_of_order = GNUNET_NO;
766 ch->max_pending_messages =
767 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
768 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
769
771 if (NULL == op)
772 {
773 /* port closed, wait for it to possibly open */
774 ch->state = CADET_CHANNEL_LOOSE;
777 &ch->h_port,
778 ch,
780 GNUNET_assert (NULL == ch->retry_control_task);
783 ch);
785 "Created loose incoming channel to port %s from peer %s\n",
786 GNUNET_h2s (&ch->port),
788 }
789 else
790 {
791 GCCH_bind (ch, op->c, &op->port);
792 }
793 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
794 return ch;
795}
796
797
807static void
808send_ack_cb (void *cls,
810{
811 struct CadetChannel *ch = cls;
812
813 GNUNET_assert (NULL != ch->last_control_qe);
814 ch->last_control_qe = NULL;
815}
816
817
823static void
825{
827
828 if (GNUNET_NO == ch->reliable)
829 return; /* no ACKs */
831 msg.header.size = htons (sizeof(msg));
832 msg.ctn = ch->ctn;
833 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
834 msg.futures = GNUNET_htonll (ch->mid_futures);
836 "Sending DATA_ACK %u:%llX via %s\n",
837 (unsigned int) ntohl (msg.mid.mid),
838 (unsigned long long) ch->mid_futures,
839 GCCH_2s (ch));
840 if (NULL != ch->last_control_qe)
841 GCT_send_cancel (ch->last_control_qe);
842 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
843 &msg.ctn);
844}
845
846
853static void
854send_open_ack (void *cls)
855{
856 struct CadetChannel *ch = cls;
858
859 ch->retry_control_task = NULL;
861 "Sending CHANNEL_OPEN_ACK on %s\n",
862 GCCH_2s (ch));
864 msg.header.size = htons (sizeof(msg));
865 msg.reserved = htonl (0);
866 msg.ctn = ch->ctn;
867 msg.port = ch->port;
868 if (NULL != ch->last_control_qe)
869 GCT_send_cancel (ch->last_control_qe);
870 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
871 &msg.ctn);
872}
873
874
883void
885 struct CadetChannel *ch,
887{
888 if (NULL == ch->dest)
889 {
891 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
892 GCCH_2s (ch));
893 return;
894 }
895 if (NULL != ch->retry_control_task)
896 {
898 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
899 GCCH_2s (ch));
900 return;
901 }
903 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
904 GCCH_2s (ch));
905 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
906}
907
908
916static void
917send_ack_to_client (struct CadetChannel *ch, int to_owner)
918{
919 struct GNUNET_MQ_Envelope *env;
920 struct GNUNET_CADET_LocalAck *ack;
921 struct CadetChannelClient *ccc;
922
923 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
924 if (NULL == ccc)
925 {
926 /* This can happen if we are just getting ACKs after
927 our local client already disconnected. */
928 GNUNET_assert (GNUNET_YES == ch->destroy);
929 return;
930 }
932 ack->ccn = ccc->ccn;
934 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
935 GSC_2s (ccc->c),
936 (GNUNET_YES == to_owner) ? "owner" : "dest",
937 ntohl (ack->ccn.channel_of_client),
938 ch->pending_messages,
939 ch->max_pending_messages);
940 GSC_send_to_client (ccc->c, env);
941}
942
943
944void
946 struct CadetClient *c,
947 const struct GNUNET_HashCode *port)
948{
949 const struct GNUNET_PeerIdentity *my_identity;
950 uint32_t options;
951 struct CadetChannelClient *cccd;
952
954 "Binding %s from %s to port %s of %s\n",
955 GCCH_2s (ch),
956 GCT_2s (ch->t),
957 GNUNET_h2s (&ch->port),
958 GSC_2s (c));
959
962
963 if (NULL != ch->retry_control_task)
964 {
965 /* there might be a timeout task here */
966 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
967 ch->retry_control_task = NULL;
968 }
969 options = 0;
970 cccd = GNUNET_new (struct CadetChannelClient);
971 GNUNET_assert (NULL == ch->dest);
972 ch->dest = cccd;
973 ch->port = *port;
974 cccd->c = c;
975 cccd->client_ready = GNUNET_YES;
976 cccd->ccn = GSC_bind (c,
977 ch,
978 (GNUNET_YES == ch->is_loopback)
980 : GCT_get_destination (ch->t),
981 port,
982 options);
983 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
985 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
986 if (GNUNET_YES == ch->is_loopback)
987 {
990 }
991 else
992 {
993 /* notify other peer that we accepted the connection */
994 ch->state = CADET_CHANNEL_READY;
995 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
996 }
997 /* give client it's initial supply of ACKs */
998 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
1000 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1002}
1003
1004
1012static void
1014{
1015 struct CadetChannel *ch = cls;
1016 struct CadetChannelClient *ccc;
1017
1018 /* Find which end is left... */
1019 ch->retry_control_task = NULL;
1020 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1023}
1024
1025
1034void
1036 struct CadetClient *c,
1038{
1040 "%s asks for destruction of %s\n",
1041 GSC_2s (c),
1042 GCCH_2s (ch));
1043 GNUNET_assert (NULL != c);
1044 if ((NULL != ch->owner) && (c == ch->owner->c) &&
1046 {
1047 free_channel_client (ch->owner);
1048 ch->owner = NULL;
1049 }
1050 else if ((NULL != ch->dest) && (c == ch->dest->c) &&
1052 {
1053 free_channel_client (ch->dest);
1054 ch->dest = NULL;
1055 }
1056 else
1057 {
1058 GNUNET_assert (0);
1059 }
1060
1061 if (GNUNET_YES == ch->destroy)
1062 {
1063 /* other end already destroyed, with the local client gone, no need
1064 to finish transmissions, just destroy immediately. */
1066 return;
1067 }
1068 if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest)))
1069 {
1070 /* Wait for other end to destroy us as well,
1071 and otherwise allow send queue to be transmitted first */
1072 ch->destroy = GNUNET_YES;
1073 return;
1074 }
1075 if ((GNUNET_YES == ch->is_loopback) &&
1076 ((NULL != ch->owner) || (NULL != ch->dest)))
1077 {
1078 if (NULL != ch->retry_control_task)
1079 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1080 ch->retry_control_task =
1082 return;
1083 }
1084 if (GNUNET_NO == ch->is_loopback)
1085 {
1086 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1087 switch (ch->state)
1088 {
1089 case CADET_CHANNEL_NEW:
1090 /* We gave up on a channel that we created as a client to a remote
1091 target, but that never went anywhere. Nothing to do here. */
1092 break;
1093
1095 break;
1096
1097 default:
1098 GCT_send_channel_destroy (ch->t, ch->ctn);
1099 }
1100 }
1101 /* Nothing left to do, just finish destruction */
1103}
1104
1105
1106void
1108 struct CadetChannel *ch,
1110 const struct GNUNET_HashCode *port)
1111{
1112 switch (ch->state)
1113 {
1114 case CADET_CHANNEL_NEW:
1115 /* this should be impossible */
1116 GNUNET_break (0);
1117 break;
1118
1120 /* This makes no sense. */
1121 GNUNET_break_op (0);
1122 break;
1123
1125 if (NULL == ch->owner)
1126 {
1127 /* We're not the owner, wrong direction! */
1128 GNUNET_break_op (0);
1129 return;
1130 }
1131 if (0 != GNUNET_memcmp (&ch->port, port))
1132 {
1133 /* Other peer failed to provide the right port,
1134 refuse connection. */
1135 GNUNET_break_op (0);
1136 return;
1137 }
1139 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1140 GCCH_2s (ch));
1141 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1142 {
1143 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1144 ch->retry_control_task = NULL;
1145 }
1146 ch->state = CADET_CHANNEL_READY;
1147 /* On first connect, send client as many ACKs as we allow messages
1148 to be buffered! */
1149 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1151 break;
1152
1154 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1156 "Received duplicate channel OPEN_ACK for %s\n",
1157 GCCH_2s (ch));
1158 GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO);
1159 break;
1160 }
1161}
1162
1163
1172static int
1173is_before (void *cls,
1174 struct CadetOutOfOrderMessage *m1,
1175 struct CadetOutOfOrderMessage *m2)
1176{
1177 int *duplicate = cls;
1178 uint32_t v1 = ntohl (m1->mid.mid);
1179 uint32_t v2 = ntohl (m2->mid.mid);
1180 uint32_t delta;
1181
1182 delta = v2 - v1;
1183 if (0 == delta)
1184 *duplicate = GNUNET_YES;
1185 if (delta > (uint32_t) INT_MAX)
1186 {
1187 /* in overflow range, we can safely assume we wrapped around */
1188 return GNUNET_NO;
1189 }
1190 else
1191 {
1192 /* result is small, thus v2 > v1, thus m1 < m2 */
1193 return GNUNET_YES;
1194 }
1195}
1196
1197
1198void
1200 struct CadetChannel *ch,
1203{
1204 struct GNUNET_MQ_Envelope *env;
1205 struct GNUNET_CADET_LocalData *ld;
1206 struct CadetChannelClient *ccc;
1207 size_t payload_size;
1208 struct CadetOutOfOrderMessage *com;
1209 int duplicate;
1210 uint32_t mid_min;
1211 uint32_t mid_max;
1212 uint32_t mid_msg;
1213 uint32_t delta;
1214
1215 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1216 if ((NULL == ch->owner) && (NULL == ch->dest))
1217 {
1218 /* This client is gone, but we still have messages to send to
1219 the other end (which is why @a ch is not yet dead). However,
1220 we cannot pass messages to our client anymore. */
1222 "Dropping incoming payload on %s as this end is already closed\n",
1223 GCCH_2s (ch));
1224 /* send back DESTROY notification to stop further retransmissions! */
1225 if (GNUNET_YES == ch->destroy)
1226 GCT_send_channel_destroy (ch->t, ch->ctn);
1227 return;
1228 }
1229 payload_size = ntohs (msg->header.size) - sizeof(*msg);
1231 payload_size,
1233 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1234 GNUNET_memcpy (&ld[1], &msg[1], payload_size);
1235 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1236 if (GNUNET_YES == ccc->client_ready)
1237 {
1238 /*
1239 * We ad-hoc send the message if
1240 * - The channel is out-of-order
1241 * - The channel is reliable and MID matches next expected MID
1242 * - The channel is unreliable and MID is before lowest seen MID
1243 */if ((GNUNET_YES == ch->out_of_order) ||
1244 ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) ||
1245 ((GNUNET_NO == ch->reliable) &&
1246 (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) &&
1247 ((NULL == ccc->head_recv) ||
1248 (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid)))))
1249 {
1251 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1252 (unsigned int) payload_size,
1253 ntohl (msg->mid.mid),
1254 GCCH_2s (ch),
1255 GSC_2s (ccc->c));
1256 ccc->client_ready = GNUNET_NO;
1257 GSC_send_to_client (ccc->c, env);
1258 if (GNUNET_NO == ch->out_of_order)
1259 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1260 else
1261 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1262 ch->mid_futures >>= 1;
1263 if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable))
1264 {
1265 /* possibly shift by more if we skipped messages */
1266 uint64_t d = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid);
1267
1268 if (d > 63)
1269 ch->mid_futures = 0;
1270 else
1271 ch->mid_futures >>= d;
1272 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1273 }
1275 return;
1276 }
1277 }
1278
1279 if (GNUNET_YES == ch->reliable)
1280 {
1281 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1282 mid_min = ntohl (ch->mid_recv.mid);
1283 mid_max = mid_min + ch->max_pending_messages;
1284 mid_msg = ntohl (msg->mid.mid);
1285 if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1286 ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages))
1287 {
1289 "%s at %u drops ancient or far-future message %u\n",
1290 GCCH_2s (ch),
1291 (unsigned int) mid_min,
1292 ntohl (msg->mid.mid));
1293
1295 "# duplicate DATA (ancient or future)",
1296 1,
1297 GNUNET_NO);
1300 return;
1301 }
1302 /* mark bit for future ACKs */
1303 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1304 if (delta < 64)
1305 {
1306 if (0 != (ch->mid_futures & (1LLU << delta)))
1307 {
1308 /* Duplicate within the queue, drop also */
1310 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1311 (unsigned int) payload_size,
1312 GCCH_2s (ch),
1313 ntohl (msg->mid.mid));
1314 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1317 return;
1318 }
1319 ch->mid_futures |= (1LLU << delta);
1321 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1322 (1LLU << delta),
1323 mid_msg,
1324 mid_min,
1325 (unsigned long long) ch->mid_futures);
1326 }
1327 }
1328 else /* ! ch->reliable */
1329 {
1330 struct CadetOutOfOrderMessage *next_msg;
1331
1336 if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready))
1337 {
1338 next_msg = ccc->head_recv;
1340 "Giving queued MID %u from %s to client %s\n",
1341 ntohl (next_msg->mid.mid),
1342 GCCH_2s (ch),
1343 GSC_2s (ccc->c));
1344 ccc->client_ready = GNUNET_NO;
1345 GSC_send_to_client (ccc->c, next_msg->env);
1346 ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid));
1347 ch->mid_futures >>= 1;
1349 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg);
1350 ccc->num_recv--;
1351 /* Do not process duplicate MID */
1352 if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */
1353 {
1354 /* Duplicate within the queue, drop */
1356 "Message on %s (mid %u) dropped, duplicate\n",
1357 GCCH_2s (ch),
1358 ntohl (msg->mid.mid));
1359 GNUNET_free (next_msg);
1361 return;
1362 }
1363 GNUNET_free (next_msg);
1364 }
1365
1366 if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */
1367 {
1368 /* Duplicate within the queue, drop */
1370 "Message on %s (mid %u) dropped, old.\n",
1371 GCCH_2s (ch),
1372 ntohl (msg->mid.mid));
1374 return;
1375 }
1376
1377 /* Channel is unreliable, so we do not ACK. But we also cannot
1378 allow buffering everything, so check if we have space... */
1379 if (ccc->num_recv >= ch->max_pending_messages)
1380 {
1381 struct CadetOutOfOrderMessage *drop;
1382
1383 /* Yep, need to drop. Drop the oldest message in
1384 the buffer. */
1386 "Queue full due slow client on %s, dropping oldest message\n",
1387 GCCH_2s (ch));
1389 "# messages dropped due to slow client",
1390 1,
1391 GNUNET_NO);
1392 drop = ccc->head_recv;
1393 GNUNET_assert (NULL != drop);
1395 ccc->num_recv--;
1396 GNUNET_MQ_discard (drop->env);
1397 GNUNET_free (drop);
1398 }
1399 }
1400
1401 /* Insert message into sorted out-of-order queue */
1402 com = GNUNET_new (struct CadetOutOfOrderMessage);
1403 com->mid = msg->mid;
1404 com->env = env;
1405 duplicate = GNUNET_NO;
1407 is_before,
1408 &duplicate,
1409 ccc->head_recv,
1410 ccc->tail_recv,
1411 com);
1412 ccc->num_recv++;
1413 if (GNUNET_YES == duplicate)
1414 {
1415 /* Duplicate within the queue, drop also (this is not covered by
1416 the case above if "delta" >= 64, which could be the case if
1417 max_pending_messages is also >= 64 or if our client is unready
1418 and we are seeing retransmissions of the message our client is
1419 blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG,
1420 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1421 (unsigned int) payload_size,
1422 GCCH_2s (ch),
1423 ntohl (msg->mid.mid));
1424 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1426 ccc->num_recv--;
1427 GNUNET_MQ_discard (com->env);
1428 GNUNET_free (com);
1430 return;
1431 }
1433 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1434 (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready",
1435 (unsigned int) payload_size,
1436 GCCH_2s (ch),
1437 ntohl (ccc->ccn.channel_of_client),
1438 ccc,
1439 ntohl (msg->mid.mid),
1440 ntohl (ch->mid_recv.mid));
1441 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1442 the sender may already be transmitting the previous one. Needs
1443 experimental evaluation to see if/when this ACK helps or
1444 hurts. (We might even want another option.) */
1446}
1447
1448
1459static void
1460data_sent_cb (void *cls,
1461 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
1462
1463
1470static void
1472{
1473 struct CadetChannel *ch = cls;
1474 struct CadetReliableMessage *crm = ch->head_sent;
1475
1476 ch->retry_data_task = NULL;
1477 GNUNET_assert (NULL == crm->qe);
1479 "Retrying transmission on %s of message %u\n",
1480 GCCH_2s (ch),
1481 (unsigned int) ntohl (crm->data_message->mid.mid));
1482 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1483 &crm->data_message->ctn);
1484 GNUNET_assert (NULL == ch->retry_data_task);
1485}
1486
1487
1496static void
1499 struct CadetReliableMessage *crm)
1500{
1501 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1502 ch->pending_messages--;
1503 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1505 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1506 GCCH_2s (ch),
1507 (unsigned int) ntohl (crm->data_message->mid.mid),
1508 ch->pending_messages);
1509 if (NULL != crm->qe)
1510 {
1511 GCT_send_cancel (crm->qe);
1512 crm->qe = NULL;
1513 }
1514 if ((1 == crm->num_transmissions) && (NULL != cti))
1515 {
1516 GCC_ack_observed (cti);
1517 if (0 == GNUNET_memcmp (cti, &crm->connection_taken))
1518 {
1522 }
1523 }
1525 GNUNET_free (crm);
1526 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1527}
1528
1529
1538void
1540 struct CadetChannel *ch,
1542 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1543{
1544 struct CadetReliableMessage *crm;
1545 struct CadetReliableMessage *crmn;
1546 int found;
1547 uint32_t mid_base;
1548 uint64_t mid_mask;
1549 unsigned int delta;
1550
1551 GNUNET_break (GNUNET_NO == ch->is_loopback);
1552 if (GNUNET_NO == ch->reliable)
1553 {
1554 /* not expecting ACKs on unreliable channel, odd */
1555 GNUNET_break_op (0);
1556 return;
1557 }
1558 /* mid_base is the MID of the next message that the
1559 other peer expects (i.e. that is missing!), everything
1560 LOWER (but excluding mid_base itself) was received. */
1561 mid_base = ntohl (ack->mid.mid);
1562 mid_mask = GNUNET_htonll (ack->futures);
1563 found = GNUNET_NO;
1564 for (crm = ch->head_sent; NULL != crm; crm = crmn)
1565 {
1566 crmn = crm->next;
1567 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1568 if (delta >= UINT_MAX - ch->max_pending_messages)
1569 {
1570 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1572 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1573 (unsigned int) mid_base,
1574 ntohl (crm->data_message->mid.mid),
1575 GCCH_2s (ch));
1576 handle_matching_ack (ch, cti, crm);
1577 found = GNUNET_YES;
1578 continue;
1579 }
1580 delta--;
1581 if (delta >= 64)
1582 continue;
1584 "Testing bit %llX for mid %u (base: %u)\n",
1585 (1LLU << delta),
1586 ntohl (crm->data_message->mid.mid),
1587 mid_base);
1588 if (0 != (mid_mask & (1LLU << delta)))
1589 {
1591 "Got DATA_ACK with mask for %u on %s\n",
1592 ntohl (crm->data_message->mid.mid),
1593 GCCH_2s (ch));
1594 handle_matching_ack (ch, cti, crm);
1595 found = GNUNET_YES;
1596 }
1597 }
1598 if (GNUNET_NO == found)
1599 {
1600 /* ACK for message we already dropped, might have been a
1601 duplicate ACK? Ignore. */
1603 "Duplicate DATA_ACK on %s, ignoring\n",
1604 GCCH_2s (ch));
1605 GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO);
1606 return;
1607 }
1608 if (NULL != ch->retry_data_task)
1609 {
1610 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1611 ch->retry_data_task = NULL;
1612 }
1613 if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe))
1614 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1616 ch);
1617}
1618
1619
1620void
1622 struct CadetChannel *ch,
1624{
1625 struct CadetChannelClient *ccc;
1626
1627 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1629 "Received remote channel DESTROY for %s\n",
1630 GCCH_2s (ch));
1631 if (GNUNET_YES == ch->destroy)
1632 {
1633 /* Local client already gone, this is instant-death. */
1635 return;
1636 }
1637 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1638 if ((NULL != ccc) && (NULL != ccc->head_recv))
1639 {
1641 "Lost end of transmission due to remote shutdown on %s\n",
1642 GCCH_2s (ch));
1643 /* FIXME: change API to notify client about truncated transmission! */
1644 }
1645 ch->destroy = GNUNET_YES;
1646 if (NULL != ccc)
1649}
1650
1651
1660static int
1662 struct CadetReliableMessage *crm1,
1663 struct CadetReliableMessage *crm2)
1664{
1666 return GNUNET_YES;
1667 return GNUNET_NO;
1668}
1669
1670
1681static void
1682data_sent_cb (void *cls,
1684{
1685 struct CadetReliableMessage *crm = cls;
1686 struct CadetChannel *ch = crm->ch;
1687
1688 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1689 GNUNET_assert (NULL != crm->qe);
1690 crm->qe = NULL;
1691 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1692 if (GNUNET_NO == ch->reliable)
1693 {
1695 GNUNET_free (crm);
1696 ch->pending_messages--;
1697 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1698 return;
1699 }
1700 if (NULL == cid)
1701 {
1702 /* There was an error sending. */
1704 }
1705 else if (GNUNET_SYSERR != crm->num_transmissions)
1706 {
1707 /* Increment transmission counter, and possibly store @a cid
1708 if this was the first transmission. */
1709 crm->num_transmissions++;
1710 if (1 == crm->num_transmissions)
1711 {
1713 crm->connection_taken = *cid;
1714 GCC_ack_expected (cid);
1715 }
1716 }
1717 if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid))
1718 {
1719 struct CadetConnection *cc = GCC_lookup (cid);
1720
1721 if (NULL != cc)
1722 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1723 else
1724 crm->retry_delay = ch->retry_time;
1725 }
1726 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1727 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY);
1728 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1729
1732 NULL,
1733 ch->head_sent,
1734 ch->tail_sent,
1735 crm);
1737 "Message %u sent, next transmission on %s in %s\n",
1738 (unsigned int) ntohl (crm->data_message->mid.mid),
1739 GCCH_2s (ch),
1742 ch->head_sent->next_retry),
1743 GNUNET_YES));
1744 if (NULL == ch->head_sent->qe)
1745 {
1746 if (NULL != ch->retry_data_task)
1747 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1748 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1750 ch);
1751 }
1752}
1753
1754
1769int
1772 const char *buf,
1773 size_t buf_len)
1774{
1775 struct CadetReliableMessage *crm;
1776
1777 if (ch->pending_messages >= ch->max_pending_messages)
1778 {
1779 GNUNET_break (0); /* Fails: #5370 */
1780 return GNUNET_SYSERR;
1781 }
1782 if (GNUNET_YES == ch->destroy)
1783 {
1784 /* we are going down, drop messages */
1785 return GNUNET_OK;
1786 }
1787 ch->pending_messages++;
1788
1789 if (GNUNET_YES == ch->is_loopback)
1790 {
1792 struct GNUNET_MQ_Envelope *env;
1793 struct GNUNET_CADET_LocalData *ld;
1794 int ack_to_owner;
1795
1796 env =
1798 if ((NULL != ch->owner) &&
1799 (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1800 {
1801 receiver = ch->dest;
1802 ack_to_owner = GNUNET_YES;
1803 }
1804 else if ((NULL != ch->dest) &&
1805 (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1806 {
1807 receiver = ch->owner;
1808 ack_to_owner = GNUNET_NO;
1809 }
1810 else
1811 {
1812 GNUNET_free (env);
1813 GNUNET_break (0);
1814 return GNUNET_SYSERR;
1815 }
1816 GNUNET_assert (NULL != receiver);
1817 ld->ccn = receiver->ccn;
1818 GNUNET_memcpy (&ld[1], buf, buf_len);
1819 if (GNUNET_YES == receiver->client_ready)
1820 {
1821 ch->pending_messages--;
1823 send_ack_to_client (ch, ack_to_owner);
1824 }
1825 else
1826 {
1827 struct CadetOutOfOrderMessage *oom;
1828
1829 oom = GNUNET_new (struct CadetOutOfOrderMessage);
1830 oom->env = env;
1832 receiver->tail_recv,
1833 oom);
1834 receiver->num_recv++;
1835 }
1836 return GNUNET_OK;
1837 }
1838
1839 /* Everything is correct, send the message. */
1840 crm = GNUNET_malloc (sizeof(*crm));
1841 crm->ch = ch;
1843 sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1844 crm->data_message->header.size =
1845 htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1846 crm->data_message->header.type =
1848 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1849 crm->data_message->mid = ch->mid_send;
1850 crm->data_message->ctn = ch->ctn;
1851 GNUNET_memcpy (&crm->data_message[1], buf, buf_len);
1852 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm);
1854 "Sending message %u from local client to %s with %lu bytes\n",
1855 ntohl (crm->data_message->mid.mid),
1856 GCCH_2s (ch),
1857 (unsigned long) buf_len);
1858 if (NULL != ch->retry_data_task)
1859 {
1860 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1861 ch->retry_data_task = NULL;
1862 }
1863 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1864 &crm->data_message->ctn);
1865 GNUNET_assert (NULL == ch->retry_data_task);
1866 return GNUNET_OK;
1867}
1868
1869
1870void
1872 struct GNUNET_CADET_ClientChannelNumber client_ccn)
1873{
1874 struct CadetChannelClient *ccc;
1875 struct CadetOutOfOrderMessage *com;
1876
1877 if ((NULL != ch->owner) &&
1878 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client))
1879 ccc = ch->owner;
1880 else if ((NULL != ch->dest) &&
1881 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client))
1882 ccc = ch->dest;
1883 else
1884 GNUNET_assert (0);
1885 ccc->client_ready = GNUNET_YES;
1886 com = ccc->head_recv;
1887 if (NULL == com)
1888 {
1890 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
1891 GSC_2s (ccc->c),
1892 ntohl (client_ccn.channel_of_client),
1893 GCCH_2s (ch),
1894 ntohl (ccc->ccn.channel_of_client),
1895 ccc);
1896 return; /* none pending */
1897 }
1898 if (GNUNET_YES == ch->is_loopback)
1899 {
1900 int to_owner;
1901
1902 /* Messages are always in-order, just send */
1904 ccc->num_recv--;
1905 GSC_send_to_client (ccc->c, com->env);
1906 /* Notify sender that we can receive more */
1907 if ((NULL != ch->owner) &&
1908 (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1909 {
1910 to_owner = GNUNET_NO;
1911 }
1912 else
1913 {
1914 GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client ==
1915 ch->dest->ccn.channel_of_client));
1916 to_owner = GNUNET_YES;
1917 }
1918 send_ack_to_client (ch, to_owner);
1919 GNUNET_free (com);
1920 return;
1921 }
1922
1923 if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) &&
1924 (GNUNET_YES == ch->reliable))
1925 {
1927 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1928 GSC_2s (ccc->c),
1929 ntohl (ccc->ccn.channel_of_client),
1930 ntohl (com->mid.mid),
1931 ntohl (ch->mid_recv.mid));
1932 return; /* missing next one in-order */
1933 }
1934
1936 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
1937 ntohl (com->mid.mid),
1938 GSC_2s (ccc->c),
1939 ntohl (ccc->ccn.channel_of_client),
1940 GCCH_2s (ch));
1941
1942 /* all good, pass next message to client */
1944 ccc->num_recv--;
1945 /* FIXME: if unreliable, this is not aggressive
1946 enough, as it would be OK to have lost some! */
1947
1948 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1949 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1950 ccc->client_ready = GNUNET_NO;
1951 GSC_send_to_client (ccc->c, com->env);
1952 GNUNET_free (com);
1954 if (NULL != ccc->head_recv)
1955 return;
1956 if (GNUNET_NO == ch->destroy)
1957 return;
1958 GCT_send_channel_destroy (ch->t, ch->ctn);
1960}
1961
1962
1963#define LOG2(level, ...) \
1964 GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__)
1965
1966
1973void
1975{
1976#if ! defined(GNUNET_CULL_LOGGING)
1977 int do_log;
1978
1980 "cadet-chn",
1981 __FILE__,
1982 __FUNCTION__,
1983 __LINE__);
1984 if (0 == do_log)
1985 return;
1986
1987 if (NULL == ch)
1988 {
1989 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1990 return;
1991 }
1992 LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
1993 if (NULL != ch->owner)
1994 {
1995 LOG2 (level,
1996 "CHN origin %s ready %s local-id: %u\n",
1997 GSC_2s (ch->owner->c),
1998 ch->owner->client_ready ? "YES" : "NO",
1999 ntohl (ch->owner->ccn.channel_of_client));
2000 }
2001 if (NULL != ch->dest)
2002 {
2003 LOG2 (level,
2004 "CHN destination %s ready %s local-id: %u\n",
2005 GSC_2s (ch->dest->c),
2006 ch->dest->client_ready ? "YES" : "NO",
2007 ntohl (ch->dest->ccn.channel_of_client));
2008 }
2009 LOG2 (level,
2010 "CHN Message IDs recv: %d (%llX), send: %d\n",
2011 ntohl (ch->mid_recv.mid),
2012 (unsigned long long) ch->mid_futures,
2013 ntohl (ch->mid_send.mid));
2014#endif
2015}
2016
2017
2018/* end of gnunet-service-cadet_channel.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
#define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI
Minimum value for channel IDs of local clients.
Definition cadet.h:70
#define INT_MAX
static mp_limb_t d[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static struct GNUNET_ARM_Operation * op
Current operation.
Definition gnunet-arm.c:143
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static struct GNUNET_CADET_Channel * ch
Channel handle.
static struct GNUNET_SCHEDULER_Task * t
Main task.
static struct GNUNET_PILS_Handle * pils
Handle to PILS.
Definition gnunet-pils.c:44
void GSC_handle_remote_channel_destroy(struct CadetClient *c, struct GNUNET_CADET_ClientChannelNumber ccn, struct CadetChannel *ch)
A channel was destroyed by the other peer.
void GSC_send_to_client(struct CadetClient *c, struct GNUNET_MQ_Envelope *env)
Send a message to a client.
struct GNUNET_CONTAINER_MultiHashMap * open_ports
All ports clients of this peer have opened.
struct GNUNET_CADET_ClientChannelNumber GSC_bind(struct CadetClient *c, struct CadetChannel *ch, struct CadetPeer *dest, const struct GNUNET_HashCode *port, uint32_t options)
Bind incoming channel to this client, and notify client about incoming connection.
struct GNUNET_CONTAINER_MultiHashMap * loose_channels
Map from ports to channels where the ports were closed at the time we got the inbound connection.
void GSC_drop_loose_channel(const struct GNUNET_HashCode *h_port, struct CadetChannel *ch)
A client that created a loose channel that was not bound to a port disconnected, drop it from the loo...
const char * GSC_2s(struct CadetClient *c)
Return identifier for a client as a string.
void GCCH_handle_channel_plaintext_data_ack(struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, const struct GNUNET_CADET_ChannelDataAckMessage *ack)
We got an acknowledgement for payload data for a channel.
static void send_channel_data_ack(struct CadetChannel *ch)
Compute and send the current GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.
static void handle_matching_ack(struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, struct CadetReliableMessage *crm)
We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from the queue and tell our client...
static void free_channel_client(struct CadetChannelClient *ccc)
Release memory associated with ccc.
static void channel_destroy(struct CadetChannel *ch)
Destroy the given channel.
CadetChannelState
All the states a channel can be in.
@ CADET_CHANNEL_NEW
Uninitialized status, should never appear in operation.
@ CADET_CHANNEL_OPEN_SENT
CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK.
@ CADET_CHANNEL_READY
Connection confirmed, ready to carry traffic.
@ CADET_CHANNEL_LOOSE
Channel is to a port that is not open, we're waiting for the port to be opened.
#define LOG2(level,...)
static void send_open_ack(void *cls)
Send our initial GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the connect...
int GCCH_handle_local_data(struct CadetChannel *ch, struct GNUNET_CADET_ClientChannelNumber sender_ccn, const char *buf, size_t buf_len)
Handle data given by a client.
static int cmp_crm_by_next_retry(void *cls, struct CadetReliableMessage *crm1, struct CadetReliableMessage *crm2)
Test if element e1 comes before element e2.
struct CadetChannel * GCCH_channel_incoming_new(struct CadetTunnel *t, struct GNUNET_CADET_ChannelTunnelNumber ctn, const struct GNUNET_HashCode *h_port, uint32_t options)
Create a new channel based on a request coming in over the network.
static void channel_open_sent_cb(void *cls, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
Function called once the tunnel confirms that we sent the create message.
static void send_ack_to_client(struct CadetChannel *ch, int to_owner)
Send a GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.
void GCCH_bind(struct CadetChannel *ch, struct CadetClient *c, const struct GNUNET_HashCode *port)
A client is bound to the port that we have a channel open to.
const char * GCCH_2s(const struct CadetChannel *ch)
Get the static string for identification of the channel.
void GCCH_handle_duplicate_open(struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
We got a GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for this channel.
static void send_ack_cb(void *cls, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
Function called once the tunnel confirms that we sent the ACK message.
void GCCH_handle_local_ack(struct CadetChannel *ch, struct GNUNET_CADET_ClientChannelNumber client_ccn)
Handle ACK from client on local channel.
void GCCH_channel_local_destroy(struct CadetChannel *ch, struct CadetClient *c, struct GNUNET_CADET_ClientChannelNumber ccn)
Destroy locally created channel.
void GCCH_assign_type_to_drop(struct CadetChannel *ch, const struct GNUNET_CADET_RequestDropCadetMessage *message)
Assign type of message to drop.
static void timeout_closed_cb(void *cls)
We had an incoming channel to a port that is closed.
#define CADET_INITIAL_RETRANSMIT_TIME
How long do we initially wait before retransmitting?
struct CadetChannel * GCCH_channel_local_new(struct CadetClient *owner, struct GNUNET_CADET_ClientChannelNumber ccn, struct CadetPeer *destination, const struct GNUNET_HashCode *port, uint32_t options)
Create a new channel.
void GCCH_tunnel_up(struct CadetChannel *ch)
Function called once and only once after a channel was bound to its tunnel via GCT_add_channel() is r...
void GCCH_hash_port(struct GNUNET_HashCode *h_port, const struct GNUNET_HashCode *port, const struct GNUNET_PeerIdentity *listener)
Hash the port and initiator and listener to calculate the "challenge" h_port we send to the other pee...
void GCCH_debug(struct CadetChannel *ch, enum GNUNET_ErrorType level)
Log channel info.
static void send_channel_open(void *cls)
Send a channel create message.
static int is_before(void *cls, struct CadetOutOfOrderMessage *m1, struct CadetOutOfOrderMessage *m2)
Test if element e1 comes before element e2.
#define TIMEOUT_CLOSED_PORT
How long do we wait before dropping state about incoming connection to closed port?
#define MIN_RTT_DELAY
How long do we wait at least before retransmitting ever?
#define LOG(level,...)
static void signal_remote_destroy_cb(void *cls)
One of our clients has disconnected, tell the other one that we are finished.
void GCCH_handle_channel_plaintext_data(struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, const struct GNUNET_CADET_ChannelAppDataMessage *msg)
We got payload data for a channel.
static void data_sent_cb(void *cls, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
Function called once the tunnel has sent one of our messages.
struct GNUNET_CADET_ChannelTunnelNumber GCCH_get_id(const struct CadetChannel *ch)
Get the channel's public ID.
static void retry_transmission(void *cls)
We need to retry a transmission, the last one took too long to be acknowledged.
void GCCH_handle_remote_destroy(struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
Destroy channel, based on the other peer closing the connection.
void GCCH_handle_channel_open_ack(struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, const struct GNUNET_HashCode *port)
We got an acknowledgement for the creation of the channel (the port is open on the other side).
int GCCH_is_type_to_drop(struct CadetChannel *ch, const struct GNUNET_MessageHeader *message)
Check if type of message is the one to drop.
GNUnet CADET service with encryption.
void GCC_latency_observed(const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, struct GNUNET_TIME_Relative latency)
We observed some the given latency on the connection identified by cti.
void GCC_ack_observed(const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
We observed an ACK for a message that was originally sent via the connection identified by cid.
const struct CadetConnectionMetrics * GCC_get_metrics(struct CadetConnection *cc)
Obtain performance metrics from cc.
void GCC_ack_expected(const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
We sent a message for which we expect to receive an ACK via the connection identified by cti.
struct CadetConnection * GCC_lookup(const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
Lookup a connection by its identifier.
A connection is a live end-to-end messaging mechanism where the peers are identified by a path and kn...
const struct GNUNET_PeerIdentity * GCP_get_id(struct CadetPeer *cp)
Obtain the peer identity for a struct CadetPeer.
struct CadetPeer * GCP_get(const struct GNUNET_PeerIdentity *peer_id, int create)
Retrieve the CadetPeer structure associated with the peer.
struct CadetTunnel * GCP_get_tunnel(struct CadetPeer *cp, int create)
Get the tunnel towards a peer.
const char * GCP_2s(const struct CadetPeer *cp)
Get the static string for a peer ID.
void GCT_remove_channel(struct CadetTunnel *t, struct CadetChannel *ch, struct GNUNET_CADET_ChannelTunnelNumber ctn)
Remove a channel from a tunnel.
struct CadetPeer * GCT_get_destination(struct CadetTunnel *t)
Return the peer to which this tunnel goes.
void GCT_send_channel_destroy(struct CadetTunnel *t, struct GNUNET_CADET_ChannelTunnelNumber ctn)
Send a DESTROY message via the tunnel.
void GCT_send_cancel(struct CadetTunnelQueueEntry *tq)
Cancel a previously sent message while it's in the queue.
struct CadetTunnelQueueEntry * GCT_send(struct CadetTunnel *t, const struct GNUNET_MessageHeader *message, GCT_SendContinuation cont, void *cont_cls, struct GNUNET_CADET_ChannelTunnelNumber *ctn)
Sends an already built message on a tunnel, encrypting it and choosing the best connection if not pro...
struct GNUNET_CADET_ChannelTunnelNumber GCT_add_channel(struct CadetTunnel *t, struct CadetChannel *ch)
Add a channel to a tunnel, and notify channel that we are ready for transmission if we are already up...
const char * GCT_2s(const struct CadetTunnel *t)
Get the static string for the peer this tunnel is directed.
Information we track per tunnel.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:727
API to create, modify and access statistics.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
int GNUNET_get_log_call_status(int caller_level, const char *comp, const char *file, const char *function, int line)
Decides whether a particular logging call should or should not be allowed to be made.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
#define GNUNET_CONTAINER_DLL_insert_sorted(TYPE, comparator, comparator_cls, head, tail, element)
Insertion sort of element into DLL from head to tail sorted by comparator.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
GNUNET_ErrorType
Types of errors.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition mq.c:285
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN
Ask the cadet service to create a new channel.
#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK
Local ACK for data.
#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK
Confirm payload data end-to-end.
#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA
Payload data (inside an encrypted tunnel).
#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA
Payload client <-> service.
#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK
Confirm the creation of a channel.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1260
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition time.c:438
struct GNUNET_TIME_Relative GNUNET_TIME_relative_max(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the maximum of two relative time values.
Definition time.c:352
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:604
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition socks.c:330
static struct GNUNET_TIME_Relative delta
Definition speedup.c:36
Client endpoint of a struct CadetChannel.
struct CadetOutOfOrderMessage * head_recv
Head of DLL of messages received out of order or while client was unready.
struct CadetClient * c
Client handle.
struct CadetOutOfOrderMessage * tail_recv
Tail DLL of messages received out of order or while client was unready.
struct GNUNET_CADET_ClientChannelNumber ccn
Local tunnel number for this client.
unsigned int num_recv
Number of entries currently in head_recv DLL.
int client_ready
Can we send data to the client?
Struct containing all information regarding a channel to a remote client.
struct CadetTunnel * t
Tunnel this channel is in.
unsigned int max_pending_messages
Maximum (reliable) messages pending ACK for this channel before we throttle the client.
unsigned int pending_messages
Total (reliable) messages pending ACK for this channel.
struct GNUNET_SCHEDULER_Task * retry_control_task
Task to resend/poll in case no ACK is received.
struct GNUNET_TIME_Absolute timestamp
Last time the channel was used.
struct ChannelMessageIdentifier mid_recv
Next MID expected for incoming traffic.
struct CadetReliableMessage * tail_sent
Tail of DLL of messages sent and not yet ACK'd.
struct GNUNET_TIME_Relative retry_time
Counter for exponential backoff.
int nobuffer
Is the tunnel bufferless (minimum latency)?
struct GNUNET_HashCode port
Destination port of the channel.
uint16_t type
Type of message to be dropped.
int destroy
Flag to signal the destruction of the channel.
enum CadetChannelState state
Channel state.
struct CadetChannelClient * owner
Client owner of the tunnel, if any.
int reliable
Is the tunnel reliable?
struct ChannelMessageIdentifier mid_send
Next MID to use for outgoing traffic.
uint64_t mid_futures
Bitfield of already-received messages past mid_recv.
int out_of_order
Is the tunnel out-of-order?
struct GNUNET_HashCode h_port
Hash'ed port of the channel with initiator and destination PID.
struct GNUNET_CADET_ChannelTunnelNumber ctn
Number identifying this channel in its tunnel.
struct GNUNET_SCHEDULER_Task * retry_data_task
Task to resend/poll in case no ACK is received.
struct CadetChannelClient * dest
Client destination of the tunnel, if any.
unsigned int skip_ack_series
Count how many ACKs we skipped, used to prevent long sequences of ACK skipping.
int is_loopback
Is this channel a loopback channel, where the destination is us again?
struct CadetReliableMessage * head_sent
Head of DLL of messages sent and not yet ACK'd.
struct CadetTunnelQueueEntry * last_control_qe
Last entry in the tunnel's queue relating to control messages (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN...
Struct containing information about a client of the service.
struct GNUNET_TIME_Relative aged_latency
Our current best estimate of the latency, based on a weighted average of at least latency_datapoints ...
Low-level connection to a destination.
struct GNUNET_CADET_ConnectionTunnelIdentifier cid
ID of the connection.
unsigned int off
Offset of our destination in path.
List of received out-of-order data messages.
struct ChannelMessageIdentifier mid
ID of the message (messages up to this point needed before we give this one to the client).
struct GNUNET_MQ_Envelope * env
The envelope with the payload of the out-of-order message.
struct CadetOutOfOrderMessage * next
Double linked list, FIFO style.
struct CadetOutOfOrderMessage * prev
Double linked list, FIFO style.
Struct containing all information regarding a given peer.
Info needed to retry a message in case it gets lost.
struct CadetTunnelQueueEntry * qe
Entry in the tunnels queue for this message, NULL if it has left the tunnel.
struct GNUNET_TIME_Absolute next_retry
How soon should we retry if we fail to get an ACK? Messages in the queue are sorted by this value.
struct CadetReliableMessage * next
Double linked list, FIFO style.
struct GNUNET_CADET_ChannelAppDataMessage * data_message
Data message we are trying to send.
struct GNUNET_CADET_ConnectionTunnelIdentifier connection_taken
Identifier of the connection that this message took when it was first transmitted.
struct CadetChannel * ch
Which channel is this message in?
struct GNUNET_TIME_Absolute first_transmission_time
Time when we first successfully transmitted the message (that is, set num_transmissions to 1).
struct CadetReliableMessage * prev
Double linked list, FIFO style.
int num_transmissions
How often was this message transmitted? GNUNET_SYSERR if there was an error transmitting the message,...
struct GNUNET_TIME_Relative retry_delay
How long do we wait for an ACK after transmission? Use for the back-off calculation.
Struct used to save messages in a non-ready tunnel to send once connected.
Struct containing all information regarding a tunnel to a peer.
Number used to uniquely identify messages in a CADET Channel.
uint32_t mid
Unique ID of the message, cycles around, in NBO.
Message for cadet data traffic.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA.
struct GNUNET_CADET_ChannelTunnelNumber ctn
ID of the channel.
struct ChannelMessageIdentifier mid
Unique ID of the payload message.
Message to acknowledge end-to-end data.
struct ChannelMessageIdentifier mid
Next message ID expected.
uint64_t futures
Bitfield of already-received newer messages.
Message to acknowledge opening a channel of type GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
Message to create a Channel.
struct GNUNET_HashCode h_port
Hash of destination port and listener.
struct GNUNET_CADET_ChannelTunnelNumber ctn
ID of the channel within the tunnel.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN.
uint32_t opt
Channel options.
Number identifying a CADET channel within a tunnel.
struct GNUNET_CADET_ClientChannelNumber ccn
Local ID of the channel, GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound.
Definition cadet.h:169
Number uniquely identifying a channel of a client.
Definition cadet.h:101
uint32_t channel_of_client
Values for channel numbering.
Definition cadet.h:109
Hash uniquely identifying a connection below a tunnel.
Message to allow the client send more data to the service (always service -> client).
Definition cadet.h:280
struct GNUNET_CADET_ClientChannelNumber ccn
ID of the channel allowed to send more data.
Definition cadet.h:289
Message for cadet data traffic.
Definition cadet.h:252
struct GNUNET_CADET_ClientChannelNumber ccn
ID of the channel.
Definition cadet.h:261
Message to drop another message of specific type.
Definition cadet.h:321
uint16_t type
Type of the message this handler covers, in host byte order.
Definition cadet.h:331
A 512-bit hashcode.
Header for all communications.
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition scheduler.c:141
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Port opened by a client.
struct GNUNET_HashCode h_port
Port hashed with our PID (matches incoming OPEN messages).