GNUnet 0.28.0
 
Loading...
Searching...
No Matches
gnunet-service-cadet_channel.c File Reference

logical links between CADET clients More...

Include dependency graph for gnunet-service-cadet_channel.c:

Go to the source code of this file.

Data Structures

struct  CadetReliableMessage
 Info needed to retry a message in case it gets lost. More...
 
struct  CadetOutOfOrderMessage
 List of received out-of-order data messages. More...
 
struct  CadetChannelClient
 Client endpoint of a struct CadetChannel. More...
 
struct  CadetChannel
 Struct containing all information regarding a channel to a remote client. More...
 

Macros

#define LOG(level, ...)   GNUNET_log_from (level, "cadet-chn", __VA_ARGS__)
 
#define CADET_INITIAL_RETRANSMIT_TIME    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
 How long do we initially wait before retransmitting?
 
#define TIMEOUT_CLOSED_PORT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
 How long do we wait before dropping state about incoming connection to closed port?
 
#define MIN_RTT_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 75)
 How long do we wait at least before retransmitting ever?
 
#define MAX_OUT_OF_ORDER_DISTANCE   1024
 Maximum message ID into the future we accept for out-of-order messages.
 
#define LOG2(level, ...)    GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__)
 

Enumerations

enum  CadetChannelState { CADET_CHANNEL_NEW , CADET_CHANNEL_LOOSE , CADET_CHANNEL_OPEN_SENT , CADET_CHANNEL_READY }
 All the states a channel can be in. More...
 

Functions

void GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct GNUNET_CADET_RequestDropCadetMessage *message)
 Assign type of message to drop.
 
int GCCH_is_type_to_drop (struct CadetChannel *ch, const struct GNUNET_MessageHeader *message)
 Check if type of message is the one to drop.
 
const char * GCCH_2s (const struct CadetChannel *ch)
 Get the static string for identification of the channel.
 
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 peer on GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN.
 
struct GNUNET_CADET_ChannelTunnelNumber GCCH_get_id (const struct CadetChannel *ch)
 Get the channel's public ID.
 
static void free_channel_client (struct CadetChannelClient *ccc)
 Release memory associated with ccc.
 
static void channel_destroy (struct CadetChannel *ch)
 Destroy the given channel.
 
static void send_channel_open (void *cls)
 Send a channel create message.
 
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.
 
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 ready for transmission.
 
struct CadetChannelGCCH_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.
 
static void timeout_closed_cb (void *cls)
 We had an incoming channel to a port that is closed.
 
struct CadetChannelGCCH_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 send_ack_cb (void *cls, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
 Function called once the tunnel confirms that we sent the ACK message.
 
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 send_open_ack (void *cls)
 Send our initial GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the connection is up.
 
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_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.
 
static void signal_remote_destroy_cb (void *cls)
 One of our clients has disconnected, tell the other one that we are finished.
 
void GCCH_channel_local_destroy (struct CadetChannel *ch, struct CadetClient *c, struct GNUNET_CADET_ClientChannelNumber ccn)
 Destroy locally created channel.
 
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).
 
static int is_before (void *cls, struct CadetOutOfOrderMessage *m1, struct CadetOutOfOrderMessage *m2)
 Test if element e1 comes before element e2.
 
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.
 
static void retry_transmission (void *cls)
 We need to retry a transmission, the last one took too long to be acknowledged.
 
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 that it can send more.
 
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.
 
void GCCH_handle_remote_destroy (struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
 Destroy channel, based on the other peer closing the connection.
 
static int cmp_crm_by_next_retry (void *cls, struct CadetReliableMessage *crm1, struct CadetReliableMessage *crm2)
 Test if element e1 comes before element e2.
 
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.
 
void GCCH_handle_local_ack (struct CadetChannel *ch, struct GNUNET_CADET_ClientChannelNumber client_ccn)
 Handle ACK from client on local channel.
 
void GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
 Log channel info.
 

Detailed Description

logical links between CADET clients

Author
Bartlomiej Polot
Christian Grothoff

TODO:

  • Congestion/flow control:
    • estimate max bandwidth using bursts and use to for CONGESTION CONTROL! (and figure out how/where to use this!)
    • figure out flow control without ACKs (unreliable traffic!)
  • revisit handling of 'unbuffered' traffic! (need to push down through tunnel into connection selection)
  • revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe reserve more bits in 'options' to allow for buffer size control?

Definition in file gnunet-service-cadet_channel.c.

Macro Definition Documentation

◆ LOG

#define LOG (   level,
  ... 
)    GNUNET_log_from (level, "cadet-chn", __VA_ARGS__)

Definition at line 45 of file gnunet-service-cadet_channel.c.

◆ CADET_INITIAL_RETRANSMIT_TIME

#define CADET_INITIAL_RETRANSMIT_TIME    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)

How long do we initially wait before retransmitting?

Definition at line 50 of file gnunet-service-cadet_channel.c.

82{
87
93
98
103};
104
105
112{
117
122
126 struct CadetChannel *ch;
127
134
139
145
151
157
163
170};
171
172
177{
182
187
193
197 struct GNUNET_MQ_Envelope *env;
198};
199
200
207{
214 struct CadetClient *c;
215
220
225
232
236 unsigned int num_recv;
237
241 int client_ready;
242};
243
244
248struct CadetChannel
249{
253 struct CadetTunnel *t;
254
260
265 struct CadetChannelClient *dest;
266
274
279
284
289
294
299
303 struct GNUNET_HashCode port;
304
308 struct GNUNET_HashCode h_port;
309
314
318 uint64_t mid_futures;
319
324
329
333 unsigned int pending_messages;
334
339 unsigned int max_pending_messages;
340
345
350
355 unsigned int skip_ack_series;
356
360 int nobuffer;
361
365 int reliable;
366
370 int out_of_order;
371
375 int is_loopback;
376
382 int destroy;
383
387 uint16_t type GNUNET_PACKED;
388
389};
390
391void
392GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
394{
395
396 ch->type = message->type;
397
398}
399
400
406int
407GCCH_is_type_to_drop (struct CadetChannel *ch, const struct
408 GNUNET_MessageHeader *message)
409{
410
411 if (ch->type == message->type)
412 {
413 ch->type = 0;
414 return GNUNET_YES;
415 }
416 else
417 return GNUNET_NO;
418}
419
420
428const char *
429GCCH_2s (const struct CadetChannel *ch)
430{
431 static char buf[128];
432
433 GNUNET_snprintf (buf,
434 sizeof(buf),
435 "Channel %s:%s ctn:%X(%X/%X)",
436 (GNUNET_YES == ch->is_loopback)
437 ? "loopback"
439 GNUNET_h2s (&ch->port),
440 ch->ctn.cn,
441 (NULL == ch->owner)
442 ? 0
443 : ntohl (ch->owner->ccn.channel_of_client),
444 (NULL == ch->dest)
445 ? 0
446 : ntohl (ch->dest->ccn.channel_of_client));
447 return buf;
448}
449
450
460void
461GCCH_hash_port (struct GNUNET_HashCode *h_port,
462 const struct GNUNET_HashCode *port,
463 const struct GNUNET_PeerIdentity *listener)
464{
465 struct GNUNET_HashContext *hc;
466
469 GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener));
472 "Calculated port hash %s\n",
473 GNUNET_h2s (h_port));
474}
475
476
485GCCH_get_id (const struct CadetChannel *ch)
486{
487 return ch->ctn;
488}
489
490
496static void
498{
499 struct CadetOutOfOrderMessage *com;
500
501 while (NULL != (com = ccc->head_recv))
502 {
504 ccc->num_recv--;
505 GNUNET_MQ_discard (com->env);
506 GNUNET_free (com);
507 }
508 GNUNET_free (ccc);
509}
510
511
517static void
519{
520 struct CadetReliableMessage *crm;
521
522 while (NULL != (crm = ch->head_sent))
523 {
524 GNUNET_assert (ch == crm->ch);
525 if (NULL != crm->qe)
526 {
527 GCT_send_cancel (crm->qe);
528 crm->qe = NULL;
529 }
530 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
532 GNUNET_free (crm);
533 }
534 if (CADET_CHANNEL_LOOSE == ch->state)
535 {
536 GSC_drop_loose_channel (&ch->h_port, ch);
537 }
538 if (NULL != ch->owner)
539 {
540 free_channel_client (ch->owner);
541 ch->owner = NULL;
542 }
543 if (NULL != ch->dest)
544 {
545 free_channel_client (ch->dest);
546 ch->dest = NULL;
547 }
548 if (NULL != ch->last_control_qe)
549 {
550 GCT_send_cancel (ch->last_control_qe);
551 ch->last_control_qe = NULL;
552 }
553 if (NULL != ch->retry_data_task)
554 {
555 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
556 ch->retry_data_task = NULL;
557 }
558 if (NULL != ch->retry_control_task)
559 {
560 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
561 ch->retry_control_task = NULL;
562 }
563 if (GNUNET_NO == ch->is_loopback)
564 {
565 GCT_remove_channel (ch->t, ch, ch->ctn);
566 ch->t = NULL;
567 }
568 GNUNET_free (ch);
569}
570
571
577static void
578send_channel_open (void *cls);
579
580
589static void
590channel_open_sent_cb (void *cls,
592{
593 struct CadetChannel *ch = cls;
594
595 GNUNET_assert (NULL != ch->last_control_qe);
596 ch->last_control_qe = NULL;
597 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
599 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
600 GCCH_2s (ch),
602 ch->retry_control_task =
604}
605
606
612static void
613send_channel_open (void *cls)
614{
615 struct CadetChannel *ch = cls;
617
618 ch->retry_control_task = NULL;
620 "Sending CHANNEL_OPEN message for %s\n",
621 GCCH_2s (ch));
622 msgcc.header.size = htons (sizeof(msgcc));
623 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
624 // 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.
625 msgcc.opt = 2;
626 msgcc.h_port = ch->h_port;
627 msgcc.ctn = ch->ctn;
629 if (NULL != ch->last_control_qe)
630 GCT_send_cancel (ch->last_control_qe);
631 ch->last_control_qe =
632 GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn);
633 GNUNET_assert (NULL == ch->retry_control_task);
634}
635
636
647void
649{
650 GNUNET_assert (NULL == ch->retry_control_task);
652 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
653 GCCH_2s (ch));
654 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch);
655}
656
657
658struct CadetChannel *
661 struct CadetPeer *destination,
662 const struct GNUNET_HashCode *port,
663 uint32_t options)
664{
665 const struct GNUNET_PeerIdentity *my_identity;
666 struct CadetChannel *ch;
667 struct CadetChannelClient *ccco;
668
671
672 ccco = GNUNET_new (struct CadetChannelClient);
673 ccco->c = owner;
674 ccco->ccn = ccn;
675 ccco->client_ready = GNUNET_YES;
676
677 ch = GNUNET_new (struct CadetChannel);
678 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
679 ch->nobuffer = GNUNET_NO;
680 ch->reliable = GNUNET_YES;
681 ch->out_of_order = GNUNET_NO;
682 ch->max_pending_messages =
683 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
684 ch->owner = ccco;
685 ch->port = *port;
686 GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination));
687 if (0 == GNUNET_memcmp (my_identity, GCP_get_id (destination)))
688 {
689 struct OpenPort *op;
690
691 ch->is_loopback = GNUNET_YES;
693 if (NULL == op)
694 {
695 /* port closed, wait for it to possibly open */
696 ch->state = CADET_CHANNEL_LOOSE;
699 &ch->h_port,
700 ch,
703 "Created loose incoming loopback channel to port %s\n",
704 GNUNET_h2s (&ch->port));
705 }
706 else
707 {
708 GCCH_bind (ch, op->c, &op->port);
709 }
710 }
711 else
712 {
713 ch->t = GCP_get_tunnel (destination, GNUNET_YES);
714 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
715 ch->ctn = GCT_add_channel (ch->t, ch);
716 }
717 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
719 "Created channel to port %s at peer %s for %s using %s\n",
721 GCP_2s (destination),
722 GSC_2s (owner),
723 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
724 return ch;
725}
726
727
734static void
735timeout_closed_cb (void *cls)
736{
737 struct CadetChannel *ch = cls;
738
739 ch->retry_control_task = NULL;
741 "Closing incoming channel to port %s from peer %s due to timeout\n",
742 GNUNET_h2s (&ch->port),
745}
746
747
748struct CadetChannel *
751 const struct GNUNET_HashCode *h_port,
752 uint32_t options)
753{
754 struct CadetChannel *ch;
755 struct OpenPort *op;
756
757 ch = GNUNET_new (struct CadetChannel);
758 ch->h_port = *h_port;
759 ch->t = t;
760 ch->ctn = ctn;
761 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
762 ch->nobuffer = GNUNET_NO;
763 ch->reliable = GNUNET_YES;
764 ch->out_of_order = GNUNET_NO;
765 ch->max_pending_messages =
766 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
767
769 if (NULL == op)
770 {
771 /* port closed, wait for it to possibly open */
772 ch->state = CADET_CHANNEL_LOOSE;
775 &ch->h_port,
776 ch,
778 GNUNET_assert (NULL == ch->retry_control_task);
781 ch);
783 "Created loose incoming channel to port %s from peer %s\n",
784 GNUNET_h2s (&ch->port),
786 }
787 else
788 {
789 GCCH_bind (ch, op->c, &op->port);
790 }
791 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
792 return ch;
793}
794
795
805static void
806send_ack_cb (void *cls,
808{
809 struct CadetChannel *ch = cls;
810
811 GNUNET_assert (NULL != ch->last_control_qe);
812 ch->last_control_qe = NULL;
813}
814
815
821static void
823{
825
826 if (GNUNET_NO == ch->reliable)
827 return; /* no ACKs */
829 msg.header.size = htons (sizeof(msg));
830 msg.ctn = ch->ctn;
831 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
832 msg.futures = GNUNET_htonll (ch->mid_futures);
834 "Sending DATA_ACK %u:%llX via %s\n",
835 (unsigned int) ntohl (msg.mid.mid),
836 (unsigned long long) ch->mid_futures,
837 GCCH_2s (ch));
838 if (NULL != ch->last_control_qe)
839 GCT_send_cancel (ch->last_control_qe);
840 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
841 &msg.ctn);
842}
843
844
851static void
852send_open_ack (void *cls)
853{
854 struct CadetChannel *ch = cls;
856
857 ch->retry_control_task = NULL;
859 "Sending CHANNEL_OPEN_ACK on %s\n",
860 GCCH_2s (ch));
862 msg.header.size = htons (sizeof(msg));
863 msg.reserved = htonl (0);
864 msg.ctn = ch->ctn;
865 msg.port = ch->port;
866 if (NULL != ch->last_control_qe)
867 GCT_send_cancel (ch->last_control_qe);
868 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
869 &msg.ctn);
870}
871
872
881void
883 struct CadetChannel *ch,
885{
886 if (NULL == ch->dest)
887 {
889 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
890 GCCH_2s (ch));
891 return;
892 }
893 if (NULL != ch->retry_control_task)
894 {
896 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
897 GCCH_2s (ch));
898 return;
899 }
901 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
902 GCCH_2s (ch));
903 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
904}
905
906
914static void
915send_ack_to_client (struct CadetChannel *ch, int to_owner)
916{
917 struct GNUNET_MQ_Envelope *env;
918 struct GNUNET_CADET_LocalAck *ack;
919 struct CadetChannelClient *ccc;
920
921 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
922 if (NULL == ccc)
923 {
924 /* This can happen if we are just getting ACKs after
925 our local client already disconnected. */
926 GNUNET_assert (GNUNET_YES == ch->destroy);
927 return;
928 }
930 ack->ccn = ccc->ccn;
932 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
933 GSC_2s (ccc->c),
934 (GNUNET_YES == to_owner) ? "owner" : "dest",
935 ntohl (ack->ccn.channel_of_client),
936 ch->pending_messages,
937 ch->max_pending_messages);
938 GSC_send_to_client (ccc->c, env);
939}
940
941
942void
943GCCH_bind (struct CadetChannel *ch,
944 struct CadetClient *c,
945 const struct GNUNET_HashCode *port)
946{
947 const struct GNUNET_PeerIdentity *my_identity;
948 uint32_t options;
949 struct CadetChannelClient *cccd;
950
952 "Binding %s from %s to port %s of %s\n",
953 GCCH_2s (ch),
954 GCT_2s (ch->t),
955 GNUNET_h2s (&ch->port),
956 GSC_2s (c));
957
960
961 if (NULL != ch->retry_control_task)
962 {
963 /* there might be a timeout task here */
964 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
965 ch->retry_control_task = NULL;
966 }
967 options = 0;
968 cccd = GNUNET_new (struct CadetChannelClient);
969 GNUNET_assert (NULL == ch->dest);
970 ch->dest = cccd;
971 ch->port = *port;
972 cccd->c = c;
973 cccd->client_ready = GNUNET_YES;
974 cccd->ccn = GSC_bind (c,
975 ch,
976 (GNUNET_YES == ch->is_loopback)
979 port,
980 options);
981 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
983 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
984 if (GNUNET_YES == ch->is_loopback)
985 {
988 }
989 else
990 {
991 /* notify other peer that we accepted the connection */
992 ch->state = CADET_CHANNEL_READY;
993 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
994 }
995 /* give client it's initial supply of ACKs */
996 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
998 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1000}
1001
1002
1010static void
1011signal_remote_destroy_cb (void *cls)
1012{
1013 struct CadetChannel *ch = cls;
1014 struct CadetChannelClient *ccc;
1015
1016 /* Find which end is left... */
1017 ch->retry_control_task = NULL;
1018 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1021}
1022
1023
1032void
1034 struct CadetClient *c,
1036{
1038 "%s asks for destruction of %s\n",
1039 GSC_2s (c),
1040 GCCH_2s (ch));
1041 GNUNET_assert (NULL != c);
1042 if ((NULL != ch->owner) && (c == ch->owner->c) &&
1044 {
1045 free_channel_client (ch->owner);
1046 ch->owner = NULL;
1047 }
1048 else if ((NULL != ch->dest) && (c == ch->dest->c) &&
1050 {
1051 free_channel_client (ch->dest);
1052 ch->dest = NULL;
1053 }
1054 else
1055 {
1056 GNUNET_assert (0);
1057 }
1058
1059 if (GNUNET_YES == ch->destroy)
1060 {
1061 /* other end already destroyed, with the local client gone, no need
1062 to finish transmissions, just destroy immediately. */
1064 return;
1065 }
1066 if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest)))
1067 {
1068 /* Wait for other end to destroy us as well,
1069 and otherwise allow send queue to be transmitted first */
1070 ch->destroy = GNUNET_YES;
1071 return;
1072 }
1073 if ((GNUNET_YES == ch->is_loopback) &&
1074 ((NULL != ch->owner) || (NULL != ch->dest)))
1075 {
1076 if (NULL != ch->retry_control_task)
1077 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1078 ch->retry_control_task =
1080 return;
1081 }
1082 if (GNUNET_NO == ch->is_loopback)
1083 {
1084 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1085 switch (ch->state)
1086 {
1087 case CADET_CHANNEL_NEW:
1088 /* We gave up on a channel that we created as a client to a remote
1089 target, but that never went anywhere. Nothing to do here. */
1090 break;
1091
1093 break;
1094
1095 default:
1096 GCT_send_channel_destroy (ch->t, ch->ctn);
1097 }
1098 }
1099 /* Nothing left to do, just finish destruction */
1101}
1102
1103
1104void
1106 struct CadetChannel *ch,
1108 const struct GNUNET_HashCode *port)
1109{
1110 switch (ch->state)
1111 {
1112 case CADET_CHANNEL_NEW:
1113 /* this should be impossible */
1114 GNUNET_break (0);
1115 break;
1116
1118 /* This makes no sense. */
1119 GNUNET_break_op (0);
1120 break;
1121
1123 if (NULL == ch->owner)
1124 {
1125 /* We're not the owner, wrong direction! */
1126 GNUNET_break_op (0);
1127 return;
1128 }
1129 if (0 != GNUNET_memcmp (&ch->port, port))
1130 {
1131 /* Other peer failed to provide the right port,
1132 refuse connection. */
1133 GNUNET_break_op (0);
1134 return;
1135 }
1137 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1138 GCCH_2s (ch));
1139 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1140 {
1141 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1142 ch->retry_control_task = NULL;
1143 }
1144 ch->state = CADET_CHANNEL_READY;
1145 /* On first connect, send client as many ACKs as we allow messages
1146 to be buffered! */
1147 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1149 break;
1150
1152 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1154 "Received duplicate channel OPEN_ACK for %s\n",
1155 GCCH_2s (ch));
1156 GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO);
1157 break;
1158 }
1159}
1160
1161
1170static int
1171is_before (void *cls,
1172 struct CadetOutOfOrderMessage *m1,
1173 struct CadetOutOfOrderMessage *m2)
1174{
1175 int *duplicate = cls;
1176 uint32_t v1 = ntohl (m1->mid.mid);
1177 uint32_t v2 = ntohl (m2->mid.mid);
1178 uint32_t delta;
1179
1180 delta = v2 - v1;
1181 if (0 == delta)
1182 *duplicate = GNUNET_YES;
1183 if (delta > (uint32_t) INT_MAX)
1184 {
1185 /* in overflow range, we can safely assume we wrapped around */
1186 return GNUNET_NO;
1187 }
1188 else
1189 {
1190 /* result is small, thus v2 > v1, thus m1 < m2 */
1191 return GNUNET_YES;
1192 }
1193}
1194
1195
1196void
1198 struct CadetChannel *ch,
1201{
1202 struct GNUNET_MQ_Envelope *env;
1203 struct GNUNET_CADET_LocalData *ld;
1204 struct CadetChannelClient *ccc;
1205 size_t payload_size;
1206 struct CadetOutOfOrderMessage *com;
1207 int duplicate;
1208 uint32_t mid_min;
1209 uint32_t mid_max;
1210 uint32_t mid_msg;
1211 uint32_t delta;
1212
1213 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1214 if ((NULL == ch->owner) && (NULL == ch->dest))
1215 {
1216 /* This client is gone, but we still have messages to send to
1217 the other end (which is why @a ch is not yet dead). However,
1218 we cannot pass messages to our client anymore. */
1220 "Dropping incoming payload on %s as this end is already closed\n",
1221 GCCH_2s (ch));
1222 /* send back DESTROY notification to stop further retransmissions! */
1223 if (GNUNET_YES == ch->destroy)
1224 GCT_send_channel_destroy (ch->t, ch->ctn);
1225 return;
1226 }
1227 payload_size = ntohs (msg->header.size) - sizeof(*msg);
1229 payload_size,
1231 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1232 GNUNET_memcpy (&ld[1], &msg[1], payload_size);
1233 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1234 if (GNUNET_YES == ccc->client_ready)
1235 {
1236 /*
1237 * We ad-hoc send the message if
1238 * - The channel is out-of-order
1239 * - The channel is reliable and MID matches next expected MID
1240 * - The channel is unreliable and MID is before lowest seen MID
1241 */if ((GNUNET_YES == ch->out_of_order) ||
1242 ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) ||
1243 ((GNUNET_NO == ch->reliable) &&
1244 (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) &&
1245 ((NULL == ccc->head_recv) ||
1246 (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid)))))
1247 {
1249 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1250 (unsigned int) payload_size,
1251 ntohl (msg->mid.mid),
1252 GCCH_2s (ch),
1253 GSC_2s (ccc->c));
1254 ccc->client_ready = GNUNET_NO;
1255 GSC_send_to_client (ccc->c, env);
1256 if (GNUNET_NO == ch->out_of_order)
1257 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1258 else
1259 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1260 ch->mid_futures >>= 1;
1261 if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable))
1262 {
1263 /* possibly shift by more if we skipped messages */
1264 uint64_t d = ntohl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid);
1265
1266 if (d > 63)
1267 ch->mid_futures = 0;
1268 else
1269 ch->mid_futures >>= d;
1270 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1271 }
1273 return;
1274 }
1275 }
1276
1277 if (GNUNET_YES == ch->reliable)
1278 {
1279 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1280 mid_min = ntohl (ch->mid_recv.mid);
1281 mid_max = mid_min + ch->max_pending_messages;
1282 mid_msg = ntohl (msg->mid.mid);
1283 if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1284 ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages))
1285 {
1287 "%s at %u drops ancient or far-future message %u\n",
1288 GCCH_2s (ch),
1289 (unsigned int) mid_min,
1290 ntohl (msg->mid.mid));
1291
1293 "# duplicate DATA (ancient or future)",
1294 1,
1295 GNUNET_NO);
1298 return;
1299 }
1300 /* mark bit for future ACKs */
1301 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1302 if (delta < 64)
1303 {
1304 if (0 != (ch->mid_futures & (1LLU << delta)))
1305 {
1306 /* Duplicate within the queue, drop also */
1308 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1309 (unsigned int) payload_size,
1310 GCCH_2s (ch),
1311 ntohl (msg->mid.mid));
1312 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1315 return;
1316 }
1317 ch->mid_futures |= (1LLU << delta);
1319 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1320 (1LLU << delta),
1321 mid_msg,
1322 mid_min,
1323 (unsigned long long) ch->mid_futures);
1324 }
1325 }
1326 else /* ! ch->reliable */
1327 {
1328 struct CadetOutOfOrderMessage *next_msg;
1329
1334 if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready))
1335 {
1336 next_msg = ccc->head_recv;
1338 "Giving queued MID %u from %s to client %s\n",
1339 ntohl (next_msg->mid.mid),
1340 GCCH_2s (ch),
1341 GSC_2s (ccc->c));
1342 ccc->client_ready = GNUNET_NO;
1343 GSC_send_to_client (ccc->c, next_msg->env);
1344 ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid));
1345 ch->mid_futures >>= 1;
1347 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg);
1348 ccc->num_recv--;
1349 /* Do not process duplicate MID */
1350 if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */
1351 {
1352 /* Duplicate within the queue, drop */
1354 "Message on %s (mid %u) dropped, duplicate\n",
1355 GCCH_2s (ch),
1356 ntohl (msg->mid.mid));
1357 GNUNET_free (next_msg);
1359 return;
1360 }
1361 GNUNET_free (next_msg);
1362 }
1363
1364 if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */
1365 {
1366 /* Duplicate within the queue, drop */
1368 "Message on %s (mid %u) dropped, old.\n",
1369 GCCH_2s (ch),
1370 ntohl (msg->mid.mid));
1372 return;
1373 }
1374
1375 /* Channel is unreliable, so we do not ACK. But we also cannot
1376 allow buffering everything, so check if we have space... */
1377 if (ccc->num_recv >= ch->max_pending_messages)
1378 {
1379 struct CadetOutOfOrderMessage *drop;
1380
1381 /* Yep, need to drop. Drop the oldest message in
1382 the buffer. */
1384 "Queue full due slow client on %s, dropping oldest message\n",
1385 GCCH_2s (ch));
1387 "# messages dropped due to slow client",
1388 1,
1389 GNUNET_NO);
1390 drop = ccc->head_recv;
1391 GNUNET_assert (NULL != drop);
1393 ccc->num_recv--;
1394 GNUNET_MQ_discard (drop->env);
1395 GNUNET_free (drop);
1396 }
1397 }
1398
1399 /* Insert message into sorted out-of-order queue */
1400 com = GNUNET_new (struct CadetOutOfOrderMessage);
1401 com->mid = msg->mid;
1402 com->env = env;
1403 duplicate = GNUNET_NO;
1405 is_before,
1406 &duplicate,
1407 ccc->head_recv,
1408 ccc->tail_recv,
1409 com);
1410 ccc->num_recv++;
1411 if (GNUNET_YES == duplicate)
1412 {
1413 /* Duplicate within the queue, drop also (this is not covered by
1414 the case above if "delta" >= 64, which could be the case if
1415 max_pending_messages is also >= 64 or if our client is unready
1416 and we are seeing retransmissions of the message our client is
1417 blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG,
1418 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1419 (unsigned int) payload_size,
1420 GCCH_2s (ch),
1421 ntohl (msg->mid.mid));
1422 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1424 ccc->num_recv--;
1425 GNUNET_MQ_discard (com->env);
1426 GNUNET_free (com);
1428 return;
1429 }
1431 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1432 (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready",
1433 (unsigned int) payload_size,
1434 GCCH_2s (ch),
1435 ntohl (ccc->ccn.channel_of_client),
1436 ccc,
1437 ntohl (msg->mid.mid),
1438 ntohl (ch->mid_recv.mid));
1439 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1440 the sender may already be transmitting the previous one. Needs
1441 experimental evaluation to see if/when this ACK helps or
1442 hurts. (We might even want another option.) */
1444}
1445
1446
1457static void
1458data_sent_cb (void *cls,
1459 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
1460
1461
1468static void
1469retry_transmission (void *cls)
1470{
1471 struct CadetChannel *ch = cls;
1472 struct CadetReliableMessage *crm = ch->head_sent;
1473
1474 ch->retry_data_task = NULL;
1475 GNUNET_assert (NULL == crm->qe);
1477 "Retrying transmission on %s of message %u\n",
1478 GCCH_2s (ch),
1479 (unsigned int) ntohl (crm->data_message->mid.mid));
1480 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1481 &crm->data_message->ctn);
1482 GNUNET_assert (NULL == ch->retry_data_task);
1483}
1484
1485
1494static void
1497 struct CadetReliableMessage *crm)
1498{
1499 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1500 ch->pending_messages--;
1501 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1503 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1504 GCCH_2s (ch),
1505 (unsigned int) ntohl (crm->data_message->mid.mid),
1506 ch->pending_messages);
1507 if (NULL != crm->qe)
1508 {
1509 GCT_send_cancel (crm->qe);
1510 crm->qe = NULL;
1511 }
1512 if ((1 == crm->num_transmissions) && (NULL != cti))
1513 {
1514 GCC_ack_observed (cti);
1515 if (0 == GNUNET_memcmp (cti, &crm->connection_taken))
1516 {
1520 }
1521 }
1523 GNUNET_free (crm);
1524 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1525}
1526
1527
1536void
1538 struct CadetChannel *ch,
1540 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1541{
1542 struct CadetReliableMessage *crm;
1543 struct CadetReliableMessage *crmn;
1544 int found;
1545 uint32_t mid_base;
1546 uint64_t mid_mask;
1547 unsigned int delta;
1548
1549 GNUNET_break (GNUNET_NO == ch->is_loopback);
1550 if (GNUNET_NO == ch->reliable)
1551 {
1552 /* not expecting ACKs on unreliable channel, odd */
1553 GNUNET_break_op (0);
1554 return;
1555 }
1556 /* mid_base is the MID of the next message that the
1557 other peer expects (i.e. that is missing!), everything
1558 LOWER (but excluding mid_base itself) was received. */
1559 mid_base = ntohl (ack->mid.mid);
1560 mid_mask = GNUNET_htonll (ack->futures);
1561 found = GNUNET_NO;
1562 for (crm = ch->head_sent; NULL != crm; crm = crmn)
1563 {
1564 crmn = crm->next;
1565 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1566 if (delta >= UINT_MAX - ch->max_pending_messages)
1567 {
1568 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1570 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1571 (unsigned int) mid_base,
1572 ntohl (crm->data_message->mid.mid),
1573 GCCH_2s (ch));
1574 handle_matching_ack (ch, cti, crm);
1575 found = GNUNET_YES;
1576 continue;
1577 }
1578 delta--;
1579 if (delta >= 64)
1580 continue;
1582 "Testing bit %llX for mid %u (base: %u)\n",
1583 (1LLU << delta),
1584 ntohl (crm->data_message->mid.mid),
1585 mid_base);
1586 if (0 != (mid_mask & (1LLU << delta)))
1587 {
1589 "Got DATA_ACK with mask for %u on %s\n",
1590 ntohl (crm->data_message->mid.mid),
1591 GCCH_2s (ch));
1592 handle_matching_ack (ch, cti, crm);
1593 found = GNUNET_YES;
1594 }
1595 }
1596 if (GNUNET_NO == found)
1597 {
1598 /* ACK for message we already dropped, might have been a
1599 duplicate ACK? Ignore. */
1601 "Duplicate DATA_ACK on %s, ignoring\n",
1602 GCCH_2s (ch));
1603 GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO);
1604 return;
1605 }
1606 if (NULL != ch->retry_data_task)
1607 {
1608 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1609 ch->retry_data_task = NULL;
1610 }
1611 if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe))
1612 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1614 ch);
1615}
1616
1617
1618void
1620 struct CadetChannel *ch,
1622{
1623 struct CadetChannelClient *ccc;
1624
1625 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1627 "Received remote channel DESTROY for %s\n",
1628 GCCH_2s (ch));
1629 if (GNUNET_YES == ch->destroy)
1630 {
1631 /* Local client already gone, this is instant-death. */
1633 return;
1634 }
1635 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1636 if ((NULL != ccc) && (NULL != ccc->head_recv))
1637 {
1639 "Lost end of transmission due to remote shutdown on %s\n",
1640 GCCH_2s (ch));
1641 /* FIXME: change API to notify client about truncated transmission! */
1642 }
1643 ch->destroy = GNUNET_YES;
1644 if (NULL != ccc)
1647}
1648
1649
1658static int
1659cmp_crm_by_next_retry (void *cls,
1660 struct CadetReliableMessage *crm1,
1661 struct CadetReliableMessage *crm2)
1662{
1664 return GNUNET_YES;
1665 return GNUNET_NO;
1666}
1667
1668
1679static void
1680data_sent_cb (void *cls,
1682{
1683 struct CadetReliableMessage *crm = cls;
1684 struct CadetChannel *ch = crm->ch;
1685
1686 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1687 GNUNET_assert (NULL != crm->qe);
1688 crm->qe = NULL;
1689 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1690 if (GNUNET_NO == ch->reliable)
1691 {
1693 GNUNET_free (crm);
1694 ch->pending_messages--;
1695 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1696 return;
1697 }
1698 if (NULL == cid)
1699 {
1700 /* There was an error sending. */
1702 }
1703 else if (GNUNET_SYSERR != crm->num_transmissions)
1704 {
1705 /* Increment transmission counter, and possibly store @a cid
1706 if this was the first transmission. */
1707 crm->num_transmissions++;
1708 if (1 == crm->num_transmissions)
1709 {
1711 crm->connection_taken = *cid;
1712 GCC_ack_expected (cid);
1713 }
1714 }
1715 if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid))
1716 {
1717 struct CadetConnection *cc = GCC_lookup (cid);
1718
1719 if (NULL != cc)
1720 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1721 else
1722 crm->retry_delay = ch->retry_time;
1723 }
1724 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1725 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY);
1726 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1727
1730 NULL,
1731 ch->head_sent,
1732 ch->tail_sent,
1733 crm);
1735 "Message %u sent, next transmission on %s in %s\n",
1736 (unsigned int) ntohl (crm->data_message->mid.mid),
1737 GCCH_2s (ch),
1740 ch->head_sent->next_retry),
1741 GNUNET_YES));
1742 if (NULL == ch->head_sent->qe)
1743 {
1744 if (NULL != ch->retry_data_task)
1745 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1746 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1748 ch);
1749 }
1750}
1751
1752
1767int
1770 const char *buf,
1771 size_t buf_len)
1772{
1773 struct CadetReliableMessage *crm;
1774
1775 if (ch->pending_messages >= ch->max_pending_messages)
1776 {
1777 GNUNET_break (0); /* Fails: #5370 */
1778 return GNUNET_SYSERR;
1779 }
1780 if (GNUNET_YES == ch->destroy)
1781 {
1782 /* we are going down, drop messages */
1783 return GNUNET_OK;
1784 }
1785 ch->pending_messages++;
1786
1787 if (GNUNET_YES == ch->is_loopback)
1788 {
1790 struct GNUNET_MQ_Envelope *env;
1791 struct GNUNET_CADET_LocalData *ld;
1792 int ack_to_owner;
1793
1794 env =
1796 if ((NULL != ch->owner) &&
1797 (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1798 {
1799 receiver = ch->dest;
1800 ack_to_owner = GNUNET_YES;
1801 }
1802 else if ((NULL != ch->dest) &&
1803 (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1804 {
1805 receiver = ch->owner;
1806 ack_to_owner = GNUNET_NO;
1807 }
1808 else
1809 {
1810 GNUNET_free (env);
1811 GNUNET_break (0);
1812 return GNUNET_SYSERR;
1813 }
1814 GNUNET_assert (NULL != receiver);
1815 ld->ccn = receiver->ccn;
1816 GNUNET_memcpy (&ld[1], buf, buf_len);
1817 if (GNUNET_YES == receiver->client_ready)
1818 {
1819 ch->pending_messages--;
1821 send_ack_to_client (ch, ack_to_owner);
1822 }
1823 else
1824 {
1825 struct CadetOutOfOrderMessage *oom;
1826
1827 oom = GNUNET_new (struct CadetOutOfOrderMessage);
1828 oom->env = env;
1830 receiver->tail_recv,
1831 oom);
1832 receiver->num_recv++;
1833 }
1834 return GNUNET_OK;
1835 }
1836
1837 /* Everything is correct, send the message. */
1838 crm = GNUNET_malloc (sizeof(*crm));
1839 crm->ch = ch;
1841 sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1842 crm->data_message->header.size =
1843 htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1844 crm->data_message->header.type =
1846 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1847 crm->data_message->mid = ch->mid_send;
1848 crm->data_message->ctn = ch->ctn;
1849 GNUNET_memcpy (&crm->data_message[1], buf, buf_len);
1850 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm);
1852 "Sending message %u from local client to %s with %lu bytes\n",
1853 ntohl (crm->data_message->mid.mid),
1854 GCCH_2s (ch),
1855 (unsigned long) buf_len);
1856 if (NULL != ch->retry_data_task)
1857 {
1858 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1859 ch->retry_data_task = NULL;
1860 }
1861 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1862 &crm->data_message->ctn);
1863 GNUNET_assert (NULL == ch->retry_data_task);
1864 return GNUNET_OK;
1865}
1866
1867
1868void
1870 struct GNUNET_CADET_ClientChannelNumber client_ccn)
1871{
1872 struct CadetChannelClient *ccc;
1873 struct CadetOutOfOrderMessage *com;
1874
1875 if ((NULL != ch->owner) &&
1876 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client))
1877 ccc = ch->owner;
1878 else if ((NULL != ch->dest) &&
1879 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client))
1880 ccc = ch->dest;
1881 else
1882 GNUNET_assert (0);
1883 ccc->client_ready = GNUNET_YES;
1884 com = ccc->head_recv;
1885 if (NULL == com)
1886 {
1888 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
1889 GSC_2s (ccc->c),
1890 ntohl (client_ccn.channel_of_client),
1891 GCCH_2s (ch),
1892 ntohl (ccc->ccn.channel_of_client),
1893 ccc);
1894 return; /* none pending */
1895 }
1896 if (GNUNET_YES == ch->is_loopback)
1897 {
1898 int to_owner;
1899
1900 /* Messages are always in-order, just send */
1902 ccc->num_recv--;
1903 GSC_send_to_client (ccc->c, com->env);
1904 /* Notify sender that we can receive more */
1905 if ((NULL != ch->owner) &&
1906 (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1907 {
1908 to_owner = GNUNET_NO;
1909 }
1910 else
1911 {
1912 GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client ==
1913 ch->dest->ccn.channel_of_client));
1914 to_owner = GNUNET_YES;
1915 }
1916 send_ack_to_client (ch, to_owner);
1917 GNUNET_free (com);
1918 return;
1919 }
1920
1921 if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) &&
1922 (GNUNET_YES == ch->reliable))
1923 {
1925 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1926 GSC_2s (ccc->c),
1927 ntohl (ccc->ccn.channel_of_client),
1928 ntohl (com->mid.mid),
1929 ntohl (ch->mid_recv.mid));
1930 return; /* missing next one in-order */
1931 }
1932
1934 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
1935 ntohl (com->mid.mid),
1936 GSC_2s (ccc->c),
1937 ntohl (ccc->ccn.channel_of_client),
1938 GCCH_2s (ch));
1939
1940 /* all good, pass next message to client */
1942 ccc->num_recv--;
1943 /* FIXME: if unreliable, this is not aggressive
1944 enough, as it would be OK to have lost some! */
1945
1946 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1947 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1948 ccc->client_ready = GNUNET_NO;
1949 GSC_send_to_client (ccc->c, com->env);
1950 GNUNET_free (com);
1952 if (NULL != ccc->head_recv)
1953 return;
1954 if (GNUNET_NO == ch->destroy)
1955 return;
1956 GCT_send_channel_destroy (ch->t, ch->ctn);
1958}
1959
1960
1961#define LOG2(level, ...) \
1962 GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__)
1963
1964
1971void
1972GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
1973{
1974#if ! defined(GNUNET_CULL_LOGGING)
1975 int do_log;
1976
1978 "cadet-chn",
1979 __FILE__,
1980 __FUNCTION__,
1981 __LINE__);
1982 if (0 == do_log)
1983 return;
1984
1985 if (NULL == ch)
1986 {
1987 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1988 return;
1989 }
1990 LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
1991 if (NULL != ch->owner)
1992 {
1993 LOG2 (level,
1994 "CHN origin %s ready %s local-id: %u\n",
1995 GSC_2s (ch->owner->c),
1996 ch->owner->client_ready ? "YES" : "NO",
1997 ntohl (ch->owner->ccn.channel_of_client));
1998 }
1999 if (NULL != ch->dest)
2000 {
2001 LOG2 (level,
2002 "CHN destination %s ready %s local-id: %u\n",
2003 GSC_2s (ch->dest->c),
2004 ch->dest->client_ready ? "YES" : "NO",
2005 ntohl (ch->dest->ccn.channel_of_client));
2006 }
2007 LOG2 (level,
2008 "CHN Message IDs recv: %d (%llX), send: %d\n",
2009 ntohl (ch->mid_recv.mid),
2010 (unsigned long long) ch->mid_futures,
2011 ntohl (ch->mid_send.mid));
2012#endif
2013}
2014
2015
2016/* 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.
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.
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.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
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
#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:610
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...
static 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.
Number identifying a CADET channel within a tunnel.
uint32_t cn
Which number does this channel have that uniquely identifies it within its 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).

◆ TIMEOUT_CLOSED_PORT

#define TIMEOUT_CLOSED_PORT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)

How long do we wait before dropping state about incoming connection to closed port?

Definition at line 57 of file gnunet-service-cadet_channel.c.

◆ MIN_RTT_DELAY

How long do we wait at least before retransmitting ever?

Definition at line 63 of file gnunet-service-cadet_channel.c.

◆ MAX_OUT_OF_ORDER_DISTANCE

#define MAX_OUT_OF_ORDER_DISTANCE   1024

Maximum message ID into the future we accept for out-of-order messages.

If the message is more than this into the future, we drop it. This is important both to detect values that are actually in the past, as well as to limit adversarially triggerable memory consumption.

Note that right now we have "max_pending_messages = 4" hard-coded in the logic below, so a value of 4 would suffice here. But we plan to allow larger windows in the future...

Definition at line 76 of file gnunet-service-cadet_channel.c.

◆ LOG2

#define LOG2 (   level,
  ... 
)     GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__)

Definition at line 1962 of file gnunet-service-cadet_channel.c.

Enumeration Type Documentation

◆ CadetChannelState

All the states a channel can be in.

Enumerator
CADET_CHANNEL_NEW 

Uninitialized status, should never appear in operation.

CADET_CHANNEL_LOOSE 

Channel is to a port that is not open, we're waiting for the port to be opened.

CADET_CHANNEL_OPEN_SENT 

CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK.

CADET_CHANNEL_READY 

Connection confirmed, ready to carry traffic.

Definition at line 82 of file gnunet-service-cadet_channel.c.

Function Documentation

◆ GCCH_assign_type_to_drop()

void GCCH_assign_type_to_drop ( struct CadetChannel ch,
const struct GNUNET_CADET_RequestDropCadetMessage message 
)

Assign type of message to drop.

Parameters
chCadetChannel to assign type to drop.
messageGNUNET_CADET_RequestDropCadetMessage to get the type from.

Definition at line 393 of file gnunet-service-cadet_channel.c.

395{
396
397 ch->type = message->type;
398
399}

References ch, and GNUNET_CADET_RequestDropCadetMessage::type.

Referenced by handle_drop_message().

Here is the caller graph for this function:

◆ GCCH_is_type_to_drop()

int GCCH_is_type_to_drop ( struct CadetChannel ch,
const struct GNUNET_MessageHeader message 
)

Check if type of message is the one to drop.

Parameters
chCadetChannel to check for message type to drop.
messageGNUNET_MessageHeader to compare the type with.

Definition at line 408 of file gnunet-service-cadet_channel.c.

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}

References ch, GNUNET_NO, GNUNET_YES, and GNUNET_MessageHeader::type.

Referenced by GCT_send().

Here is the caller graph for this function:

◆ GCCH_2s()

const char * GCCH_2s ( const struct CadetChannel ch)

Get the static string for identification of the channel.

Parameters
chChannel.
Returns
Static string with the channel IDs.

Definition at line 430 of file gnunet-service-cadet_channel.c.

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}

References GNUNET_CADET_Channel::ccn, ch, GNUNET_CADET_ClientChannelNumber::channel_of_client, GCP_get_id(), GCT_get_destination(), GNUNET_h2s(), GNUNET_i2s(), GNUNET_snprintf(), and GNUNET_YES.

Referenced by channel_destroy_iterator(), channel_open_sent_cb(), data_sent_cb(), GCCH_bind(), GCCH_channel_local_destroy(), GCCH_handle_channel_open_ack(), GCCH_handle_channel_plaintext_data(), GCCH_handle_channel_plaintext_data_ack(), GCCH_handle_duplicate_open(), GCCH_handle_local_ack(), GCCH_handle_local_data(), GCCH_handle_remote_destroy(), GCCH_tunnel_up(), GCT_add_channel(), GCT_remove_channel(), GSC_bind(), handle_channel_destroy(), handle_local_ack(), handle_local_data(), handle_matching_ack(), handle_plaintext_channel_destroy(), handle_plaintext_channel_open(), handle_plaintext_channel_open_ack(), retry_transmission(), send_channel_data_ack(), send_channel_open(), and send_open_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_hash_port()

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 peer on GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN.

Parameters
[out]h_portset to the hash of port, initiator and listener
portcadet port, as seen by CADET clients
listenerpeer that is listining on port

Definition at line 462 of file gnunet-service-cadet_channel.c.

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}

References GNUNET_CRYPTO_hash_context_finish(), GNUNET_CRYPTO_hash_context_read(), GNUNET_CRYPTO_hash_context_start(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), LOG, and port.

Referenced by GCCH_channel_local_new(), and handle_port_open().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_get_id()

struct GNUNET_CADET_ChannelTunnelNumber GCCH_get_id ( const struct CadetChannel ch)

Get the channel's public ID.

Parameters
chChannel.
Returns
ID used to identify the channel with the remote peer.

Definition at line 486 of file gnunet-service-cadet_channel.c.

487{
488 return ch->ctn;
489}

References ch.

◆ free_channel_client()

static void free_channel_client ( struct CadetChannelClient ccc)
static

Release memory associated with ccc.

Parameters
cccdata structure to clean up

Definition at line 498 of file gnunet-service-cadet_channel.c.

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}

References CadetOutOfOrderMessage::env, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_MQ_discard(), CadetChannelClient::head_recv, CadetChannelClient::num_recv, and CadetChannelClient::tail_recv.

Referenced by channel_destroy(), and GCCH_channel_local_destroy().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ channel_destroy()

static void channel_destroy ( struct CadetChannel ch)
static

Destroy the given channel.

Parameters
chchannel to destroy

Definition at line 519 of file gnunet-service-cadet_channel.c.

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}

References CADET_CHANNEL_LOOSE, ch, CadetReliableMessage::ch, CadetReliableMessage::data_message, free_channel_client(), GCT_remove_channel(), GCT_send_cancel(), GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NO, GNUNET_SCHEDULER_cancel(), GSC_drop_loose_channel(), and CadetReliableMessage::qe.

Referenced by GCCH_channel_local_destroy(), GCCH_handle_local_ack(), GCCH_handle_remote_destroy(), reconnect(), signal_remote_destroy_cb(), and timeout_closed_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_channel_open()

static void send_channel_open ( void *  cls)
static

Send a channel create message.

Send a channel open message.

Parameters
clsChannel for which to send.

Definition at line 614 of file gnunet-service-cadet_channel.c.

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));
624 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
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}

References CADET_CHANNEL_OPEN_SENT, ch, channel_open_sent_cb(), GNUNET_CADET_ChannelOpenMessage::ctn, GCCH_2s(), GCT_send(), GCT_send_cancel(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN, GNUNET_CADET_ChannelOpenMessage::h_port, GNUNET_CADET_ChannelOpenMessage::header, LOG, GNUNET_CADET_ChannelOpenMessage::opt, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by channel_open_sent_cb(), and GCCH_tunnel_up().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ channel_open_sent_cb()

static void channel_open_sent_cb ( void *  cls,
const struct GNUNET_CADET_ConnectionTunnelIdentifier cid 
)
static

Function called once the tunnel confirms that we sent the create message.

Delays for a bit until we retry.

Parameters
clsour struct CadetChannel.
cididentifier of the connection within the tunnel, NULL if transmission failed

Definition at line 591 of file gnunet-service-cadet_channel.c.

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}

References ch, GCCH_2s(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_STD_BACKOFF, GNUNET_YES, LOG, and send_channel_open().

Referenced by send_channel_open().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_tunnel_up()

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 ready for transmission.

Note that this is only the case for channels that this peer initiates, as for incoming channels we assume that they are ready for transmission immediately upon receiving the open message. Used to bootstrap the GCT_send() process.

Parameters
chthe channel for which the tunnel is now ready

Definition at line 649 of file gnunet-service-cadet_channel.c.

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}

References ch, GCCH_2s(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_SCHEDULER_add_now(), LOG, and send_channel_open().

Referenced by GCT_add_channel(), and notify_tunnel_up_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_channel_local_new()

struct CadetChannel * GCCH_channel_local_new ( struct CadetClient owner,
struct GNUNET_CADET_ClientChannelNumber  owner_id,
struct CadetPeer destination,
const struct GNUNET_HashCode port,
uint32_t  options 
)

Create a new channel.

Parameters
ownerlocal client owning the channel
owner_idlocal chid of this channel at the owner
destinationpeer to which we should build the channel
portdesired port at destination
optionsoptions for the channel
Returns
handle to the new channel

Definition at line 660 of file gnunet-service-cadet_channel.c.

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}

References CadetChannelClient::c, CADET_CHANNEL_LOOSE, CADET_INITIAL_RETRANSMIT_TIME, CadetChannelClient::ccn, ch, CadetChannelClient::client_ready, GCCH_bind(), GCCH_hash_port(), GCP_2s(), GCP_get_id(), GCP_get_tunnel(), GCT_2s(), GCT_add_channel(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_memcmp, GNUNET_new, GNUNET_NO, GNUNET_PILS_get_identity(), GNUNET_STATISTICS_update(), GNUNET_YES, GSC_2s(), LOG, loose_channels, my_identity, op, open_ports, pils, port, and stats.

Referenced by handle_channel_create().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ timeout_closed_cb()

static void timeout_closed_cb ( void *  cls)
static

We had an incoming channel to a port that is closed.

It has not been opened for a while, drop it.

Parameters
clsthe channel to drop

Definition at line 736 of file gnunet-service-cadet_channel.c.

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}

References ch, channel_destroy(), GCP_2s(), GCT_get_destination(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), and LOG.

Referenced by GCCH_channel_incoming_new().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_channel_incoming_new()

struct CadetChannel * GCCH_channel_incoming_new ( struct CadetTunnel t,
struct GNUNET_CADET_ChannelTunnelNumber  chid,
const struct GNUNET_HashCode h_port,
uint32_t  options 
)

Create a new channel based on a request coming in over the network.

Parameters
ttunnel to the remote peer
chididentifier of this channel in the tunnel
h_porthash of desired local port
optionsoptions for the channel
Returns
handle to the new channel

Definition at line 750 of file gnunet-service-cadet_channel.c.

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
770 if (NULL == op)
771 {
772 /* port closed, wait for it to possibly open */
773 ch->state = CADET_CHANNEL_LOOSE;
776 &ch->h_port,
777 ch,
779 GNUNET_assert (NULL == ch->retry_control_task);
782 ch);
784 "Created loose incoming channel to port %s from peer %s\n",
785 GNUNET_h2s (&ch->port),
787 }
788 else
789 {
790 GCCH_bind (ch, op->c, &op->port);
791 }
792 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
793 return ch;
794}

References CADET_CHANNEL_LOOSE, CADET_INITIAL_RETRANSMIT_TIME, ch, GCCH_bind(), GCP_2s(), GCT_get_destination(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_new, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_STATISTICS_update(), GNUNET_YES, OpenPort::h_port, LOG, loose_channels, op, open_ports, stats, t, timeout_closed_cb(), and TIMEOUT_CLOSED_PORT.

Referenced by handle_plaintext_channel_open().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_ack_cb()

static void send_ack_cb ( void *  cls,
const struct GNUNET_CADET_ConnectionTunnelIdentifier cid 
)
static

Function called once the tunnel confirms that we sent the ACK message.

Just remembers it was sent, we do not expect ACKs for ACKs ;-).

Parameters
clsour struct CadetChannel.
cididentifier of the connection within the tunnel, NULL if transmission failed

Definition at line 807 of file gnunet-service-cadet_channel.c.

809{
810 struct CadetChannel *ch = cls;
811
812 GNUNET_assert (NULL != ch->last_control_qe);
813 ch->last_control_qe = NULL;
814}

References ch, and GNUNET_assert.

Referenced by send_channel_data_ack(), and send_open_ack().

Here is the caller graph for this function:

◆ send_channel_data_ack()

static void send_channel_data_ack ( struct CadetChannel ch)
static

Compute and send the current GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.

Parameters
chchannel to send the GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for

Definition at line 823 of file gnunet-service-cadet_channel.c.

824{
826
827 if (GNUNET_NO == ch->reliable)
828 return; /* no ACKs */
830 msg.header.size = htons (sizeof(msg));
831 msg.ctn = ch->ctn;
832 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
833 msg.futures = GNUNET_htonll (ch->mid_futures);
835 "Sending DATA_ACK %u:%llX via %s\n",
836 (unsigned int) ntohl (msg.mid.mid),
837 (unsigned long long) ch->mid_futures,
838 GCCH_2s (ch));
839 if (NULL != ch->last_control_qe)
840 GCT_send_cancel (ch->last_control_qe);
841 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
842 &msg.ctn);
843}

References ch, GCCH_2s(), GCT_send(), GCT_send_cancel(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_htonll(), GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK, GNUNET_NO, LOG, msg, send_ack_cb(), GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by GCCH_handle_channel_plaintext_data(), and GCCH_handle_local_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_open_ack()

static void send_open_ack ( void *  cls)
static

Send our initial GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the connection is up.

Parameters
clsthe struct CadetChannel

Definition at line 853 of file gnunet-service-cadet_channel.c.

854{
855 struct CadetChannel *ch = cls;
857
858 ch->retry_control_task = NULL;
860 "Sending CHANNEL_OPEN_ACK on %s\n",
861 GCCH_2s (ch));
863 msg.header.size = htons (sizeof(msg));
864 msg.reserved = htonl (0);
865 msg.ctn = ch->ctn;
866 msg.port = ch->port;
867 if (NULL != ch->last_control_qe)
868 GCT_send_cancel (ch->last_control_qe);
869 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
870 &msg.ctn);
871}

References ch, GCCH_2s(), GCT_send(), GCT_send_cancel(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK, LOG, msg, send_ack_cb(), GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by GCCH_bind(), and GCCH_handle_duplicate_open().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_handle_duplicate_open()

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.

If the binding was successful, (re)transmit the GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.

Parameters
chchannel that got the duplicate open
ctiidentifier of the connection that delivered the message

Definition at line 883 of file gnunet-service-cadet_channel.c.

886{
887 if (NULL == ch->dest)
888 {
890 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
891 GCCH_2s (ch));
892 return;
893 }
894 if (NULL != ch->retry_control_task)
895 {
897 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
898 GCCH_2s (ch));
899 return;
900 }
902 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
903 GCCH_2s (ch));
904 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
905}

References ch, GCCH_2s(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_SCHEDULER_add_now(), LOG, and send_open_ack().

Referenced by handle_plaintext_channel_open().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_ack_to_client()

static void send_ack_to_client ( struct CadetChannel ch,
int  to_owner 
)
static

Send a GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.

Parameters
chchannel the ack is for
to_ownerGNUNET_YES to send to owner, GNUNET_NO to send to dest

Definition at line 916 of file gnunet-service-cadet_channel.c.

917{
918 struct GNUNET_MQ_Envelope *env;
919 struct GNUNET_CADET_LocalAck *ack;
920 struct CadetChannelClient *ccc;
921
922 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
923 if (NULL == ccc)
924 {
925 /* This can happen if we are just getting ACKs after
926 our local client already disconnected. */
927 GNUNET_assert (GNUNET_YES == ch->destroy);
928 return;
929 }
931 ack->ccn = ccc->ccn;
933 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
934 GSC_2s (ccc->c),
935 (GNUNET_YES == to_owner) ? "owner" : "dest",
936 ntohl (ack->ccn.channel_of_client),
937 ch->pending_messages,
938 ch->max_pending_messages);
939 GSC_send_to_client (ccc->c, env);
940}

References CadetChannelClient::c, GNUNET_CADET_LocalAck::ccn, CadetChannelClient::ccn, ch, GNUNET_CADET_ClientChannelNumber::channel_of_client, env, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, GNUNET_MQ_msg, GNUNET_YES, GSC_2s(), GSC_send_to_client(), and LOG.

Referenced by data_sent_cb(), GCCH_bind(), GCCH_handle_channel_open_ack(), GCCH_handle_local_ack(), GCCH_handle_local_data(), and handle_matching_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_bind()

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.

Send the acknowledgement for the connection request and establish the link with the client.

Parameters
chopen incoming channel
cclient listening on the respective port
portport number c is listening on

Definition at line 944 of file gnunet-service-cadet_channel.c.

947{
948 const struct GNUNET_PeerIdentity *my_identity;
949 uint32_t options;
950 struct CadetChannelClient *cccd;
951
953 "Binding %s from %s to port %s of %s\n",
954 GCCH_2s (ch),
955 GCT_2s (ch->t),
956 GNUNET_h2s (&ch->port),
957 GSC_2s (c));
958
961
962 if (NULL != ch->retry_control_task)
963 {
964 /* there might be a timeout task here */
965 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
966 ch->retry_control_task = NULL;
967 }
968 options = 0;
969 cccd = GNUNET_new (struct CadetChannelClient);
970 GNUNET_assert (NULL == ch->dest);
971 ch->dest = cccd;
972 ch->port = *port;
973 cccd->c = c;
974 cccd->client_ready = GNUNET_YES;
975 cccd->ccn = GSC_bind (c,
976 ch,
977 (GNUNET_YES == ch->is_loopback)
980 port,
981 options);
982 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
984 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
985 if (GNUNET_YES == ch->is_loopback)
986 {
989 }
990 else
991 {
992 /* notify other peer that we accepted the connection */
993 ch->state = CADET_CHANNEL_READY;
994 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
995 }
996 /* give client it's initial supply of ACKs */
997 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
999 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1001}

References CadetChannelClient::c, CADET_CHANNEL_OPEN_SENT, CADET_CHANNEL_READY, CadetChannelClient::ccn, ch, GNUNET_CADET_ClientChannelNumber::channel_of_client, CadetChannelClient::client_ready, GCCH_2s(), GCCH_handle_channel_open_ack(), GCP_get(), GCT_2s(), GCT_get_destination(), GNUNET_assert, GNUNET_CADET_LOCAL_CHANNEL_ID_CLI, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_new, GNUNET_NO, GNUNET_PILS_get_identity(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNUNET_YES, GSC_2s(), GSC_bind(), LOG, my_identity, options, pils, port, send_ack_to_client(), and send_open_ack().

Referenced by bind_loose_channel(), GCCH_channel_incoming_new(), and GCCH_channel_local_new().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ signal_remote_destroy_cb()

static void signal_remote_destroy_cb ( void *  cls)
static

One of our clients has disconnected, tell the other one that we are finished.

Done asynchronously to avoid concurrent modification issues if this is the same client.

Parameters
clsthe struct CadetChannel where one of the ends is now dead

Definition at line 1012 of file gnunet-service-cadet_channel.c.

1013{
1014 struct CadetChannel *ch = cls;
1015 struct CadetChannelClient *ccc;
1016
1017 /* Find which end is left... */
1018 ch->retry_control_task = NULL;
1019 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1022}

References CadetChannelClient::c, CadetChannelClient::ccn, ch, channel_destroy(), and GSC_handle_remote_channel_destroy().

Referenced by GCCH_channel_local_destroy().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_channel_local_destroy()

void GCCH_channel_local_destroy ( struct CadetChannel ch,
struct CadetClient c,
struct GNUNET_CADET_ClientChannelNumber  ccn 
)

Destroy locally created channel.

Called by the local client, so no need to tell the client.

Parameters
chchannel to destroy
cclient that caused the destruction
ccnclient number of the client c

Definition at line 1034 of file gnunet-service-cadet_channel.c.

1037{
1039 "%s asks for destruction of %s\n",
1040 GSC_2s (c),
1041 GCCH_2s (ch));
1042 GNUNET_assert (NULL != c);
1043 if ((NULL != ch->owner) && (c == ch->owner->c) &&
1044 (ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1045 {
1046 free_channel_client (ch->owner);
1047 ch->owner = NULL;
1048 }
1049 else if ((NULL != ch->dest) && (c == ch->dest->c) &&
1050 (ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1051 {
1052 free_channel_client (ch->dest);
1053 ch->dest = NULL;
1054 }
1055 else
1056 {
1057 GNUNET_assert (0);
1058 }
1059
1060 if (GNUNET_YES == ch->destroy)
1061 {
1062 /* other end already destroyed, with the local client gone, no need
1063 to finish transmissions, just destroy immediately. */
1065 return;
1066 }
1067 if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest)))
1068 {
1069 /* Wait for other end to destroy us as well,
1070 and otherwise allow send queue to be transmitted first */
1071 ch->destroy = GNUNET_YES;
1072 return;
1073 }
1074 if ((GNUNET_YES == ch->is_loopback) &&
1075 ((NULL != ch->owner) || (NULL != ch->dest)))
1076 {
1077 if (NULL != ch->retry_control_task)
1078 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1079 ch->retry_control_task =
1081 return;
1082 }
1083 if (GNUNET_NO == ch->is_loopback)
1084 {
1085 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1086 switch (ch->state)
1087 {
1088 case CADET_CHANNEL_NEW:
1089 /* We gave up on a channel that we created as a client to a remote
1090 target, but that never went anywhere. Nothing to do here. */
1091 break;
1092
1094 break;
1095
1096 default:
1097 GCT_send_channel_destroy (ch->t, ch->ctn);
1098 }
1099 }
1100 /* Nothing left to do, just finish destruction */
1102}

References CadetChannelClient::c, CADET_CHANNEL_LOOSE, CADET_CHANNEL_NEW, GNUNET_CADET_Channel::ccn, CadetChannelClient::ccn, ch, channel_destroy(), GNUNET_CADET_ClientChannelNumber::channel_of_client, free_channel_client(), GCCH_2s(), GCT_send_channel_destroy(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_NO, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNUNET_YES, GSC_2s(), LOG, and signal_remote_destroy_cb().

Referenced by channel_destroy_iterator(), and handle_channel_destroy().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_handle_channel_open_ack()

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).

Verify that the other end really has the right port, and begin transmissions.

Parameters
chchannel to destroy
ctiidentifier of the connection that delivered the message, NULL if the ACK was inferred because we got payload or are on loopback
portport number (needed to verify receiver knows the port)

Definition at line 1106 of file gnunet-service-cadet_channel.c.

1110{
1111 switch (ch->state)
1112 {
1113 case CADET_CHANNEL_NEW:
1114 /* this should be impossible */
1115 GNUNET_break (0);
1116 break;
1117
1119 /* This makes no sense. */
1120 GNUNET_break_op (0);
1121 break;
1122
1124 if (NULL == ch->owner)
1125 {
1126 /* We're not the owner, wrong direction! */
1127 GNUNET_break_op (0);
1128 return;
1129 }
1130 if (0 != GNUNET_memcmp (&ch->port, port))
1131 {
1132 /* Other peer failed to provide the right port,
1133 refuse connection. */
1134 GNUNET_break_op (0);
1135 return;
1136 }
1138 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1139 GCCH_2s (ch));
1140 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1141 {
1142 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1143 ch->retry_control_task = NULL;
1144 }
1145 ch->state = CADET_CHANNEL_READY;
1146 /* On first connect, send client as many ACKs as we allow messages
1147 to be buffered! */
1148 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1150 break;
1151
1153 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1155 "Received duplicate channel OPEN_ACK for %s\n",
1156 GCCH_2s (ch));
1157 GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO);
1158 break;
1159 }
1160}

References CADET_CHANNEL_LOOSE, CADET_CHANNEL_NEW, CADET_CHANNEL_OPEN_SENT, CADET_CHANNEL_READY, ch, GCCH_2s(), GNUNET_break, GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_memcmp, GNUNET_NO, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_YES, LOG, port, send_ack_to_client(), and stats.

Referenced by GCCH_bind(), and handle_plaintext_channel_open_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_before()

static int is_before ( void *  cls,
struct CadetOutOfOrderMessage m1,
struct CadetOutOfOrderMessage m2 
)
static

Test if element e1 comes before element e2.

Parameters
clsclosure, to a flag where we indicate duplicate packets
m1a message of to sort
m2another message to sort
Returns
GNUNET_YES if e1 < e2, otherwise GNUNET_NO

Definition at line 1172 of file gnunet-service-cadet_channel.c.

1175{
1176 int *duplicate = cls;
1177 uint32_t v1 = ntohl (m1->mid.mid);
1178 uint32_t v2 = ntohl (m2->mid.mid);
1179 uint32_t delta;
1180
1181 delta = v2 - v1;
1182 if (0 == delta)
1183 *duplicate = GNUNET_YES;
1184 if (delta > (uint32_t) INT_MAX)
1185 {
1186 /* in overflow range, we can safely assume we wrapped around */
1187 return GNUNET_NO;
1188 }
1189 else
1190 {
1191 /* result is small, thus v2 > v1, thus m1 < m2 */
1192 return GNUNET_YES;
1193 }
1194}

References delta, GNUNET_NO, GNUNET_YES, INT_MAX, ChannelMessageIdentifier::mid, and CadetOutOfOrderMessage::mid.

Referenced by GCCH_handle_channel_plaintext_data().

Here is the caller graph for this function:

◆ GCCH_handle_channel_plaintext_data()

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.

Pass it on to the client and send an ACK to the other end (once flow control allows it!)

Parameters
chchannel that got data
ctiidentifier of the connection that delivered the message
msgmessage that was received

We always send if possible in this case. It is guaranteed that the queued MID < received MID

Definition at line 1198 of file gnunet-service-cadet_channel.c.

1202{
1203 struct GNUNET_MQ_Envelope *env;
1204 struct GNUNET_CADET_LocalData *ld;
1205 struct CadetChannelClient *ccc;
1206 size_t payload_size;
1207 struct CadetOutOfOrderMessage *com;
1208 int duplicate;
1209 uint32_t mid_min;
1210 uint32_t mid_max;
1211 uint32_t mid_msg;
1212 uint32_t delta;
1213
1214 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1215 if ((NULL == ch->owner) && (NULL == ch->dest))
1216 {
1217 /* This client is gone, but we still have messages to send to
1218 the other end (which is why @a ch is not yet dead). However,
1219 we cannot pass messages to our client anymore. */
1221 "Dropping incoming payload on %s as this end is already closed\n",
1222 GCCH_2s (ch));
1223 /* send back DESTROY notification to stop further retransmissions! */
1224 if (GNUNET_YES == ch->destroy)
1225 GCT_send_channel_destroy (ch->t, ch->ctn);
1226 return;
1227 }
1228 payload_size = ntohs (msg->header.size) - sizeof(*msg);
1230 payload_size,
1232 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1233 GNUNET_memcpy (&ld[1], &msg[1], payload_size);
1234 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1235 if (GNUNET_YES == ccc->client_ready)
1236 {
1237 /*
1238 * We ad-hoc send the message if
1239 * - The channel is out-of-order
1240 * - The channel is reliable and MID matches next expected MID
1241 * - The channel is unreliable and MID is before lowest seen MID
1242 */if ((GNUNET_YES == ch->out_of_order) ||
1243 ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) ||
1244 ((GNUNET_NO == ch->reliable) &&
1245 (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) &&
1246 ((NULL == ccc->head_recv) ||
1247 (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid)))))
1248 {
1250 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1251 (unsigned int) payload_size,
1252 ntohl (msg->mid.mid),
1253 GCCH_2s (ch),
1254 GSC_2s (ccc->c));
1255 ccc->client_ready = GNUNET_NO;
1256 GSC_send_to_client (ccc->c, env);
1257 if (GNUNET_NO == ch->out_of_order)
1258 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1259 else
1260 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1261 ch->mid_futures >>= 1;
1262 if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable))
1263 {
1264 /* possibly shift by more if we skipped messages */
1265 uint64_t d = ntohl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid);
1266
1267 if (d > 63)
1268 ch->mid_futures = 0;
1269 else
1270 ch->mid_futures >>= d;
1271 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1272 }
1274 return;
1275 }
1276 }
1277
1278 if (GNUNET_YES == ch->reliable)
1279 {
1280 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1281 mid_min = ntohl (ch->mid_recv.mid);
1282 mid_max = mid_min + ch->max_pending_messages;
1283 mid_msg = ntohl (msg->mid.mid);
1284 if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1285 ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages))
1286 {
1288 "%s at %u drops ancient or far-future message %u\n",
1289 GCCH_2s (ch),
1290 (unsigned int) mid_min,
1291 ntohl (msg->mid.mid));
1292
1294 "# duplicate DATA (ancient or future)",
1295 1,
1296 GNUNET_NO);
1299 return;
1300 }
1301 /* mark bit for future ACKs */
1302 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1303 if (delta < 64)
1304 {
1305 if (0 != (ch->mid_futures & (1LLU << delta)))
1306 {
1307 /* Duplicate within the queue, drop also */
1309 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1310 (unsigned int) payload_size,
1311 GCCH_2s (ch),
1312 ntohl (msg->mid.mid));
1313 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1316 return;
1317 }
1318 ch->mid_futures |= (1LLU << delta);
1320 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1321 (1LLU << delta),
1322 mid_msg,
1323 mid_min,
1324 (unsigned long long) ch->mid_futures);
1325 }
1326 }
1327 else /* ! ch->reliable */
1328 {
1329 struct CadetOutOfOrderMessage *next_msg;
1330
1335 if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready))
1336 {
1337 next_msg = ccc->head_recv;
1339 "Giving queued MID %u from %s to client %s\n",
1340 ntohl (next_msg->mid.mid),
1341 GCCH_2s (ch),
1342 GSC_2s (ccc->c));
1343 ccc->client_ready = GNUNET_NO;
1344 GSC_send_to_client (ccc->c, next_msg->env);
1345 ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid));
1346 ch->mid_futures >>= 1;
1348 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg);
1349 ccc->num_recv--;
1350 /* Do not process duplicate MID */
1351 if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */
1352 {
1353 /* Duplicate within the queue, drop */
1355 "Message on %s (mid %u) dropped, duplicate\n",
1356 GCCH_2s (ch),
1357 ntohl (msg->mid.mid));
1358 GNUNET_free (next_msg);
1360 return;
1361 }
1362 GNUNET_free (next_msg);
1363 }
1364
1365 if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */
1366 {
1367 /* Duplicate within the queue, drop */
1369 "Message on %s (mid %u) dropped, old.\n",
1370 GCCH_2s (ch),
1371 ntohl (msg->mid.mid));
1373 return;
1374 }
1375
1376 /* Channel is unreliable, so we do not ACK. But we also cannot
1377 allow buffering everything, so check if we have space... */
1378 if (ccc->num_recv >= ch->max_pending_messages)
1379 {
1380 struct CadetOutOfOrderMessage *drop;
1381
1382 /* Yep, need to drop. Drop the oldest message in
1383 the buffer. */
1385 "Queue full due slow client on %s, dropping oldest message\n",
1386 GCCH_2s (ch));
1388 "# messages dropped due to slow client",
1389 1,
1390 GNUNET_NO);
1391 drop = ccc->head_recv;
1392 GNUNET_assert (NULL != drop);
1394 ccc->num_recv--;
1395 GNUNET_MQ_discard (drop->env);
1396 GNUNET_free (drop);
1397 }
1398 }
1399
1400 /* Insert message into sorted out-of-order queue */
1401 com = GNUNET_new (struct CadetOutOfOrderMessage);
1402 com->mid = msg->mid;
1403 com->env = env;
1404 duplicate = GNUNET_NO;
1406 is_before,
1407 &duplicate,
1408 ccc->head_recv,
1409 ccc->tail_recv,
1410 com);
1411 ccc->num_recv++;
1412 if (GNUNET_YES == duplicate)
1413 {
1414 /* Duplicate within the queue, drop also (this is not covered by
1415 the case above if "delta" >= 64, which could be the case if
1416 max_pending_messages is also >= 64 or if our client is unready
1417 and we are seeing retransmissions of the message our client is
1418 blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG,
1419 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1420 (unsigned int) payload_size,
1421 GCCH_2s (ch),
1422 ntohl (msg->mid.mid));
1423 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1425 ccc->num_recv--;
1426 GNUNET_MQ_discard (com->env);
1427 GNUNET_free (com);
1429 return;
1430 }
1432 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1433 (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready",
1434 (unsigned int) payload_size,
1435 GCCH_2s (ch),
1436 ntohl (ccc->ccn.channel_of_client),
1437 ccc,
1438 ntohl (msg->mid.mid),
1439 ntohl (ch->mid_recv.mid));
1440 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1441 the sender may already be transmitting the previous one. Needs
1442 experimental evaluation to see if/when this ACK helps or
1443 hurts. (We might even want another option.) */
1445}

References CadetChannelClient::c, GNUNET_CADET_Channel::ccn, GNUNET_CADET_LocalData::ccn, CadetChannelClient::ccn, ch, GNUNET_CADET_ClientChannelNumber::channel_of_client, CadetChannelClient::client_ready, d, delta, env, CadetOutOfOrderMessage::env, GCCH_2s(), GCT_send_channel_destroy(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert_sorted, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, GNUNET_MQ_discard(), GNUNET_MQ_msg_extra, GNUNET_new, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, GSC_2s(), GSC_send_to_client(), CadetChannelClient::head_recv, is_before(), LOG, ChannelMessageIdentifier::mid, CadetOutOfOrderMessage::mid, msg, CadetChannelClient::num_recv, send_channel_data_ack(), GNUNET_MessageHeader::size, stats, and CadetChannelClient::tail_recv.

Referenced by handle_plaintext_data().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ data_sent_cb()

static void data_sent_cb ( void *  cls,
const struct GNUNET_CADET_ConnectionTunnelIdentifier cid 
)
static

Function called once the tunnel has sent one of our messages.

If the message is unreliable, simply frees the crm. If the message was reliable, calculate retransmission time and wait for ACK (or retransmit).

Parameters
clsthe struct CadetReliableMessage that was sent
cididentifier of the connection within the tunnel, NULL if transmission failed

Definition at line 1681 of file gnunet-service-cadet_channel.c.

1683{
1684 struct CadetReliableMessage *crm = cls;
1685 struct CadetChannel *ch = crm->ch;
1686
1687 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1688 GNUNET_assert (NULL != crm->qe);
1689 crm->qe = NULL;
1690 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1691 if (GNUNET_NO == ch->reliable)
1692 {
1694 GNUNET_free (crm);
1695 ch->pending_messages--;
1696 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1697 return;
1698 }
1699 if (NULL == cid)
1700 {
1701 /* There was an error sending. */
1703 }
1704 else if (GNUNET_SYSERR != crm->num_transmissions)
1705 {
1706 /* Increment transmission counter, and possibly store @a cid
1707 if this was the first transmission. */
1708 crm->num_transmissions++;
1709 if (1 == crm->num_transmissions)
1710 {
1712 crm->connection_taken = *cid;
1713 GCC_ack_expected (cid);
1714 }
1715 }
1716 if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid))
1717 {
1718 struct CadetConnection *cc = GCC_lookup (cid);
1719
1720 if (NULL != cc)
1721 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1722 else
1723 crm->retry_delay = ch->retry_time;
1724 }
1725 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1726 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY);
1727 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1728
1731 NULL,
1732 ch->head_sent,
1733 ch->tail_sent,
1734 crm);
1736 "Message %u sent, next transmission on %s in %s\n",
1737 (unsigned int) ntohl (crm->data_message->mid.mid),
1738 GCCH_2s (ch),
1741 ch->head_sent->next_retry),
1742 GNUNET_YES));
1743 if (NULL == ch->head_sent->qe)
1744 {
1745 if (NULL != ch->retry_data_task)
1746 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1747 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1749 ch);
1750 }
1751}

References CadetConnectionMetrics::aged_latency, ch, CadetReliableMessage::ch, CadetConnection::cid, cmp_crm_by_next_retry(), CadetReliableMessage::connection_taken, CadetReliableMessage::data_message, CadetReliableMessage::first_transmission_time, GCC_ack_expected(), GCC_get_metrics(), GCC_lookup(), GCCH_2s(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert_sorted, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_NO, GNUNET_SCHEDULER_add_at(), GNUNET_SCHEDULER_cancel(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_max(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_STD_BACKOFF, GNUNET_YES, LOG, MIN_RTT_DELAY, CadetReliableMessage::num_transmissions, CadetConnection::off, CadetReliableMessage::qe, GNUNET_TIME_Relative::rel_value_us, CadetReliableMessage::retry_delay, retry_transmission(), and send_ack_to_client().

Referenced by GCCH_handle_local_data(), and retry_transmission().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ retry_transmission()

static void retry_transmission ( void *  cls)
static

We need to retry a transmission, the last one took too long to be acknowledged.

Parameters
clsthe struct CadetChannel where we need to retransmit

Definition at line 1470 of file gnunet-service-cadet_channel.c.

1471{
1472 struct CadetChannel *ch = cls;
1473 struct CadetReliableMessage *crm = ch->head_sent;
1474
1475 ch->retry_data_task = NULL;
1476 GNUNET_assert (NULL == crm->qe);
1478 "Retrying transmission on %s of message %u\n",
1479 GCCH_2s (ch),
1480 (unsigned int) ntohl (crm->data_message->mid.mid));
1481 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1482 &crm->data_message->ctn);
1483 GNUNET_assert (NULL == ch->retry_data_task);
1484}

References ch, GNUNET_CADET_ChannelAppDataMessage::ctn, CadetReliableMessage::data_message, data_sent_cb(), GCCH_2s(), GCT_send(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_CADET_ChannelAppDataMessage::header, LOG, ChannelMessageIdentifier::mid, GNUNET_CADET_ChannelAppDataMessage::mid, and CadetReliableMessage::qe.

Referenced by data_sent_cb(), and GCCH_handle_channel_plaintext_data_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_matching_ack()

static void handle_matching_ack ( struct CadetChannel ch,
const struct GNUNET_CADET_ConnectionTunnelIdentifier cti,
struct CadetReliableMessage crm 
)
static

We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from the queue and tell our client that it can send more.

Parameters
chthe channel that got the PLAINTEXT_DATA_ACK
ctiidentifier of the connection that delivered the message
crmthe message that got acknowledged

Definition at line 1496 of file gnunet-service-cadet_channel.c.

1499{
1500 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1501 ch->pending_messages--;
1502 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1504 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1505 GCCH_2s (ch),
1506 (unsigned int) ntohl (crm->data_message->mid.mid),
1507 ch->pending_messages);
1508 if (NULL != crm->qe)
1509 {
1510 GCT_send_cancel (crm->qe);
1511 crm->qe = NULL;
1512 }
1513 if ((1 == crm->num_transmissions) && (NULL != cti))
1514 {
1515 GCC_ack_observed (cti);
1516 if (0 == GNUNET_memcmp (cti, &crm->connection_taken))
1517 {
1521 }
1522 }
1524 GNUNET_free (crm);
1525 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1526}

References ch, CadetReliableMessage::connection_taken, CadetReliableMessage::data_message, CadetReliableMessage::first_transmission_time, GCC_ack_observed(), GCC_latency_observed(), GCCH_2s(), GCT_send_cancel(), GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_memcmp, GNUNET_NO, GNUNET_TIME_absolute_get_duration(), GNUNET_YES, LOG, ChannelMessageIdentifier::mid, GNUNET_CADET_ChannelAppDataMessage::mid, CadetReliableMessage::num_transmissions, CadetReliableMessage::qe, and send_ack_to_client().

Referenced by GCCH_handle_channel_plaintext_data_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_handle_channel_plaintext_data_ack()

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.

Possibly resume transmissions.

Parameters
chchannel that got the ack
ctiidentifier of the connection that delivered the message
ackdetails about what was received

Definition at line 1538 of file gnunet-service-cadet_channel.c.

1542{
1543 struct CadetReliableMessage *crm;
1544 struct CadetReliableMessage *crmn;
1545 int found;
1546 uint32_t mid_base;
1547 uint64_t mid_mask;
1548 unsigned int delta;
1549
1550 GNUNET_break (GNUNET_NO == ch->is_loopback);
1551 if (GNUNET_NO == ch->reliable)
1552 {
1553 /* not expecting ACKs on unreliable channel, odd */
1554 GNUNET_break_op (0);
1555 return;
1556 }
1557 /* mid_base is the MID of the next message that the
1558 other peer expects (i.e. that is missing!), everything
1559 LOWER (but excluding mid_base itself) was received. */
1560 mid_base = ntohl (ack->mid.mid);
1561 mid_mask = GNUNET_htonll (ack->futures);
1562 found = GNUNET_NO;
1563 for (crm = ch->head_sent; NULL != crm; crm = crmn)
1564 {
1565 crmn = crm->next;
1566 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1567 if (delta >= UINT_MAX - ch->max_pending_messages)
1568 {
1569 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1571 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1572 (unsigned int) mid_base,
1573 ntohl (crm->data_message->mid.mid),
1574 GCCH_2s (ch));
1575 handle_matching_ack (ch, cti, crm);
1576 found = GNUNET_YES;
1577 continue;
1578 }
1579 delta--;
1580 if (delta >= 64)
1581 continue;
1583 "Testing bit %llX for mid %u (base: %u)\n",
1584 (1LLU << delta),
1585 ntohl (crm->data_message->mid.mid),
1586 mid_base);
1587 if (0 != (mid_mask & (1LLU << delta)))
1588 {
1590 "Got DATA_ACK with mask for %u on %s\n",
1591 ntohl (crm->data_message->mid.mid),
1592 GCCH_2s (ch));
1593 handle_matching_ack (ch, cti, crm);
1594 found = GNUNET_YES;
1595 }
1596 }
1597 if (GNUNET_NO == found)
1598 {
1599 /* ACK for message we already dropped, might have been a
1600 duplicate ACK? Ignore. */
1602 "Duplicate DATA_ACK on %s, ignoring\n",
1603 GCCH_2s (ch));
1604 GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO);
1605 return;
1606 }
1607 if (NULL != ch->retry_data_task)
1608 {
1609 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1610 ch->retry_data_task = NULL;
1611 }
1612 if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe))
1613 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1615 ch);
1616}

References ch, CadetReliableMessage::data_message, delta, GNUNET_CADET_ChannelDataAckMessage::futures, GCCH_2s(), GNUNET_break, GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_htonll(), GNUNET_NO, GNUNET_SCHEDULER_add_at(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_YES, handle_matching_ack(), LOG, ChannelMessageIdentifier::mid, GNUNET_CADET_ChannelAppDataMessage::mid, GNUNET_CADET_ChannelDataAckMessage::mid, CadetReliableMessage::next, retry_transmission(), and stats.

Referenced by handle_plaintext_data_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_handle_remote_destroy()

void GCCH_handle_remote_destroy ( struct CadetChannel ch,
const struct GNUNET_CADET_ConnectionTunnelIdentifier cti 
)

Destroy channel, based on the other peer closing the connection.

Also needs to remove this channel from the tunnel.

FIXME: need to make it possible to defer destruction until we have received all messages up to the destroy, and right now the destroy message (and this API) fails to give is the information we need!

FIXME: also need to know if the other peer got a destroy from us before!

Parameters
chchannel to destroy
ctiidentifier of the connection that delivered the message, NULL if we are simulating receiving a destroy due to shutdown

Definition at line 1620 of file gnunet-service-cadet_channel.c.

1623{
1624 struct CadetChannelClient *ccc;
1625
1626 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1628 "Received remote channel DESTROY for %s\n",
1629 GCCH_2s (ch));
1630 if (GNUNET_YES == ch->destroy)
1631 {
1632 /* Local client already gone, this is instant-death. */
1634 return;
1635 }
1636 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1637 if ((NULL != ccc) && (NULL != ccc->head_recv))
1638 {
1640 "Lost end of transmission due to remote shutdown on %s\n",
1641 GCCH_2s (ch));
1642 /* FIXME: change API to notify client about truncated transmission! */
1643 }
1644 ch->destroy = GNUNET_YES;
1645 if (NULL != ccc)
1648}

References CadetChannelClient::c, CadetChannelClient::ccn, ch, channel_destroy(), GCCH_2s(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_NO, GNUNET_YES, GSC_handle_remote_channel_destroy(), CadetChannelClient::head_recv, and LOG.

Referenced by destroy_remaining_channels(), and handle_plaintext_channel_destroy().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cmp_crm_by_next_retry()

static int cmp_crm_by_next_retry ( void *  cls,
struct CadetReliableMessage crm1,
struct CadetReliableMessage crm2 
)
static

Test if element e1 comes before element e2.

Parameters
clsclosure, to a flag where we indicate duplicate packets
crm1an element of to sort
crm2another element to sort
Returns
GNUNET_YES if e1 < e2, otherwise GNUNET_NO

Definition at line 1660 of file gnunet-service-cadet_channel.c.

1663{
1665 return GNUNET_YES;
1666 return GNUNET_NO;
1667}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_NO, GNUNET_YES, and CadetReliableMessage::next_retry.

Referenced by data_sent_cb().

Here is the caller graph for this function:

◆ GCCH_handle_local_data()

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.

Check whether the client is allowed to send in this tunnel, save if channel is reliable and send an ACK to the client if there is still buffer space in the tunnel.

Parameters
chChannel.
sender_ccnccn of the sender
bufpayload to transmit.
buf_lennumber of bytes in buf
Returns
GNUNET_OK if everything goes well, GNUNET_SYSERR in case of an error.

Definition at line 1769 of file gnunet-service-cadet_channel.c.

1773{
1774 struct CadetReliableMessage *crm;
1775
1776 if (ch->pending_messages >= ch->max_pending_messages)
1777 {
1778 GNUNET_break (0); /* Fails: #5370 */
1779 return GNUNET_SYSERR;
1780 }
1781 if (GNUNET_YES == ch->destroy)
1782 {
1783 /* we are going down, drop messages */
1784 return GNUNET_OK;
1785 }
1786 ch->pending_messages++;
1787
1788 if (GNUNET_YES == ch->is_loopback)
1789 {
1791 struct GNUNET_MQ_Envelope *env;
1792 struct GNUNET_CADET_LocalData *ld;
1793 int ack_to_owner;
1794
1795 env =
1797 if ((NULL != ch->owner) &&
1798 (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1799 {
1800 receiver = ch->dest;
1801 ack_to_owner = GNUNET_YES;
1802 }
1803 else if ((NULL != ch->dest) &&
1804 (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1805 {
1806 receiver = ch->owner;
1807 ack_to_owner = GNUNET_NO;
1808 }
1809 else
1810 {
1811 GNUNET_free (env);
1812 GNUNET_break (0);
1813 return GNUNET_SYSERR;
1814 }
1815 GNUNET_assert (NULL != receiver);
1816 ld->ccn = receiver->ccn;
1817 GNUNET_memcpy (&ld[1], buf, buf_len);
1818 if (GNUNET_YES == receiver->client_ready)
1819 {
1820 ch->pending_messages--;
1822 send_ack_to_client (ch, ack_to_owner);
1823 }
1824 else
1825 {
1826 struct CadetOutOfOrderMessage *oom;
1827
1828 oom = GNUNET_new (struct CadetOutOfOrderMessage);
1829 oom->env = env;
1831 receiver->tail_recv,
1832 oom);
1833 receiver->num_recv++;
1834 }
1835 return GNUNET_OK;
1836 }
1837
1838 /* Everything is correct, send the message. */
1839 crm = GNUNET_malloc (sizeof(*crm));
1840 crm->ch = ch;
1842 sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1843 crm->data_message->header.size =
1844 htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1845 crm->data_message->header.type =
1847 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1848 crm->data_message->mid = ch->mid_send;
1849 crm->data_message->ctn = ch->ctn;
1850 GNUNET_memcpy (&crm->data_message[1], buf, buf_len);
1851 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm);
1853 "Sending message %u from local client to %s with %lu bytes\n",
1854 ntohl (crm->data_message->mid.mid),
1855 GCCH_2s (ch),
1856 (unsigned long) buf_len);
1857 if (NULL != ch->retry_data_task)
1858 {
1859 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1860 ch->retry_data_task = NULL;
1861 }
1862 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1863 &crm->data_message->ctn);
1864 GNUNET_assert (NULL == ch->retry_data_task);
1865 return GNUNET_OK;
1866}

References GNUNET_CADET_Channel::ccn, GNUNET_CADET_LocalData::ccn, ch, CadetReliableMessage::ch, GNUNET_CADET_ClientChannelNumber::channel_of_client, GNUNET_CADET_ChannelAppDataMessage::ctn, CadetReliableMessage::data_message, data_sent_cb(), env, CadetOutOfOrderMessage::env, GCCH_2s(), GCT_send(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_malloc, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, GNUNET_MQ_msg_extra, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_SYSERR, GNUNET_YES, GSC_send_to_client(), GNUNET_CADET_ChannelAppDataMessage::header, LOG, ChannelMessageIdentifier::mid, GNUNET_CADET_ChannelAppDataMessage::mid, CadetReliableMessage::qe, receiver(), send_ack_to_client(), GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by handle_local_data().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_handle_local_ack()

void GCCH_handle_local_ack ( struct CadetChannel ch,
struct GNUNET_CADET_ClientChannelNumber  client_ccn 
)

Handle ACK from client on local channel.

Means the client is ready for more data, see if we have any for it.

Parameters
chchannel to destroy
client_ccnccn of the client sending the ack

Definition at line 1870 of file gnunet-service-cadet_channel.c.

1872{
1873 struct CadetChannelClient *ccc;
1874 struct CadetOutOfOrderMessage *com;
1875
1876 if ((NULL != ch->owner) &&
1877 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client))
1878 ccc = ch->owner;
1879 else if ((NULL != ch->dest) &&
1880 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client))
1881 ccc = ch->dest;
1882 else
1883 GNUNET_assert (0);
1884 ccc->client_ready = GNUNET_YES;
1885 com = ccc->head_recv;
1886 if (NULL == com)
1887 {
1889 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
1890 GSC_2s (ccc->c),
1891 ntohl (client_ccn.channel_of_client),
1892 GCCH_2s (ch),
1893 ntohl (ccc->ccn.channel_of_client),
1894 ccc);
1895 return; /* none pending */
1896 }
1897 if (GNUNET_YES == ch->is_loopback)
1898 {
1899 int to_owner;
1900
1901 /* Messages are always in-order, just send */
1903 ccc->num_recv--;
1904 GSC_send_to_client (ccc->c, com->env);
1905 /* Notify sender that we can receive more */
1906 if ((NULL != ch->owner) &&
1907 (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1908 {
1909 to_owner = GNUNET_NO;
1910 }
1911 else
1912 {
1913 GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client ==
1914 ch->dest->ccn.channel_of_client));
1915 to_owner = GNUNET_YES;
1916 }
1917 send_ack_to_client (ch, to_owner);
1918 GNUNET_free (com);
1919 return;
1920 }
1921
1922 if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) &&
1923 (GNUNET_YES == ch->reliable))
1924 {
1926 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1927 GSC_2s (ccc->c),
1928 ntohl (ccc->ccn.channel_of_client),
1929 ntohl (com->mid.mid),
1930 ntohl (ch->mid_recv.mid));
1931 return; /* missing next one in-order */
1932 }
1933
1935 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
1936 ntohl (com->mid.mid),
1937 GSC_2s (ccc->c),
1938 ntohl (ccc->ccn.channel_of_client),
1939 GCCH_2s (ch));
1940
1941 /* all good, pass next message to client */
1943 ccc->num_recv--;
1944 /* FIXME: if unreliable, this is not aggressive
1945 enough, as it would be OK to have lost some! */
1946
1947 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1948 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1949 ccc->client_ready = GNUNET_NO;
1950 GSC_send_to_client (ccc->c, com->env);
1951 GNUNET_free (com);
1953 if (NULL != ccc->head_recv)
1954 return;
1955 if (GNUNET_NO == ch->destroy)
1956 return;
1957 GCT_send_channel_destroy (ch->t, ch->ctn);
1959}

References CadetChannelClient::c, GNUNET_CADET_Channel::ccn, CadetChannelClient::ccn, ch, channel_destroy(), GNUNET_CADET_ClientChannelNumber::channel_of_client, CadetChannelClient::client_ready, CadetOutOfOrderMessage::env, GCCH_2s(), GCT_send_channel_destroy(), GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_NO, GNUNET_YES, GSC_2s(), GSC_send_to_client(), CadetChannelClient::head_recv, LOG, ChannelMessageIdentifier::mid, CadetOutOfOrderMessage::mid, CadetChannelClient::num_recv, send_ack_to_client(), send_channel_data_ack(), and CadetChannelClient::tail_recv.

Referenced by handle_local_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GCCH_debug()

void GCCH_debug ( struct CadetChannel ch,
enum GNUNET_ErrorType  level 
)

Log channel info.

Parameters
chChannel.
levelDebug level to use.

Definition at line 1973 of file gnunet-service-cadet_channel.c.

1974{
1975#if ! defined(GNUNET_CULL_LOGGING)
1976 int do_log;
1977
1979 "cadet-chn",
1980 __FILE__,
1981 __FUNCTION__,
1982 __LINE__);
1983 if (0 == do_log)
1984 return;
1985
1986 if (NULL == ch)
1987 {
1988 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1989 return;
1990 }
1991 LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
1992 if (NULL != ch->owner)
1993 {
1994 LOG2 (level,
1995 "CHN origin %s ready %s local-id: %u\n",
1996 GSC_2s (ch->owner->c),
1997 ch->owner->client_ready ? "YES" : "NO",
1998 ntohl (ch->owner->ccn.channel_of_client));
1999 }
2000 if (NULL != ch->dest)
2001 {
2002 LOG2 (level,
2003 "CHN destination %s ready %s local-id: %u\n",
2004 GSC_2s (ch->dest->c),
2005 ch->dest->client_ready ? "YES" : "NO",
2006 ntohl (ch->dest->ccn.channel_of_client));
2007 }
2008 LOG2 (level,
2009 "CHN Message IDs recv: %d (%llX), send: %d\n",
2010 ntohl (ch->mid_recv.mid),
2011 (unsigned long long) ch->mid_futures,
2012 ntohl (ch->mid_send.mid));
2013#endif
2014}

References GNUNET_CADET_Channel::ccn, ch, GNUNET_CADET_ClientChannelNumber::channel_of_client, GCT_2s(), GNUNET_ERROR_TYPE_BULK, GNUNET_get_log_call_status(), GSC_2s(), and LOG2.

Referenced by debug_channel().

Here is the call graph for this function:
Here is the caller graph for this function: