GNUnet  0.20.0
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? More...
 
#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? More...
 
#define MIN_RTT_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 75)
 How long do we wait at least before retransmitting ever? More...
 
#define MAX_OUT_OF_ORDER_DISTANCE   1024
 Maximum message ID into the future we accept for out-of-order messages. More...
 
#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. More...
 
int GCCH_is_type_to_drop (struct CadetChannel *ch, const struct GNUNET_MessageHeader *message)
 Check if type of message is the one to drop. More...
 
const char * GCCH_2s (const struct CadetChannel *ch)
 Get the static string for identification of the channel. More...
 
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. More...
 
struct GNUNET_CADET_ChannelTunnelNumber GCCH_get_id (const struct CadetChannel *ch)
 Get the channel's public ID. More...
 
static void free_channel_client (struct CadetChannelClient *ccc)
 Release memory associated with ccc. More...
 
static void channel_destroy (struct CadetChannel *ch)
 Destroy the given channel. More...
 
static void send_channel_open (void *cls)
 Send a channel create message. More...
 
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. More...
 
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. More...
 
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. More...
 
static void timeout_closed_cb (void *cls)
 We had an incoming channel to a port that is closed. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
static void signal_remote_destroy_cb (void *cls)
 One of our clients has disconnected, tell the other one that we are finished. More...
 
void GCCH_channel_local_destroy (struct CadetChannel *ch, struct CadetClient *c, struct GNUNET_CADET_ClientChannelNumber ccn)
 Destroy locally created channel. More...
 
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). More...
 
static int is_before (void *cls, struct CadetOutOfOrderMessage *m1, struct CadetOutOfOrderMessage *m2)
 Test if element e1 comes before element e2. More...
 
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. More...
 
static void data_sent_cb (void *cls, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
 Function called once the tunnel has sent one of our messages. More...
 
static void retry_transmission (void *cls)
 We need to retry a transmission, the last one took too long to be acknowledged. More...
 
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. 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. More...
 
void GCCH_handle_remote_destroy (struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
 Destroy channel, based on the other peer closing the connection. More...
 
static int cmp_crm_by_next_retry (void *cls, struct CadetReliableMessage *crm1, struct CadetReliableMessage *crm2)
 Test if element e1 comes before element e2. More...
 
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. More...
 
void GCCH_handle_local_ack (struct CadetChannel *ch, struct GNUNET_CADET_ClientChannelNumber client_ccn)
 Handle ACK from client on local channel. More...
 
void GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
 Log channel info. More...
 

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 44 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 49 of file gnunet-service-cadet_channel.c.

◆ 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 56 of file gnunet-service-cadet_channel.c.

◆ MIN_RTT_DELAY

How long do we wait at least before retransmitting ever?

Definition at line 62 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 75 of file gnunet-service-cadet_channel.c.

◆ LOG2

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

Definition at line 1953 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 81 of file gnunet-service-cadet_channel.c.

82 {
87 
93 
98 
103 };
@ 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.

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 392 of file gnunet-service-cadet_channel.c.

394 {
395 
396  ch->type = message->type;
397 
398 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
uint16_t type
Type of the message this handler covers, in host byte order.
Definition: cadet.h:331

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 407 of file gnunet-service-cadet_channel.c.

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 }
@ GNUNET_YES
@ GNUNET_NO
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.

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 429 of file gnunet-service-cadet_channel.c.

430 {
431  static char buf[128];
432 
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 }
const struct GNUNET_PeerIdentity * GCP_get_id(struct CadetPeer *cp)
Obtain the peer identity for a struct CadetPeer.
struct CadetPeer * GCT_get_destination(struct CadetTunnel *t)
Return the peer to which this tunnel goes.
static char buf[2048]
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
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.
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
uint32_t channel_of_client
Values for channel numbering.
Definition: cadet.h:109

References buf, 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_remove_channel(), 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 461 of file gnunet-service-cadet_channel.c.

464 {
465  struct GNUNET_HashContext *hc;
466 
468  GNUNET_CRYPTO_hash_context_read (hc, port, sizeof(*port));
469  GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener));
472  "Calculated port hash %s\n",
473  GNUNET_h2s (h_port));
474 }
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
#define LOG(level,...)
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
Definition: crypto_hash.c:350
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
Definition: crypto_hash.c:366
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:390
@ GNUNET_ERROR_TYPE_DEBUG

Referenced by GCCH_channel_local_new(), and handle_port_open().

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 461 of file gnunet-service-cadet_channel.c.

486 {
487  return ch->ctn;
488 }

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.

Here is the call graph for this function:

◆ 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 497 of file gnunet-service-cadet_channel.c.

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 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#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
struct CadetOutOfOrderMessage * head_recv
Head of DLL of messages received out of order or while client was unready.
struct CadetOutOfOrderMessage * tail_recv
Tail DLL of messages received out of order or while client was unready.
unsigned int num_recv
Number of entries currently in head_recv DLL.
List of received out-of-order data messages.
struct GNUNET_MQ_Envelope * env
The envelope with the payload of the out-of-order message.

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 518 of file gnunet-service-cadet_channel.c.

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);
531  GNUNET_free (crm->data_message);
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 }
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...
static void free_channel_client(struct CadetChannelClient *ccc)
Release memory associated with ccc.
void GCT_remove_channel(struct CadetTunnel *t, struct CadetChannel *ch, struct GNUNET_CADET_ChannelTunnelNumber ctn)
Remove a channel from a tunnel.
void GCT_send_cancel(struct CadetTunnelQueueEntry *tq)
Cancel a previously sent message while it's in the queue.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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_CADET_ChannelAppDataMessage * data_message
Data message we are trying to send.
struct CadetChannel * ch
Which channel is this message in?

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 613 of file gnunet-service-cadet_channel.c.

614 {
615  struct CadetChannel *ch = cls;
616  struct GNUNET_CADET_ChannelOpenMessage msgcc;
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;
628  ch->state = CADET_CHANNEL_OPEN_SENT;
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 }
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.
const char * GCCH_2s(const struct CadetChannel *ch)
Get the static string for identification of the channel.
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...
#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN
Ask the cadet service to create a new channel.
Struct containing all information regarding a channel to a remote client.
Message to create a Channel.

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 590 of file gnunet-service-cadet_channel.c.

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 }
static void send_channel_open(void *cls)
Send a channel create message.
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:1272
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:569
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...

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 648 of file gnunet-service-cadet_channel.c.

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 }
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:1299

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

Referenced by 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 659 of file gnunet-service-cadet_channel.c.

664 {
665  struct CadetChannel *ch;
666  struct CadetChannelClient *ccco;
667 
668  ccco = GNUNET_new (struct CadetChannelClient);
669  ccco->c = owner;
670  ccco->ccn = ccn;
671  ccco->client_ready = GNUNET_YES;
672 
673  ch = GNUNET_new (struct CadetChannel);
674  ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
675  ch->nobuffer = GNUNET_NO;
676  ch->reliable = GNUNET_YES;
677  ch->out_of_order = GNUNET_NO;
678  ch->max_pending_messages =
679  (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
680  ch->owner = ccco;
681  ch->port = *port;
682  GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination));
683  if (0 == GNUNET_memcmp (&my_full_id, GCP_get_id (destination)))
684  {
685  struct OpenPort *op;
686 
687  ch->is_loopback = GNUNET_YES;
689  if (NULL == op)
690  {
691  /* port closed, wait for it to possibly open */
692  ch->state = CADET_CHANNEL_LOOSE;
695  &ch->h_port,
696  ch,
699  "Created loose incoming loopback channel to port %s\n",
700  GNUNET_h2s (&ch->port));
701  }
702  else
703  {
704  GCCH_bind (ch, op->c, &op->port);
705  }
706  }
707  else
708  {
709  ch->t = GCP_get_tunnel (destination, GNUNET_YES);
710  ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
711  ch->ctn = GCT_add_channel (ch->t, ch);
712  }
713  GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
715  "Created channel to port %s at peer %s for %s using %s\n",
716  GNUNET_h2s (port),
717  GCP_2s (destination),
718  GSC_2s (owner),
719  (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
720  return ch;
721 }
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
struct GNUNET_PeerIdentity my_full_id
Local peer own ID.
const char * GSC_2s(struct CadetClient *c)
Return identifier for a client as a string.
struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
struct GNUNET_CONTAINER_MultiHashMap * open_ports
All ports clients of this peer have opened.
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 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.
#define CADET_INITIAL_RETRANSMIT_TIME
How long do we initially wait before retransmitting?
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...
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.
const char * GCT_2s(const struct CadetTunnel *t)
Get the static string for the peer this tunnel is directed.
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...
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.
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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
Client endpoint of a struct CadetChannel.
struct CadetClient * c
Client handle.
struct GNUNET_CADET_ClientChannelNumber ccn
Local tunnel number for this client.
int client_ready
Can we send data to the client?
Port opened by a client.

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_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_memcmp, GNUNET_new, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, GSC_2s(), LOG, loose_channels, my_full_id, op, open_ports, 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 731 of file gnunet-service-cadet_channel.c.

732 {
733  struct CadetChannel *ch = cls;
734 
735  ch->retry_control_task = NULL;
737  "Closing incoming channel to port %s from peer %s due to timeout\n",
738  GNUNET_h2s (&ch->port),
739  GCP_2s (GCT_get_destination (ch->t)));
741 }
static void channel_destroy(struct CadetChannel *ch)
Destroy the given channel.

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 745 of file gnunet-service-cadet_channel.c.

749 {
750  struct CadetChannel *ch;
751  struct OpenPort *op;
752 
753  ch = GNUNET_new (struct CadetChannel);
754  ch->h_port = *h_port;
755  ch->t = t;
756  ch->ctn = ctn;
757  ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
758  ch->nobuffer = GNUNET_NO;
759  ch->reliable = GNUNET_YES;
760  ch->out_of_order = GNUNET_NO;
761  ch->max_pending_messages =
762  (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
763  GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
764 
766  if (NULL == op)
767  {
768  /* port closed, wait for it to possibly open */
769  ch->state = CADET_CHANNEL_LOOSE;
772  &ch->h_port,
773  ch,
775  GNUNET_assert (NULL == ch->retry_control_task);
776  ch->retry_control_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
778  ch);
780  "Created loose incoming channel to port %s from peer %s\n",
781  GNUNET_h2s (&ch->port),
782  GCP_2s (GCT_get_destination (ch->t)));
783  }
784  else
785  {
786  GCCH_bind (ch, op->c, &op->port);
787  }
788  GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
789  return ch;
790 }
static void timeout_closed_cb(void *cls)
We had an incoming channel to a port that is closed.
#define TIMEOUT_CLOSED_PORT
How long do we wait before dropping state about incoming connection to closed port?
static struct GNUNET_SCHEDULER_Task * t
Main task.
struct GNUNET_HashCode h_port
Port hashed with our PID (matches incoming OPEN messages).

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 803 of file gnunet-service-cadet_channel.c.

805 {
806  struct CadetChannel *ch = cls;
807 
808  GNUNET_assert (NULL != ch->last_control_qe);
809  ch->last_control_qe = NULL;
810 }

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 819 of file gnunet-service-cadet_channel.c.

820 {
822 
823  if (GNUNET_NO == ch->reliable)
824  return; /* no ACKs */
826  msg.header.size = htons (sizeof(msg));
827  msg.ctn = ch->ctn;
828  msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
829  msg.futures = GNUNET_htonll (ch->mid_futures);
831  "Sending DATA_ACK %u:%llX via %s\n",
832  (unsigned int) ntohl (msg.mid.mid),
833  (unsigned long long) ch->mid_futures,
834  GCCH_2s (ch));
835  if (NULL != ch->last_control_qe)
836  GCT_send_cancel (ch->last_control_qe);
837  ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
838  &msg.ctn);
839 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
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.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK
Confirm payload data end-to-end.
Message to acknowledge end-to-end data.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.

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 849 of file gnunet-service-cadet_channel.c.

850 {
851  struct CadetChannel *ch = cls;
853 
854  ch->retry_control_task = NULL;
856  "Sending CHANNEL_OPEN_ACK on %s\n",
857  GCCH_2s (ch));
859  msg.header.size = htons (sizeof(msg));
860  msg.reserved = htonl (0);
861  msg.ctn = ch->ctn;
862  msg.port = ch->port;
863  if (NULL != ch->last_control_qe)
864  GCT_send_cancel (ch->last_control_qe);
865  ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
866  &msg.ctn);
867 }
#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK
Confirm the creation of a channel.
Message to acknowledge opening a channel of type GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.

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 879 of file gnunet-service-cadet_channel.c.

882 {
883  if (NULL == ch->dest)
884  {
886  "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
887  GCCH_2s (ch));
888  return;
889  }
890  if (NULL != ch->retry_control_task)
891  {
893  "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
894  GCCH_2s (ch));
895  return;
896  }
898  "Retransmitting CHANNEL_OPEN_ACK on %s\n",
899  GCCH_2s (ch));
900  ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
901 }
static void send_open_ack(void *cls)
Send our initial GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the connect...

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 912 of file gnunet-service-cadet_channel.c.

913 {
914  struct GNUNET_MQ_Envelope *env;
915  struct GNUNET_CADET_LocalAck *ack;
916  struct CadetChannelClient *ccc;
917 
918  ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
919  if (NULL == ccc)
920  {
921  /* This can happen if we are just getting ACKs after
922  our local client already disconnected. */
923  GNUNET_assert (GNUNET_YES == ch->destroy);
924  return;
925  }
927  ack->ccn = ccc->ccn;
929  "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
930  GSC_2s (ccc->c),
931  (GNUNET_YES == to_owner) ? "owner" : "dest",
932  ntohl (ack->ccn.channel_of_client),
933  ch->pending_messages,
934  ch->max_pending_messages);
935  GSC_send_to_client (ccc->c, env);
936 }
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
void GSC_send_to_client(struct CadetClient *c, struct GNUNET_MQ_Envelope *env)
Send a message to a client.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK
Local ACK for data.
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

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 940 of file gnunet-service-cadet_channel.c.

943 {
944  uint32_t options;
945  struct CadetChannelClient *cccd;
946 
948  "Binding %s from %s to port %s of %s\n",
949  GCCH_2s (ch),
950  GCT_2s (ch->t),
951  GNUNET_h2s (&ch->port),
952  GSC_2s (c));
953  if (NULL != ch->retry_control_task)
954  {
955  /* there might be a timeout task here */
956  GNUNET_SCHEDULER_cancel (ch->retry_control_task);
957  ch->retry_control_task = NULL;
958  }
959  options = 0;
960  cccd = GNUNET_new (struct CadetChannelClient);
961  GNUNET_assert (NULL == ch->dest);
962  ch->dest = cccd;
963  ch->port = *port;
964  cccd->c = c;
965  cccd->client_ready = GNUNET_YES;
966  cccd->ccn = GSC_bind (c,
967  ch,
968  (GNUNET_YES == ch->is_loopback)
970  : GCT_get_destination (ch->t),
971  port,
972  options);
973  GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
975  ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
976  if (GNUNET_YES == ch->is_loopback)
977  {
978  ch->state = CADET_CHANNEL_OPEN_SENT;
980  }
981  else
982  {
983  /* notify other peer that we accepted the connection */
984  ch->state = CADET_CHANNEL_READY;
985  ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
986  }
987  /* give client it's initial supply of ACKs */
988  GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
990  for (unsigned int i = 0; i < ch->max_pending_messages; i++)
992 }
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI
Minimum value for channel IDs of local clients.
Definition: cadet.h:70
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.
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_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).
struct CadetPeer * GCP_get(const struct GNUNET_PeerIdentity *peer_id, int create)
Retrieve the CadetPeer structure associated with the peer.

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_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNUNET_YES, GSC_2s(), GSC_bind(), LOG, my_full_id, options, 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 1003 of file gnunet-service-cadet_channel.c.

1004 {
1005  struct CadetChannel *ch = cls;
1006  struct CadetChannelClient *ccc;
1007 
1008  /* Find which end is left... */
1009  ch->retry_control_task = NULL;
1010  ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1011  GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1012  channel_destroy (ch);
1013 }
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.

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 1025 of file gnunet-service-cadet_channel.c.

1028 {
1030  "%s asks for destruction of %s\n",
1031  GSC_2s (c),
1032  GCCH_2s (ch));
1033  GNUNET_assert (NULL != c);
1034  if ((NULL != ch->owner) && (c == ch->owner->c) &&
1035  (ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1036  {
1037  free_channel_client (ch->owner);
1038  ch->owner = NULL;
1039  }
1040  else if ((NULL != ch->dest) && (c == ch->dest->c) &&
1041  (ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1042  {
1043  free_channel_client (ch->dest);
1044  ch->dest = NULL;
1045  }
1046  else
1047  {
1048  GNUNET_assert (0);
1049  }
1050 
1051  if (GNUNET_YES == ch->destroy)
1052  {
1053  /* other end already destroyed, with the local client gone, no need
1054  to finish transmissions, just destroy immediately. */
1055  channel_destroy (ch);
1056  return;
1057  }
1058  if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest)))
1059  {
1060  /* Wait for other end to destroy us as well,
1061  and otherwise allow send queue to be transmitted first */
1062  ch->destroy = GNUNET_YES;
1063  return;
1064  }
1065  if ((GNUNET_YES == ch->is_loopback) &&
1066  ((NULL != ch->owner) || (NULL != ch->dest)))
1067  {
1068  if (NULL != ch->retry_control_task)
1069  GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1070  ch->retry_control_task =
1072  return;
1073  }
1074  if (GNUNET_NO == ch->is_loopback)
1075  {
1076  /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1077  switch (ch->state)
1078  {
1079  case CADET_CHANNEL_NEW:
1080  /* We gave up on a channel that we created as a client to a remote
1081  target, but that never went anywhere. Nothing to do here. */
1082  break;
1083 
1084  case CADET_CHANNEL_LOOSE:
1085  break;
1086 
1087  default:
1088  GCT_send_channel_destroy (ch->t, ch->ctn);
1089  }
1090  }
1091  /* Nothing left to do, just finish destruction */
1092  channel_destroy (ch);
1093 }
static void signal_remote_destroy_cb(void *cls)
One of our clients has disconnected, tell the other one that we are finished.
void GCT_send_channel_destroy(struct CadetTunnel *t, struct GNUNET_CADET_ChannelTunnelNumber ctn)
Send a DESTROY message via the tunnel.

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 1097 of file gnunet-service-cadet_channel.c.

1101 {
1102  switch (ch->state)
1103  {
1104  case CADET_CHANNEL_NEW:
1105  /* this should be impossible */
1106  GNUNET_break (0);
1107  break;
1108 
1109  case CADET_CHANNEL_LOOSE:
1110  /* This makes no sense. */
1111  GNUNET_break_op (0);
1112  break;
1113 
1115  if (NULL == ch->owner)
1116  {
1117  /* We're not the owner, wrong direction! */
1118  GNUNET_break_op (0);
1119  return;
1120  }
1121  if (0 != GNUNET_memcmp (&ch->port, port))
1122  {
1123  /* Other peer failed to provide the right port,
1124  refuse connection. */
1125  GNUNET_break_op (0);
1126  return;
1127  }
1129  "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1130  GCCH_2s (ch));
1131  if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1132  {
1133  GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1134  ch->retry_control_task = NULL;
1135  }
1136  ch->state = CADET_CHANNEL_READY;
1137  /* On first connect, send client as many ACKs as we allow messages
1138  to be buffered! */
1139  for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1141  break;
1142 
1143  case CADET_CHANNEL_READY:
1144  /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1146  "Received duplicate channel OPEN_ACK for %s\n",
1147  GCCH_2s (ch));
1148  GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO);
1149  break;
1150  }
1151 }
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.

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 1163 of file gnunet-service-cadet_channel.c.

1166 {
1167  int *duplicate = cls;
1168  uint32_t v1 = ntohl (m1->mid.mid);
1169  uint32_t v2 = ntohl (m2->mid.mid);
1170  uint32_t delta;
1171 
1172  delta = v2 - v1;
1173  if (0 == delta)
1174  *duplicate = GNUNET_YES;
1175  if (delta > (uint32_t) INT_MAX)
1176  {
1177  /* in overflow range, we can safely assume we wrapped around */
1178  return GNUNET_NO;
1179  }
1180  else
1181  {
1182  /* result is small, thus v2 > v1, thus m1 < m2 */
1183  return GNUNET_YES;
1184  }
1185 }
#define INT_MAX
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
struct ChannelMessageIdentifier mid
ID of the message (messages up to this point needed before we give this one to the client).
uint32_t mid
Unique ID of the message, cycles around, in NBO.

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 1189 of file gnunet-service-cadet_channel.c.

1193 {
1194  struct GNUNET_MQ_Envelope *env;
1195  struct GNUNET_CADET_LocalData *ld;
1196  struct CadetChannelClient *ccc;
1197  size_t payload_size;
1198  struct CadetOutOfOrderMessage *com;
1199  int duplicate;
1200  uint32_t mid_min;
1201  uint32_t mid_max;
1202  uint32_t mid_msg;
1203  uint32_t delta;
1204 
1205  GNUNET_assert (GNUNET_NO == ch->is_loopback);
1206  if ((NULL == ch->owner) && (NULL == ch->dest))
1207  {
1208  /* This client is gone, but we still have messages to send to
1209  the other end (which is why @a ch is not yet dead). However,
1210  we cannot pass messages to our client anymore. */
1212  "Dropping incoming payload on %s as this end is already closed\n",
1213  GCCH_2s (ch));
1214  /* send back DESTROY notification to stop further retransmissions! */
1215  if (GNUNET_YES == ch->destroy)
1216  GCT_send_channel_destroy (ch->t, ch->ctn);
1217  return;
1218  }
1219  payload_size = ntohs (msg->header.size) - sizeof(*msg);
1220  env = GNUNET_MQ_msg_extra (ld,
1221  payload_size,
1223  ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1224  GNUNET_memcpy (&ld[1], &msg[1], payload_size);
1225  ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1226  if (GNUNET_YES == ccc->client_ready)
1227  {
1228  /*
1229  * We ad-hoc send the message if
1230  * - The channel is out-of-order
1231  * - The channel is reliable and MID matches next expected MID
1232  * - The channel is unreliable and MID is before lowest seen MID
1233  */if ((GNUNET_YES == ch->out_of_order) ||
1234  ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) ||
1235  ((GNUNET_NO == ch->reliable) &&
1236  (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) &&
1237  ((NULL == ccc->head_recv) ||
1238  (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid)))))
1239  {
1241  "Giving %u bytes of payload with MID %u from %s to client %s\n",
1242  (unsigned int) payload_size,
1243  ntohl (msg->mid.mid),
1244  GCCH_2s (ch),
1245  GSC_2s (ccc->c));
1246  ccc->client_ready = GNUNET_NO;
1247  GSC_send_to_client (ccc->c, env);
1248  if (GNUNET_NO == ch->out_of_order)
1249  ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1250  else
1251  ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1252  ch->mid_futures >>= 1;
1253  if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable))
1254  {
1255  /* possibly shift by more if we skipped messages */
1256  uint64_t delta = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid);
1257 
1258  if (delta > 63)
1259  ch->mid_futures = 0;
1260  else
1261  ch->mid_futures >>= delta;
1262  ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1263  }
1265  return;
1266  }
1267  }
1268 
1269  if (GNUNET_YES == ch->reliable)
1270  {
1271  /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1272  mid_min = ntohl (ch->mid_recv.mid);
1273  mid_max = mid_min + ch->max_pending_messages;
1274  mid_msg = ntohl (msg->mid.mid);
1275  if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1276  ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages))
1277  {
1279  "%s at %u drops ancient or far-future message %u\n",
1280  GCCH_2s (ch),
1281  (unsigned int) mid_min,
1282  ntohl (msg->mid.mid));
1283 
1285  "# duplicate DATA (ancient or future)",
1286  1,
1287  GNUNET_NO);
1290  return;
1291  }
1292  /* mark bit for future ACKs */
1293  delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1294  if (delta < 64)
1295  {
1296  if (0 != (ch->mid_futures & (1LLU << delta)))
1297  {
1298  /* Duplicate within the queue, drop also */
1300  "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1301  (unsigned int) payload_size,
1302  GCCH_2s (ch),
1303  ntohl (msg->mid.mid));
1304  GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1307  return;
1308  }
1309  ch->mid_futures |= (1LLU << delta);
1311  "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1312  (1LLU << delta),
1313  mid_msg,
1314  mid_min,
1315  (unsigned long long) ch->mid_futures);
1316  }
1317  }
1318  else /* ! ch->reliable */
1319  {
1320  struct CadetOutOfOrderMessage *next_msg;
1321 
1326  if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready))
1327  {
1328  next_msg = ccc->head_recv;
1330  "Giving queued MID %u from %s to client %s\n",
1331  ntohl (next_msg->mid.mid),
1332  GCCH_2s (ch),
1333  GSC_2s (ccc->c));
1334  ccc->client_ready = GNUNET_NO;
1335  GSC_send_to_client (ccc->c, next_msg->env);
1336  ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid));
1337  ch->mid_futures >>= 1;
1339  GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg);
1340  ccc->num_recv--;
1341  /* Do not process duplicate MID */
1342  if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */
1343  {
1344  /* Duplicate within the queue, drop */
1346  "Message on %s (mid %u) dropped, duplicate\n",
1347  GCCH_2s (ch),
1348  ntohl (msg->mid.mid));
1349  GNUNET_free (next_msg);
1351  return;
1352  }
1353  GNUNET_free (next_msg);
1354  }
1355 
1356  if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */
1357  {
1358  /* Duplicate within the queue, drop */
1360  "Message on %s (mid %u) dropped, old.\n",
1361  GCCH_2s (ch),
1362  ntohl (msg->mid.mid));
1364  return;
1365  }
1366 
1367  /* Channel is unreliable, so we do not ACK. But we also cannot
1368  allow buffering everything, so check if we have space... */
1369  if (ccc->num_recv >= ch->max_pending_messages)
1370  {
1371  struct CadetOutOfOrderMessage *drop;
1372 
1373  /* Yep, need to drop. Drop the oldest message in
1374  the buffer. */
1376  "Queue full due slow client on %s, dropping oldest message\n",
1377  GCCH_2s (ch));
1379  "# messages dropped due to slow client",
1380  1,
1381  GNUNET_NO);
1382  drop = ccc->head_recv;
1383  GNUNET_assert (NULL != drop);
1384  GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, drop);
1385  ccc->num_recv--;
1386  GNUNET_MQ_discard (drop->env);
1387  GNUNET_free (drop);
1388  }
1389  }
1390 
1391  /* Insert message into sorted out-of-order queue */
1392  com = GNUNET_new (struct CadetOutOfOrderMessage);
1393  com->mid = msg->mid;
1394  com->env = env;
1395  duplicate = GNUNET_NO;
1397  is_before,
1398  &duplicate,
1399  ccc->head_recv,
1400  ccc->tail_recv,
1401  com);
1402  ccc->num_recv++;
1403  if (GNUNET_YES == duplicate)
1404  {
1405  /* Duplicate within the queue, drop also (this is not covered by
1406  the case above if "delta" >= 64, which could be the case if
1407  max_pending_messages is also >= 64 or if our client is unready
1408  and we are seeing retransmissions of the message our client is
1409  blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG,
1410  "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1411  (unsigned int) payload_size,
1412  GCCH_2s (ch),
1413  ntohl (msg->mid.mid));
1414  GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1416  ccc->num_recv--;
1417  GNUNET_MQ_discard (com->env);
1418  GNUNET_free (com);
1420  return;
1421  }
1423  "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1424  (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready",
1425  (unsigned int) payload_size,
1426  GCCH_2s (ch),
1427  ntohl (ccc->ccn.channel_of_client),
1428  ccc,
1429  ntohl (msg->mid.mid),
1430  ntohl (ch->mid_recv.mid));
1431  /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1432  the sender may already be transmitting the previous one. Needs
1433  experimental evaluation to see if/when this ACK helps or
1434  hurts. (We might even want another option.) */
1436 }
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 int is_before(void *cls, struct CadetOutOfOrderMessage *m1, struct CadetOutOfOrderMessage *m2)
Test if element e1 comes before element e2.
#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.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA
Payload client <-> service.
Message for cadet data traffic.
Definition: cadet.h:252
struct GNUNET_CADET_ClientChannelNumber ccn
ID of the channel.
Definition: cadet.h:261

References CadetChannelClient::c, GNUNET_CADET_Channel::ccn, GNUNET_CADET_LocalData::ccn, CadetChannelClient::ccn, ch, GNUNET_CADET_ClientChannelNumber::channel_of_client, CadetChannelClient::client_ready, 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 1672 of file gnunet-service-cadet_channel.c.

1674 {
1675  struct CadetReliableMessage *crm = cls;
1676  struct CadetChannel *ch = crm->ch;
1677 
1678  GNUNET_assert (GNUNET_NO == ch->is_loopback);
1679  GNUNET_assert (NULL != crm->qe);
1680  crm->qe = NULL;
1681  GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1682  if (GNUNET_NO == ch->reliable)
1683  {
1684  GNUNET_free (crm->data_message);
1685  GNUNET_free (crm);
1686  ch->pending_messages--;
1687  send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1688  return;
1689  }
1690  if (NULL == cid)
1691  {
1692  /* There was an error sending. */
1694  }
1695  else if (GNUNET_SYSERR != crm->num_transmissions)
1696  {
1697  /* Increment transmission counter, and possibly store @a cid
1698  if this was the first transmission. */
1699  crm->num_transmissions++;
1700  if (1 == crm->num_transmissions)
1701  {
1703  crm->connection_taken = *cid;
1704  GCC_ack_expected (cid);
1705  }
1706  }
1707  if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid))
1708  {
1709  struct CadetConnection *cc = GCC_lookup (cid);
1710 
1711  if (NULL != cc)
1713  else
1714  crm->retry_delay = ch->retry_time;
1715  }
1719 
1722  NULL,
1723  ch->head_sent,
1724  ch->tail_sent,
1725  crm);
1727  "Message %u sent, next transmission on %s in %s\n",
1728  (unsigned int) ntohl (crm->data_message->mid.mid),
1729  GCCH_2s (ch),
1732  ch->head_sent->next_retry),
1733  GNUNET_YES));
1734  if (NULL == ch->head_sent->qe)
1735  {
1736  if (NULL != ch->retry_data_task)
1737  GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1738  ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1740  ch);
1741  }
1742 }
static int cmp_crm_by_next_retry(void *cls, struct CadetReliableMessage *crm1, struct CadetReliableMessage *crm2)
Test if element e1 comes before element e2.
#define MIN_RTT_DELAY
How long do we wait at least before retransmitting ever?
static void retry_transmission(void *cls)
We need to retry a transmission, the last one took too long to be acknowledged.
const struct CadetConnectionMetrics * GCC_get_metrics(struct CadetConnection *cc)
Obtain performance metrics from cc.
struct CadetConnection * GCC_lookup(const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
Lookup a connection by its identifier.
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.
@ GNUNET_SYSERR
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:1249
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:351
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:405
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
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.
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 GNUNET_CADET_ConnectionTunnelIdentifier connection_taken
Identifier of the connection that this message took when it was first transmitted.
struct GNUNET_TIME_Absolute first_transmission_time
Time when we first successfully transmitted the message (that is, set num_transmissions to 1).
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 ChannelMessageIdentifier mid
Unique ID of the payload message.
uint64_t rel_value_us
The actual value.

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, GNUNET_CADET_ChannelAppDataMessage::mid, ChannelMessageIdentifier::mid, MIN_RTT_DELAY, CadetReliableMessage::next_retry, CadetReliableMessage::num_transmissions, 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 1461 of file gnunet-service-cadet_channel.c.

1462 {
1463  struct CadetChannel *ch = cls;
1464  struct CadetReliableMessage *crm = ch->head_sent;
1465 
1466  ch->retry_data_task = NULL;
1467  GNUNET_assert (NULL == crm->qe);
1469  "Retrying transmission on %s of message %u\n",
1470  GCCH_2s (ch),
1471  (unsigned int) ntohl (crm->data_message->mid.mid));
1472  crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1473  &crm->data_message->ctn);
1474  GNUNET_assert (NULL == ch->retry_data_task);
1475 }
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_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA.
struct GNUNET_CADET_ChannelTunnelNumber ctn
ID of the channel.

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, GNUNET_CADET_ChannelAppDataMessage::mid, ChannelMessageIdentifier::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 1487 of file gnunet-service-cadet_channel.c.

1490 {
1491  GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1492  ch->pending_messages--;
1493  GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1495  "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1496  GCCH_2s (ch),
1497  (unsigned int) ntohl (crm->data_message->mid.mid),
1498  ch->pending_messages);
1499  if (NULL != crm->qe)
1500  {
1501  GCT_send_cancel (crm->qe);
1502  crm->qe = NULL;
1503  }
1504  if ((1 == crm->num_transmissions) && (NULL != cti))
1505  {
1506  GCC_ack_observed (cti);
1507  if (0 == GNUNET_memcmp (cti, &crm->connection_taken))
1508  {
1509  GCC_latency_observed (cti,
1511  crm->first_transmission_time));
1512  }
1513  }
1514  GNUNET_free (crm->data_message);
1515  GNUNET_free (crm);
1516  send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1517 }
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.
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:436

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, GNUNET_CADET_ChannelAppDataMessage::mid, ChannelMessageIdentifier::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 1529 of file gnunet-service-cadet_channel.c.

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

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(), consensus-simulation::int, LOG, GNUNET_CADET_ChannelAppDataMessage::mid, ChannelMessageIdentifier::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 1611 of file gnunet-service-cadet_channel.c.

1614 {
1615  struct CadetChannelClient *ccc;
1616 
1617  GNUNET_assert (GNUNET_NO == ch->is_loopback);
1619  "Received remote channel DESTROY for %s\n",
1620  GCCH_2s (ch));
1621  if (GNUNET_YES == ch->destroy)
1622  {
1623  /* Local client already gone, this is instant-death. */
1624  channel_destroy (ch);
1625  return;
1626  }
1627  ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1628  if ((NULL != ccc) && (NULL != ccc->head_recv))
1629  {
1631  "Lost end of transmission due to remote shutdown on %s\n",
1632  GCCH_2s (ch));
1633  /* FIXME: change API to notify client about truncated transmission! */
1634  }
1635  ch->destroy = GNUNET_YES;
1636  if (NULL != ccc)
1637  GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1638  channel_destroy (ch);
1639 }
@ GNUNET_ERROR_TYPE_WARNING

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 1651 of file gnunet-service-cadet_channel.c.

1654 {
1655  if (crm1->next_retry.abs_value_us < crm2->next_retry.abs_value_us)
1656  return GNUNET_YES;
1657  return GNUNET_NO;
1658 }
uint64_t abs_value_us
The actual value.

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 1760 of file gnunet-service-cadet_channel.c.

1764 {
1765  struct CadetReliableMessage *crm;
1766 
1767  if (ch->pending_messages >= ch->max_pending_messages)
1768  {
1769  GNUNET_break (0); /* Fails: #5370 */
1770  return GNUNET_SYSERR;
1771  }
1772  if (GNUNET_YES == ch->destroy)
1773  {
1774  /* we are going down, drop messages */
1775  return GNUNET_OK;
1776  }
1777  ch->pending_messages++;
1778 
1779  if (GNUNET_YES == ch->is_loopback)
1780  {
1781  struct CadetChannelClient *receiver;
1782  struct GNUNET_MQ_Envelope *env;
1783  struct GNUNET_CADET_LocalData *ld;
1784  int ack_to_owner;
1785 
1786  env =
1788  if ((NULL != ch->owner) &&
1789  (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1790  {
1791  receiver = ch->dest;
1792  ack_to_owner = GNUNET_YES;
1793  }
1794  else if ((NULL != ch->dest) &&
1795  (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1796  {
1797  receiver = ch->owner;
1798  ack_to_owner = GNUNET_NO;
1799  }
1800  else
1801  {
1802  GNUNET_free (env);
1803  GNUNET_break (0);
1804  return GNUNET_SYSERR;
1805  }
1806  GNUNET_assert (NULL != receiver);
1807  ld->ccn = receiver->ccn;
1808  GNUNET_memcpy (&ld[1], buf, buf_len);
1809  if (GNUNET_YES == receiver->client_ready)
1810  {
1811  ch->pending_messages--;
1813  send_ack_to_client (ch, ack_to_owner);
1814  }
1815  else
1816  {
1817  struct CadetOutOfOrderMessage *oom;
1818 
1819  oom = GNUNET_new (struct CadetOutOfOrderMessage);
1820  oom->env = env;
1822  receiver->tail_recv,
1823  oom);
1824  receiver->num_recv++;
1825  }
1826  return GNUNET_OK;
1827  }
1828 
1829  /* Everything is correct, send the message. */
1830  crm = GNUNET_malloc (sizeof(*crm));
1831  crm->ch = ch;
1832  crm->data_message = GNUNET_malloc (
1833  sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1834  crm->data_message->header.size =
1835  htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1836  crm->data_message->header.type =
1838  ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1839  crm->data_message->mid = ch->mid_send;
1840  crm->data_message->ctn = ch->ctn;
1841  GNUNET_memcpy (&crm->data_message[1], buf, buf_len);
1842  GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm);
1844  "Sending message %u from local client to %s with %lu bytes\n",
1845  ntohl (crm->data_message->mid.mid),
1846  GCCH_2s (ch),
1847  (unsigned long) buf_len);
1848  if (NULL != ch->retry_data_task)
1849  {
1850  GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1851  ch->retry_data_task = NULL;
1852  }
1853  crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1854  &crm->data_message->ctn);
1855  GNUNET_assert (NULL == ch->retry_data_task);
1856  return GNUNET_OK;
1857 }
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
@ GNUNET_OK
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA
Payload data (inside an encrypted tunnel).
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
Message for cadet data traffic.

References buf, 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, GNUNET_CADET_ChannelAppDataMessage::mid, ChannelMessageIdentifier::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 1861 of file gnunet-service-cadet_channel.c.

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

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 1964 of file gnunet-service-cadet_channel.c.

1965 {
1966 #if ! defined(GNUNET_CULL_LOGGING)
1967  int do_log;
1968 
1970  "cadet-chn",
1971  __FILE__,
1972  __FUNCTION__,
1973  __LINE__);
1974  if (0 == do_log)
1975  return;
1976 
1977  if (NULL == ch)
1978  {
1979  LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1980  return;
1981  }
1982  LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
1983  if (NULL != ch->owner)
1984  {
1985  LOG2 (level,
1986  "CHN origin %s ready %s local-id: %u\n",
1987  GSC_2s (ch->owner->c),
1988  ch->owner->client_ready ? "YES" : "NO",
1989  ntohl (ch->owner->ccn.channel_of_client));
1990  }
1991  if (NULL != ch->dest)
1992  {
1993  LOG2 (level,
1994  "CHN destination %s ready %s local-id: %u\n",
1995  GSC_2s (ch->dest->c),
1996  ch->dest->client_ready ? "YES" : "NO",
1997  ntohl (ch->dest->ccn.channel_of_client));
1998  }
1999  LOG2 (level,
2000  "CHN Message IDs recv: %d (%llX), send: %d\n",
2001  ntohl (ch->mid_recv.mid),
2002  (unsigned long long) ch->mid_futures,
2003  ntohl (ch->mid_send.mid));
2004 #endif
2005 }
#define LOG2(level,...)
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.
@ GNUNET_ERROR_TYPE_BULK

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: