GNUnet  0.11.x
Data Structures | Macros | Typedefs | Functions
plugin_transport_udp.c File Reference

Implementation of the UDP transport protocol. More...

#include "platform.h"
#include "plugin_transport_udp.h"
#include "gnunet_hello_lib.h"
#include "gnunet_util_lib.h"
#include "gnunet_fragmentation_lib.h"
#include "gnunet_nat_service.h"
#include "gnunet_protocols.h"
#include "gnunet_resolver_service.h"
#include "gnunet_signatures.h"
#include "gnunet_constants.h"
#include "gnunet_statistics_service.h"
#include "gnunet_transport_service.h"
#include "gnunet_transport_plugin.h"
#include "transport.h"
Include dependency graph for plugin_transport_udp.c:

Go to the source code of this file.

Data Structures

struct  UDPMessage
 UDP Message-Packet header (after defragmentation). More...
 
struct  PrettyPrinterContext
 Closure for append_port(). More...
 
struct  GNUNET_ATS_Session
 Session handle for connections. More...
 
struct  DefragContext
 Data structure to track defragmentation contexts based on the source of the UDP traffic. More...
 
struct  UDP_FragmentationContext
 Context to send fragmented messages. More...
 
struct  UDP_MessageWrapper
 Information we track for each message in the queue. More...
 
struct  UDP_ACK_Message
 UDP ACK Message-Packet header. More...
 
struct  GNUNET_ATS_SessionCompareContext
 Closure for session_cmp_it(). More...
 
struct  FindReceiveContext
 Closure for find_receive_context(). More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
 
#define UDP_SESSION_TIME_OUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
 After how much inactivity should a UDP session time out? More...
 
#define UDP_MAX_MESSAGES_IN_DEFRAG   3
 Number of messages we can defragment in parallel. More...
 
#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG   128
 We keep a defragmentation queue per sender address. More...
 

Typedefs

typedef void(* QueueContinuation) (void *cls, struct UDP_MessageWrapper *udpw, int result)
 Function called when a message is removed from the transmission queue. More...
 

Functions

static GNUNET_NETWORK_STRUCT_END void notify_session_monitor (struct Plugin *plugin, struct GNUNET_ATS_Session *session, enum GNUNET_TRANSPORT_SessionState state)
 If a session monitor is attached, notify it about the new session state. More...
 
static int send_session_info_iter (void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
 Return information about the given session to the monitor callback. More...
 
static void udp_plugin_setup_monitor (void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
 Begin monitoring sessions of a plugin. More...
 
static void free_session (struct GNUNET_ATS_Session *s)
 Function to free last resources associated with a session. More...
 
static unsigned int udp_query_keepalive_factor (void *cls)
 Function that is called to get the keepalive factor. More...
 
static enum GNUNET_NetworkType udp_plugin_get_network (void *cls, struct GNUNET_ATS_Session *session)
 Function obtain the network type for a session. More...
 
static enum GNUNET_NetworkType udp_plugin_get_network_for_address (void *cls, const struct GNUNET_HELLO_Address *address)
 Function obtain the network type for an address. More...
 
static void udp_plugin_select_v4 (void *cls)
 We have been notified that our readset has something to read. More...
 
static void udp_plugin_select_v6 (void *cls)
 We have been notified that our readset has something to read. More...
 
static void schedule_select_v4 (struct Plugin *plugin)
 (re)schedule IPv4-select tasks for this plugin. More...
 
static void schedule_select_v6 (struct Plugin *plugin)
 (re)schedule IPv6-select tasks for this plugin. More...
 
const char * udp_address_to_string (void *cls, const void *addr, size_t addrlen)
 Function called for a quick conversion of the binary address to a numeric address. More...
 
static int udp_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added)
 Function called to convert a string address to a binary address. More...
 
static void append_port (void *cls, const char *hostname)
 Append our port and forward the result. More...
 
static void udp_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
 Convert the transports address to a nice, human-readable format. More...
 
static int check_port (const struct Plugin *plugin, uint16_t in_port)
 Check if the given port is plausible (must be either our listen port or our advertised port). More...
 
static int udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
 Function that will be called to check if a binary address for this plugin is well-formed and corresponds to an address for THIS peer (as per our configuration). More...
 
static void udp_nat_port_map_callback (void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
 Our external IP address/port mapping has changed. More...
 
static int session_cmp_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Find a session with a matching address. More...
 
static struct GNUNET_ATS_Sessionudp_plugin_lookup_session (void *cls, const struct GNUNET_HELLO_Address *address)
 Locate an existing session the transport service is using to send data to another peer. More...
 
static void reschedule_session_timeout (struct GNUNET_ATS_Session *s)
 Increment session timeout due to activity. More...
 
static void udp_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session)
 Function that will be called whenever the transport service wants to notify the plugin that a session is still active and in use and therefore the session timeout for this session has to be updated. More...
 
static void dequeue (struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
 Remove the given message from the transmission queue and update all applicable statistics. More...
 
static void enqueue (struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
 Enqueue a message for transmission and update statistics. More...
 
static void fragmented_message_done (struct UDP_FragmentationContext *frag_ctx, int result)
 We have completed our (attempt) to transmit a message that had to be fragmented – either because we got an ACK saying that all fragments were received, or because of timeout / disconnect. More...
 
static void qc_fragment_sent (void *cls, struct UDP_MessageWrapper *udpw, int result)
 We are finished with a fragment in the message queue. More...
 
static void enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
 Function that is called with messages created by the fragmentation module. More...
 
static void qc_message_sent (void *cls, struct UDP_MessageWrapper *udpw, int result)
 We are finished with a message from the message queue. More...
 
static ssize_t udp_plugin_send (void *cls, struct GNUNET_ATS_Session *s, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
 Function that can be used by the transport service to transmit a message using the plugin. More...
 
static int find_receive_context (void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost)
 Scan the heap for a receive context with the given address. More...
 
static int udp_disconnect_session (void *cls, struct GNUNET_ATS_Session *s)
 Functions with this signature are called whenever we need to close a session due to a disconnect or failure to establish a connection. More...
 
static void read_process_ack (struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const union UdpAddress *udp_addr, socklen_t udp_addr_len)
 Handle a GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK message. More...
 
static int process_inbound_tokenized_messages (void *cls, const struct GNUNET_MessageHeader *hdr)
 Message tokenizer has broken up an incoming message. More...
 
static int disconnect_and_free_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Destroy a session, plugin is being unloaded. More...
 
static void udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
 Disconnect from a remote node. More...
 
static void session_timeout (void *cls)
 Session was idle, so disconnect it. More...
 
static struct GNUNET_ATS_Sessionudp_plugin_create_session (void *cls, const struct GNUNET_HELLO_Address *address, enum GNUNET_NetworkType network_type)
 Allocate a new session for the given endpoint address. More...
 
static struct GNUNET_ATS_Sessionudp_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address)
 Creates a new outbound session the transport service will use to send data to the peer. More...
 
static void process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
 We've received a UDP Message. More...
 
static void fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
 Process a defragmented message. More...
 
static void ack_message_sent (void *cls, struct UDP_MessageWrapper *udpw, int result)
 We finished sending an acknowledgement. More...
 
static void ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
 Transmit an acknowledgement. More...
 
static void read_process_fragment (struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
 We received a fragment, process it. More...
 
static void udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
 Read and process a message from the given socket. More...
 
static struct UDP_MessageWrapperremove_timeout_messages_and_select (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
 Removes messages from the transmission queue that have timed out, and then selects a message that should be transmitted next. More...
 
static void analyze_send_error (struct Plugin *plugin, const struct sockaddr *sa, socklen_t slen, int error)
 We failed to transmit a message via UDP. More...
 
static void udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
 It is time to try to transmit a UDP message. More...
 
static unsigned int setup_sockets (struct Plugin *plugin, const struct sockaddr_in6 *bind_v6, const struct sockaddr_in *bind_v4)
 Setup the UDP sockets (for IPv4 and IPv6) for the plugin. More...
 
void * libgnunet_plugin_transport_udp_init (void *cls)
 The exported method. More...
 
static int heap_cleanup_iterator (void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost)
 Function called on each entry in the defragmentation heap to clean it up. More...
 
void * libgnunet_plugin_transport_udp_done (void *cls)
 The exported method. More...
 

Detailed Description

Implementation of the UDP transport protocol.

Author
Christian Grothoff
Nathan Evans
Matthias Wachs

Definition in file plugin_transport_udp.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)

Definition at line 43 of file plugin_transport_udp.c.

◆ UDP_SESSION_TIME_OUT

#define UDP_SESSION_TIME_OUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)

After how much inactivity should a UDP session time out?

Definition at line 48 of file plugin_transport_udp.c.

◆ UDP_MAX_MESSAGES_IN_DEFRAG

#define UDP_MAX_MESSAGES_IN_DEFRAG   3

Number of messages we can defragment in parallel.

We only really defragment 1 message at a time, but if messages get re-ordered, we may want to keep knowledge about the previous message to avoid discarding the current message in favor of a single fragment of a previous message. 3 should be good since we don't expect massive message reorderings with UDP.

Definition at line 59 of file plugin_transport_udp.c.

◆ UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG

#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG   128

We keep a defragmentation queue per sender address.

How many sender addresses do we support at the same time? Memory consumption is roughly a factor of 32k * UDP_MAX_MESSAGES_IN_DEFRAG times this value. (So 128 corresponds to 12 MB and should suffice for connecting to roughly 128 peers via UDP).

Definition at line 68 of file plugin_transport_udp.c.

Typedef Documentation

◆ QueueContinuation

typedef void(* QueueContinuation) (void *cls, struct UDP_MessageWrapper *udpw, int result)

Function called when a message is removed from the transmission queue.

Parameters
clsclosure
udpwmessage wrapper finished
resultGNUNET_OK on success (message was sent) GNUNET_SYSERR if the target disconnected or we had a timeout or other trouble sending

Definition at line 387 of file plugin_transport_udp.c.

Function Documentation

◆ notify_session_monitor()

static GNUNET_NETWORK_STRUCT_END void notify_session_monitor ( struct Plugin plugin,
struct GNUNET_ATS_Session session,
enum GNUNET_TRANSPORT_SessionState  state 
)
static

If a session monitor is attached, notify it about the new session state.

Parameters
pluginour plugin
sessionsession that changed state
statenew state of the session

Definition at line 515 of file plugin_transport_udp.c.

518 {
519  struct GNUNET_TRANSPORT_SessionInfo info;
520 
521  if (NULL == plugin->sic)
522  return;
523  if (GNUNET_YES == session->in_destroy)
524  return; /* already destroyed, just RC>0 left-over actions */
525  memset (&info, 0, sizeof(info));
526  info.state = state;
527  info.is_inbound = GNUNET_SYSERR; /* hard to say */
528  info.num_msg_pending = session->msgs_in_queue;
529  info.num_bytes_pending = session->bytes_in_queue;
530  /* info.receive_delay remains zero as this is not supported by UDP
531  (cannot selectively not receive from 'some' peer while continuing
532  to receive from others) */
533  info.session_timeout = session->timeout;
534  info.address = session->address;
535  plugin->sic (plugin->sic_cls, session, &info);
536 }
struct Plugin * plugin
The process handle to the testbed service.
enum State state
current state of profiling
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
int in_destroy
Is this session about to be destroyed (sometimes we cannot destroy a session immediately as below us ...
struct GNUNET_TIME_Absolute timeout
When does this session time out.
struct GNUNET_HELLO_Address * address
Address.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
Information about a plugin's session.
void * sic_cls
Closure for sic.
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.

References GNUNET_TRANSPORT_SessionInfo::address, GNUNET_ATS_Session::address, GNUNET_ATS_Session::bytes_in_queue, GNUNET_SYSERR, GNUNET_YES, GNUNET_ATS_Session::in_destroy, GNUNET_TRANSPORT_SessionInfo::is_inbound, GNUNET_ATS_Session::msgs_in_queue, GNUNET_TRANSPORT_SessionInfo::num_bytes_pending, GNUNET_TRANSPORT_SessionInfo::num_msg_pending, plugin, GNUNET_TRANSPORT_SessionInfo::session_timeout, Plugin::sic, Plugin::sic_cls, GNUNET_TRANSPORT_SessionInfo::state, state, and GNUNET_ATS_Session::timeout.

Referenced by ack_proc(), fragmented_message_done(), process_udp_message(), remove_timeout_messages_and_select(), send_session_info_iter(), session_timeout(), udp_disconnect_session(), udp_plugin_create_session(), udp_plugin_send(), and udp_select_send().

Here is the caller graph for this function:

◆ send_session_info_iter()

static int send_session_info_iter ( void *  cls,
const struct GNUNET_PeerIdentity peer,
void *  value 
)
static

Return information about the given session to the monitor callback.

Parameters
clsthe struct Plugin with the monitor callback (sic)
peerpeer we send information about
valueour struct GNUNET_ATS_Session to send information about
Returns
GNUNET_OK (continue to iterate)

Definition at line 548 of file plugin_transport_udp.c.

551 {
552  struct Plugin *plugin = cls;
553  struct GNUNET_ATS_Session *session = value;
554 
557  return GNUNET_OK;
558 }
static char * value
Value of the record to add/remove.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_TRANSPORT_SS_INIT
The session was created (first call for each session object).
@ GNUNET_TRANSPORT_SS_UP
Session is fully UP.
static GNUNET_NETWORK_STRUCT_END void notify_session_monitor(struct Plugin *plugin, struct GNUNET_ATS_Session *session, enum GNUNET_TRANSPORT_SessionState state)
If a session monitor is attached, notify it about the new session state.
Session handle for connections.
Handle for a plugin.
Definition: block.c:38

References GNUNET_OK, GNUNET_TRANSPORT_SS_INIT, GNUNET_TRANSPORT_SS_UP, notify_session_monitor(), plugin, and value.

Referenced by udp_plugin_setup_monitor().

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

◆ udp_plugin_setup_monitor()

static void udp_plugin_setup_monitor ( void *  cls,
GNUNET_TRANSPORT_SessionInfoCallback  sic,
void *  sic_cls 
)
static

Begin monitoring sessions of a plugin.

There can only be one active monitor per plugin (i.e. if there are multiple monitors, the transport service needs to multiplex the generated events over all of them).

Parameters
clsclosure of the plugin
siccallback to invoke, NULL to disable monitor; plugin will being by iterating over all active sessions immediately and then enter monitor mode
sic_clsclosure for sic

Definition at line 574 of file plugin_transport_udp.c.

577 {
578  struct Plugin *plugin = cls;
579 
580  plugin->sic = sic;
582  if (NULL != sic)
583  {
586  plugin);
587  /* signal end of first iteration */
588  sic (sic_cls, NULL, NULL);
589  }
590 }
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
static int send_session_info_iter(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Return information about the given session to the monitor callback.
struct GNUNET_ATS_Session * sessions
List of open sessions (or peer map, or...)

References GNUNET_CONTAINER_multipeermap_iterate(), plugin, send_session_info_iter(), Plugin::sessions, Plugin::sic, and Plugin::sic_cls.

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ free_session()

static void free_session ( struct GNUNET_ATS_Session s)
static

Function to free last resources associated with a session.

Parameters
ssession to free

Definition at line 602 of file plugin_transport_udp.c.

603 {
604  if (NULL != s->address)
605  {
607  s->address = NULL;
608  }
609  if (NULL != s->frag_ctx)
610  {
612  GNUNET_free (s->frag_ctx);
613  s->frag_ctx = NULL;
614  }
615  if (NULL != s->mst)
616  {
617  GNUNET_MST_destroy (s->mst);
618  s->mst = NULL;
619  }
620  GNUNET_free (s);
621 }
void GNUNET_FRAGMENT_context_destroy(struct GNUNET_FRAGMENT_Context *fc, struct GNUNET_TIME_Relative *msg_delay, struct GNUNET_TIME_Relative *ack_delay)
Destroy the given fragmentation context (stop calling 'proc', free resources).
#define GNUNET_HELLO_address_free(addr)
Free an address.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:411
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer for inbound messages.
struct UDP_FragmentationContext * frag_ctx
Context for dealing with fragments.
struct GNUNET_FRAGMENT_Context * frag
Handle for fragmentation.

References GNUNET_ATS_Session::address, UDP_FragmentationContext::frag, GNUNET_ATS_Session::frag_ctx, GNUNET_FRAGMENT_context_destroy(), GNUNET_free, GNUNET_HELLO_address_free, GNUNET_MST_destroy(), and GNUNET_ATS_Session::mst.

Referenced by process_udp_message(), and udp_disconnect_session().

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

◆ udp_query_keepalive_factor()

static unsigned int udp_query_keepalive_factor ( void *  cls)
static

Function that is called to get the keepalive factor.

GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to calculate the interval between keepalive packets.

Parameters
clsclosure with the struct Plugin
Returns
keepalive factor

Definition at line 633 of file plugin_transport_udp.c.

634 {
635  return 15;
636 }

Referenced by libgnunet_plugin_transport_udp_init().

Here is the caller graph for this function:

◆ udp_plugin_get_network()

static enum GNUNET_NetworkType udp_plugin_get_network ( void *  cls,
struct GNUNET_ATS_Session session 
)
static

Function obtain the network type for a session.

Parameters
clsclosure (struct Plugin *)
sessionthe session
Returns
the network type

Definition at line 633 of file plugin_transport_udp.c.

648 {
649  return session->scope;
650 }
enum GNUNET_NetworkType scope
ATS network type.

Referenced by libgnunet_plugin_transport_udp_init().

Here is the caller graph for this function:

◆ udp_plugin_get_network_for_address()

static enum GNUNET_NetworkType udp_plugin_get_network_for_address ( void *  cls,
const struct GNUNET_HELLO_Address address 
)
static

Function obtain the network type for an address.

Parameters
clsclosure (struct Plugin *)
addressthe address
Returns
the network type

Definition at line 633 of file plugin_transport_udp.c.

663 {
664  struct Plugin *plugin = cls;
665  size_t addrlen;
666  struct sockaddr_in a4;
667  struct sockaddr_in6 a6;
668  const struct IPv4UdpAddress *u4;
669  const struct IPv6UdpAddress *u6;
670  const void *sb;
671  size_t sbs;
672 
673  addrlen = address->address_length;
674  if (addrlen == sizeof(struct IPv6UdpAddress))
675  {
676  GNUNET_assert (NULL != address->address); /* make static analysis happy */
677  u6 = address->address;
678  memset (&a6, 0, sizeof(a6));
679 #if HAVE_SOCKADDR_IN_SIN_LEN
680  a6.sin6_len = sizeof(a6);
681 #endif
682  a6.sin6_family = AF_INET6;
683  a6.sin6_port = u6->u6_port;
684  GNUNET_memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof(struct in6_addr));
685  sb = &a6;
686  sbs = sizeof(a6);
687  }
688  else if (addrlen == sizeof(struct IPv4UdpAddress))
689  {
690  GNUNET_assert (NULL != address->address); /* make static analysis happy */
691  u4 = address->address;
692  memset (&a4, 0, sizeof(a4));
693 #if HAVE_SOCKADDR_IN_SIN_LEN
694  a4.sin_len = sizeof(a4);
695 #endif
696  a4.sin_family = AF_INET;
697  a4.sin_port = u4->u4_port;
698  a4.sin_addr.s_addr = u4->ipv4_addr;
699  sb = &a4;
700  sbs = sizeof(a4);
701  }
702  else
703  {
704  GNUNET_break (0);
705  return GNUNET_NT_UNSPECIFIED;
706  }
707  return plugin->env->get_address_type (plugin->env->cls, sb, sbs);
708 }
static char * address
GNS address for this phone.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_NT_UNSPECIFIED
Category of last resort.
Definition: gnunet_nt_lib.h:40
void * cls
Closure to use for callbacks.
Network format for IPv4 addresses.
uint16_t u4_port
Port number, in network byte order.
uint32_t ipv4_addr
IPv4 address, in network byte order.
Network format for IPv6 addresses.
uint16_t u6_port
Port number, in network byte order.
struct in6_addr ipv6_addr
IPv6 address.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.

Referenced by libgnunet_plugin_transport_udp_init().

Here is the caller graph for this function:

◆ udp_plugin_select_v4()

static void udp_plugin_select_v4 ( void *  cls)
static

We have been notified that our readset has something to read.

We don't know which socket needs to be read, so we have to check each one Then reschedule this function to be called again once more is available.

Parameters
clsthe plugin handle

Definition at line 3321 of file plugin_transport_udp.c.

3322 {
3323  struct Plugin *plugin = cls;
3324  const struct GNUNET_SCHEDULER_TaskContext *tc;
3325 
3326  plugin->select_task_v4 = NULL;
3327  if (NULL == plugin->sockv4)
3328  return;
3330  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
3335 }
int GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Check whether a socket is part of the fd set.
Definition: network.c:1024
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:752
@ GNUNET_SCHEDULER_REASON_READ_READY
The reading socket is ready.
static void udp_select_read(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
Read and process a message from the given socket.
static void udp_select_send(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
It is time to try to transmit a UDP message.
static void schedule_select_v4(struct Plugin *plugin)
(re)schedule IPv4-select tasks for this plugin.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:423
Context information passed to each scheduler task.
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
struct GNUNET_SCHEDULER_Task * select_task_v4
ID of select task for IPv4.
struct GNUNET_NETWORK_Handle * sockv4
The read socket for IPv4.

References GNUNET_NETWORK_fdset_isset(), GNUNET_SCHEDULER_get_task_context(), GNUNET_SCHEDULER_REASON_READ_READY, plugin, GNUNET_SCHEDULER_TaskContext::read_ready, GNUNET_SCHEDULER_TaskContext::reason, schedule_select_v4(), Plugin::select_task_v4, Plugin::sockv4, tc, udp_select_read(), and udp_select_send().

Referenced by schedule_select_v4().

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

◆ udp_plugin_select_v6()

static void udp_plugin_select_v6 ( void *  cls)
static

We have been notified that our readset has something to read.

We don't know which socket needs to be read, so we have to check each one Then reschedule this function to be called again once more is available.

Parameters
clsthe plugin handle

Definition at line 3346 of file plugin_transport_udp.c.

3347 {
3348  struct Plugin *plugin = cls;
3349  const struct GNUNET_SCHEDULER_TaskContext *tc;
3350 
3351  plugin->select_task_v6 = NULL;
3352  if (NULL == plugin->sockv6)
3353  return;
3355  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
3358 
3361 }
static void schedule_select_v6(struct Plugin *plugin)
(re)schedule IPv6-select tasks for this plugin.
struct GNUNET_NETWORK_Handle * sockv6
The read socket for IPv6.
struct GNUNET_SCHEDULER_Task * select_task_v6
ID of select task for IPv6.

References GNUNET_NETWORK_fdset_isset(), GNUNET_SCHEDULER_get_task_context(), GNUNET_SCHEDULER_REASON_READ_READY, plugin, GNUNET_SCHEDULER_TaskContext::read_ready, GNUNET_SCHEDULER_TaskContext::reason, schedule_select_v6(), Plugin::select_task_v6, Plugin::sockv6, tc, udp_select_read(), and udp_select_send().

Referenced by schedule_select_v6().

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

◆ schedule_select_v4()

static void schedule_select_v4 ( struct Plugin plugin)
static

(re)schedule IPv4-select tasks for this plugin.

Parameters
pluginplugin to reschedule

Definition at line 741 of file plugin_transport_udp.c.

742 {
743  struct GNUNET_TIME_Relative min_delay;
745  struct UDP_MessageWrapper *udpw;
746  struct UDP_MessageWrapper *min_udpw;
747 
748  if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4))
749  {
750  /* Find a message ready to send:
751  * Flow delay from other peer is expired or not set (0) */
752  min_delay = GNUNET_TIME_UNIT_FOREVER_REL;
753  min_udpw = NULL;
754  for (udpw = plugin->ipv4_queue_head; NULL != udpw; udpw = udpw->next)
755  {
757  if (delay.rel_value_us < min_delay.rel_value_us)
758  {
759  min_delay = delay;
760  min_udpw = udpw;
761  }
762  }
763  if (NULL != plugin->select_task_v4)
765  if (NULL != min_udpw)
766  {
767  if (min_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
768  {
770  "Calculated flow delay for UDPv4 at %s for %s\n",
772  GNUNET_YES),
773  GNUNET_i2s (&min_udpw->session->target));
774  }
775  else
776  {
778  "Calculated flow delay for UDPv4 at %s for %s\n",
780  GNUNET_YES),
781  GNUNET_i2s (&min_udpw->session->target));
782  }
783  }
786  plugin->sockv4,
788  plugin);
789  }
790 }
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
#define GNUNET_log(kind,...)
#define GNUNET_CONSTANTS_LATENCY_WARN
After what amount of latency for a message do we print a warning?
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1517
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
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:232
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:557
static void udp_plugin_select_v4(void *cls)
We have been notified that our readset has something to read.
struct GNUNET_PeerIdentity target
To whom are we talking to.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
struct UDP_MessageWrapper * ipv4_queue_head
Head of messages in IPv4 queue.
int enable_ipv4
Is IPv4 enabled: GNUNET_YES or GNUNET_NO.
Information we track for each message in the queue.
struct GNUNET_ATS_Session * session
Session this message belongs to.
struct UDP_MessageWrapper * next
DLL of messages, next element.
struct GNUNET_TIME_Absolute transmission_time
Desired transmission time for this message, based on the flow limiting information we got from the ot...

References delay, Plugin::enable_ipv4, GNUNET_CONSTANTS_LATENCY_WARN, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_i2s(), GNUNET_log, GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_cancel(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, Plugin::ipv4_queue_head, UDP_MessageWrapper::next, plugin, GNUNET_TIME_Relative::rel_value_us, Plugin::select_task_v4, UDP_MessageWrapper::session, Plugin::sockv4, GNUNET_ATS_Session::target, UDP_MessageWrapper::transmission_time, and udp_plugin_select_v4().

Referenced by ack_proc(), enqueue_fragment(), setup_sockets(), udp_plugin_select_v4(), and udp_plugin_send().

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

◆ schedule_select_v6()

static void schedule_select_v6 ( struct Plugin plugin)
static

(re)schedule IPv6-select tasks for this plugin.

Parameters
pluginplugin to reschedule

Definition at line 799 of file plugin_transport_udp.c.

800 {
801  struct GNUNET_TIME_Relative min_delay;
803  struct UDP_MessageWrapper *udpw;
804  struct UDP_MessageWrapper *min_udpw;
805 
806  if ((GNUNET_YES == plugin->enable_ipv6) && (NULL != plugin->sockv6))
807  {
808  min_delay = GNUNET_TIME_UNIT_FOREVER_REL;
809  min_udpw = NULL;
810  for (udpw = plugin->ipv6_queue_head; NULL != udpw; udpw = udpw->next)
811  {
813  if (delay.rel_value_us < min_delay.rel_value_us)
814  {
815  min_delay = delay;
816  min_udpw = udpw;
817  }
818  }
819  if (NULL != plugin->select_task_v6)
821  if (NULL != min_udpw)
822  {
823  if (min_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
824  {
826  "Calculated flow delay for UDPv6 at %s for %s\n",
828  GNUNET_YES),
829  GNUNET_i2s (&min_udpw->session->target));
830  }
831  else
832  {
834  "Calculated flow delay for UDPv6 at %s for %s\n",
836  GNUNET_YES),
837  GNUNET_i2s (&min_udpw->session->target));
838  }
839  }
842  plugin->sockv6,
844  plugin);
845  }
846 }
static void udp_plugin_select_v6(void *cls)
We have been notified that our readset has something to read.
int enable_ipv6
Is IPv6 enabled: GNUNET_YES or GNUNET_NO.
struct UDP_MessageWrapper * ipv6_queue_head
Head of messages in IPv6 queue.

References delay, Plugin::enable_ipv6, GNUNET_CONSTANTS_LATENCY_WARN, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_i2s(), GNUNET_log, GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_cancel(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, Plugin::ipv6_queue_head, UDP_MessageWrapper::next, plugin, GNUNET_TIME_Relative::rel_value_us, Plugin::select_task_v6, UDP_MessageWrapper::session, Plugin::sockv6, GNUNET_ATS_Session::target, UDP_MessageWrapper::transmission_time, and udp_plugin_select_v6().

Referenced by ack_proc(), enqueue_fragment(), setup_sockets(), udp_plugin_select_v6(), and udp_plugin_send().

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

◆ udp_address_to_string()

const char* udp_address_to_string ( void *  cls,
const void *  addr,
size_t  addrlen 
)

Function called for a quick conversion of the binary address to a numeric address.

Note that the caller must not free the address and that the next call to this function is allowed to override the address again.

Parameters
clsclosure
addrbinary address (a union UdpAddress)
addrlenlength of the addr
Returns
string representing the same address

Definition at line 864 of file plugin_transport_udp.c.

865 {
866  static char rbuf[INET6_ADDRSTRLEN + 10];
867  char buf[INET6_ADDRSTRLEN];
868  const void *sb;
869  struct in_addr a4;
870  struct in6_addr a6;
871  const struct IPv4UdpAddress *t4;
872  const struct IPv6UdpAddress *t6;
873  int af;
874  uint16_t port;
875  uint32_t options;
876 
877  if (NULL == addr)
878  {
879  GNUNET_break_op (0);
880  return NULL;
881  }
882 
883  if (addrlen == sizeof(struct IPv6UdpAddress))
884  {
885  t6 = addr;
886  af = AF_INET6;
887  options = ntohl (t6->options);
888  port = ntohs (t6->u6_port);
889  a6 = t6->ipv6_addr;
890  sb = &a6;
891  }
892  else if (addrlen == sizeof(struct IPv4UdpAddress))
893  {
894  t4 = addr;
895  af = AF_INET;
896  options = ntohl (t4->options);
897  port = ntohs (t4->u4_port);
898  a4.s_addr = t4->ipv4_addr;
899  sb = &a4;
900  }
901  else
902  {
903  GNUNET_break_op (0);
904  return NULL;
905  }
906  inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
907  GNUNET_snprintf (rbuf,
908  sizeof(rbuf),
909  (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
910  PLUGIN_NAME,
911  options,
912  buf,
913  port);
914  return rbuf;
915 }
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
static uint16_t port
Port number.
Definition: gnunet-bcd.c:83
static struct GNUNET_SCHEDULER_Task * t4
Task for IPv4 socket.
static struct GNUNET_SCHEDULER_Task * t6
Task for IPv6 socket.
static char buf[2048]
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define PLUGIN_NAME

References buf, GNUNET_break_op, GNUNET_snprintf(), options, PLUGIN_NAME, port, t4, and t6.

Referenced by ack_proc(), broadcast_mst_cb(), libgnunet_plugin_transport_udp_init(), read_process_ack(), read_process_fragment(), udp_disconnect_session(), udp_plugin_create_session(), udp_plugin_lookup_session(), and udp_plugin_send().

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

◆ udp_string_to_address()

static int udp_string_to_address ( void *  cls,
const char *  addr,
uint16_t  addrlen,
void **  buf,
size_t *  added 
)
static

Function called to convert a string address to a binary address.

Parameters
clsclosure (struct Plugin *)
addrstring address
addrlenlength of the address
buflocation to store the buffer
addedlocation to store the number of bytes in the buffer. If the function returns GNUNET_SYSERR, its contents are undefined.
Returns
GNUNET_OK on success, GNUNET_SYSERR on failure

Definition at line 930 of file plugin_transport_udp.c.

935 {
936  struct sockaddr_storage socket_address;
937  char *address;
938  char *plugin;
939  char *optionstr;
940  uint32_t options;
941 
942  /* Format tcp.options.address:port */
943  address = NULL;
944  plugin = NULL;
945  optionstr = NULL;
946 
947  if ((NULL == addr) || (0 == addrlen))
948  {
949  GNUNET_break (0);
950  return GNUNET_SYSERR;
951  }
952  if ('\0' != addr[addrlen - 1])
953  {
954  GNUNET_break (0);
955  return GNUNET_SYSERR;
956  }
957  if (strlen (addr) != addrlen - 1)
958  {
959  GNUNET_break (0);
960  return GNUNET_SYSERR;
961  }
962  plugin = GNUNET_strdup (addr);
963  optionstr = strchr (plugin, '.');
964  if (NULL == optionstr)
965  {
966  GNUNET_break (0);
968  return GNUNET_SYSERR;
969  }
970  optionstr[0] = '\0';
971  optionstr++;
972  options = atol (optionstr);
973  address = strchr (optionstr, '.');
974  if (NULL == address)
975  {
976  GNUNET_break (0);
978  return GNUNET_SYSERR;
979  }
980  address[0] = '\0';
981  address++;
982 
983  if (GNUNET_OK !=
984  GNUNET_STRINGS_to_address_ip (address, strlen (address), &socket_address))
985  {
986  GNUNET_break (0);
988  return GNUNET_SYSERR;
989  }
991 
992  switch (socket_address.ss_family)
993  {
994  case AF_INET: {
995  struct IPv4UdpAddress *u4;
996  const struct sockaddr_in *in4 =
997  (const struct sockaddr_in *) &socket_address;
998 
999  u4 = GNUNET_new (struct IPv4UdpAddress);
1000  u4->options = htonl (options);
1001  u4->ipv4_addr = in4->sin_addr.s_addr;
1002  u4->u4_port = in4->sin_port;
1003  *buf = u4;
1004  *added = sizeof(struct IPv4UdpAddress);
1005  return GNUNET_OK;
1006  }
1007 
1008  case AF_INET6: {
1009  struct IPv6UdpAddress *u6;
1010  const struct sockaddr_in6 *in6 =
1011  (const struct sockaddr_in6 *) &socket_address;
1012 
1013  u6 = GNUNET_new (struct IPv6UdpAddress);
1014  u6->options = htonl (options);
1015  u6->ipv6_addr = in6->sin6_addr;
1016  u6->u6_port = in6->sin6_port;
1017  *buf = u6;
1018  *added = sizeof(struct IPv6UdpAddress);
1019  return GNUNET_OK;
1020  }
1021 
1022  default:
1023  GNUNET_break (0);
1024  return GNUNET_SYSERR;
1025  }
1026 }
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_to_address_ip(const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf)
Tries to convert addr string to an IP (v4 or v6) address.
Definition: strings.c:1121
uint32_t options
Optional options and flags for this address.
uint32_t options
Optional options and flags for this address.

References address, buf, GNUNET_break, GNUNET_free, GNUNET_new, GNUNET_OK, GNUNET_strdup, GNUNET_STRINGS_to_address_ip(), GNUNET_SYSERR, IPv4UdpAddress::ipv4_addr, IPv6UdpAddress::ipv6_addr, options, IPv4UdpAddress::options, IPv6UdpAddress::options, plugin, IPv4UdpAddress::u4_port, and IPv6UdpAddress::u6_port.

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ append_port()

static void append_port ( void *  cls,
const char *  hostname 
)
static

Append our port and forward the result.

Parameters
clsa struct PrettyPrinterContext *
hostnameresult from DNS resolver

Definition at line 1036 of file plugin_transport_udp.c.

1037 {
1038  struct PrettyPrinterContext *ppc = cls;
1039  struct Plugin *plugin = ppc->plugin;
1040  char *ret;
1041 
1042  if (NULL == hostname)
1043  {
1044  /* Final call, done */
1047  ppc);
1048  ppc->resolver_handle = NULL;
1049  ppc->asc (ppc->asc_cls, NULL, GNUNET_OK);
1050  GNUNET_free (ppc);
1051  return;
1052  }
1053  if (GNUNET_YES == ppc->ipv6)
1054  GNUNET_asprintf (&ret,
1055  "%s.%u.[%s]:%d",
1056  PLUGIN_NAME,
1057  ppc->options,
1058  hostname,
1059  ppc->port);
1060  else
1061  GNUNET_asprintf (&ret,
1062  "%s.%u.%s:%d",
1063  PLUGIN_NAME,
1064  ppc->options,
1065  hostname,
1066  ppc->port);
1067  ppc->asc (ppc->asc_cls, ret, GNUNET_OK);
1068  GNUNET_free (ret);
1069 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static char * hostname
Our hostname; we give this to all the peers we start.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
struct PrettyPrinterContext * ppc_dll_head
Running pretty printers: head.
struct PrettyPrinterContext * ppc_dll_tail
Running pretty printers: tail.
Closure for append_port().
struct GNUNET_RESOLVER_RequestHandle * resolver_handle
Resolver handle.
uint16_t port
Port to add after the IP address.
void * asc_cls
Clsoure for asc.
GNUNET_TRANSPORT_AddressStringCallback asc
Function to call with the result.
uint32_t options
Address options.

References PrettyPrinterContext::asc, PrettyPrinterContext::asc_cls, GNUNET_asprintf(), GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_OK, GNUNET_YES, hostname, PrettyPrinterContext::ipv6, PrettyPrinterContext::options, plugin, PrettyPrinterContext::plugin, PLUGIN_NAME, PrettyPrinterContext::port, Plugin::ppc_dll_head, Plugin::ppc_dll_tail, PrettyPrinterContext::resolver_handle, and ret.

Referenced by udp_plugin_address_pretty_printer().

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

◆ udp_plugin_address_pretty_printer()

static void udp_plugin_address_pretty_printer ( void *  cls,
const char *  type,
const void *  addr,
size_t  addrlen,
int  numeric,
struct GNUNET_TIME_Relative  timeout,
GNUNET_TRANSPORT_AddressStringCallback  asc,
void *  asc_cls 
)
static

Convert the transports address to a nice, human-readable format.

Parameters
clsclosure with the struct Plugin *
typename of the transport that generated the address
addrone of the addresses of the host, NULL for the last address the specific address format depends on the transport; a union UdpAddress
addrlenlength of the address
numericshould (IP) addresses be displayed in numeric form?
timeoutafter how long should we give up?
ascfunction to call on each string
asc_clsclosure for asc

Definition at line 1087 of file plugin_transport_udp.c.

1095 {
1096  struct Plugin *plugin = cls;
1097  struct PrettyPrinterContext *ppc;
1098  const struct sockaddr *sb;
1099  size_t sbs;
1100  struct sockaddr_in a4;
1101  struct sockaddr_in6 a6;
1102  const struct IPv4UdpAddress *u4;
1103  const struct IPv6UdpAddress *u6;
1104  uint16_t port;
1105  uint32_t options;
1106 
1107  if (addrlen == sizeof(struct IPv6UdpAddress))
1108  {
1109  u6 = addr;
1110  memset (&a6, 0, sizeof(a6));
1111  a6.sin6_family = AF_INET6;
1112 #if HAVE_SOCKADDR_IN_SIN_LEN
1113  a6.sin6_len = sizeof(a6);
1114 #endif
1115  a6.sin6_port = u6->u6_port;
1116  a6.sin6_addr = u6->ipv6_addr;
1117  port = ntohs (u6->u6_port);
1118  options = ntohl (u6->options);
1119  sb = (const struct sockaddr *) &a6;
1120  sbs = sizeof(a6);
1121  }
1122  else if (addrlen == sizeof(struct IPv4UdpAddress))
1123  {
1124  u4 = addr;
1125  memset (&a4, 0, sizeof(a4));
1126  a4.sin_family = AF_INET;
1127 #if HAVE_SOCKADDR_IN_SIN_LEN
1128  a4.sin_len = sizeof(a4);
1129 #endif
1130  a4.sin_port = u4->u4_port;
1131  a4.sin_addr.s_addr = u4->ipv4_addr;
1132  port = ntohs (u4->u4_port);
1133  options = ntohl (u4->options);
1134  sb = (const struct sockaddr *) &a4;
1135  sbs = sizeof(a4);
1136  }
1137  else
1138  {
1139  /* invalid address */
1140  GNUNET_break_op (0);
1141  asc (asc_cls, NULL, GNUNET_SYSERR);
1142  asc (asc_cls, NULL, GNUNET_OK);
1143  return;
1144  }
1145  ppc = GNUNET_new (struct PrettyPrinterContext);
1146  ppc->plugin = plugin;
1147  ppc->asc = asc;
1148  ppc->asc_cls = asc_cls;
1149  ppc->port = port;
1150  ppc->options = options;
1151  if (addrlen == sizeof(struct IPv6UdpAddress))
1152  ppc->ipv6 = GNUNET_YES;
1153  else
1154  ppc->ipv6 = GNUNET_NO;
1157  sbs,
1158  ! numeric,
1159  timeout,
1160  &append_port,
1161  ppc);
1162 }
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static int numeric
Option -n.
@ GNUNET_NO
Definition: gnunet_common.h:94
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get(const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls)
Perform a reverse DNS lookup.
static void append_port(void *cls, const char *hostname)
Append our port and forward the result.

References append_port(), PrettyPrinterContext::asc, PrettyPrinterContext::asc_cls, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_RESOLVER_hostname_get(), GNUNET_SYSERR, GNUNET_YES, IPv4UdpAddress::ipv4_addr, PrettyPrinterContext::ipv6, IPv6UdpAddress::ipv6_addr, numeric, options, PrettyPrinterContext::options, IPv4UdpAddress::options, IPv6UdpAddress::options, plugin, PrettyPrinterContext::plugin, port, PrettyPrinterContext::port, Plugin::ppc_dll_head, Plugin::ppc_dll_tail, PrettyPrinterContext::resolver_handle, timeout, IPv4UdpAddress::u4_port, and IPv6UdpAddress::u6_port.

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ check_port()

static int check_port ( const struct Plugin plugin,
uint16_t  in_port 
)
static

Check if the given port is plausible (must be either our listen port or our advertised port).

If it is neither, we return GNUNET_SYSERR.

Parameters
pluginglobal variables
in_portport number to check
Returns
GNUNET_OK if port is either our open or advertised port

Definition at line 1175 of file plugin_transport_udp.c.

1176 {
1177  if ((plugin->port == in_port) || (plugin->aport == in_port))
1178  return GNUNET_OK;
1179  return GNUNET_SYSERR;
1180 }
uint16_t aport
Port we advertise on.
char * port
Port we bind to.

References Plugin::aport, GNUNET_OK, GNUNET_SYSERR, plugin, and Plugin::port.

Referenced by udp_plugin_check_address().

Here is the caller graph for this function:

◆ udp_plugin_check_address()

static int udp_plugin_check_address ( void *  cls,
const void *  addr,
size_t  addrlen 
)
static

Function that will be called to check if a binary address for this plugin is well-formed and corresponds to an address for THIS peer (as per our configuration).

Naturally, if absolutely necessary, plugins can be a bit conservative in their answer, but in general plugins should make sure that the address does not redirect traffic to a 3rd party that might try to man-in-the-middle our traffic.

Parameters
clsclosure, should be our handle to the Plugin
addrpointer to a union UdpAddress
addrlenlength of addr
Returns
GNUNET_OK if this is a plausible address for this peer and transport, GNUNET_SYSERR if not

Definition at line 1199 of file plugin_transport_udp.c.

1200 {
1201  struct Plugin *plugin = cls;
1202  const struct IPv4UdpAddress *v4;
1203  const struct IPv6UdpAddress *v6;
1204 
1205  if (sizeof(struct IPv4UdpAddress) == addrlen)
1206  {
1207  struct sockaddr_in s4;
1208 
1209  v4 = (const struct IPv4UdpAddress *) addr;
1210  if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port)))
1211  return GNUNET_SYSERR;
1212  memset (&s4, 0, sizeof(s4));
1213  s4.sin_family = AF_INET;
1214 #if HAVE_SOCKADDR_IN_SIN_LEN
1215  s4.sin_len = sizeof(s4);
1216 #endif
1217  s4.sin_port = v4->u4_port;
1218  s4.sin_addr.s_addr = v4->ipv4_addr;
1219 
1220  if (GNUNET_OK !=
1221  GNUNET_NAT_test_address (plugin->nat, &s4, sizeof(struct sockaddr_in)))
1222  return GNUNET_SYSERR;
1223  }
1224  else if (sizeof(struct IPv6UdpAddress) == addrlen)
1225  {
1226  struct sockaddr_in6 s6;
1227 
1228  v6 = (const struct IPv6UdpAddress *) addr;
1229  if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1230  return GNUNET_OK; /* plausible, if unlikely... */
1231  memset (&s6, 0, sizeof(s6));
1232  s6.sin6_family = AF_INET6;
1233 #if HAVE_SOCKADDR_IN_SIN_LEN
1234  s6.sin6_len = sizeof(s6);
1235 #endif
1236  s6.sin6_port = v6->u6_port;
1237  s6.sin6_addr = v6->ipv6_addr;
1238 
1240  &s6,
1241  sizeof(struct sockaddr_in6)))
1242  return GNUNET_SYSERR;
1243  }
1244  else
1245  {
1246  GNUNET_break_op (0);
1247  return GNUNET_SYSERR;
1248  }
1249  return GNUNET_OK;
1250 }
int GNUNET_NAT_test_address(struct GNUNET_NAT_Handle *nh, const void *addr, socklen_t addrlen)
Test if the given address is (currently) a plausible IP address for this peer.
Definition: nat_api.c:625
static int check_port(const struct Plugin *plugin, uint16_t in_port)
Check if the given port is plausible (must be either our listen port or our advertised port).
struct GNUNET_NAT_Handle * nat
NAT handle & address management.

References check_port(), GNUNET_break_op, GNUNET_NAT_test_address(), GNUNET_OK, GNUNET_SYSERR, Plugin::nat, and plugin.

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ udp_nat_port_map_callback()

static void udp_nat_port_map_callback ( void *  cls,
void **  app_ctx,
int  add_remove,
enum GNUNET_NAT_AddressClass  ac,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Our external IP address/port mapping has changed.

Parameters
clsclosure, the struct Plugin
app_ctx[in,out]location where the app can store stuff on add and retrieve it on remove
add_removeGNUNET_YES to mean the new public IP address, GNUNET_NO to mean the previous (now invalid) one
acaddress class the address belongs to
addreither the previous or the new public IP address
addrlenactual length of the addr

Definition at line 1266 of file plugin_transport_udp.c.

1272 {
1273  struct Plugin *plugin = cls;
1274  struct GNUNET_HELLO_Address *address;
1275  struct IPv4UdpAddress u4;
1276  struct IPv6UdpAddress u6;
1277  void *arg;
1278  size_t args;
1279 
1280  (void) app_ctx;
1282  (GNUNET_YES == add_remove) ? "NAT notification to add address `%s'\n"
1283  : "NAT notification to remove address `%s'\n",
1284  GNUNET_a2s (addr, addrlen));
1285  /* convert 'address' to our internal format */
1286  switch (addr->sa_family)
1287  {
1288  case AF_INET: {
1289  const struct sockaddr_in *i4;
1290 
1291  GNUNET_assert (sizeof(struct sockaddr_in) == addrlen);
1292  i4 = (const struct sockaddr_in *) addr;
1293  if (0 == ntohs (i4->sin_port))
1294  return; /* Port = 0 means unmapped, ignore these for UDP. */
1295  memset (&u4, 0, sizeof(u4));
1296  u4.options = htonl (plugin->myoptions);
1297  u4.ipv4_addr = i4->sin_addr.s_addr;
1298  u4.u4_port = i4->sin_port;
1299  arg = &u4;
1300  args = sizeof(struct IPv4UdpAddress);
1301  break;
1302  }
1303 
1304  case AF_INET6: {
1305  const struct sockaddr_in6 *i6;
1306 
1307  GNUNET_assert (sizeof(struct sockaddr_in6) == addrlen);
1308  i6 = (const struct sockaddr_in6 *) addr;
1309  if (0 == ntohs (i6->sin6_port))
1310  return; /* Port = 0 means unmapped, ignore these for UDP. */
1311  memset (&u6, 0, sizeof(u6));
1312  u6.options = htonl (plugin->myoptions);
1313  u6.ipv6_addr = i6->sin6_addr;
1314  u6.u6_port = i6->sin6_port;
1315  arg = &u6;
1316  args = sizeof(struct IPv6UdpAddress);
1317  break;
1318  }
1319 
1320  default:
1321  GNUNET_break (0);
1322  return;
1323  }
1324  /* modify our published address list */
1325  /* TODO: use 'ac' here in the future... */
1327  PLUGIN_NAME,
1328  arg,
1329  args,
1331  plugin->env->notify_address (plugin->env->cls, add_remove, address);
1333 }
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_allocate(const struct GNUNET_PeerIdentity *peer, const char *transport_name, const void *address, size_t address_length, enum GNUNET_HELLO_AddressInfo local_info)
Allocate an address struct.
Definition: address.c:73
@ GNUNET_HELLO_ADDRESS_INFO_NONE
No additional information.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
#define LOG(kind,...)
An address for communicating with a peer.
uint32_t myoptions
Address options.

References address, find_typedefs::arg, consensus-simulation::args, GNUNET_DATACACHE_PluginEnvironment::cls, Plugin::env, GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELLO_address_allocate(), GNUNET_HELLO_address_free, GNUNET_HELLO_ADDRESS_INFO_NONE, GNUNET_YES, IPv4UdpAddress::ipv4_addr, IPv6UdpAddress::ipv6_addr, LOG, Plugin::myoptions, IPv4UdpAddress::options, IPv6UdpAddress::options, plugin, PLUGIN_NAME, IPv4UdpAddress::u4_port, and IPv6UdpAddress::u6_port.

Referenced by setup_sockets().

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

◆ session_cmp_it()

static int session_cmp_it ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Find a session with a matching address.

Parameters
clsthe struct GNUNET_ATS_SessionCompareContext *
keypeer identity (unused)
valuethe struct GNUNET_ATS_Session *
Returns
GNUNET_NO if we found the session, GNUNET_OK if not

Definition at line 1365 of file plugin_transport_udp.c.

1366 {
1367  struct GNUNET_ATS_SessionCompareContext *cctx = cls;
1368  struct GNUNET_ATS_Session *s = value;
1369 
1370  if (0 == GNUNET_HELLO_address_cmp (s->address, cctx->address))
1371  {
1373  cctx->res = s;
1374  return GNUNET_NO;
1375  }
1376  return GNUNET_OK;
1377 }
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
Closure for session_cmp_it().
const struct GNUNET_HELLO_Address * address
Address we are looking for.
struct GNUNET_ATS_Session * res
Set to session matching the address.

References GNUNET_ATS_Session::address, GNUNET_ATS_SessionCompareContext::address, GNUNET_assert, GNUNET_HELLO_address_cmp(), GNUNET_NO, GNUNET_OK, GNUNET_ATS_Session::in_destroy, GNUNET_ATS_SessionCompareContext::res, and value.

Referenced by udp_plugin_lookup_session().

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

◆ udp_plugin_lookup_session()

static struct GNUNET_ATS_Session* udp_plugin_lookup_session ( void *  cls,
const struct GNUNET_HELLO_Address address 
)
static

Locate an existing session the transport service is using to send data to another peer.

Performs some basic sanity checks on the address and then tries to locate a matching session.

Parameters
clsthe plugin
addressthe address we should locate the session by
Returns
the session if it exists, or NULL if it is not found

Definition at line 1390 of file plugin_transport_udp.c.

1392 {
1393  struct Plugin *plugin = cls;
1394  const struct IPv6UdpAddress *udp_a6;
1395  const struct IPv4UdpAddress *udp_a4;
1397 
1398  if (NULL == address->address)
1399  {
1400  GNUNET_break (0);
1401  return NULL;
1402  }
1403  if (sizeof(struct IPv4UdpAddress) == address->address_length)
1404  {
1405  if (NULL == plugin->sockv4)
1406  return NULL;
1407  udp_a4 = (const struct IPv4UdpAddress *) address->address;
1408  if (0 == udp_a4->u4_port)
1409  {
1410  GNUNET_break (0);
1411  return NULL;
1412  }
1413  }
1414  else if (sizeof(struct IPv6UdpAddress) == address->address_length)
1415  {
1416  if (NULL == plugin->sockv6)
1417  return NULL;
1418  udp_a6 = (const struct IPv6UdpAddress *) address->address;
1419  if (0 == udp_a6->u6_port)
1420  {
1421  GNUNET_break (0);
1422  return NULL;
1423  }
1424  }
1425  else
1426  {
1427  GNUNET_break (0);
1428  return NULL;
1429  }
1430 
1431  /* check if session already exists */
1432  cctx.address = address;
1433  cctx.res = NULL;
1435  "Looking for existing session for peer `%s' with address `%s'\n",
1436  GNUNET_i2s (&address->peer),
1438  address->address,
1439  address->address_length));
1441  &address->peer,
1442  &session_cmp_it,
1443  &cctx);
1444  if (NULL == cctx.res)
1445  return NULL;
1446  LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res);
1447  return cctx.res;
1448 }
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
const char * udp_address_to_string(void *cls, const void *addr, size_t addrlen)
Function called for a quick conversion of the binary address to a numeric address.
static int session_cmp_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Find a session with a matching address.

References address, GNUNET_ATS_SessionCompareContext::address, GNUNET_break, GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), LOG, plugin, GNUNET_ATS_SessionCompareContext::res, session_cmp_it(), Plugin::sessions, Plugin::sockv4, Plugin::sockv6, IPv4UdpAddress::u4_port, IPv6UdpAddress::u6_port, and udp_address_to_string().

Referenced by ack_proc(), process_udp_message(), read_process_ack(), and udp_plugin_get_session().

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

◆ reschedule_session_timeout()

static void reschedule_session_timeout ( struct GNUNET_ATS_Session s)
static

Increment session timeout due to activity.

Parameters
ssession to reschedule timeout activity for

Definition at line 1460 of file plugin_transport_udp.c.

1461 {
1462  if (GNUNET_YES == s->in_destroy)
1463  return;
1464  GNUNET_assert (NULL != s->timeout_task);
1466 }
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:181
#define UDP_SESSION_TIME_OUT
After how much inactivity should a UDP session time out?
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.

References GNUNET_assert, GNUNET_TIME_relative_to_absolute(), GNUNET_YES, GNUNET_ATS_Session::in_destroy, GNUNET_ATS_Session::timeout, GNUNET_ATS_Session::timeout_task, and UDP_SESSION_TIME_OUT.

Referenced by process_inbound_tokenized_messages(), and udp_plugin_update_session_timeout().

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

◆ udp_plugin_update_session_timeout()

static void udp_plugin_update_session_timeout ( void *  cls,
const struct GNUNET_PeerIdentity peer,
struct GNUNET_ATS_Session session 
)
static

Function that will be called whenever the transport service wants to notify the plugin that a session is still active and in use and therefore the session timeout for this session has to be updated.

Parameters
clsclosure with the struct Plugin
peerwhich peer was the session for
sessionwhich session is being updated

Definition at line 1479 of file plugin_transport_udp.c.

1482 {
1483  struct Plugin *plugin = cls;
1484 
1485  if (GNUNET_YES !=
1487  peer,
1488  session))
1489  {
1490  GNUNET_break (0);
1491  return;
1492  }
1493  /* Reschedule session timeout */
1494  reschedule_session_timeout (session);
1495 }
int GNUNET_CONTAINER_multipeermap_contains_value(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Check if the map contains the given value under the given key.
static void reschedule_session_timeout(struct GNUNET_ATS_Session *s)
Increment session timeout due to activity.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.

References GNUNET_break, GNUNET_CONTAINER_multipeermap_contains_value(), GNUNET_YES, peer, plugin, reschedule_session_timeout(), and Plugin::sessions.

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ dequeue()

static void dequeue ( struct Plugin plugin,
struct UDP_MessageWrapper udpw 
)
static

Remove the given message from the transmission queue and update all applicable statistics.

Parameters
pluginthe UDP plugin
udpwmessage wrapper to dequeue

Definition at line 1509 of file plugin_transport_udp.c.

1510 {
1511  struct GNUNET_ATS_Session *session = udpw->session;
1512 
1513  if (plugin->bytes_in_buffer < udpw->msg_size)
1514  {
1515  GNUNET_break (0);
1516  }
1517  else
1518  {
1520  "# UDP, total bytes in send buffers",
1521  -(long long) udpw->msg_size,
1522  GNUNET_NO);
1523  plugin->bytes_in_buffer -= udpw->msg_size;
1524  }
1526  "# UDP, total messages in send buffers",
1527  -1,
1528  GNUNET_NO);
1529  if (sizeof(struct IPv4UdpAddress) == udpw->session->address->address_length)
1530  {
1533  udpw);
1534  }
1535  else if (sizeof(struct IPv6UdpAddress) ==
1536  udpw->session->address->address_length)
1537  {
1540  udpw);
1541  }
1542  else
1543  {
1544  GNUNET_break (0);
1545  return;
1546  }
1547  GNUNET_assert (session->msgs_in_queue > 0);
1548  session->msgs_in_queue--;
1549  GNUNET_assert (session->bytes_in_queue >= udpw->msg_size);
1550  session->bytes_in_queue -= udpw->msg_size;
1551 }
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
size_t address_length
Number of bytes in address.
struct UDP_MessageWrapper * ipv4_queue_tail
Tail of messages in IPv4 queue.
struct UDP_MessageWrapper * ipv6_queue_tail
Tail of messages in IPv6 queue.
int64_t bytes_in_buffer
Bytes currently in buffer.
size_t msg_size
Size of UDP message to send, including UDP-specific overhead.

References GNUNET_ATS_Session::address, GNUNET_HELLO_Address::address_length, Plugin::bytes_in_buffer, GNUNET_ATS_Session::bytes_in_queue, Plugin::env, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_NO, GNUNET_STATISTICS_update(), Plugin::ipv4_queue_head, Plugin::ipv4_queue_tail, Plugin::ipv6_queue_head, Plugin::ipv6_queue_tail, UDP_MessageWrapper::msg_size, GNUNET_ATS_Session::msgs_in_queue, plugin, and UDP_MessageWrapper::session.

Referenced by fragmented_message_done(), remove_timeout_messages_and_select(), udp_disconnect_session(), and udp_select_send().

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

◆ enqueue()

static void enqueue ( struct Plugin plugin,
struct UDP_MessageWrapper udpw 
)
static

Enqueue a message for transmission and update statistics.

Parameters
pluginthe UDP plugin
udpwmessage wrapper to queue

Definition at line 1561 of file plugin_transport_udp.c.

1562 {
1563  struct GNUNET_ATS_Session *session = udpw->session;
1564 
1565  if (GNUNET_YES == session->in_destroy)
1566  {
1567  GNUNET_break (0);
1568  GNUNET_free (udpw);
1569  return;
1570  }
1571  if (plugin->bytes_in_buffer > INT64_MAX - udpw->msg_size)
1572  {
1573  GNUNET_break (0);
1574  }
1575  else
1576  {
1578  "# UDP, total bytes in send buffers",
1579  udpw->msg_size,
1580  GNUNET_NO);
1581  plugin->bytes_in_buffer += udpw->msg_size;
1582  }
1584  "# UDP, total messages in send buffers",
1585  1,
1586  GNUNET_NO);
1587  if (sizeof(struct IPv4UdpAddress) == udpw->session->address->address_length)
1588  {
1591  udpw);
1592  }
1593  else if (sizeof(struct IPv6UdpAddress) ==
1594  udpw->session->address->address_length)
1595  {
1598  udpw);
1599  }
1600  else
1601  {
1602  GNUNET_break (0);
1603  udpw->cont (udpw->cont_cls,
1604  &session->target,
1605  GNUNET_SYSERR,
1606  udpw->msg_size,
1607  0);
1608  GNUNET_free (udpw);
1609  return;
1610  }
1611  session->msgs_in_queue++;
1612  session->bytes_in_queue += udpw->msg_size;
1613 }
void * cont_cls
Closure for cont.
GNUNET_TRANSPORT_TransmitContinuation cont
External continuation to call upon completion of the transmission, NULL if this queue entry is not fo...

References GNUNET_ATS_Session::address, GNUNET_HELLO_Address::address_length, Plugin::bytes_in_buffer, GNUNET_ATS_Session::bytes_in_queue, UDP_MessageWrapper::cont, UDP_MessageWrapper::cont_cls, Plugin::env, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_free, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_YES, GNUNET_ATS_Session::in_destroy, Plugin::ipv4_queue_head, Plugin::ipv4_queue_tail, Plugin::ipv6_queue_head, Plugin::ipv6_queue_tail, UDP_MessageWrapper::msg_size, GNUNET_ATS_Session::msgs_in_queue, plugin, UDP_MessageWrapper::session, and GNUNET_ATS_Session::target.

Referenced by ack_proc(), enqueue_fragment(), and udp_plugin_send().

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

◆ fragmented_message_done()

static void fragmented_message_done ( struct UDP_FragmentationContext frag_ctx,
int  result 
)
static

We have completed our (attempt) to transmit a message that had to be fragmented – either because we got an ACK saying that all fragments were received, or because of timeout / disconnect.

Clean up our state.

Parameters
frag_ctxfragmentation context to clean up
resultGNUNET_OK if we succeeded (got ACK), GNUNET_SYSERR if the transmission failed

Definition at line 1627 of file plugin_transport_udp.c.

1628 {
1629  struct Plugin *plugin = frag_ctx->plugin;
1630  struct GNUNET_ATS_Session *s = frag_ctx->session;
1631  struct UDP_MessageWrapper *udpw;
1632  struct UDP_MessageWrapper *tmp;
1633  size_t overhead;
1634  struct GNUNET_TIME_Relative delay;
1635 
1637  "%p: Fragmented message removed with result %s\n",
1638  frag_ctx,
1639  (result == GNUNET_SYSERR) ? "FAIL" : "SUCCESS");
1640  /* Call continuation for fragmented message */
1641  if (frag_ctx->on_wire_size >= frag_ctx->payload_size)
1642  overhead = frag_ctx->on_wire_size - frag_ctx->payload_size;
1643  else
1644  overhead = frag_ctx->on_wire_size;
1647  {
1649  "Fragmented message acknowledged after %s (expected at %s)\n",
1652  }
1653  else
1654  {
1656  "Fragmented message acknowledged after %s (expected at %s)\n",
1659  }
1660 
1661  if (NULL != frag_ctx->cont)
1662  frag_ctx->cont (frag_ctx->cont_cls,
1663  &s->target,
1664  result,
1665  s->frag_ctx->payload_size,
1666  frag_ctx->on_wire_size);
1668  "# UDP, fragmented messages active",
1669  -1,
1670  GNUNET_NO);
1671 
1672  if (GNUNET_OK == result)
1673  {
1675  "# UDP, fragmented msgs, messages, sent, success",
1676  1,
1677  GNUNET_NO);
1679  "# UDP, fragmented msgs, bytes payload, sent, success",
1680  s->frag_ctx->payload_size,
1681  GNUNET_NO);
1683  plugin->env->stats,
1684  "# UDP, fragmented msgs, bytes overhead, sent, success",
1685  overhead,
1686  GNUNET_NO);
1688  "# UDP, total, bytes overhead, sent",
1689  overhead,
1690  GNUNET_NO);
1692  "# UDP, total, bytes payload, sent",
1693  s->frag_ctx->payload_size,
1694  GNUNET_NO);
1695  }
1696  else
1697  {
1699  "# UDP, fragmented msgs, messages, sent, failure",
1700  1,
1701  GNUNET_NO);
1703  "# UDP, fragmented msgs, bytes payload, sent, failure",
1704  s->frag_ctx->payload_size,
1705  GNUNET_NO);
1707  "# UDP, fragmented msgs, bytes payload, sent, failure",
1708  overhead,
1709  GNUNET_NO);
1711  "# UDP, fragmented msgs, bytes payload, sent, failure",
1712  overhead,
1713  GNUNET_NO);
1714  }
1715 
1716  /* Remove remaining fragments from queue, no need to transmit those
1717  any longer. */
1718  if (s->address->address_length == sizeof(struct IPv6UdpAddress))
1719  {
1720  udpw = plugin->ipv6_queue_head;
1721  while (NULL != udpw)
1722  {
1723  tmp = udpw->next;
1724  if ((udpw->frag_ctx != NULL) && (udpw->frag_ctx == frag_ctx))
1725  {
1726  dequeue (plugin, udpw);
1727  GNUNET_free (udpw);
1728  }
1729  udpw = tmp;
1730  }
1731  }
1732  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
1733  {
1734  udpw = plugin->ipv4_queue_head;
1735  while (NULL != udpw)
1736  {
1737  tmp = udpw->next;
1738  if ((NULL != udpw->frag_ctx) && (udpw->frag_ctx == frag_ctx))
1739  {
1740  dequeue (plugin, udpw);
1741  GNUNET_free (udpw);
1742  }
1743  udpw = tmp;
1744  }
1745  }
1750  s->frag_ctx = NULL;
1751  GNUNET_free (frag_ctx);
1752 }
static int result
Global testing status.
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:263
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:604
@ GNUNET_TRANSPORT_SS_UPDATE
This is just an update about the session, the state did not change.
static void dequeue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
Remove the given message from the transmission queue and update all applicable statistics.
struct Plugin * plugin
Pointer to the global plugin struct.
struct GNUNET_TIME_Relative last_expected_msg_delay
desired delay between UDP messages
struct GNUNET_TIME_Relative last_expected_ack_delay
expected delay for ACKs
struct GNUNET_TIME_Absolute next_frag_time
Transmission time for the next fragment.
GNUNET_TRANSPORT_TransmitContinuation cont
Function to call upon completion of the transmission.
struct GNUNET_TIME_Absolute start_time
Start time.
struct Plugin * plugin
The plugin.
size_t payload_size
Payload size of original unfragmented message.
void * cont_cls
Closure for cont.
struct GNUNET_ATS_Session * session
The session this fragmentation context belongs to.
size_t on_wire_size
Bytes used to send all fragments on wire including UDP overhead.
struct UDP_FragmentationContext * frag_ctx
Fragmentation context.

References GNUNET_ATS_Session::address, GNUNET_HELLO_Address::address_length, UDP_FragmentationContext::cont, UDP_FragmentationContext::cont_cls, delay, dequeue(), Plugin::env, UDP_FragmentationContext::frag, GNUNET_ATS_Session::frag_ctx, UDP_MessageWrapper::frag_ctx, GNUNET_CONSTANTS_LATENCY_WARN, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_FRAGMENT_context_destroy(), GNUNET_free, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_duration(), GNUNET_TRANSPORT_SS_UPDATE, GNUNET_YES, Plugin::ipv4_queue_head, Plugin::ipv6_queue_head, GNUNET_ATS_Session::last_expected_ack_delay, GNUNET_ATS_Session::last_expected_msg_delay, LOG, UDP_MessageWrapper::next, UDP_FragmentationContext::next_frag_time, notify_session_monitor(), UDP_FragmentationContext::on_wire_size, UDP_FragmentationContext::payload_size, plugin, GNUNET_ATS_Session::plugin, UDP_FragmentationContext::plugin, GNUNET_TIME_Relative::rel_value_us, result, UDP_FragmentationContext::session, UDP_FragmentationContext::start_time, and GNUNET_ATS_Session::target.

Referenced by qc_fragment_sent(), read_process_ack(), and udp_disconnect_session().

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

◆ qc_fragment_sent()

static void qc_fragment_sent ( void *  cls,
struct UDP_MessageWrapper udpw,
int  result 
)
static

We are finished with a fragment in the message queue.

Notify the continuation and update statistics.

Parameters
clsthe struct Plugin *
udpwthe queue entry
resultGNUNET_OK on success, GNUNET_SYSERR on failure

Definition at line 1764 of file plugin_transport_udp.c.

1765 {
1766  struct Plugin *plugin = cls;
1767 
1768  GNUNET_assert (NULL != udpw->frag_ctx);
1769  if (GNUNET_OK == result)
1770  {
1772  "Fragment of message with %u bytes transmitted to %s\n",
1773  (unsigned int) udpw->payload_size,
1774  GNUNET_i2s (&udpw->session->target));
1777  "# UDP, fragmented msgs, fragments, sent, success",
1778  1,
1779  GNUNET_NO);
1781  plugin->env->stats,
1782  "# UDP, fragmented msgs, fragments bytes, sent, success",
1783  udpw->msg_size,
1784  GNUNET_NO);
1785  }
1786  else
1787  {
1789  "Failed to transmit fragment of message with %u bytes to %s\n",
1790  (unsigned int) udpw->payload_size,
1791  GNUNET_i2s (&udpw->session->target));
1794  "# UDP, fragmented msgs, fragments, sent, failure",
1795  1,
1796  GNUNET_NO);
1798  plugin->env->stats,
1799  "# UDP, fragmented msgs, fragments bytes, sent, failure",
1800  udpw->msg_size,
1801  GNUNET_NO);
1802  }
1803 }
void GNUNET_FRAGMENT_context_transmission_done(struct GNUNET_FRAGMENT_Context *fc)
Continuation to call from the 'proc' function after the fragment has been transmitted (and hence the ...
static void fragmented_message_done(struct UDP_FragmentationContext *frag_ctx, int result)
We have completed our (attempt) to transmit a message that had to be fragmented – either because we g...
size_t payload_size
Payload size of original message.

References Plugin::env, UDP_FragmentationContext::frag, UDP_MessageWrapper::frag_ctx, fragmented_message_done(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_FRAGMENT_context_transmission_done(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, UDP_MessageWrapper::msg_size, UDP_MessageWrapper::payload_size, plugin, result, UDP_MessageWrapper::session, and GNUNET_ATS_Session::target.

Referenced by enqueue_fragment().

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

◆ enqueue_fragment()

static void enqueue_fragment ( void *  cls,
const struct GNUNET_MessageHeader msg 
)
static

Function that is called with messages created by the fragmentation module.

In the case of the proc callback of the GNUNET_FRAGMENT_context_create() function, this function must eventually call GNUNET_FRAGMENT_context_transmission_done().

Parameters
clsclosure, the struct UDP_FragmentationContext
msgthe message that was created

Definition at line 1816 of file plugin_transport_udp.c.

1817 {
1818  struct UDP_FragmentationContext *frag_ctx = cls;
1819  struct Plugin *plugin = frag_ctx->plugin;
1820  struct UDP_MessageWrapper *udpw;
1821  struct GNUNET_ATS_Session *session = frag_ctx->session;
1822  size_t msg_len = ntohs (msg->size);
1823 
1824  LOG (GNUNET_ERROR_TYPE_DEBUG, "Enqueuing fragment with %lu bytes\n",
1825  (unsigned long) msg_len);
1826  udpw = GNUNET_malloc (sizeof(struct UDP_MessageWrapper) + msg_len);
1827  udpw->session = session;
1828  udpw->msg_buf = (char *) &udpw[1];
1829  udpw->msg_size = msg_len;
1830  udpw->payload_size = msg_len; /* FIXME: minus fragment overhead */
1831  udpw->timeout = frag_ctx->timeout;
1832  udpw->start_time = frag_ctx->start_time;
1837  udpw->frag_ctx = frag_ctx;
1838  udpw->qc = &qc_fragment_sent;
1839  udpw->qc_cls = plugin;
1840  GNUNET_memcpy (udpw->msg_buf, msg, msg_len);
1841  enqueue (plugin, udpw);
1842  if (session->address->address_length == sizeof(struct IPv4UdpAddress))
1844  else
1846 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:277
static void qc_fragment_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We are finished with a fragment in the message queue.
static void enqueue(struct Plugin *plugin, struct UDP_MessageWrapper *udpw)
Enqueue a message for transmission and update statistics.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Context to send fragmented messages.
struct GNUNET_TIME_Relative flow_delay_from_other_peer
Desired delay for transmissions we received from other peer.
struct GNUNET_TIME_Absolute timeout
Message timeout.
char * msg_buf
Message with msg_size bytes including UDP-specific overhead.
QueueContinuation qc
Function to call once the message wrapper is being removed from the queue (with success or failure).
struct GNUNET_TIME_Absolute start_time
Message enqueue time.
struct GNUNET_TIME_Absolute timeout
Message timeout.
void * qc_cls
Closure for qc.

References GNUNET_ATS_Session::address, GNUNET_HELLO_Address::address_length, enqueue(), UDP_FragmentationContext::flow_delay_from_other_peer, GNUNET_ATS_Session::frag_ctx, UDP_MessageWrapper::frag_ctx, GNUNET_ERROR_TYPE_DEBUG, GNUNET_malloc, GNUNET_memcpy, GNUNET_TIME_absolute_add(), LOG, msg, UDP_MessageWrapper::msg_buf, UDP_MessageWrapper::msg_size, UDP_FragmentationContext::next_frag_time, UDP_MessageWrapper::payload_size, plugin, UDP_FragmentationContext::plugin, UDP_MessageWrapper::qc, UDP_MessageWrapper::qc_cls, qc_fragment_sent(), schedule_select_v4(), schedule_select_v6(), UDP_FragmentationContext::session, UDP_MessageWrapper::session, GNUNET_MessageHeader::size, UDP_FragmentationContext::start_time, UDP_MessageWrapper::start_time, UDP_FragmentationContext::timeout, UDP_MessageWrapper::timeout, and UDP_MessageWrapper::transmission_time.

Referenced by udp_plugin_send().

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

◆ qc_message_sent()

static void qc_message_sent ( void *  cls,
struct UDP_MessageWrapper udpw,
int  result 
)
static

We are finished with a message from the message queue.

Notify the continuation and update statistics.

Parameters
clsthe struct Plugin *
udpwthe queue entry
resultGNUNET_OK on success, GNUNET_SYSERR on failure

Definition at line 1858 of file plugin_transport_udp.c.

1859 {
1860  struct Plugin *plugin = cls;
1861  size_t overhead;
1862  struct GNUNET_TIME_Relative delay;
1863 
1864  if (udpw->msg_size >= udpw->payload_size)
1865  overhead = udpw->msg_size - udpw->payload_size;
1866  else
1867  overhead = udpw->msg_size;
1868 
1869  if (NULL != udpw->cont)
1870  {
1873  {
1875  "Message sent via UDP with delay of %s\n",
1877  }
1878  else
1879  {
1881  "Message sent via UDP with delay of %s\n",
1883  }
1884  udpw->cont (udpw->cont_cls,
1885  &udpw->session->target,
1886  result,
1887  udpw->payload_size,
1888  overhead);
1889  }
1890  if (GNUNET_OK == result)
1891  {
1893  "# UDP, unfragmented msgs, messages, sent, success",
1894  1,
1895  GNUNET_NO);
1897  plugin->env->stats,
1898  "# UDP, unfragmented msgs, bytes payload, sent, success",
1899  udpw->payload_size,
1900  GNUNET_NO);
1902  plugin->env->stats,
1903  "# UDP, unfragmented msgs, bytes overhead, sent, success",
1904  overhead,
1905  GNUNET_NO);
1907  "# UDP, total, bytes overhead, sent",
1908  overhead,
1909  GNUNET_NO);
1911  "# UDP, total, bytes payload, sent",
1912  udpw->payload_size,
1913  GNUNET_NO);
1914  }
1915  else
1916  {
1918  "# UDP, unfragmented msgs, messages, sent, failure",
1919  1,
1920  GNUNET_NO);
1922  plugin->env->stats,
1923  "# UDP, unfragmented msgs, bytes payload, sent, failure",
1924  udpw->payload_size,
1925  GNUNET_NO);
1927  plugin->env->stats,
1928  "# UDP, unfragmented msgs, bytes overhead, sent, failure",
1929  overhead,
1930  GNUNET_NO);
1931  }
1932 }

References UDP_MessageWrapper::cont, UDP_MessageWrapper::cont_cls, delay, Plugin::env, GNUNET_CONSTANTS_LATENCY_WARN, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_duration(), GNUNET_YES, LOG, UDP_MessageWrapper::msg_size, UDP_MessageWrapper::payload_size, plugin, GNUNET_TIME_Relative::rel_value_us, result, UDP_MessageWrapper::session, UDP_MessageWrapper::start_time, and GNUNET_ATS_Session::target.

Referenced by udp_plugin_send().

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

◆ udp_plugin_send()

static ssize_t udp_plugin_send ( void *  cls,
struct GNUNET_ATS_Session s,
const char *  msgbuf,
size_t  msgbuf_size,
unsigned int  priority,
struct GNUNET_TIME_Relative  to,
GNUNET_TRANSPORT_TransmitContinuation  cont,
void *  cont_cls 
)
static

Function that can be used by the transport service to transmit a message using the plugin.

Note that in the case of a peer disconnecting, the continuation MUST be called prior to the disconnect notification itself. This function will be called with this peer's HELLO message to initiate a fresh connection to another peer.

Parameters
clsclosure
swhich session must be used
msgbufthe message to transmit
msgbuf_sizenumber of bytes in msgbuf
priorityhow important is the message (most plugins will ignore message priority and just FIFO)
tohow long to wait at most for the transmission (does not require plugins to discard the message after the timeout, just advisory for the desired delay; most plugins will ignore this as well)
contcontinuation to call once the message has been transmitted (or if the transport is ready for the next transmission call; or if the peer disconnected...); can be NULL
cont_clsclosure for cont
Returns
number of bytes used (on the physical network, with overheads); -1 on hard errors (i.e. address invalid); 0 is a legal value and does NOT mean that the message was not transmitted (DV)

Definition at line 1963 of file plugin_transport_udp.c.

1971 {
1972  struct Plugin *plugin = cls;
1973  size_t udpmlen = msgbuf_size + sizeof(struct UDPMessage);
1974  struct UDP_FragmentationContext *frag_ctx;
1975  struct UDP_MessageWrapper *udpw;
1976  struct UDPMessage *udp;
1977  char mbuf[udpmlen] GNUNET_ALIGN;
1978  struct GNUNET_TIME_Relative latency;
1979 
1980  if ((sizeof(struct IPv6UdpAddress) == s->address->address_length) &&
1981  (NULL == plugin->sockv6))
1982  return GNUNET_SYSERR;
1983  if ((sizeof(struct IPv4UdpAddress) == s->address->address_length) &&
1984  (NULL == plugin->sockv4))
1985  return GNUNET_SYSERR;
1986  if (udpmlen >= GNUNET_MAX_MESSAGE_SIZE)
1987  {
1988  GNUNET_break (0);
1989  return GNUNET_SYSERR;
1990  }
1991  if (GNUNET_YES !=
1993  &s->target,
1994  s))
1995  {
1996  GNUNET_break (0);
1997  return GNUNET_SYSERR;
1998  }
2000  "UDP transmits %lu-byte message to `%s' using address `%s'\n",
2001  (unsigned long) udpmlen,
2002  GNUNET_i2s (&s->target),
2004  s->address->address,
2005  s->address->address_length));
2006 
2007  udp = (struct UDPMessage *) mbuf;
2008  udp->header.size = htons (udpmlen);
2009  udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE);
2010  udp->reserved = htonl (0);
2011  udp->sender = *plugin->env->my_identity;
2012 
2013  /* We do not update the session time out here! Otherwise this
2014  * session will not timeout since we send keep alive before session
2015  * can timeout.
2016  *
2017  * For UDP we update session timeout only on receive, this will
2018  * cover keep alives, since remote peer will reply with keep alive
2019  * responses!
2020  */if (udpmlen <= UDP_MTU)
2021  {
2022  /* unfragmented message */
2023  udpw = GNUNET_malloc (sizeof(struct UDP_MessageWrapper) + udpmlen);
2024  udpw->session = s;
2025  udpw->msg_buf = (char *) &udpw[1];
2026  udpw->msg_size = udpmlen; /* message size with UDP overhead */
2027  udpw->payload_size = msgbuf_size; /* message size without UDP overhead */
2031  s->last_transmit_time =
2034  udpw->cont = cont;
2035  udpw->cont_cls = cont_cls;
2036  udpw->frag_ctx = NULL;
2037  udpw->qc = &qc_message_sent;
2038  udpw->qc_cls = plugin;
2039  GNUNET_memcpy (udpw->msg_buf, udp, sizeof(struct UDPMessage));
2040  GNUNET_memcpy (&udpw->msg_buf[sizeof(struct UDPMessage)],
2041  msgbuf,
2042  msgbuf_size);
2043  enqueue (plugin, udpw);
2045  "# UDP, unfragmented messages queued total",
2046  1,
2047  GNUNET_NO);
2049  "# UDP, unfragmented bytes payload queued total",
2050  msgbuf_size,
2051  GNUNET_NO);
2052  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
2054  else
2056  }
2057  else
2058  {
2059  /* fragmented message */
2060  if (NULL != s->frag_ctx)
2061  return GNUNET_SYSERR;
2062  GNUNET_memcpy (&udp[1], msgbuf, msgbuf_size);
2063  frag_ctx = GNUNET_new (struct UDP_FragmentationContext);
2064  frag_ctx->plugin = plugin;
2065  frag_ctx->session = s;
2066  frag_ctx->cont = cont;
2067  frag_ctx->cont_cls = cont_cls;
2068  frag_ctx->start_time = GNUNET_TIME_absolute_get ();
2069  frag_ctx->next_frag_time = s->last_transmit_time;
2070  frag_ctx->flow_delay_from_other_peer =
2072  1 + (msgbuf_size / UDP_MTU));
2073  frag_ctx->timeout = GNUNET_TIME_relative_to_absolute (to);
2074  frag_ctx->payload_size =
2075  msgbuf_size; /* unfragmented message size without UDP overhead */
2076  frag_ctx->on_wire_size = 0; /* bytes with UDP and fragmentation overhead */
2077  frag_ctx->frag = GNUNET_FRAGMENT_context_create (plugin->env->stats,
2078  UDP_MTU,
2079  &plugin->tracker,
2082  &udp->header,
2084  frag_ctx);
2085  s->frag_ctx = frag_ctx;
2086  s->last_transmit_time = frag_ctx->next_frag_time;
2088  if (latency.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
2090  "Enqueued fragments will take %s for transmission to %s (queue size: %u)\n",
2092  GNUNET_i2s (&s->target),
2093  (unsigned int) s->msgs_in_queue);
2094  else
2096  "Enqueued fragments will take %s for transmission to %s (queue size: %u)\n",
2098  GNUNET_i2s (&s->target),
2099  (unsigned int) s->msgs_in_queue);
2100 
2102  "# UDP, fragmented messages active",
2103  1,
2104  GNUNET_NO);
2106  "# UDP, fragmented messages, total",
2107  1,
2108  GNUNET_NO);
2110  "# UDP, fragmented bytes (payload)",
2111  frag_ctx->payload_size,
2112  GNUNET_NO);
2113  }
2115  return udpmlen;
2116 }
static int udp
Option -u: UDP requested.
Definition: gnunet-vpn.c:76
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
struct GNUNET_FRAGMENT_Context * GNUNET_FRAGMENT_context_create(struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, struct GNUNET_BANDWIDTH_Tracker *tracker, struct GNUNET_TIME_Relative msg_delay, struct GNUNET_TIME_Relative ack_delay, const struct GNUNET_MessageHeader *msg, GNUNET_FRAGMENT_MessageProcessor proc, void *proc_cls)
Create a fragmentation context for the given message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE
Normal UDP message type.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:376
static void qc_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We are finished with a message from the message queue.
static void enqueue_fragment(void *cls, const struct GNUNET_MessageHeader *msg)
Function that is called with messages created by the fragmentation module.
#define UDP_MTU
MTU for fragmentation subsystem.
struct GNUNET_TIME_Relative flow_delay_from_other_peer
Desired delay for transmissions we received from other peer.
struct GNUNET_TIME_Absolute last_transmit_time
What time did we last transmit?
const void * address
Binary representation of the address (plugin-specific).
struct GNUNET_BANDWIDTH_Tracker tracker
Bandwidth tracker to limit global UDP traffic.
UDP Message-Packet header (after defragmentation).

References GNUNET_HELLO_Address::address, GNUNET_ATS_Session::address, GNUNET_HELLO_Address::address_length, UDP_FragmentationContext::cont, UDP_MessageWrapper::cont, UDP_FragmentationContext::cont_cls, UDP_MessageWrapper::cont_cls, enqueue(), enqueue_fragment(), Plugin::env, GNUNET_ATS_Session::flow_delay_from_other_peer, UDP_FragmentationContext::flow_delay_from_other_peer, UDP_FragmentationContext::frag, GNUNET_ATS_Session::frag_ctx, UDP_MessageWrapper::frag_ctx, GNUNET_ALIGN, GNUNET_break, GNUNET_CONSTANTS_LATENCY_WARN, GNUNET_CONTAINER_multipeermap_contains_value(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_FRAGMENT_context_create(), GNUNET_i2s(), GNUNET_malloc, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE, GNUNET_new, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_add(), GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_to_absolute(), GNUNET_TRANSPORT_SS_UPDATE, GNUNET_YES, GNUNET_ATS_Session::last_expected_ack_delay, GNUNET_ATS_Session::last_expected_msg_delay, GNUNET_ATS_Session::last_transmit_time, LOG, UDP_MessageWrapper::msg_buf, UDP_MessageWrapper::msg_size, GNUNET_ATS_Session::msgs_in_queue, UDP_FragmentationContext::next_frag_time, notify_session_monitor(), UDP_FragmentationContext::on_wire_size, UDP_FragmentationContext::payload_size, UDP_MessageWrapper::payload_size, plugin, GNUNET_ATS_Session::plugin, UDP_FragmentationContext::plugin, UDP_MessageWrapper::qc, UDP_MessageWrapper::qc_cls, qc_message_sent(), GNUNET_TIME_Relative::rel_value_us, schedule_select_v4(), schedule_select_v6(), UDP_FragmentationContext::session, UDP_MessageWrapper::session, Plugin::sessions, Plugin::sockv4, Plugin::sockv6, UDP_FragmentationContext::start_time, UDP_MessageWrapper::start_time, GNUNET_ATS_Session::target, UDP_FragmentationContext::timeout, UDP_MessageWrapper::timeout, Plugin::tracker, UDP_MessageWrapper::transmission_time, udp, udp_address_to_string(), and UDP_MTU.

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ find_receive_context()

static int find_receive_context ( void *  cls,
struct GNUNET_CONTAINER_HeapNode node,
void *  element,
GNUNET_CONTAINER_HeapCostType  cost 
)
static

Scan the heap for a receive context with the given address.

Parameters
clsthe struct FindReceiveContext
nodeinternal node of the heap
elementvalue stored at the node (a struct ReceiveContext)
costcost associated with the node
Returns
GNUNET_YES if we should continue to iterate, GNUNET_NO if not.

Definition at line 2160 of file plugin_transport_udp.c.

2164 {
2165  struct FindReceiveContext *frc = cls;
2166  struct DefragContext *e = element;
2167 
2168  if ((frc->udp_addr_len == e->udp_addr_len) &&
2169  (0 == memcmp (frc->udp_addr, e->udp_addr, frc->udp_addr_len)))
2170  {
2171  frc->rc = e;
2172  return GNUNET_NO;
2173  }
2174  return GNUNET_YES;
2175 }
static struct Experiment * e
Data structure to track defragmentation contexts based on the source of the UDP traffic.
Closure for find_receive_context().
struct DefragContext * rc
Where to store the result.
size_t udp_addr_len
Number of bytes in udp_addr.
const union UdpAddress * udp_addr
Address to find.

References e, GNUNET_NO, GNUNET_YES, FindReceiveContext::rc, FindReceiveContext::udp_addr, and FindReceiveContext::udp_addr_len.

Referenced by read_process_fragment(), and udp_disconnect_session().

Here is the caller graph for this function:

◆ udp_disconnect_session()

static int udp_disconnect_session ( void *  cls,
struct GNUNET_ATS_Session s 
)
static

Functions with this signature are called whenever we need to close a session due to a disconnect or failure to establish a connection.

Parameters
clsclosure with the struct Plugin
ssession to close down
Returns
GNUNET_OK on success

Definition at line 2187 of file plugin_transport_udp.c.

2188 {
2189  struct Plugin *plugin = cls;
2190  struct UDP_MessageWrapper *udpw;
2191  struct UDP_MessageWrapper *next;
2192  struct FindReceiveContext frc;
2193 
2196  "Session %p to peer `%s' at address %s ended\n",
2197  s,
2198  GNUNET_i2s (&s->target),
2200  s->address->address,
2201  s->address->address_length));
2202  if (NULL != s->timeout_task)
2203  {
2205  s->timeout_task = NULL;
2206  }
2207  if (NULL != s->frag_ctx)
2208  {
2209  /* Remove fragmented message due to disconnect */
2211  }
2212  GNUNET_assert (
2213  GNUNET_YES ==
2215  frc.rc = NULL;
2216  frc.udp_addr = s->address->address;
2217  frc.udp_addr_len = s->address->address_length;
2218  /* Lookup existing receive context for this address */
2219  if (NULL != plugin->defrag_ctxs)
2220  {
2223  &frc);
2224  if (NULL != frc.rc)
2225  {
2226  struct DefragContext *d_ctx = frc.rc;
2227 
2230  GNUNET_free (d_ctx);
2231  }
2232  }
2233  s->in_destroy = GNUNET_YES;
2234  next = plugin->ipv4_queue_head;
2235  while (NULL != (udpw = next))
2236  {
2237  next = udpw->next;
2238  if (udpw->session == s)
2239  {
2240  dequeue (plugin, udpw);
2241  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
2242  GNUNET_free (udpw);
2243  }
2244  }
2245  next = plugin->ipv6_queue_head;
2246  while (NULL != (udpw = next))
2247  {
2248  next = udpw->next;
2249  if (udpw->session == s)
2250  {
2251  dequeue (plugin, udpw);
2252  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
2253  GNUNET_free (udpw);
2254  }
2255  }
2256  if ((NULL != s->frag_ctx) && (NULL != s->frag_ctx->cont))
2257  {
2258  /* The 'frag_ctx' itself will be freed in #free_session() a bit
2259  later, as it might be in use right now */
2261  "Calling continuation for fragemented message to `%s' with result SYSERR\n",
2262  GNUNET_i2s (&s->target));
2263  s->frag_ctx->cont (s->frag_ctx->cont_cls,
2264  &s->target,
2265  GNUNET_SYSERR,
2266  s->frag_ctx->payload_size,
2267  s->frag_ctx->on_wire_size);
2268  }
2270  plugin->env->session_end (plugin->env->cls, s->address, s);
2271  GNUNET_STATISTICS_set (plugin->env->stats,
2272  "# UDP sessions active",
2274  GNUNET_NO);
2275  if (0 == s->rc)
2276  free_session (s);
2277  return GNUNET_OK;
2278 }
void GNUNET_DEFRAGMENT_context_destroy(struct GNUNET_DEFRAGMENT_Context *dc)
Destroy the given defragmentation context.
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void GNUNET_CONTAINER_heap_iterate(const struct GNUNET_CONTAINER_Heap *heap, GNUNET_CONTAINER_HeapIterator iterator, void *iterator_cls)
Iterate over all entries in the heap.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
@ GNUNET_TRANSPORT_SS_DONE
Session is being torn down and about to disappear.
static void free_session(struct GNUNET_ATS_Session *s)
Function to free last resources associated with a session.
static int find_receive_context(void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost)
Scan the heap for a receive context with the given address.
struct GNUNET_DEFRAGMENT_Context * defrag
Defragmentation context.
struct GNUNET_CONTAINER_HeapNode * hnode
Node in the defrag heap.
unsigned int rc
Reference counter to indicate that this session is currently being used and must not be destroyed; se...
struct GNUNET_CONTAINER_Heap * defrag_ctxs
Heap with all of our defragmentation activities.

References GNUNET_HELLO_Address::address, GNUNET_ATS_Session::address, GNUNET_HELLO_Address::address_length, GNUNET_DATACACHE_PluginEnvironment::cls, UDP_FragmentationContext::cont, UDP_FragmentationContext::cont_cls, DefragContext::defrag, Plugin::defrag_ctxs, dequeue(), Plugin::env, find_receive_context(), GNUNET_ATS_Session::frag_ctx, fragmented_message_done(), free_session(), GNUNET_assert, GNUNET_CONTAINER_heap_iterate(), GNUNET_CONTAINER_heap_remove_node(), GNUNET_CONTAINER_multipeermap_remove(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_DEFRAGMENT_context_destroy(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_set(), GNUNET_SYSERR, GNUNET_TRANSPORT_SS_DONE, GNUNET_YES, DefragContext::hnode, GNUNET_ATS_Session::in_destroy, Plugin::ipv4_queue_head, Plugin::ipv6_queue_head, LOG, UDP_MessageWrapper::next, notify_session_monitor(), UDP_FragmentationContext::on_wire_size, UDP_FragmentationContext::payload_size, plugin, GNUNET_ATS_Session::plugin, UDP_MessageWrapper::qc, UDP_MessageWrapper::qc_cls, GNUNET_ATS_Session::rc, FindReceiveContext::rc, UDP_MessageWrapper::session, Plugin::sessions, GNUNET_ATS_Session::target, GNUNET_ATS_Session::timeout_task, FindReceiveContext::udp_addr, FindReceiveContext::udp_addr_len, and udp_address_to_string().

Referenced by disconnect_and_free_it(), libgnunet_plugin_transport_udp_init(), read_process_ack(), and session_timeout().

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

◆ read_process_ack()

static void read_process_ack ( struct Plugin plugin,
const struct GNUNET_MessageHeader msg,
const union UdpAddress udp_addr,
socklen_t  udp_addr_len 
)
static

Handle a GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK message.

Parameters
pluginthe UDP plugin
msgthe (presumed) UDP ACK message
udp_addrsender address
udp_addr_lennumber of bytes in udp_addr

Definition at line 2290 of file plugin_transport_udp.c.

2294 {
2295  const struct GNUNET_MessageHeader *ack;
2296  const struct UDP_ACK_Message *udp_ack;
2297  struct GNUNET_HELLO_Address *address;
2298  struct GNUNET_ATS_Session *s;
2299  struct GNUNET_TIME_Relative flow_delay;
2300 
2301  /* check message format */
2302  if (ntohs (msg->size) <
2303  sizeof(struct UDP_ACK_Message) + sizeof(struct GNUNET_MessageHeader))
2304  {
2305  GNUNET_break_op (0);
2306  return;
2307  }
2308  udp_ack = (const struct UDP_ACK_Message *) msg;
2309  ack = (const struct GNUNET_MessageHeader *) &udp_ack[1];
2310  if (ntohs (ack->size) != ntohs (msg->size) - sizeof(struct UDP_ACK_Message))
2311  {
2312  GNUNET_break_op (0);
2313  return;
2314  }
2315 
2316  /* Locate session */
2318  PLUGIN_NAME,
2319  udp_addr,
2320  udp_addr_len,
2323  if (NULL == s)
2324  {
2326  "UDP session of address %s for ACK not found\n",
2328  address->address,
2329  address->address_length));
2331  return;
2332  }
2333  if (NULL == s->frag_ctx)
2334  {
2336  "Fragmentation context of address %s for ACK (%s) not found\n",
2338  address->address,
2339  address->address_length),
2342  return;
2343  }
2345 
2346  /* evaluate flow delay: how long should we wait between messages? */
2347  if (UINT32_MAX == ntohl (udp_ack->delay))
2348  {
2349  /* Other peer asked for us to terminate the session */
2351  "Asked to disconnect UDP session of %s\n",
2352  GNUNET_i2s (&udp_ack->sender));
2354  return;
2355  }
2356  flow_delay.rel_value_us = (uint64_t) ntohl (udp_ack->delay);
2357  if (flow_delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
2359  "We received a sending delay of %s for %s\n",
2361  GNUNET_i2s (&udp_ack->sender));
2362  else
2364  "We received a sending delay of %s for %s\n",
2366  GNUNET_i2s (&udp_ack->sender));
2367  /* Flow delay is for the reassembled packet, however, our delay
2368  is per packet, so we need to adjust: */
2369  s->flow_delay_from_other_peer = flow_delay;
2370 
2371  /* Handle ACK */
2373  {
2375  "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
2376  (unsigned int) ntohs (msg->size),
2377  GNUNET_i2s (&udp_ack->sender),
2378  udp_address_to_string (plugin, udp_addr, udp_addr_len));
2379  /* Expect more ACKs to arrive */
2380  return;
2381  }
2382 
2383  /* Remove fragmented message after successful sending */
2385  "Message from %s at %s full ACK'ed\n",
2386  GNUNET_i2s (&udp_ack->sender),
2387  udp_address_to_string (plugin, udp_addr, udp_addr_len));
2389 }
const char * GNUNET_FRAGMENT_print_ack(const struct GNUNET_MessageHeader *ack)
Convert an ACK message to a printable format suitable for logging.
int GNUNET_FRAGMENT_process_ack(struct GNUNET_FRAGMENT_Context *fc, const struct GNUNET_MessageHeader *msg)
Process an acknowledgement message we got from the other side (to control re-transmits).
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_INFO
static int udp_disconnect_session(void *cls, struct GNUNET_ATS_Session *s)
Functions with this signature are called whenever we need to close a session due to a disconnect or f...
static struct GNUNET_ATS_Session * udp_plugin_lookup_session(void *cls, const struct GNUNET_HELLO_Address *address)
Locate an existing session the transport service is using to send data to another peer.
Header for all communications.
UDP ACK Message-Packet header.
uint32_t delay
Desired delay for flow control, in us (in NBO).
struct GNUNET_PeerIdentity sender
What is the identity of the sender.

References address, UDP_ACK_Message::delay, GNUNET_ATS_Session::flow_delay_from_other_peer, UDP_FragmentationContext::frag, GNUNET_ATS_Session::frag_ctx, fragmented_message_done(), GNUNET_break_op, GNUNET_CONSTANTS_LATENCY_WARN, GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_FRAGMENT_print_ack(), GNUNET_FRAGMENT_process_ack(), GNUNET_HELLO_address_allocate(), GNUNET_HELLO_address_free, GNUNET_HELLO_ADDRESS_INFO_NONE, GNUNET_i2s(), GNUNET_OK, GNUNET_STRINGS_relative_time_to_string(), GNUNET_YES, LOG, msg, plugin, PLUGIN_NAME, GNUNET_TIME_Relative::rel_value_us, UDP_ACK_Message::sender, GNUNET_MessageHeader::size, udp_address_to_string(), udp_disconnect_session(), and udp_plugin_lookup_session().

Referenced by udp_select_read().

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

◆ process_inbound_tokenized_messages()

static int process_inbound_tokenized_messages ( void *  cls,
const struct GNUNET_MessageHeader hdr 
)
static

Message tokenizer has broken up an incoming message.

Pass it on to the service.

Parameters
clsthe struct GNUNET_ATS_Session *
hdrthe actual message
Returns
GNUNET_OK (always)

Definition at line 2401 of file plugin_transport_udp.c.

2403 {
2404  struct GNUNET_ATS_Session *session = cls;
2405  struct Plugin *plugin = session->plugin;
2406 
2407  if (GNUNET_YES == session->in_destroy)
2408  return GNUNET_OK;
2409  reschedule_session_timeout (session);
2410  session->flow_delay_for_other_peer =
2411  plugin->env->receive (plugin->env->cls, session->address, session, hdr);
2412  return GNUNET_OK;
2413 }
struct GNUNET_TIME_Relative flow_delay_for_other_peer
Desired delay for next sending we send to other peer.

References GNUNET_ATS_Session::address, GNUNET_DATACACHE_PluginEnvironment::cls, Plugin::env, GNUNET_ATS_Session::flow_delay_for_other_peer, GNUNET_OK, GNUNET_YES, GNUNET_ATS_Session::in_destroy, plugin, GNUNET_ATS_Session::plugin, and reschedule_session_timeout().

Referenced by udp_plugin_create_session().

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

◆ disconnect_and_free_it()

static int disconnect_and_free_it ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Destroy a session, plugin is being unloaded.

Parameters
clsthe struct Plugin
keyhash of public key of target peer
valuea struct PeerSession * to clean up
Returns
GNUNET_OK (continue to iterate)

Definition at line 2425 of file plugin_transport_udp.c.

2428 {
2429  struct Plugin *plugin = cls;
2430 
2432  return GNUNET_OK;
2433 }

References GNUNET_OK, plugin, udp_disconnect_session(), and value.

Referenced by udp_disconnect().

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

◆ udp_disconnect()

static void udp_disconnect ( void *  cls,
const struct GNUNET_PeerIdentity target 
)
static

Disconnect from a remote node.

Clean up session if we have one for this peer.

Parameters
clsclosure for this call (should be handle to Plugin)
targetthe peeridentity of the peer to disconnect
Returns
GNUNET_OK on success, GNUNET_SYSERR if the operation failed

Definition at line 2445 of file plugin_transport_udp.c.

2446 {
2447  struct Plugin *plugin = cls;
2448 
2450  "Disconnecting from peer `%s'\n",
2451  GNUNET_i2s (target));
2453  target,
2455  plugin);
2456 }
static int disconnect_and_free_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Destroy a session, plugin is being unloaded.

References disconnect_and_free_it(), GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), LOG, plugin, and Plugin::sessions.

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ session_timeout()

static void session_timeout ( void *  cls)
static

Session was idle, so disconnect it.

Parameters
clsthe struct GNUNET_ATS_Session to time out

Definition at line 2465 of file plugin_transport_udp.c.

2466 {
2467  struct GNUNET_ATS_Session *s = cls;
2468  struct Plugin *plugin = s->plugin;
2469  struct GNUNET_TIME_Relative left;
2470 
2471  s->timeout_task = NULL;
2473  if (left.rel_value_us > 0)
2474  {
2475  /* not actually our turn yet, but let's at least update
2476  the monitor, it may think we're about to die ... */
2479  return;
2480  }
2482  "Session %p was idle for %s, disconnecting\n",
2483  s,
2485  GNUNET_YES));
2486  /* call session destroy function */
2488 }
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:1269
static void session_timeout(void *cls)
Session was idle, so disconnect it.

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TRANSPORT_SS_UPDATE, GNUNET_YES, LOG, notify_session_monitor(), plugin, GNUNET_ATS_Session::plugin, GNUNET_TIME_Relative::rel_value_us, GNUNET_ATS_Session::timeout, GNUNET_ATS_Session::timeout_task, udp_disconnect_session(), and UDP_SESSION_TIME_OUT.

Referenced by udp_plugin_create_session().

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

◆ udp_plugin_create_session()

static struct GNUNET_ATS_Session* udp_plugin_create_session ( void *  cls,
const struct GNUNET_HELLO_Address address,
enum GNUNET_NetworkType  network_type 
)
static

Allocate a new session for the given endpoint address.

Note that this function does not inform the service of the new session, this is the responsibility of the caller (if needed).

Parameters
clsthe struct Plugin
addressaddress of the other peer to use
network_typenetwork type the address belongs to
Returns
NULL on error, otherwise session handle

Definition at line 2503 of file plugin_transport_udp.c.

2506 {
2507  struct Plugin *plugin = cls;
2508  struct GNUNET_ATS_Session *s;
2509 
2510  s = GNUNET_new (struct GNUNET_ATS_Session);
2512  s->plugin = plugin;
2514  s->target = address->peer;
2522  s->timeout_task =
2524  s->scope = network_type;
2525 
2527  "Creating new session %p for peer `%s' address `%s'\n",
2528  s,
2529  GNUNET_i2s (&address->peer),
2531  address->address,
2532  address->address_length));
2534  plugin->sessions,
2535  &s->target,
2536  s,
2538  GNUNET_STATISTICS_set (plugin->env->stats,
2539  "# UDP sessions active",
2541  GNUNET_NO);
2543  return s;
2544 }
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *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.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:85
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:311
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
static int process_inbound_tokenized_messages(void *cls, const struct GNUNET_MessageHeader *hdr)
Message tokenizer has broken up an incoming message.

References address, GNUNET_ATS_Session::address, Plugin::env, GNUNET_ATS_Session::flow_delay_for_other_peer, GNUNET_ATS_Session::flow_delay_from_other_peer, GNUNET_assert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_CONTAINER_multipeermap_put(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELLO_address_copy(), GNUNET_i2s(), GNUNET_MST_create(), GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_STATISTICS_set(), GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_TIME_UNIT_ZERO, GNUNET_TRANSPORT_SS_INIT, GNUNET_ATS_Session::last_expected_ack_delay, GNUNET_ATS_Session::last_expected_msg_delay, GNUNET_ATS_Session::last_transmit_time, LOG, GNUNET_ATS_Session::mst, notify_session_monitor(), plugin, GNUNET_ATS_Session::plugin, process_inbound_tokenized_messages(), GNUNET_ATS_Session::scope, session_timeout(), Plugin::sessions, GNUNET_ATS_Session::target, GNUNET_ATS_Session::timeout, GNUNET_ATS_Session::timeout_task, udp_address_to_string(), and UDP_SESSION_TIME_OUT.

Referenced by process_udp_message(), and udp_plugin_get_session().

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

◆ udp_plugin_get_session()

static struct GNUNET_ATS_Session* udp_plugin_get_session ( void *  cls,
const struct GNUNET_HELLO_Address address 
)
static

Creates a new outbound session the transport service will use to send data to the peer.

Parameters
clsthe struct Plugin *
addressthe address
Returns
the session or NULL of max connections exceeded

Definition at line 2556 of file plugin_transport_udp.c.

2557 {
2558  struct Plugin *plugin = cls;
2559  struct GNUNET_ATS_Session *s;
2560  enum GNUNET_NetworkType network_type = GNUNET_NT_UNSPECIFIED;
2561  const struct IPv4UdpAddress *udp_v4;
2562  const struct IPv6UdpAddress *udp_v6;
2563 
2564  if (NULL == address)
2565  {
2566  GNUNET_break (0);
2567  return NULL;
2568  }
2569  if ((address->address_length != sizeof(struct IPv4UdpAddress)) &&
2570  (address->address_length != sizeof(struct IPv6UdpAddress)))
2571  {
2572  GNUNET_break_op (0);
2573  return NULL;
2574  }
2575  if (NULL != (s = udp_plugin_lookup_session (cls, address)))
2576  return s;
2577 
2578  /* need to create new session */
2579  if (sizeof(struct IPv4UdpAddress) == address->address_length)
2580  {
2581  struct sockaddr_in v4;
2582 
2583  udp_v4 = (const struct IPv4UdpAddress *) address->address;
2584  memset (&v4, '\0', sizeof(v4));
2585  v4.sin_family = AF_INET;
2586 #if HAVE_SOCKADDR_IN_SIN_LEN
2587  v4.sin_len = sizeof(struct sockaddr_in);
2588 #endif
2589  v4.sin_port = udp_v4->u4_port;
2590  v4.sin_addr.s_addr = udp_v4->ipv4_addr;
2591  network_type = plugin->env->get_address_type (plugin->env->cls,
2592  (const struct sockaddr *) &v4,
2593  sizeof(v4));
2594  }
2595  if (sizeof(struct IPv6UdpAddress) == address->address_length)
2596  {
2597  struct sockaddr_in6 v6;
2598 
2599  udp_v6 = (const struct IPv6UdpAddress *) address->address;
2600  memset (&v6, '\0', sizeof(v6));
2601  v6.sin6_family = AF_INET6;
2602 #if HAVE_SOCKADDR_IN_SIN_LEN
2603  v6.sin6_len = sizeof(struct sockaddr_in6);
2604 #endif
2605  v6.sin6_port = udp_v6->u6_port;
2606  v6.sin6_addr = udp_v6->ipv6_addr;
2607  network_type = plugin->env->get_address_type (plugin->env->cls,
2608  (const struct sockaddr *) &v6,
2609  sizeof(v6));
2610  }
2611  GNUNET_break (GNUNET_NT_UNSPECIFIED != network_type);
2612  return udp_plugin_create_session (cls, address, network_type);
2613 }
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:36
static struct GNUNET_ATS_Session * udp_plugin_create_session(void *cls, const struct GNUNET_HELLO_Address *address, enum GNUNET_NetworkType network_type)
Allocate a new session for the given endpoint address.

References address, GNUNET_DATACACHE_PluginEnvironment::cls, Plugin::env, GNUNET_break, GNUNET_break_op, GNUNET_NT_UNSPECIFIED, plugin, udp_plugin_create_session(), and udp_plugin_lookup_session().

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ process_udp_message()

static void process_udp_message ( struct Plugin plugin,
const struct UDPMessage msg,
const union UdpAddress udp_addr,
size_t  udp_addr_len,
enum GNUNET_NetworkType  network_type 
)
static

We've received a UDP Message.

Process it (pass contents to main service).

Parameters
pluginplugin context
msgthe message
udp_addrsender address
udp_addr_lennumber of bytes in udp_addr
network_typenetwork type the address belongs to

Definition at line 2626 of file plugin_transport_udp.c.

2631 {
2632  struct GNUNET_ATS_Session *s;
2633  struct GNUNET_HELLO_Address *address;
2634 
2635  GNUNET_break (GNUNET_NT_UNSPECIFIED != network_type);
2636  if (0 != ntohl (msg->reserved))
2637  {
2638  GNUNET_break_op (0);
2639  return;
2640  }
2641  if (ntohs (msg->header.size) <
2642  sizeof(struct GNUNET_MessageHeader) + sizeof(struct UDPMessage))
2643  {
2644  GNUNET_break_op (0);
2645  return;
2646  }
2647 
2649  PLUGIN_NAME,
2650  udp_addr,
2651  udp_addr_len,
2653  if (NULL == (s = udp_plugin_lookup_session (plugin, address)))
2654  {
2655  s = udp_plugin_create_session (plugin, address, network_type);
2656  plugin->env->session_start (plugin->env->cls, address, s, s->scope);
2658  }
2659  GNUNET_free (address);
2660 
2661  s->rc++;
2663  (const char *) &msg[1],
2664  ntohs (msg->header.size) - sizeof(struct UDPMessage),
2665  GNUNET_YES,
2666  GNUNET_NO);
2667  s->rc--;
2668  if ((0 == s->rc) && (GNUNET_YES == s->in_destroy))
2669  free_session (s);
2670 }
int GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:114

References address, GNUNET_DATACACHE_PluginEnvironment::cls, Plugin::env, free_session(), GNUNET_break, GNUNET_break_op, GNUNET_free, GNUNET_HELLO_address_allocate(), GNUNET_HELLO_ADDRESS_INFO_NONE, GNUNET_MST_from_buffer(), GNUNET_NO, GNUNET_NT_UNSPECIFIED, GNUNET_TRANSPORT_SS_UP, GNUNET_YES, GNUNET_ATS_Session::in_destroy, msg, GNUNET_ATS_Session::mst, notify_session_monitor(), plugin, PLUGIN_NAME, GNUNET_ATS_Session::rc, GNUNET_ATS_Session::scope, GNUNET_MessageHeader::size, udp_plugin_create_session(), and udp_plugin_lookup_session().

Referenced by fragment_msg_proc(), and udp_select_read().

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

◆ fragment_msg_proc()

static void fragment_msg_proc ( void *  cls,
const struct GNUNET_MessageHeader msg 
)
static

Process a defragmented message.

Parameters
clsthe struct DefragContext *
msgthe message

Definition at line 2680 of file plugin_transport_udp.c.

2681 {
2682  struct DefragContext *dc = cls;
2683  const struct UDPMessage *um;
2684 
2686  {
2687  GNUNET_break_op (0);
2688  return;
2689  }
2690  if (ntohs (msg->size) < sizeof(struct UDPMessage))
2691  {
2692  GNUNET_break_op (0);
2693  return;
2694  }
2695  um = (const struct UDPMessage *) msg;
2696  dc->sender = um->sender;
2697  dc->have_sender = GNUNET_YES;
2698  process_udp_message (dc->plugin,
2699  um,
2700  dc->udp_addr,
2701  dc->udp_addr_len,
2702  dc->network_type);
2703 }
static struct GNUNET_FS_DownloadContext * dc
static void process_udp_message(struct Plugin *plugin, const struct UDPMessage *msg, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We've received a UDP Message.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
struct GNUNET_PeerIdentity sender
What is the identity of the sender.

References dc, GNUNET_break_op, GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE, GNUNET_YES, msg, process_udp_message(), UDPMessage::sender, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by read_process_fragment().

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

◆ ack_message_sent()

static void ack_message_sent ( void *  cls,
struct UDP_MessageWrapper udpw,
int  result 
)
static

We finished sending an acknowledgement.

Update statistics.

Parameters
clsthe struct Plugin
udpwmessage queue entry of the ACK
resultGNUNET_OK if the transmission worked, GNUNET_SYSERR if we failed to send the ACK

Definition at line 2716 of file plugin_transport_udp.c.

2717 {
2718  struct Plugin *plugin = cls;
2719 
2720  if (GNUNET_OK == result)
2721  {
2723  "# UDP, ACK messages sent",
2724  1,
2725  GNUNET_NO);
2726  }
2727  else
2728  {
2730  "# UDP, ACK transmissions failed",
2731  1,
2732  GNUNET_NO);
2733  }
2734 }

References Plugin::env, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), plugin, and result.

Referenced by ack_proc().

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

◆ ack_proc()

static void ack_proc ( void *  cls,
uint32_t  id,
const struct GNUNET_MessageHeader msg 
)
static

Transmit an acknowledgement.

Parameters
clsthe struct DefragContext *
idmessage ID (unused)
msgack to transmit

Definition at line 2745 of file plugin_transport_udp.c.

2746 {
2747  struct DefragContext *rc = cls;
2748  struct Plugin *plugin = rc->plugin;
2749  size_t msize = sizeof(struct UDP_ACK_Message) + ntohs (msg->size);
2750  struct UDP_ACK_Message *udp_ack;
2751  uint32_t delay;
2752  struct UDP_MessageWrapper *udpw;
2753  struct GNUNET_ATS_Session *s;
2754  struct GNUNET_HELLO_Address *address;
2755 
2756  if (GNUNET_NO == rc->have_sender)
2757  {
2758  /* tried to defragment but never succeeded, hence will not ACK */
2759  /* This can happen if we just lost msgs */
2761  "# UDP, fragments discarded without ACK",
2762  1,
2763  GNUNET_NO);
2764  return;
2765  }
2767  PLUGIN_NAME,
2768  rc->udp_addr,
2769  rc->udp_addr_len,
2773  if (NULL == s)
2774  {
2776  "Trying to transmit ACK to peer `%s' but no session found!\n",
2780  GNUNET_free (rc);
2782  "# UDP, ACK transmissions failed",
2783  1,
2784  GNUNET_NO);
2785  return;
2786  }
2787  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
2789  delay = UINT32_MAX;
2790  else if (s->flow_delay_for_other_peer.rel_value_us < UINT32_MAX)
2792  else
2793  delay = UINT32_MAX - 1; /* largest value we can communicate */
2795  "Sending ACK to `%s' including delay of %s\n",
2798  GNUNET_YES));
2799  udpw = GNUNET_malloc (sizeof(struct UDP_MessageWrapper) + msize);
2800  udpw->msg_size = msize;
2801  udpw->payload_size = 0;
2802  udpw->session = s;
2805  udpw->msg_buf = (char *) &udpw[1];
2806  udpw->qc = &ack_message_sent;
2807  udpw->qc_cls = plugin;
2808  udp_ack = (struct UDP_ACK_Message *) udpw->msg_buf;
2809  udp_ack->header.size = htons ((uint16_t) msize);
2811  udp_ack->delay = htonl (delay);
2812  udp_ack->sender = *plugin->env->my_identity;
2813  GNUNET_memcpy (&udp_ack[1], msg, ntohs (msg->size));
2814  enqueue (plugin, udpw);
2816  if (s->address->address_length == sizeof(struct IPv4UdpAddress))
2818  else
2820 }
@ GNUNET_ERROR_TYPE_ERROR
#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK
UDP ACK.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition: peer.c:67
static void ack_message_sent(void *cls, struct UDP_MessageWrapper *udpw, int result)
We finished sending an acknowledgement.
struct GNUNET_PeerIdentity sender
Who's message(s) are we defragmenting here? Only initialized once we succeeded and have_sender is set...
int have_sender
Has the sender field been initialized yet?
const union UdpAddress * udp_addr
Source address this receive context is for (allocated at the end of the struct).
struct Plugin * plugin
Reference to master plugin struct.
size_t udp_addr_len
Length of udp_addr.
struct GNUNET_MessageHeader header
Message header.

References ack_message_sent(), address, GNUNET_ATS_Session::address, GNUNET_HELLO_Address::address_length, DefragContext::defrag, delay, UDP_ACK_Message::delay, enqueue(), Plugin::env, GNUNET_ATS_Session::flow_delay_for_other_peer, GNUNET_CONTAINER_heap_remove_node(), GNUNET_DEFRAGMENT_context_destroy(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_HELLO_address_allocate(), GNUNET_HELLO_address_free, GNUNET_HELLO_ADDRESS_INFO_NONE, GNUNET_malloc, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_SS_UPDATE, GNUNET_YES, DefragContext::have_sender, UDP_ACK_Message::header, DefragContext::hnode, LOG, msg, UDP_MessageWrapper::msg_buf, UDP_MessageWrapper::msg_size, notify_session_monitor(), UDP_MessageWrapper::payload_size, plugin, DefragContext::plugin, PLUGIN_NAME, UDP_MessageWrapper::qc, UDP_MessageWrapper::qc_cls, GNUNET_TIME_Relative::rel_value_us, schedule_select_v4(), schedule_select_v6(), DefragContext::sender, UDP_ACK_Message::sender, UDP_MessageWrapper::session, GNUNET_MessageHeader::size, size, UDP_MessageWrapper::start_time, UDP_MessageWrapper::timeout, GNUNET_MessageHeader::type, DefragContext::udp_addr, DefragContext::udp_addr_len, udp_address_to_string(), and udp_plugin_lookup_session().

Referenced by read_process_fragment().

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

◆ read_process_fragment()

static void read_process_fragment ( struct Plugin plugin,
const struct GNUNET_MessageHeader msg,
const union UdpAddress udp_addr,
size_t  udp_addr_len,
enum GNUNET_NetworkType  network_type 
)
static

We received a fragment, process it.

Parameters
pluginour plugin
msga message of type GNUNET_MESSAGE_TYPE_FRAGMENT
udp_addrsender address
udp_addr_lennumber of bytes in udp_addr
network_typenetwork type the address belongs to

Definition at line 2833 of file plugin_transport_udp.c.

2838 {
2839  struct DefragContext *d_ctx;
2840  struct GNUNET_TIME_Absolute now;
2841  struct FindReceiveContext frc;
2842 
2843  frc.rc = NULL;
2844  frc.udp_addr = udp_addr;
2845  frc.udp_addr_len = udp_addr_len;
2846 
2847  /* Lookup existing receive context for this address */
2850  &frc);
2851  now = GNUNET_TIME_absolute_get ();
2852  d_ctx = frc.rc;
2853 
2854  if (NULL == d_ctx)
2855  {
2856  /* Create a new defragmentation context */
2857  d_ctx = GNUNET_malloc (sizeof(struct DefragContext) + udp_addr_len);
2858  GNUNET_memcpy (&d_ctx[1], udp_addr, udp_addr_len);
2859  d_ctx->udp_addr = (const union UdpAddress *) &d_ctx[1];
2860  d_ctx->udp_addr_len = udp_addr_len;
2861  d_ctx->network_type = network_type;
2862  d_ctx->plugin = plugin;
2863  d_ctx->defrag =
2865  UDP_MTU,
2867  d_ctx,
2869  &ack_proc);
2871  d_ctx,
2873  now.abs_value_us);
2875  "Created new defragmentation context for %u-byte fragment from `%s'\n",
2876  (unsigned int) ntohs (msg->size),
2877  udp_address_to_string (plugin, udp_addr, udp_addr_len));
2878  }
2879  else
2880  {
2882  "Found existing defragmentation context for %u-byte fragment from `%s'\n",
2883  (unsigned int) ntohs (msg->size),
2884  udp_address_to_string (plugin, udp_addr, udp_addr_len));
2885  }
2886 
2888  {
2889  /* keep this 'rc' from expiring */
2892  now.abs_value_us);
2893  }
2896  {
2897  /* remove 'rc' that was inactive the longest */
2899  GNUNET_assert (NULL != d_ctx);
2901  GNUNET_free (d_ctx);
2903  "# UDP, Defragmentations aborted",
2904  1,
2905  GNUNET_NO);
2906  }
2907 }
int GNUNET_DEFRAGMENT_process_fragment(struct GNUNET_DEFRAGMENT_Context *dc, const struct GNUNET_MessageHeader *msg)
We have received a fragment.
struct GNUNET_DEFRAGMENT_Context * GNUNET_DEFRAGMENT_context_create(struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, unsigned int num_msgs, void *cls, GNUNET_FRAGMENT_MessageProcessor proc, GNUNET_DEFRAGMENT_AckProcessor ackp)
Create a defragmentation context.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
uint64_t GNUNET_CONTAINER_HeapCostType
Cost by which elements in a heap can be ordered.
static void fragment_msg_proc(void *cls, const struct GNUNET_MessageHeader *msg)
Process a defragmented message.
#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
We keep a defragmentation queue per sender address.
static void ack_proc(void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
Transmit an acknowledgement.
#define UDP_MAX_MESSAGES_IN_DEFRAG
Number of messages we can defragment in parallel.
enum GNUNET_NetworkType network_type
Network type the address belongs to.
Time for absolute times used by GNUnet, in microseconds.
Either an IPv4 or IPv6 UDP address.

References GNUNET_TIME_Absolute::abs_value_us, ack_proc(), DefragContext::defrag, Plugin::defrag_ctxs, Plugin::env, find_receive_context(), fragment_msg_proc(), GNUNET_assert, GNUNET_CONTAINER_heap_get_size(), GNUNET_CONTAINER_heap_insert(), GNUNET_CONTAINER_heap_iterate(), GNUNET_CONTAINER_heap_remove_root(), GNUNET_CONTAINER_heap_update_cost(), GNUNET_DEFRAGMENT_context_create(), GNUNET_DEFRAGMENT_context_destroy(), GNUNET_DEFRAGMENT_process_fragment(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get(), DefragContext::hnode, LOG, msg, DefragContext::network_type, plugin, DefragContext::plugin, FindReceiveContext::rc, GNUNET_MessageHeader::size, DefragContext::udp_addr, FindReceiveContext::udp_addr, DefragContext::udp_addr_len, FindReceiveContext::udp_addr_len, udp_address_to_string(), UDP_MAX_MESSAGES_IN_DEFRAG, UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG, and UDP_MTU.

Referenced by udp_select_read().

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

◆ udp_select_read()

static void udp_select_read ( struct Plugin plugin,
struct GNUNET_NETWORK_Handle rsock 
)
static

Read and process a message from the given socket.

Parameters
pluginthe overall plugin
rsocksocket to read from

Definition at line 2917 of file plugin_transport_udp.c.

2918 {
2919  socklen_t fromlen;
2920  struct sockaddr_storage addr;
2921  char buf[65536] GNUNET_ALIGN;
2922  ssize_t size;
2923  const struct GNUNET_MessageHeader *msg;
2924  struct IPv4UdpAddress v4;
2925  struct IPv6UdpAddress v6;
2926  const struct sockaddr *sa;
2927  const struct sockaddr_in *sa4;
2928  const struct sockaddr_in6 *sa6;
2929  const union UdpAddress *int_addr;
2930  size_t int_addr_len;
2931  enum GNUNET_NetworkType network_type;
2932 
2933  fromlen = sizeof(addr);
2934  memset (&addr, 0, sizeof(addr));
2936  buf,
2937  sizeof(buf),
2938  (struct sockaddr *) &addr,
2939  &fromlen);
2940  sa = (const struct sockaddr *) &addr;
2941 
2942  if (-1 == size)
2943  {
2945  "UDP failed to receive data: %s\n",
2946  strerror (errno));
2947  /* Connection failure or something. Not a protocol violation. */
2948  return;
2949  }
2950 
2951  /* Check if this is a STUN packet */
2952  if (GNUNET_NO !=
2954  (const struct sockaddr *) &addr,
2955  fromlen,
2956  buf,
2957  size))
2958  return; /* was STUN, do not process further */
2959 
2960  if (size < sizeof(struct GNUNET_MessageHeader))
2961  {
2963  "UDP got %u bytes from %s, which is not enough for a GNUnet message header\n",
2964  (unsigned int) size,
2965  GNUNET_a2s (sa, fromlen));
2966  /* _MAY_ be a connection failure (got partial message) */
2967  /* But it _MAY_ also be that the other side uses non-GNUnet protocol. */
2968  GNUNET_break_op (0);
2969  return;
2970  }
2971 
2972  msg = (const struct GNUNET_MessageHeader *) buf;
2974  "UDP received %u-byte message from `%s' type %u\n",
2975  (unsigned int) size,
2976  GNUNET_a2s (sa, fromlen),
2977  ntohs (msg->type));
2978  if (size != ntohs (msg->size))
2979  {
2981  "UDP malformed message (size %u) header from %s\n",
2982  (unsigned int) size,
2983  GNUNET_a2s (sa, fromlen));
2984  GNUNET_break_op (0);
2985  return;
2986  }
2988  "# UDP, total bytes received",
2989  size,
2990  GNUNET_NO);
2991  network_type = plugin->env->get_address_type (plugin->env->cls, sa, fromlen);
2992  switch (sa->sa_family)
2993  {
2994  case AF_INET:
2995  sa4 = (const struct sockaddr_in *) &addr;
2996  v4.options = 0;
2997  v4.ipv4_addr = sa4->sin_addr.s_addr;
2998  v4.u4_port = sa4->sin_port;
2999  int_addr = (union UdpAddress *) &v4;
3000  int_addr_len = sizeof(v4);
3001  break;
3002 
3003  case AF_INET6:
3004  sa6 = (const struct sockaddr_in6 *) &addr;
3005  v6.options = 0;
3006  v6.ipv6_addr = sa6->sin6_addr;
3007  v6.u6_port = sa6->sin6_port;
3008  int_addr = (union UdpAddress *) &v6;
3009  int_addr_len = sizeof(v6);
3010  break;
3011 
3012  default:
3013  GNUNET_break (0);
3014  return;
3015  }
3016 
3017  switch (ntohs (msg->type))
3018  {
3022  buf,
3023  size,
3024  int_addr,
3025  int_addr_len,
3026  network_type);
3027  return;
3028 
3030  if (ntohs (msg->size) < sizeof(struct UDPMessage))
3031  {
3032  GNUNET_break_op (0);
3033  return;
3034  }
3036  (const struct UDPMessage *) msg,
3037  int_addr,
3038  int_addr_len,
3039  network_type);
3040  return;
3041 
3043  read_process_ack (plugin, msg, int_addr, int_addr_len);
3044  return;
3045 
3047  read_process_fragment (plugin, msg, int_addr, int_addr_len, network_type);
3048  return;
3049 
3050  default:
3051  GNUNET_break_op (0);
3052  return;
3053  }
3054 }
int GNUNET_NAT_stun_handle_packet(struct GNUNET_NAT_Handle *nh, const struct sockaddr *sender_addr, size_t sender_addr_len, const void *data, size_t data_size)
Handle an incoming STUN message.
Definition: nat_api.c:583
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition: network.c:754
#define GNUNET_MESSAGE_TYPE_FRAGMENT
FRAGMENT of a larger message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON
Message send by a peer to notify the other to keep the session alive.
static void read_process_ack(struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const union UdpAddress *udp_addr, socklen_t udp_addr_len)
Handle a GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK message.
static void read_process_fragment(struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We received a fragment, process it.
void udp_broadcast_receive(struct Plugin *plugin, const char *buf, ssize_t size, const union UdpAddress *udp_addr, size_t udp_addr_len, enum GNUNET_NetworkType network_type)
We received a broadcast message.
int enable_broadcasting_receiving
Is receiving broadcasts enabled: GNUNET_YES or GNUNET_NO.
struct IPv4UdpAddress v4
IPv4 case.
struct IPv6UdpAddress v6
IPv6 case.

References buf, GNUNET_DATACACHE_PluginEnvironment::cls, Plugin::enable_broadcasting_receiving, Plugin::env, GNUNET_a2s(), GNUNET_ALIGN, GNUNET_break, GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_MESSAGE_TYPE_FRAGMENT, GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON, GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK, GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE, GNUNET_NAT_stun_handle_packet(), GNUNET_NETWORK_socket_recvfrom(), GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, IPv4UdpAddress::ipv4_addr, IPv6UdpAddress::ipv6_addr, LOG, msg, Plugin::nat, IPv4UdpAddress::options, IPv6UdpAddress::options, plugin, process_udp_message(), read_process_ack(), read_process_fragment(), GNUNET_MessageHeader::size, size, GNUNET_MessageHeader::type, IPv4UdpAddress::u4_port, IPv6UdpAddress::u6_port, udp_broadcast_receive(), UdpAddress::v4, and UdpAddress::v6.

Referenced by udp_plugin_select_v4(), and udp_plugin_select_v6().

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

◆ remove_timeout_messages_and_select()

static struct UDP_MessageWrapper* remove_timeout_messages_and_select ( struct Plugin plugin,
struct GNUNET_NETWORK_Handle sock 
)
static

Removes messages from the transmission queue that have timed out, and then selects a message that should be transmitted next.

Parameters
pluginthe UDP plugin
sockwhich socket should we process the queue for (v4 or v6)
Returns
message selected for transmission, or NULL for none

Definition at line 3067 of file plugin_transport_udp.c.

3069 {
3070  struct UDP_MessageWrapper *udpw;
3071  struct GNUNET_TIME_Relative remaining;
3072  struct GNUNET_ATS_Session *session;
3073  int removed;
3074 
3075  removed = GNUNET_NO;
3076  udpw = (sock == plugin->sockv4) ? plugin->ipv4_queue_head
3078  while (NULL != udpw)
3079  {
3080  session = udpw->session;
3081  /* Find messages with timeout */
3082  remaining = GNUNET_TIME_absolute_get_remaining (udpw->timeout);
3083  if (GNUNET_TIME_UNIT_ZERO.rel_value_us == remaining.rel_value_us)
3084  {
3085  /* Message timed out */
3086  removed = GNUNET_YES;
3087  dequeue (plugin, udpw);
3088  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
3089  GNUNET_free (udpw);
3090 
3091  if (sock == plugin->sockv4)
3092  {
3093  udpw = plugin->ipv4_queue_head;
3094  }
3095  else if (sock == plugin->sockv6)
3096  {
3097  udpw = plugin->ipv6_queue_head;
3098  }
3099  else
3100  {
3101  GNUNET_break (0); /* should never happen */
3102  udpw = NULL;
3103  }
3105  "# messages discarded due to timeout",
3106  1,
3107  GNUNET_NO);
3108  }
3109  else
3110  {
3111  /* Message did not time out, check transmission time */
3113  if (0 == remaining.rel_value_us)
3114  {
3115  /* this message is not delayed */
3117  "Message for peer `%s' (%lu bytes) is not delayed \n",
3118  GNUNET_i2s (&udpw->session->target),
3119  (unsigned long) udpw->payload_size);
3120  break; /* Found message to send, break */
3121  }
3122  else
3123  {
3124  /* Message is delayed, try next */
3126  "Message for peer `%s' (%lu bytes) is delayed for %s\n",
3127  GNUNET_i2s (&udpw->session->target),
3128  (unsigned long) udpw->payload_size,
3130  udpw = udpw->next;
3131  }
3132  }
3133  }
3134  if (GNUNET_YES == removed)
3135  notify_session_monitor (session->plugin,
3136  session,
3138  return udpw;
3139 }

References dequeue(), Plugin::env, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_UNIT_ZERO, GNUNET_TRANSPORT_SS_UPDATE, GNUNET_YES, Plugin::ipv4_queue_head, Plugin::ipv6_queue_head, LOG, UDP_MessageWrapper::next, notify_session_monitor(), UDP_MessageWrapper::payload_size, plugin, GNUNET_ATS_Session::plugin, UDP_MessageWrapper::qc, UDP_MessageWrapper::qc_cls, GNUNET_TIME_Relative::rel_value_us, UDP_MessageWrapper::session, Plugin::sockv4, Plugin::sockv6, GNUNET_ATS_Session::target, UDP_MessageWrapper::timeout, and UDP_MessageWrapper::transmission_time.

Referenced by udp_select_send().

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

◆ analyze_send_error()

static void analyze_send_error ( struct Plugin plugin,
const struct sockaddr *  sa,
socklen_t  slen,
int  error 
)
static

We failed to transmit a message via UDP.

Generate a descriptive error message.

Parameters
pluginour plugin
satarget address we were trying to reach
slennumber of bytes in sa
errorthe errno value returned from the sendto() call

Definition at line 3152 of file plugin_transport_udp.c.

3156 {
3157  enum GNUNET_NetworkType type;
3158 
3159  type = plugin->env->get_address_type (plugin->env->cls, sa, slen);
3160  if (((GNUNET_NT_LAN == type) || (GNUNET_NT_WAN == type)) &&
3161  ((ENETUNREACH == errno) || (ENETDOWN == errno)))
3162  {
3163  if (slen == sizeof(struct sockaddr_in))
3164  {
3165  /* IPv4: "Network unreachable" or "Network down"
3166  *
3167  * This indicates we do not have connectivity
3168  */
3170  _ ("UDP could not transmit message to `%s': "
3171  "Network seems down, please check your network configuration\n"),
3172  GNUNET_a2s (sa, slen));
3173  }
3174  if (slen == sizeof(struct sockaddr_in6))
3175  {
3176  /* IPv6: "Network unreachable" or "Network down"
3177  *
3178  * This indicates that this system is IPv6 enabled, but does not
3179  * have a valid global IPv6 address assigned or we do not have
3180  * connectivity
3182  _ (
3183  "UDP could not transmit IPv6 message! "
3184  "Please check your network configuration and disable IPv6 if your "
3185  "connection does not have a global IPv6 address\n"));
3186  }
3187  }
3188  else
3189  {
3191  "UDP could not transmit message to `%s': `%s'\n",
3192  GNUNET_a2s (sa, slen),
3193  strerror (error));
3194  }
3195 }
@ GNUNET_NT_WAN
Wide area network (i.e.
Definition: gnunet_nt_lib.h:55
@ GNUNET_NT_LAN
Local area network.
Definition: gnunet_nt_lib.h:50
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model

References _, GNUNET_DATACACHE_PluginEnvironment::cls, Plugin::env, GNUNET_a2s(), GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_WARNING, GNUNET_NT_LAN, GNUNET_NT_WAN, LOG, plugin, and type.

Referenced by udp_select_send().

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

◆ udp_select_send()

static void udp_select_send ( struct Plugin plugin,
struct GNUNET_NETWORK_Handle sock 
)
static

It is time to try to transmit a UDP message.

Select one and send.

Parameters
pluginthe plugin
sockwhich socket (v4/v6) to send on

Definition at line 3206 of file plugin_transport_udp.c.

3207 {
3208  ssize_t sent;
3209  socklen_t slen;
3210  const struct sockaddr *a;
3211  const struct IPv4UdpAddress *u4;
3212  struct sockaddr_in a4;
3213  const struct IPv6UdpAddress *u6;
3214  struct sockaddr_in6 a6;
3215  struct UDP_MessageWrapper *udpw;
3216 
3217  /* Find message(s) to send */
3218  while (NULL != (udpw = remove_timeout_messages_and_select (plugin, sock)))
3219  {
3220  if (sizeof(struct IPv4UdpAddress) ==
3221  udpw->session->address->address_length)
3222  {
3223  u4 = udpw->session->address->address;
3224  memset (&a4, 0, sizeof(a4));
3225  a4.sin_family = AF_INET;
3226 #if HAVE_SOCKADDR_IN_SIN_LEN
3227  a4.sin_len = sizeof(a4);
3228 #endif
3229  a4.sin_port = u4->u4_port;
3230  a4.sin_addr.s_addr = u4->ipv4_addr;
3231  a = (const struct sockaddr *) &a4;
3232  slen = sizeof(a4);
3233  }
3234  else if (sizeof(struct IPv6UdpAddress) ==
3235  udpw->session->address->address_length)
3236  {
3237  u6 = udpw->session->address->address;
3238  memset (&a6, 0, sizeof(a6));
3239  a6.sin6_family = AF_INET6;
3240 #if HAVE_SOCKADDR_IN_SIN_LEN
3241  a6.sin6_len = sizeof(a6);
3242 #endif
3243  a6.sin6_port = u6->u6_port;
3244  a6.sin6_addr = u6->ipv6_addr;
3245  a = (const struct sockaddr *) &a6;
3246  slen = sizeof(a6);
3247  }
3248  else
3249  {
3250  GNUNET_break (0);
3251  dequeue (plugin, udpw);
3252  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
3254  udpw->session,
3256  GNUNET_free (udpw);
3257  continue;
3258  }
3259  sent = GNUNET_NETWORK_socket_sendto (sock,
3260  udpw->msg_buf,
3261  udpw->msg_size,
3262  a,
3263  slen);
3264  udpw->session->last_transmit_time =
3266  udpw->session->last_transmit_time);
3267  dequeue (plugin, udpw);
3268  if (GNUNET_SYSERR == sent)
3269  {
3270  /* Failure */
3271  analyze_send_error (plugin, a, slen, errno);
3272  udpw->qc (udpw->qc_cls, udpw, GNUNET_SYSERR);
3274  "# UDP, total, bytes, sent, failure",
3275  sent,
3276  GNUNET_NO);
3278  "# UDP, total, messages, sent, failure",
3279  1,
3280  GNUNET_NO);
3281  }
3282  else
3283  {
3284  /* Success */
3286  "UDP transmitted %u-byte message to `%s' `%s' (%d: %s)\n",
3287  (unsigned int) (udpw->msg_size),
3288  GNUNET_i2s (&udpw->session->target),
3289  GNUNET_a2s (a, slen),
3290  (int) sent,
3291  (sent < 0) ? strerror (errno) : "ok");
3293  "# UDP, total, bytes, sent, success",
3294  sent,
3295  GNUNET_NO);
3297  "# UDP, total, messages, sent, success",
3298  1,
3299  GNUNET_NO);
3300  if (NULL != udpw->frag_ctx)
3301  udpw->frag_ctx->on_wire_size += udpw->msg_size;
3302  udpw->qc (udpw->qc_cls, udpw, GNUNET_OK);
3303  }
3305  GNUNET_free (udpw);
3306  }
3307 }
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition: network.c:846
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:224
static void analyze_send_error(struct Plugin *plugin, const struct sockaddr *sa, socklen_t slen, int error)
We failed to transmit a message via UDP.
static struct UDP_MessageWrapper * remove_timeout_messages_and_select(struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
Removes messages from the transmission queue that have timed out, and then selects a message that sho...

References GNUNET_HELLO_Address::address, GNUNET_ATS_Session::address, GNUNET_HELLO_Address::address_length, analyze_send_error(), dequeue(), Plugin::env, UDP_MessageWrapper::frag_ctx, GNUNET_a2s(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_NETWORK_socket_sendto(), GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_max(), GNUNET_TRANSPORT_SS_UPDATE, IPv4UdpAddress::ipv4_addr, IPv6UdpAddress::ipv6_addr, GNUNET_ATS_Session::last_transmit_time, LOG, UDP_MessageWrapper::msg_buf, UDP_MessageWrapper::msg_size, notify_session_monitor(), UDP_FragmentationContext::on_wire_size, plugin, UDP_MessageWrapper::qc, UDP_MessageWrapper::qc_cls, remove_timeout_messages_and_select(), UDP_MessageWrapper::session, GNUNET_ATS_Session::target, IPv4UdpAddress::u4_port, and IPv6UdpAddress::u6_port.

Referenced by udp_plugin_select_v4(), and udp_plugin_select_v6().

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

◆ setup_sockets()

static unsigned int setup_sockets ( struct Plugin plugin,
const struct sockaddr_in6 *  bind_v6,
const struct sockaddr_in *  bind_v4 
)
static

Setup the UDP sockets (for IPv4 and IPv6) for the plugin.

Parameters
pluginthe plugin to initialize
bind_v6IPv6 address to bind to (can be NULL, for 'any')
bind_v4IPv4 address to bind to (can be NULL, for 'any')
Returns
number of sockets that were successfully bound

Definition at line 3376 of file plugin_transport_udp.c.

3379 {
3380  int tries;
3381  unsigned int sockets_created = 0;
3382  struct sockaddr_in6 server_addrv6;
3383  struct sockaddr_in server_addrv4;
3384  const struct sockaddr *server_addr;
3385  const struct sockaddr *addrs[2];
3386  socklen_t addrlens[2];
3387  socklen_t addrlen;
3388  int eno;
3389 
3390  /* Create IPv6 socket */
3391  eno = EINVAL;
3392  if (GNUNET_YES == plugin->enable_ipv6)
3393  {
3394  plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
3395  if (NULL == plugin->sockv6)
3396  {
3398  _ ("Disabling IPv6 since it is not supported on this system!\n"));
3400  }
3401  else
3402  {
3403  memset (&server_addrv6, 0, sizeof(struct sockaddr_in6));
3404 #if HAVE_SOCKADDR_IN_SIN_LEN
3405  server_addrv6.sin6_len = sizeof(struct sockaddr_in6);
3406 #endif
3407  server_addrv6.sin6_family = AF_INET6;
3408  if (NULL != bind_v6)
3409  server_addrv6.sin6_addr = bind_v6->sin6_addr;
3410  else
3411  server_addrv6.sin6_addr = in6addr_any;
3412 
3413  if (0 == plugin->port) /* autodetect */
3414  server_addrv6.sin6_port = htons (
3416  + 32000);
3417  else
3418  server_addrv6.sin6_port = htons (plugin->port);
3419  addrlen = sizeof(struct sockaddr_in6);
3420  server_addr = (const struct sockaddr *) &server_addrv6;
3421 
3422  tries = 0;
3423  while (tries < 10)
3424  {
3426  "Binding to IPv6 `%s'\n",
3427  GNUNET_a2s (server_addr, addrlen));
3428  /* binding */
3429  if (GNUNET_OK ==
3430  GNUNET_NETWORK_socket_bind (plugin->sockv6, server_addr, addrlen))
3431  break;
3432  eno = errno;
3433  if (0 != plugin->port)
3434  {
3435  tries = 10; /* fail immediately */
3436  break; /* bind failed on specific port */
3437  }
3438  /* autodetect */
3439  server_addrv6.sin6_port = htons (
3441  + 32000);
3442  tries++;
3443  }
3444  if (tries >= 10)
3445  {
3448  plugin->sockv6 = NULL;
3449  }
3450  else
3451  {
3452  plugin->port = ntohs (server_addrv6.sin6_port);
3453  }
3454  if (NULL != plugin->sockv6)
3455  {
3457  "IPv6 UDP socket created listinging at %s\n",
3458  GNUNET_a2s (server_addr, addrlen));
3459  addrs[sockets_created] = server_addr;
3460  addrlens[sockets_created] = addrlen;
3461  sockets_created++;
3462  }
3463  else
3464  {
3466  _ ("Failed to bind UDP socket to %s: %s\n"),
3467  GNUNET_a2s (server_addr, addrlen),
3468  strerror (eno));
3469  }
3470  }
3471  }
3472 
3473  /* Create IPv4 socket */
3474  eno = EINVAL;
3475  plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
3476  if (NULL == plugin->sockv4)
3477  {
3480  _ ("Disabling IPv4 since it is not supported on this system!\n"));
3482  }
3483  else
3484  {
3485  memset (&server_addrv4, 0, sizeof(struct sockaddr_in));
3486 #if HAVE_SOCKADDR_IN_SIN_LEN
3487  server_addrv4.sin_len = sizeof(struct sockaddr_in);
3488 #endif
3489  server_addrv4.sin_family = AF_INET;
3490  if (NULL != bind_v4)
3491  server_addrv4.sin_addr = bind_v4->sin_addr;
3492  else
3493  server_addrv4.sin_addr.s_addr = INADDR_ANY;
3494 
3495  if (0 == plugin->port)
3496  /* autodetect */
3497  server_addrv4.sin_port = htons (
3499  else
3500  server_addrv4.sin_port = htons (plugin->port);
3501 
3502  addrlen = sizeof(struct sockaddr_in);
3503  server_addr = (const struct sockaddr *) &server_addrv4;
3504 
3505  tries = 0;
3506  while (tries < 10)
3507  {
3509  "Binding to IPv4 `%s'\n",
3510  GNUNET_a2s (server_addr, addrlen));
3511 
3512  /* binding */
3513  if (GNUNET_OK ==
3514  GNUNET_NETWORK_socket_bind (plugin->sockv4, server_addr, addrlen))
3515  break;
3516  eno = errno;
3517  if (0 != plugin->port)
3518  {
3519  tries = 10; /* fail */
3520  break; /* bind failed on specific port */
3521  }
3522 
3523  /* autodetect */
3524  server_addrv4.sin_port = htons (
3526  tries++;
3527  }
3528  if (tries >= 10)
3529  {
3532  plugin->sockv4 = NULL;
3533  }
3534  else
3535  {
3536  plugin->port = ntohs (server_addrv4.sin_port);
3537  }
3538 
3539  if (NULL != plugin->sockv4)
3540  {
3542  "IPv4 socket created on port %s\n",
3543  GNUNET_a2s (server_addr, addrlen));
3544  addrs[sockets_created] = server_addr;
3545  addrlens[sockets_created] = addrlen;
3546  sockets_created++;
3547  }
3548  else
3549  {
3551  _ ("Failed to bind UDP socket to %s: %s\n"),
3552  GNUNET_a2s (server_addr, addrlen),
3553  strerror (eno));
3554  }
3555  }
3556 
3557  if (0 == sockets_created)
3558  {
3559  LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Failed to open UDP sockets\n"));
3560  return 0; /* No sockets created, return */
3561  }
3565  "transport-udp",
3566  IPPROTO_UDP,
3567  sockets_created,
3568  addrs,
3569  addrlens,
3571  NULL,
3572  plugin);
3573  return sockets_created;
3574 }
static struct GNUNET_NETWORK_Handle * bind_v6()
Create an IPv6 listen socket bound to our port.
static struct GNUNET_NETWORK_Handle * bind_v4()
Create an IPv4 listen socket bound to our port.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition: nat_api.c:378
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:907
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:485
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:560
static void udp_nat_port_map_callback(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Our external IP address/port mapping has changed.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.

References _, bind_v4(), bind_v6(), GNUNET_DATACACHE_PluginEnvironment::cfg, Plugin::enable_ipv4, Plugin::enable_ipv6, Plugin::env, GNUNET_a2s(), GNUNET_CRYPTO_QUALITY_STRONG, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log_strerror, GNUNET_NAT_register(), GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NO, GNUNET_OK, GNUNET_YES, LOG, Plugin::nat, plugin, Plugin::port, schedule_select_v4(), schedule_select_v6(), Plugin::sockv4, Plugin::sockv6, and udp_nat_port_map_callback().

Referenced by libgnunet_plugin_transport_udp_init().

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

◆ libgnunet_plugin_transport_udp_init()

void* libgnunet_plugin_transport_udp_init ( void *  cls)

The exported method.

Makes the core api available via a global and returns the udp transport API.

Parameters
clsour struct GNUNET_TRANSPORT_PluginEnvironment
Returns
our struct GNUNET_TRANSPORT_PluginFunctions

Definition at line 3585 of file plugin_transport_udp.c.

3586 {
3589  struct Plugin *p;
3590  unsigned long long port;
3591  unsigned long long aport;
3592  unsigned long long udp_max_bps;
3593  int enable_v6;
3594  int enable_broadcasting;
3595  int enable_broadcasting_recv;
3596  char *bind4_address;
3597  char *bind6_address;
3599  struct sockaddr_in server_addrv4;
3600  struct sockaddr_in6 server_addrv6;
3601  unsigned int res;
3602  int have_bind4;
3603  int have_bind6;
3604 
3605  if (NULL == env->receive)
3606  {
3607  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3608  initialize the plugin or the API */
3610  api->cls = NULL;
3614  return api;
3615  }
3616 
3617  /* Get port number: port == 0 : autodetect a port,
3618  * > 0 : use this port, not given : 2086 default */
3620  "transport-udp",
3621  "PORT",
3622  &port))
3623  port = 2086;
3624  if (port > 65535)
3625  {
3627  "transport-udp",
3628  "PORT",
3629  _ ("must be in [0,65535]"));
3630  return NULL;
3631  }
3633  "transport-udp",
3634  "ADVERTISED_PORT",
3635  &aport))
3636  aport = port;
3637  if (aport > 65535)
3638  {
3640  "transport-udp",
3641  "ADVERTISED_PORT",
3642  _ ("must be in [0,65535]"));
3643  return NULL;
3644  }
3645 
3646  if (GNUNET_YES ==
3647  GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "nat", "DISABLEV6"))
3648  enable_v6 = GNUNET_NO;
3649  else
3650  enable_v6 = GNUNET_YES;
3651 
3652  have_bind4 = GNUNET_NO;
3653  memset (&server_addrv4, 0, sizeof(server_addrv4));
3655  "transport-udp",
3656  "BINDTO",
3657  &bind4_address))
3658  {
3660  "Binding UDP plugin to specific address: `%s'\n",
3661  bind4_address);
3662  if (1 != inet_pton (AF_INET, bind4_address, &server_addrv4.sin_addr))
3663  {
3665  "transport-udp",
3666  "BINDTO",
3667  _ ("must be valid IPv4 address"));
3668  GNUNET_free (bind4_address);
3669  return NULL;
3670  }
3671  have_bind4 = GNUNET_YES;
3672  }
3673  GNUNET_free (bind4_address);
3674  have_bind6 = GNUNET_NO;
3675  memset (&server_addrv6, 0, sizeof(server_addrv6));
3677  "transport-udp",
3678  "BINDTO6",
3679  &bind6_address))
3680  {
3682  "Binding udp plugin to specific address: `%s'\n",
3683  bind6_address);
3684  if (1 != inet_pton (AF_INET6, bind6_address, &server_addrv6.sin6_addr))
3685  {
3687  "transport-udp",
3688  "BINDTO6",
3689  _ ("must be valid IPv6 address"));
3690  GNUNET_free (bind6_address);
3691  return NULL;
3692  }
3693  have_bind6 = GNUNET_YES;
3694  }
3695  GNUNET_free (bind6_address);
3696 
3697  enable_broadcasting = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
3698  "transport-udp",
3699  "BROADCAST");
3700  if (enable_broadcasting == GNUNET_SYSERR)
3701  enable_broadcasting = GNUNET_NO;
3702 
3703  enable_broadcasting_recv =
3705  "transport-udp",
3706  "BROADCAST_RECEIVE");
3707  if (enable_broadcasting_recv == GNUNET_SYSERR)
3708  enable_broadcasting_recv = GNUNET_YES;
3709 
3710  if (GNUNET_SYSERR ==
3712  "transport-udp",
3713  "BROADCAST_INTERVAL",
3714  &interval))
3715  {
3717  }
3719  "transport-udp",
3720  "MAX_BPS",
3721  &udp_max_bps))
3722  {
3723  /* 50 MB/s == infinity for practical purposes */
3724  udp_max_bps = 1024 * 1024 * 50;
3725  }
3726 
3727  p = GNUNET_new (struct Plugin);
3728  p->port = port;
3729  p->aport = aport;
3730  p->broadcast_interval = interval;
3731  p->enable_ipv6 = enable_v6;
3732  p->enable_ipv4 = GNUNET_YES; /* default */
3733  p->enable_broadcasting = enable_broadcasting;
3734  p->enable_broadcasting_receiving = enable_broadcasting_recv;
3735  p->env = env;
3737  p->defrag_ctxs =
3739  GNUNET_BANDWIDTH_tracker_init (&p->tracker,
3740  NULL,
3741  NULL,
3743  (uint32_t) udp_max_bps),
3744  30);
3745  res = setup_sockets (p,
3746  (GNUNET_YES == have_bind6) ? &server_addrv6 : NULL,
3747  (GNUNET_YES == have_bind4) ? &server_addrv4 : NULL);
3748  if ((0 == res) || ((NULL == p->sockv4) && (NULL == p->sockv6)))
3749  {
3750  LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to create UDP network sockets\n"));
3752  GNUNET_CONTAINER_heap_destroy (p->defrag_ctxs);
3753  if (NULL != p->nat)
3754  GNUNET_NAT_unregister (p->nat);
3755  GNUNET_free (p);
3756  return NULL;
3757  }
3758 
3759  /* Setup broadcasting and receiving beacons */
3760  setup_broadcast (p, &server_addrv6, &server_addrv4);
3761 
3763  api->cls = p;
3772  api->send = &udp_plugin_send;
3777  return api;
3778 }
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static int res
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init(uint32_t bytes_per_second)
Create a new bandwidth value.
Definition: bandwidth.c:39
void GNUNET_BANDWIDTH_tracker_init(struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s)
Initialize bandwidth tracker.
Definition: bandwidth.c:302
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.