GNUnet 0.26.2-113-ged4734898
 
Loading...
Searching...
No Matches
gnunet-service-cadet_channel.h File Reference

GNUnet CADET service with encryption. More...

Include dependency graph for gnunet-service-cadet_channel.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

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.
 
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 GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct GNUNET_CADET_RequestDropCadetMessage *message)
 Assign type of message to drop.
 
const char * GCCH_2s (const struct CadetChannel *ch)
 Get the static string for identification of the channel.
 
void GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
 Log channel info.
 
struct GNUNET_CADET_ChannelTunnelNumber GCCH_get_id (const struct CadetChannel *ch)
 Get the channel's public ID.
 
struct CadetChannelGCCH_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.
 
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.
 
void GCCH_channel_local_destroy (struct CadetChannel *ch, struct CadetClient *c, struct GNUNET_CADET_ClientChannelNumber ccn)
 Destroy locally created 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 ready for transmission.
 
struct CadetChannelGCCH_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.
 
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.
 
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.
 
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_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).
 
void GCCH_handle_remote_destroy (struct CadetChannel *ch, const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
 Destroy channel, based on the other peer closing the connection.
 
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.
 

Detailed Description

GNUnet CADET service with encryption.

Author
Bartlomiej Polot
Christian Grothoff

Definition in file gnunet-service-cadet_channel.h.

Function Documentation

◆ 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}
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
#define LOG(level,...)
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG

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_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}
static struct GNUNET_CADET_Channel * ch
Channel handle.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
@ GNUNET_YES
@ GNUNET_NO

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

Referenced by GCT_send().

Here is the caller graph for this function:

◆ 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}
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_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}
static struct GNUNET_SCHEDULER_Task * t
Main task.
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.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity 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.

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_debug()

void GCCH_debug ( struct CadetChannel ch,
enum GNUNET_ErrorType  level 
)

Log channel info.

Parameters
chChannel.
levelDebug level to use.

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

1975{
1976#if ! defined(GNUNET_CULL_LOGGING)
1977 int do_log;
1978
1980 "cadet-chn",
1981 __FILE__,
1982 __FUNCTION__,
1983 __LINE__);
1984 if (0 == do_log)
1985 return;
1986
1987 if (NULL == ch)
1988 {
1989 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1990 return;
1991 }
1992 LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
1993 if (NULL != ch->owner)
1994 {
1995 LOG2 (level,
1996 "CHN origin %s ready %s local-id: %u\n",
1997 GSC_2s (ch->owner->c),
1998 ch->owner->client_ready ? "YES" : "NO",
1999 ntohl (ch->owner->ccn.channel_of_client));
2000 }
2001 if (NULL != ch->dest)
2002 {
2003 LOG2 (level,
2004 "CHN destination %s ready %s local-id: %u\n",
2005 GSC_2s (ch->dest->c),
2006 ch->dest->client_ready ? "YES" : "NO",
2007 ntohl (ch->dest->ccn.channel_of_client));
2008 }
2009 LOG2 (level,
2010 "CHN Message IDs recv: %d (%llX), send: %d\n",
2011 ntohl (ch->mid_recv.mid),
2012 (unsigned long long) ch->mid_futures,
2013 ntohl (ch->mid_send.mid));
2014#endif
2015}
const char * GSC_2s(struct CadetClient *c)
Return identifier for a client as a string.
#define LOG2(level,...)
const char * GCT_2s(const struct CadetTunnel *t)
Get the static string for the peer this tunnel is directed.
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:

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

◆ 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}
static struct GNUNET_ARM_Operation * op
Current operation.
Definition gnunet-arm.c:143
static struct GNUNET_PILS_Handle * pils
Handle to PILS.
Definition gnunet-pils.c:44
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.
@ CADET_CHANNEL_LOOSE
Channel is to a port that is not open, we're waiting for the port to be opened.
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.
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...
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
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.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#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?
Struct containing all information regarding a channel to a remote client.
The identity of the host (wraps the signing key of the peer).
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_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:

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

948{
949 const struct GNUNET_PeerIdentity *my_identity;
950 uint32_t options;
951 struct CadetChannelClient *cccd;
952
954 "Binding %s from %s to port %s of %s\n",
955 GCCH_2s (ch),
956 GCT_2s (ch->t),
957 GNUNET_h2s (&ch->port),
958 GSC_2s (c));
959
962
963 if (NULL != ch->retry_control_task)
964 {
965 /* there might be a timeout task here */
966 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
967 ch->retry_control_task = NULL;
968 }
969 options = 0;
970 cccd = GNUNET_new (struct CadetChannelClient);
971 GNUNET_assert (NULL == ch->dest);
972 ch->dest = cccd;
973 ch->port = *port;
974 cccd->c = c;
975 cccd->client_ready = GNUNET_YES;
976 cccd->ccn = GSC_bind (c,
977 ch,
978 (GNUNET_YES == ch->is_loopback)
981 port,
982 options);
983 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
985 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
986 if (GNUNET_YES == ch->is_loopback)
987 {
990 }
991 else
992 {
993 /* notify other peer that we accepted the connection */
994 ch->state = CADET_CHANNEL_READY;
995 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
996 }
997 /* give client it's initial supply of ACKs */
998 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
1000 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1002}
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.
@ CADET_CHANNEL_OPEN_SENT
CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK.
@ CADET_CHANNEL_READY
Connection confirmed, ready to carry traffic.
static void send_open_ack(void *cls)
Send our initial GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the connect...
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.
const char * GCCH_2s(const struct CadetChannel *ch)
Get the static string for identification of the 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).
struct CadetPeer * GCP_get(const struct GNUNET_PeerIdentity *peer_id, int create)
Retrieve the CadetPeer structure associated with the peer.
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
uint32_t channel_of_client
Values for channel numbering.
Definition cadet.h:109

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:

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

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

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_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}
static void send_channel_open(void *cls)
Send a channel create message.

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

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

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

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:

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

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

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

1543{
1544 struct CadetReliableMessage *crm;
1545 struct CadetReliableMessage *crmn;
1546 int found;
1547 uint32_t mid_base;
1548 uint64_t mid_mask;
1549 unsigned int delta;
1550
1551 GNUNET_break (GNUNET_NO == ch->is_loopback);
1552 if (GNUNET_NO == ch->reliable)
1553 {
1554 /* not expecting ACKs on unreliable channel, odd */
1555 GNUNET_break_op (0);
1556 return;
1557 }
1558 /* mid_base is the MID of the next message that the
1559 other peer expects (i.e. that is missing!), everything
1560 LOWER (but excluding mid_base itself) was received. */
1561 mid_base = ntohl (ack->mid.mid);
1562 mid_mask = GNUNET_htonll (ack->futures);
1563 found = GNUNET_NO;
1564 for (crm = ch->head_sent; NULL != crm; crm = crmn)
1565 {
1566 crmn = crm->next;
1567 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1568 if (delta >= UINT_MAX - ch->max_pending_messages)
1569 {
1570 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1572 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1573 (unsigned int) mid_base,
1574 ntohl (crm->data_message->mid.mid),
1575 GCCH_2s (ch));
1576 handle_matching_ack (ch, cti, crm);
1577 found = GNUNET_YES;
1578 continue;
1579 }
1580 delta--;
1581 if (delta >= 64)
1582 continue;
1584 "Testing bit %llX for mid %u (base: %u)\n",
1585 (1LLU << delta),
1586 ntohl (crm->data_message->mid.mid),
1587 mid_base);
1588 if (0 != (mid_mask & (1LLU << delta)))
1589 {
1591 "Got DATA_ACK with mask for %u on %s\n",
1592 ntohl (crm->data_message->mid.mid),
1593 GCCH_2s (ch));
1594 handle_matching_ack (ch, cti, crm);
1595 found = GNUNET_YES;
1596 }
1597 }
1598 if (GNUNET_NO == found)
1599 {
1600 /* ACK for message we already dropped, might have been a
1601 duplicate ACK? Ignore. */
1603 "Duplicate DATA_ACK on %s, ignoring\n",
1604 GCCH_2s (ch));
1605 GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO);
1606 return;
1607 }
1608 if (NULL != ch->retry_data_task)
1609 {
1610 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1611 ch->retry_data_task = NULL;
1612 }
1613 if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe))
1614 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1616 ch);
1617}
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 retry_transmission(void *cls)
We need to retry a transmission, the last one took too long to be acknowledged.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
#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.
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
Info needed to retry a message in case it gets lost.
struct CadetReliableMessage * next
Double linked list, FIFO style.
struct GNUNET_CADET_ChannelAppDataMessage * data_message
Data message we are trying to send.
struct ChannelMessageIdentifier mid
Unique ID of the payload message.
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(), 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_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 1107 of file gnunet-service-cadet_channel.c.

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

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:

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

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

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

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

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

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

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: