GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
nat.c File Reference

Library for NAT traversal related functionality. More...

#include "platform.h"
#include "gnunet_util_lib.h"
Include dependency graph for nat.c:

Go to the source code of this file.

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util-nat", __VA_ARGS__)
 
#define SEND_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, 10)
 
#define TIMEOUT_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
 
#define RTT_DIFF    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 150)
 Difference of the average RTT for the DistanceVector calculate by us and the target we are willing to accept for starting the burst.
 

Functions

struct GNUNET_BurstSyncGNUNET_get_burst_sync_msg (struct GNUNET_TIME_Relative rtt_average, enum GNUNET_GenericReturnValue sync_ready)
 Create GNUNET_BurstSync message.
 
void GNUNET_is_burst_ready (struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
 Checks if we are ready and starts burst when we and the other peer is ready.
 
void GNUNET_stop_burst (struct GNUNET_NETWORK_Handle *do_not_touch)
 Method to stop all sockets we established to the other peer.
 
static void sock_read (void *cls)
 Socket read task.
 
static struct sockaddr * udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
 Convert UDP bind specification to a struct sockaddr *
 
static void timeout_task_cb (void *cls)
 
static void read_send (void *cls)
 
struct GNUNET_SCHEDULER_TaskGNUNET_get_udp_socket (struct GNUNET_UdpSocketInfo *sock_info, GNUNET_NotifyUdpSocket nus)
 Method to get a UDP socket for a peer that is natted.
 

Variables

static struct GNUNET_UdpSocketInfosock_infos_head
 
static struct GNUNET_UdpSocketInfosock_infos_tail
 
static struct GNUNET_SCHEDULER_Taskread_send_task
 
unsigned int udp_port
 
unsigned int nr_open_sockets
 Maximum of open sockets.
 

Detailed Description

Library for NAT traversal related functionality.

Author
t3sserakt

Definition in file nat.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-nat", __VA_ARGS__)

Definition at line 31 of file nat.c.

◆ SEND_DELAY

Definition at line 33 of file nat.c.

67{
68 struct GNUNET_BurstSync *burst_sync = GNUNET_new (struct GNUNET_BurstSync);
69
71 burst_sync->sync_ready = sync_ready;
72
73 return burst_sync;
74}
75
76
87void
89 struct GNUNET_BurstSync *burst_sync,
91 struct GNUNET_StartBurstCls *task_cls)
92{
93 struct GNUNET_TIME_Relative other_rtt;
94 struct GNUNET_TIME_Relative rel1;
95 struct GNUNET_TIME_Relative rel2;
96
97 other_rtt = GNUNET_TIME_relative_ntoh (burst_sync->rtt_average);
98 rel1 = GNUNET_TIME_relative_subtract (other_rtt, rtt_average);
99 rel2 = GNUNET_TIME_relative_subtract (rtt_average, other_rtt);
101 "other sync ready %u, other rtt %lu and rtt %lu rel1 %lu rel2 %lu\n",
102 burst_sync->sync_ready,
103 (unsigned long) other_rtt.rel_value_us,
104 (unsigned long) rtt_average.rel_value_us,
105 (unsigned long) rel1.rel_value_us,
106 (unsigned long) rel2.rel_value_us);
107 if ((other_rtt.rel_value_us != GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us &&
108 rtt_average.rel_value_us != GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) &&
109 rel1.rel_value_us < RTT_DIFF.rel_value_us &&
110 rel2.rel_value_us < RTT_DIFF.rel_value_us)
111 {
113 "other sync ready 1\n");
114 if (GNUNET_YES == burst_sync->sync_ready)
115 {
117 "other sync ready 2\n");
118 task_cls->delay = GNUNET_TIME_relative_saturating_multiply (rtt_average,
119 2);
120 }
121 else
122 {
124 "other sync ready 3\n");
125 task_cls->delay = GNUNET_TIME_relative_saturating_multiply (rtt_average,
126 4);
127 }
128 task_cls->sync_ready = GNUNET_YES;
129 task (task_cls);
130 }
131 else
132 {
134 "other sync ready 6\n");
135 task_cls->sync_ready = GNUNET_NO;
136 }
137}
138
139
140void
141GNUNET_stop_burst (struct GNUNET_NETWORK_Handle *do_not_touch);
142
143
149static void
150sock_read (void *cls)
151{
152 struct GNUNET_UdpSocketInfo *sock_info = cls;
153 struct sockaddr_storage sa;
154 socklen_t salen = sizeof(sa);
155 char buf[UINT16_MAX];
156 ssize_t rcvd;
157
158 sock_info->read_task = NULL;
159
161 "Reading from socket\n");
162 while (1)
163 {
164 rcvd = GNUNET_NETWORK_socket_recvfrom (sock_info->udp_sock,
165 buf,
166 sizeof(buf),
167 (struct sockaddr *) &sa,
168 &salen);
169 if (-1 == rcvd)
170 {
171 struct sockaddr *addr = (struct sockaddr*) &sa;
172
173 if (EAGAIN == errno)
174 break; // We are done reading data
176 "Failed to recv from %s family %d failed sock %p\n",
177 GNUNET_a2s ((struct sockaddr*) &sa,
178 sizeof (*addr)),
179 addr->sa_family,
180 sock_info->udp_sock);
182 return;
183 }
185 "Read %llu bytes\n",
186 (unsigned long long) rcvd);
187 if (0 == rcvd)
188 {
189 GNUNET_break_op (0);
191 "Read 0 bytes from UDP socket\n");
192 return;
193 }
194 /* first, see if it is a GNUNET_BurstMessage */
195 if (rcvd == sizeof (struct GNUNET_BurstMessage))
196 {
197 struct GNUNET_BurstMessage *bm = (struct GNUNET_BurstMessage *) buf;
198
200 "Received a burst message from remote port %u to local port %u!\n",
201 bm->local_port,
202 sock_info->port);
203 sock_info->actual_address = (struct sockaddr *) &sa;
204 sock_info->nus (sock_info);
205 GNUNET_stop_burst (sock_info->udp_sock);
206 return;
207 }
208 else
210 "Received a non burst message on local port %u %lu!\n",
211 sock_info->port,
212 sizeof (struct GNUNET_BurstMessage));
213 }
214}
215
216
224static struct sockaddr *
225udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
226{
227 struct sockaddr *in;
228 unsigned int port;
229 char dummy[2];
230 char *colon;
231 char *cp;
232
233 cp = GNUNET_strdup (bindto);
234 colon = strrchr (cp, ':');
235 if (NULL != colon)
236 {
237 /* interpret value after colon as port */
238 *colon = '\0';
239 colon++;
240 if (1 == sscanf (colon, "%u%1s", &port, dummy))
241 {
242 /* interpreting value as just a PORT number */
243 if (port > UINT16_MAX)
244 {
246 "BINDTO specification `%s' invalid: value too large for port\n",
247 bindto);
248 GNUNET_free (cp);
249 return NULL;
250 }
251 }
252 else
253 {
254 GNUNET_log (
256 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
257 bindto);
258 GNUNET_free (cp);
259 return NULL;
260 }
261 }
262 else
263 {
264 /* interpret missing port as 0, aka pick any free one */
265 port = 0;
266 }
267 {
268 /* try IPv4 */
269 struct sockaddr_in v4;
270
271 memset (&v4, 0, sizeof(v4));
272 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
273 {
274 v4.sin_family = AF_INET;
275 v4.sin_port = htons ((uint16_t) port);
276#if HAVE_SOCKADDR_IN_SIN_LEN
277 v4.sin_len = sizeof(struct sockaddr_in);
278#endif
279 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
280 *sock_len = sizeof(struct sockaddr_in);
281 GNUNET_free (cp);
282 return in;
283 }
284 }
285 {
286 /* try IPv6 */
287 struct sockaddr_in6 v6;
288 const char *start;
289
290 memset (&v6, 0, sizeof(v6));
291 start = cp;
292 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
293 {
294 start++; /* skip over '[' */
295 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
296 }
297 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
298 {
299 v6.sin6_family = AF_INET6;
300 v6.sin6_port = htons ((uint16_t) port);
301#if HAVE_SOCKADDR_IN_SIN_LEN
302 v6.sin6_len = sizeof(struct sockaddr_in6);
303#endif
304 in = GNUNET_memdup (&v6, sizeof(v6));
305 *sock_len = sizeof(v6);
306 GNUNET_free (cp);
307 return in;
308 }
309 }
310 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
311 GNUNET_free (cp);
312 return NULL;
313}
314
315
316static void
317timeout_task_cb (void *cls)
318{
319 struct GNUNET_UdpSocketInfo *sock_info = cls;
320
322 "timeout task\n");
323 if (NULL != sock_info->read_task)
328 "timeout nr_open_sockets %u\n",
330 if (NULL != sock_infos_head)
333 sock_info);
335 "freeing sock_info %p\n",
336 sock_info);
337 GNUNET_free (sock_info);
338}
339
340
341static void
342read_send (void *cls)
343{
344 struct GNUNET_UdpSocketInfo *sock_info = cls;
347 struct GNUNET_BurstMessage bm;
348 struct sockaddr *in;
349 socklen_t in_len;
350 char dgram[sizeof (struct GNUNET_BurstMessage)];
351 char *address;
352 struct sockaddr *bind_in;
353 socklen_t bind_in_len;
354 char *bind_address;
355 struct GNUNET_TIME_Relative again = GNUNET_TIME_relative_multiply (sock_info->
356 rtt,
357 4);
358
359 read_send_task = NULL;
360 GNUNET_memcpy (si, sock_info, sizeof (struct GNUNET_UdpSocketInfo));
361 if (sock_info->std_port == udp_port)
362 udp_port++;
363 if (512 < nr_open_sockets)
364 {
366 "Trying again in %s",
369 &read_send,
370 sock_info);
371 }
372
374 "%s:%u",
375 sock_info->address,
376 udp_port);
378 "3 sock %p addr %s addr %s %u\n",
379 sock_info,
380 sock_info->address,
381 address,
383 in = udp_address_to_sockaddr (address, &in_len);
384 if (NULL == in)
385 {
387 "Failed to setup UDP socket address with path `%s'\n",
388 address);
389 GNUNET_assert (0);
390 }
392 address = NULL;
393 GNUNET_asprintf (&bind_address,
394 "%s:%u",
395 sock_info->bind_address,
396 udp_port);
398 "4 sock addr %s addr %s\n",
399 sock_info->bind_address,
400 bind_address);
401 bind_in = udp_address_to_sockaddr (bind_address, &bind_in_len);
402 if (NULL == bind_in)
403 {
405 "Failed to setup UDP socket bind address with path `%s'\n",
406 bind_address);
407 GNUNET_assert (0);
408 }
409 GNUNET_free (bind_address);
410 bind_address = NULL;
411 udp_sock =
412 GNUNET_NETWORK_socket_create (bind_in->sa_family,
413 SOCK_DGRAM,
414 IPPROTO_UDP);
415 if (NULL == udp_sock)
416 {
419 "Failed to create socket for %s family %d\n",
420 GNUNET_a2s (bind_in,
421 bind_in_len),
422 in->sa_family);
423 GNUNET_free (bind_in);
424 if (EMFILE == errno)
425 {
427 "Trying again in %s, because of EMFILE\n",
430 &read_send,
431 sock_info);
432 GNUNET_free (si);
433 GNUNET_free (in);
434 GNUNET_free (bind_in);
435 return;
436 }
437 GNUNET_free (sock_info);
438 goto next_port;
439 }
440 if (GNUNET_OK !=
442 bind_in,
443 bind_in_len))
444 {
447 "Failed to bind socket for %s family %d sock %p\n",
448 GNUNET_a2s (bind_in,
449 bind_in_len),
450 bind_in->sa_family,
451 udp_sock);
453 udp_sock = NULL;
454 GNUNET_free (sock_info);
455 goto next_port;
456 }
458 bm.local_port = udp_port;
459 sock_info->udp_sock = udp_sock;
460 sock_info->port = udp_port;
463 udp_sock,
464 &sock_read,
465 sock_info);
467 "Timeout in %s\n",
469 ;
472 sock_info);
473
475
476 memcpy (dgram, &bm, sizeof(bm));
478 dgram,
479 sizeof(dgram),
480 in,
481 in_len))
482 {
484 "Sending burst to %s family %d failed sock %p\n",
485 GNUNET_a2s (in,
486 in_len),
487 in->sa_family,
488 udp_sock);
489 timeout_task_cb (sock_info);
490 }
491
492next_port:
493 GNUNET_free (si);
494 GNUNET_free (in);
495 GNUNET_free (bind_in);
496
497 if (65535 == udp_port)
498 return;
499 udp_port++;
500
502 &read_send,
503 si);
504}
505
506
510{
511 struct GNUNET_BurstMessage bm = {0};
513 char dgram[sizeof (struct GNUNET_BurstMessage)];
514 char *address;
515 struct sockaddr *in;
516 socklen_t in_len;
517
519 "%s:%u",
520 sock_info->address,
521 sock_info->std_port);
523 "2 sock addr %s addr %s rtt %s %u\n",
524 sock_info->address,
525 address,
526 GNUNET_TIME_relative2s (sock_info->rtt,
527 false),
528 sock_info->std_port);
529 bm.local_port = sock_info->std_port;
530 in = udp_address_to_sockaddr (address, &in_len);
531 memcpy (dgram, &bm, sizeof(bm));
532 if (-1 == GNUNET_NETWORK_socket_sendto (sock_info->udp_sock,
533 dgram,
534 sizeof(dgram),
535 in,
536 in_len))
537 {
539 "Sending burst to %s family %d failed sock %p\n",
540 GNUNET_a2s (in,
541 in_len),
542 in->sa_family,
543 sock_info->udp_sock);
544 }
545
546 nr_open_sockets = 0;
547 udp_port = 1024;
548 sock_info->has_port = GNUNET_NO;
549 sock_info->nus = nus;
550
551 GNUNET_memcpy (si, sock_info, sizeof (struct GNUNET_UdpSocketInfo));
552
554 &read_send,
555 si);
556 GNUNET_free (in);
558 return read_send_task;
559}
560
561
562void
563GNUNET_stop_burst (struct GNUNET_NETWORK_Handle *do_not_touch)
564{
565 struct GNUNET_UdpSocketInfo *sock_info;
566 struct GNUNET_UdpSocketInfo *pos;
567
569 "stopping burst\n");
570 if (NULL != read_send_task)
571 {
573 read_send_task = NULL;
574 }
575 pos = sock_infos_head;
576 while (NULL != pos)
577 {
578 sock_info = pos;
579 pos = sock_info->next;
582 sock_info);
583 if (NULL != sock_info->read_task)
585 if (NULL != sock_info->timeout_task)
587 if (do_not_touch != sock_info->udp_sock)
588 {
590 if (NULL != sock_info->address)
591 GNUNET_free (sock_info->address);
593 "freeing sock_info %p\n",
594 sock_info);
595 GNUNET_free (sock_info);
596 }
597 }
598}
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static struct GNUNET_NETWORK_Handle * udp_sock
Our socket.
static char * address
GNS address for this phone.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
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 GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
void GNUNET_is_burst_ready(struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
Checks if we are ready and starts burst when we and the other peer is ready.
Definition nat.c:89
struct GNUNET_SCHEDULER_Task * GNUNET_get_udp_socket(struct GNUNET_UdpSocketInfo *sock_info, GNUNET_NotifyUdpSocket nus)
Method to get a UDP socket for a peer that is natted.
Definition nat.c:509
void GNUNET_stop_burst(struct GNUNET_NETWORK_Handle *do_not_touch)
Method to stop all sockets we established to the other peer.
Definition nat.c:564
void(* GNUNET_NotifyUdpSocket)(struct GNUNET_UdpSocketInfo *sock_info)
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
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:688
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:833
enum GNUNET_GenericReturnValue 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:439
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:772
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:1511
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
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:1277
const char * GNUNET_TIME_relative2s(struct GNUNET_TIME_Relative delta, bool do_round)
Give relative time in human-readable fancy format.
Definition time.c:264
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition time.c:630
struct GNUNET_TIME_Relative GNUNET_TIME_relative_saturating_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Saturating multiply relative time by a given factor.
Definition time.c:533
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:599
struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Subtract relative timestamp from the other.
Definition time.c:605
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:486
struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton(struct GNUNET_TIME_Relative a)
Convert relative time to network byte order.
Definition time.c:620
static void timeout_task_cb(void *cls)
Definition nat.c:318
#define RTT_DIFF
Difference of the average RTT for the DistanceVector calculate by us and the target we are willing to...
Definition nat.c:43
static void read_send(void *cls)
Definition nat.c:343
static void sock_read(void *cls)
Socket read task.
Definition nat.c:151
#define SEND_DELAY
Definition nat.c:33
static struct GNUNET_SCHEDULER_Task * read_send_task
Definition nat.c:50
#define TIMEOUT_DELAY
Definition nat.c:36
static struct sockaddr * udp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert UDP bind specification to a struct sockaddr *
Definition nat.c:226
static struct GNUNET_UdpSocketInfo * sock_infos_tail
Definition nat.c:48
static struct GNUNET_UdpSocketInfo * sock_infos_head
Definition nat.c:46
unsigned int nr_open_sockets
Maximum of open sockets.
Definition nat.c:57
unsigned int udp_port
Definition nat.c:52
Message send during burst mode.
unsigned int local_port
The local port the message was send from.
Wrapper struct with the average RTT of message to some peer and if this peer und us is ready to sync.
enum GNUNET_GenericReturnValue sync_ready
Is this peer already ready to sync.
struct GNUNET_TIME_RelativeNBO rtt_average
The average RTT for the peer to communicate with.
handle to a socket
Definition network.c:53
Entry in list of pending tasks.
Definition scheduler.c:136
Struct wrapping information we use for starting the burst.
struct GNUNET_TIME_Relative delay
The delay - calculate from the RTT and which peer was ready to sync first, after we will start the bu...
unsigned int sync_ready
We are ready to start the burst.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Struct with the socket we like to use to send messages to another peer.
const char * bind_address
Our address without port.
enum GNUNET_GenericReturnValue has_port
Flag indicating, if the address is without port information.
struct GNUNET_TIME_Relative rtt
The actual RTT between the peers.
GNUNET_NotifyUdpSocket nus
The notify function to call if burst mode was successful.
char * address
The address of the other peer without port.
unsigned int port
The port we are bound to.
struct GNUNET_UdpSocketInfo * next
This is a linked list.
unsigned int std_port
Default local port we are bound to.
struct sockaddr * actual_address
The address of the other peer we received a burst message from.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task for this socket.
struct GNUNET_NETWORK_Handle * udp_sock
struct GNUNET_SCHEDULER_Task * read_task
The read task for retrieving a burst message for this socket.

◆ TIMEOUT_DELAY

Definition at line 36 of file nat.c.

◆ RTT_DIFF

Difference of the average RTT for the DistanceVector calculate by us and the target we are willing to accept for starting the burst.

Definition at line 43 of file nat.c.

Function Documentation

◆ sock_read()

static void sock_read ( void *  cls)
static

Socket read task.

Parameters
clsNULL

Definition at line 151 of file nat.c.

152{
153 struct GNUNET_UdpSocketInfo *sock_info = cls;
154 struct sockaddr_storage sa;
155 socklen_t salen = sizeof(sa);
156 char buf[UINT16_MAX];
157 ssize_t rcvd;
158
159 sock_info->read_task = NULL;
160
162 "Reading from socket\n");
163 while (1)
164 {
165 rcvd = GNUNET_NETWORK_socket_recvfrom (sock_info->udp_sock,
166 buf,
167 sizeof(buf),
168 (struct sockaddr *) &sa,
169 &salen);
170 if (-1 == rcvd)
171 {
172 struct sockaddr *addr = (struct sockaddr*) &sa;
173
174 if (EAGAIN == errno)
175 break; // We are done reading data
177 "Failed to recv from %s family %d failed sock %p\n",
178 GNUNET_a2s ((struct sockaddr*) &sa,
179 sizeof (*addr)),
180 addr->sa_family,
181 sock_info->udp_sock);
183 return;
184 }
186 "Read %llu bytes\n",
187 (unsigned long long) rcvd);
188 if (0 == rcvd)
189 {
190 GNUNET_break_op (0);
192 "Read 0 bytes from UDP socket\n");
193 return;
194 }
195 /* first, see if it is a GNUNET_BurstMessage */
196 if (rcvd == sizeof (struct GNUNET_BurstMessage))
197 {
198 struct GNUNET_BurstMessage *bm = (struct GNUNET_BurstMessage *) buf;
199
201 "Received a burst message from remote port %u to local port %u!\n",
202 bm->local_port,
203 sock_info->port);
204 sock_info->actual_address = (struct sockaddr *) &sa;
205 sock_info->nus (sock_info);
206 GNUNET_stop_burst (sock_info->udp_sock);
207 return;
208 }
209 else
211 "Received a non burst message on local port %u %lu!\n",
212 sock_info->port,
213 sizeof (struct GNUNET_BurstMessage));
214 }
215}

References GNUNET_UdpSocketInfo::actual_address, GNUNET_a2s(), GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_recvfrom(), GNUNET_stop_burst(), GNUNET_BurstMessage::local_port, GNUNET_UdpSocketInfo::nus, GNUNET_UdpSocketInfo::port, GNUNET_UdpSocketInfo::read_task, and GNUNET_UdpSocketInfo::udp_sock.

Referenced by read_send().

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

◆ udp_address_to_sockaddr()

static struct sockaddr * udp_address_to_sockaddr ( const char *  bindto,
socklen_t *  sock_len 
)
static

Convert UDP bind specification to a struct sockaddr *

Parameters
bindtobind specification to convert
[out]sock_lenset to the length of the address
Returns
converted bindto specification

Definition at line 226 of file nat.c.

227{
228 struct sockaddr *in;
229 unsigned int port;
230 char dummy[2];
231 char *colon;
232 char *cp;
233
234 cp = GNUNET_strdup (bindto);
235 colon = strrchr (cp, ':');
236 if (NULL != colon)
237 {
238 /* interpret value after colon as port */
239 *colon = '\0';
240 colon++;
241 if (1 == sscanf (colon, "%u%1s", &port, dummy))
242 {
243 /* interpreting value as just a PORT number */
244 if (port > UINT16_MAX)
245 {
247 "BINDTO specification `%s' invalid: value too large for port\n",
248 bindto);
249 GNUNET_free (cp);
250 return NULL;
251 }
252 }
253 else
254 {
255 GNUNET_log (
257 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
258 bindto);
259 GNUNET_free (cp);
260 return NULL;
261 }
262 }
263 else
264 {
265 /* interpret missing port as 0, aka pick any free one */
266 port = 0;
267 }
268 {
269 /* try IPv4 */
270 struct sockaddr_in v4;
271
272 memset (&v4, 0, sizeof(v4));
273 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
274 {
275 v4.sin_family = AF_INET;
276 v4.sin_port = htons ((uint16_t) port);
277#if HAVE_SOCKADDR_IN_SIN_LEN
278 v4.sin_len = sizeof(struct sockaddr_in);
279#endif
280 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
281 *sock_len = sizeof(struct sockaddr_in);
282 GNUNET_free (cp);
283 return in;
284 }
285 }
286 {
287 /* try IPv6 */
288 struct sockaddr_in6 v6;
289 const char *start;
290
291 memset (&v6, 0, sizeof(v6));
292 start = cp;
293 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
294 {
295 start++; /* skip over '[' */
296 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
297 }
298 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
299 {
300 v6.sin6_family = AF_INET6;
301 v6.sin6_port = htons ((uint16_t) port);
302#if HAVE_SOCKADDR_IN_SIN_LEN
303 v6.sin6_len = sizeof(struct sockaddr_in6);
304#endif
305 in = GNUNET_memdup (&v6, sizeof(v6));
306 *sock_len = sizeof(v6);
307 GNUNET_free (cp);
308 return in;
309 }
310 }
311 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
312 GNUNET_free (cp);
313 return NULL;
314}

References dummy, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_memdup, GNUNET_strdup, port, and start.

Referenced by GNUNET_get_udp_socket(), and read_send().

Here is the caller graph for this function:

◆ timeout_task_cb()

static void timeout_task_cb ( void *  cls)
static

Definition at line 318 of file nat.c.

319{
320 struct GNUNET_UdpSocketInfo *sock_info = cls;
321
323 "timeout task\n");
324 if (NULL != sock_info->read_task)
329 "timeout nr_open_sockets %u\n",
331 if (NULL != sock_infos_head)
334 sock_info);
336 "freeing sock_info %p\n",
337 sock_info);
338 GNUNET_free (sock_info);
339}

References GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NETWORK_socket_close(), GNUNET_SCHEDULER_cancel(), nr_open_sockets, GNUNET_UdpSocketInfo::read_task, sock_infos_head, sock_infos_tail, and GNUNET_UdpSocketInfo::udp_sock.

Referenced by read_send().

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

◆ read_send()

static void read_send ( void *  cls)
static

Definition at line 343 of file nat.c.

344{
345 struct GNUNET_UdpSocketInfo *sock_info = cls;
348 struct GNUNET_BurstMessage bm;
349 struct sockaddr *in;
350 socklen_t in_len;
351 char dgram[sizeof (struct GNUNET_BurstMessage)];
352 char *address;
353 struct sockaddr *bind_in;
354 socklen_t bind_in_len;
355 char *bind_address;
356 struct GNUNET_TIME_Relative again = GNUNET_TIME_relative_multiply (sock_info->
357 rtt,
358 4);
359
360 read_send_task = NULL;
361 GNUNET_memcpy (si, sock_info, sizeof (struct GNUNET_UdpSocketInfo));
362 if (sock_info->std_port == udp_port)
363 udp_port++;
364 if (512 < nr_open_sockets)
365 {
367 "Trying again in %s",
370 &read_send,
371 sock_info);
372 }
373
375 "%s:%u",
376 sock_info->address,
377 udp_port);
379 "3 sock %p addr %s addr %s %u\n",
380 sock_info,
381 sock_info->address,
382 address,
384 in = udp_address_to_sockaddr (address, &in_len);
385 if (NULL == in)
386 {
388 "Failed to setup UDP socket address with path `%s'\n",
389 address);
390 GNUNET_assert (0);
391 }
393 address = NULL;
394 GNUNET_asprintf (&bind_address,
395 "%s:%u",
396 sock_info->bind_address,
397 udp_port);
399 "4 sock addr %s addr %s\n",
400 sock_info->bind_address,
401 bind_address);
402 bind_in = udp_address_to_sockaddr (bind_address, &bind_in_len);
403 if (NULL == bind_in)
404 {
406 "Failed to setup UDP socket bind address with path `%s'\n",
407 bind_address);
408 GNUNET_assert (0);
409 }
410 GNUNET_free (bind_address);
411 bind_address = NULL;
412 udp_sock =
413 GNUNET_NETWORK_socket_create (bind_in->sa_family,
414 SOCK_DGRAM,
415 IPPROTO_UDP);
416 if (NULL == udp_sock)
417 {
420 "Failed to create socket for %s family %d\n",
421 GNUNET_a2s (bind_in,
422 bind_in_len),
423 in->sa_family);
424 GNUNET_free (bind_in);
425 if (EMFILE == errno)
426 {
428 "Trying again in %s, because of EMFILE\n",
431 &read_send,
432 sock_info);
433 GNUNET_free (si);
434 GNUNET_free (in);
435 GNUNET_free (bind_in);
436 return;
437 }
438 GNUNET_free (sock_info);
439 goto next_port;
440 }
441 if (GNUNET_OK !=
443 bind_in,
444 bind_in_len))
445 {
448 "Failed to bind socket for %s family %d sock %p\n",
449 GNUNET_a2s (bind_in,
450 bind_in_len),
451 bind_in->sa_family,
452 udp_sock);
454 udp_sock = NULL;
455 GNUNET_free (sock_info);
456 goto next_port;
457 }
459 bm.local_port = udp_port;
460 sock_info->udp_sock = udp_sock;
461 sock_info->port = udp_port;
464 udp_sock,
465 &sock_read,
466 sock_info);
468 "Timeout in %s\n",
470 ;
473 sock_info);
474
476
477 memcpy (dgram, &bm, sizeof(bm));
479 dgram,
480 sizeof(dgram),
481 in,
482 in_len))
483 {
485 "Sending burst to %s family %d failed sock %p\n",
486 GNUNET_a2s (in,
487 in_len),
488 in->sa_family,
489 udp_sock);
490 timeout_task_cb (sock_info);
491 }
492
493next_port:
494 GNUNET_free (si);
495 GNUNET_free (in);
496 GNUNET_free (bind_in);
497
498 if (65535 == udp_port)
499 return;
500 udp_port++;
501
503 &read_send,
504 si);
505}

References address, GNUNET_UdpSocketInfo::address, GNUNET_UdpSocketInfo::bind_address, GNUNET_a2s(), GNUNET_asprintf(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_log_strerror, GNUNET_memcpy, GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NETWORK_socket_sendto(), GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_read_net(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_BurstMessage::local_port, nr_open_sockets, GNUNET_UdpSocketInfo::port, read_send(), read_send_task, GNUNET_UdpSocketInfo::read_task, SEND_DELAY, sock_infos_head, sock_infos_tail, sock_read(), GNUNET_UdpSocketInfo::std_port, TIMEOUT_DELAY, GNUNET_UdpSocketInfo::timeout_task, timeout_task_cb(), udp_address_to_sockaddr(), udp_port, GNUNET_UdpSocketInfo::udp_sock, and udp_sock.

Referenced by GNUNET_get_udp_socket(), and read_send().

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

Variable Documentation

◆ sock_infos_head

struct GNUNET_UdpSocketInfo* sock_infos_head
static

Definition at line 46 of file nat.c.

Referenced by GNUNET_stop_burst(), read_send(), and timeout_task_cb().

◆ sock_infos_tail

struct GNUNET_UdpSocketInfo* sock_infos_tail
static

Definition at line 48 of file nat.c.

Referenced by GNUNET_stop_burst(), read_send(), and timeout_task_cb().

◆ read_send_task

struct GNUNET_SCHEDULER_Task* read_send_task
static

Definition at line 50 of file nat.c.

Referenced by GNUNET_get_udp_socket(), GNUNET_stop_burst(), and read_send().

◆ udp_port

unsigned int udp_port

Definition at line 52 of file nat.c.

Referenced by GNUNET_get_udp_socket(), and read_send().

◆ nr_open_sockets

unsigned int nr_open_sockets

Maximum of open sockets.

Definition at line 57 of file nat.c.

Referenced by GNUNET_get_udp_socket(), read_send(), and timeout_task_cb().