aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_udp.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-07-14 17:45:45 +0000
committerChristian Grothoff <christian@grothoff.org>2011-07-14 17:45:45 +0000
commit245187d11cba38164d73afdcb6ddd2a09d701eed (patch)
tree64e03b975b70fab03113a5afd9379ee2015e856b /src/transport/plugin_transport_udp.c
parentc5678b2b20d198c2e7715a509d990619dc73c144 (diff)
downloadgnunet-245187d11cba38164d73afdcb6ddd2a09d701eed.tar.gz
gnunet-245187d11cba38164d73afdcb6ddd2a09d701eed.zip
renaming
Diffstat (limited to 'src/transport/plugin_transport_udp.c')
-rw-r--r--src/transport/plugin_transport_udp.c1686
1 files changed, 789 insertions, 897 deletions
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index b3a64b286..4f57c6942 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 (C) 2010 Christian Grothoff (and other contributing authors) 3 (C) 2010, 2011 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -24,29 +24,14 @@
24 * transport service 24 * transport service
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 * @author Nathan Evans 26 * @author Nathan Evans
27 *
28 * The idea with this transport is to connect gnunet peers to each other
29 * when ONE is behind a NAT. This is based on pwnat (http://samy.pl/pwnat)
30 * created by Samy Kamkar. When configured with the PWNAT options, this
31 * transport will start a server daemon which sends dummy ICMP and UDP
32 * messages out to a predefined address (typically 1.2.3.4).
33 *
34 * When a non-NAT'd peer (the client) learns of the NAT'd peer (the server)
35 * address, it will send ICMP RESPONSES to the NAT'd peers external address.
36 * The NAT box should forward these faked responses to the server, which
37 * can then connect directly to the non-NAT'd peer.
38 */ 27 */
39
40#include "platform.h" 28#include "platform.h"
41#include "gnunet_hello_lib.h" 29#include "gnunet_hello_lib.h"
42#include "gnunet_connection_lib.h" 30#include "gnunet_util_lib.h"
43#include "gnunet_container_lib.h" 31#include "gnunet_fragmentation_lib.h"
44#include "gnunet_nat_lib.h" 32#include "gnunet_nat_lib.h"
45#include "gnunet_os_lib.h"
46#include "gnunet_peerinfo_service.h"
47#include "gnunet_protocols.h" 33#include "gnunet_protocols.h"
48#include "gnunet_resolver_service.h" 34#include "gnunet_resolver_service.h"
49#include "gnunet_server_lib.h"
50#include "gnunet_signatures.h" 35#include "gnunet_signatures.h"
51#include "gnunet_statistics_service.h" 36#include "gnunet_statistics_service.h"
52#include "gnunet_transport_service.h" 37#include "gnunet_transport_service.h"
@@ -55,27 +40,34 @@
55 40
56#define DEBUG_UDP GNUNET_NO 41#define DEBUG_UDP GNUNET_NO
57 42
58#define MAX_PROBES 20 43/**
59 44 * MTU for fragmentation subsystem. Should be conservative since
60/* 45 * all communicating peers MUST work with this MTU.
61 * Transport cost to peer, always 1 for UDP (direct connection)
62 */ 46 */
63#define UDP_DIRECT_DISTANCE 1 47#define UDP_MTU 1400
64
65#define DEFAULT_NAT_PORT 0
66 48
67/** 49/**
68 * How long until we give up on transmitting the welcome message? 50 * Number of messages we can defragment in parallel. We only really
51 * defragment 1 message at a time, but if messages get re-ordered, we
52 * may want to keep knowledge about the previous message to avoid
53 * discarding the current message in favor of a single fragment of a
54 * previous message. 3 should be good since we don't expect massive
55 * message reorderings with UDP.
69 */ 56 */
70#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 57#define UDP_MAX_MESSAGES_IN_DEFRAG 3
71 58
72/** 59/**
73 * Starting port for listening and sending, eventually a config value 60 * We keep a defragmentation queue per sender address. How many
61 * sender addresses do we support at the same time? Memory consumption
62 * is roughly a factor of 32k * UDP_MAX_MESSAGES_IN_DEFRAG times this
63 * value. (So 128 corresponds to 12 MB and should suffice for
64 * connecting to roughly 128 peers via UDP).
74 */ 65 */
75#define UDP_NAT_DEFAULT_PORT 22086 66#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
67
76 68
77/** 69/**
78 * UDP Message-Packet header. 70 * UDP Message-Packet header (after defragmentation).
79 */ 71 */
80struct UDPMessage 72struct UDPMessage
81{ 73{
@@ -85,12 +77,18 @@ struct UDPMessage
85 struct GNUNET_MessageHeader header; 77 struct GNUNET_MessageHeader header;
86 78
87 /** 79 /**
88 * What is the identity of the sender (GNUNET_hash of public key) 80 * Always zero for now.
81 */
82 uint32_t reserved;
83
84 /**
85 * What is the identity of the sender
89 */ 86 */
90 struct GNUNET_PeerIdentity sender; 87 struct GNUNET_PeerIdentity sender;
91 88
92}; 89};
93 90
91
94/** 92/**
95 * Network format for IPv4 addresses. 93 * Network format for IPv4 addresses.
96 */ 94 */
@@ -113,6 +111,7 @@ struct IPv4UdpAddress
113 */ 111 */
114struct IPv6UdpAddress 112struct IPv6UdpAddress
115{ 113{
114
116 /** 115 /**
117 * IPv6 address. 116 * IPv6 address.
118 */ 117 */
@@ -124,125 +123,21 @@ struct IPv6UdpAddress
124 uint16_t u6_port GNUNET_PACKED; 123 uint16_t u6_port GNUNET_PACKED;
125}; 124};
126 125
126
127/* Forward definition */ 127/* Forward definition */
128struct Plugin; 128struct Plugin;
129 129
130struct PrettyPrinterContext
131{
132 /**
133 * Function to call with the result.
134 */
135 GNUNET_TRANSPORT_AddressStringCallback asc;
136
137 /**
138 * Clsoure for 'asc'.
139 */
140 void *asc_cls;
141
142 /**
143 * The address
144 */
145 void * addr;
146
147 /**
148 * address length
149 */
150 size_t addr_len;
151
152 /**
153 * Port to add after the IP address.
154 */
155 uint16_t port;
156};
157
158
159struct MessageQueue
160{
161 /**
162 * Linked List
163 */
164 struct MessageQueue *next;
165
166 /**
167 * Session this message belongs to
168 */
169 struct PeerSession *session;
170
171 /**
172 * Actual message to be sent
173 */
174 char *msgbuf;
175
176 /**
177 * Size of message buffer to be sent
178 */
179 size_t msgbuf_size;
180
181 /**
182 * When to discard this message
183 */
184 struct GNUNET_TIME_Absolute timeout;
185
186 /**
187 * Continuation to call when this message goes out
188 */
189 GNUNET_TRANSPORT_TransmitContinuation cont;
190
191 /**
192 * closure for continuation
193 */
194 void *cont_cls;
195
196};
197
198/**
199 * UDP NAT Probe message definition
200 */
201struct UDP_NAT_ProbeMessage
202{
203 /**
204 * Message header
205 */
206 struct GNUNET_MessageHeader header;
207
208};
209 130
210/** 131/**
211 * UDP NAT Probe message reply definition 132 * Session with another peer.
212 */
213struct UDP_NAT_ProbeMessageReply
214{
215 /**
216 * Message header
217 */
218 struct GNUNET_MessageHeader header;
219
220};
221
222
223/**
224 * UDP NAT Probe message confirm definition
225 */
226struct UDP_NAT_ProbeMessageConfirmation
227{
228 /**
229 * Message header
230 */
231 struct GNUNET_MessageHeader header;
232
233};
234
235
236/**
237 * UDP NAT "Session"
238 */ 133 */
239struct PeerSession 134struct PeerSession
240{ 135{
241 136
242 /** 137 /**
243 * Stored in a linked list. 138 * Which peer is this session for?
244 */ 139 */
245 struct PeerSession *next; 140 struct GNUNET_PeerIdentity target;
246 141
247 /** 142 /**
248 * Pointer to the global plugin struct. 143 * Pointer to the global plugin struct.
@@ -250,90 +145,61 @@ struct PeerSession
250 struct Plugin *plugin; 145 struct Plugin *plugin;
251 146
252 /** 147 /**
253 * To whom are we talking to (set to our identity 148 * Address of the other peer
254 * if we are still waiting for the welcome message)
255 */
256 struct GNUNET_PeerIdentity target;
257
258 /**
259 * Address of the other peer (either based on our 'connect'
260 * call or on our 'accept' call).
261 */ 149 */
262 void *connect_addr; 150 const struct sockaddr *sock_addr;
263 151
264 /** 152 /**
265 * Length of connect_addr. 153 * Function to call upon completion of the transmission.
266 */ 154 */
267 size_t connect_alen; 155 GNUNET_TRANSPORT_TransmitContinuation cont;
268 156
269 /** 157 /**
270 * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO) 158 * Closure for 'cont'.
271 */ 159 */
272 int expecting_welcome; 160 void *cont_cls;
273 161
274 /** 162 /**
275 * From which socket do we need to send to this peer? 163 * Current outgoing message to this peer.
276 */
277 struct GNUNET_NETWORK_Handle *sock;
278
279 /*
280 * Queue of messages for this peer, in the case that
281 * we have to await a connection...
282 */ 164 */
283 struct MessageQueue *messages; 165 struct GNUNET_FRAGMENT_Context *frag;
284 166
285}; 167};
286 168
287struct UDP_NAT_Probes
288{
289 169
290 /** 170/**
291 * Linked list 171 * Data structure to track defragmentation contexts based
292 */ 172 * on the source of the UDP traffic.
293 struct UDP_NAT_Probes *next; 173 */
174struct ReceiveContext
175{
294 176
295 /** 177 /**
296 * Timeout for this set of probes 178 * Defragmentation context.
297 */ 179 */
298 struct GNUNET_TIME_Absolute timeout; 180 struct GNUNET_DEFRAGMENT_Context *defrag;
299 181
300 /** 182 /**
301 * Count of how many probes we've attempted 183 * Source address this receive context is for (allocated at the
184 * end of the struct).
302 */ 185 */
303 int count; 186 const struct sockaddr *src_addr;
304 187
305 /** 188 /**
306 * The plugin this probe belongs to 189 * Reference to master plugin struct.
307 */ 190 */
308 struct Plugin *plugin; 191 struct Plugin *plugin;
309 192
310 /** 193 /**
311 * The task used to send these probes 194 * Node in the defrag heap.
312 */ 195 */
313 GNUNET_SCHEDULER_TaskIdentifier task; 196 struct GNUNET_CONTAINER_HeapNode *hnode;
314 197
315 /** 198 /**
316 * Network address (always ipv4!) 199 * Length of 'src_addr'
317 */ 200 */
318 struct IPv4UdpAddress addr; 201 size_t addr_len;
319
320};
321
322
323/**
324 * Information we keep for each of our listen sockets.
325 */
326struct UDP_Sock_Info
327{
328 /**
329 * The network handle
330 */
331 struct GNUNET_NETWORK_Handle *desc;
332 202
333 /**
334 * The port we bound to
335 */
336 uint16_t port;
337}; 203};
338 204
339 205
@@ -342,15 +208,22 @@ struct UDP_Sock_Info
342 */ 208 */
343struct Plugin 209struct Plugin
344{ 210{
211
345 /** 212 /**
346 * Our environment. 213 * Our environment.
347 */ 214 */
348 struct GNUNET_TRANSPORT_PluginEnvironment *env; 215 struct GNUNET_TRANSPORT_PluginEnvironment *env;
349 216
350 /* 217 /**
351 * Session of peers with whom we are currently connected 218 * Session of peers with whom we are currently connected,
219 * map of peer identity to 'struct PeerSession'.
220 */
221 struct GNUNET_CONTAINER_MultiHashMap *sessions;
222
223 /**
224 * Heap with all of our defragmentation activities.
352 */ 225 */
353 struct PeerSession *sessions; 226 struct GNUNET_CONTAINER_Heap *defrags;
354 227
355 /** 228 /**
356 * ID of select task 229 * ID of select task
@@ -358,14 +231,19 @@ struct Plugin
358 GNUNET_SCHEDULER_TaskIdentifier select_task; 231 GNUNET_SCHEDULER_TaskIdentifier select_task;
359 232
360 /** 233 /**
361 * Port to listen on. 234 * Tokenizer for inbound messages.
362 */ 235 */
363 uint16_t port; 236 struct GNUNET_SERVER_MessageStreamTokenizer *mst;
237
238 /**
239 * Bandwidth tracker to limit global UDP traffic.
240 */
241 struct GNUNET_BANDWIDTH_Tracker tracker;
364 242
365 /** 243 /**
366 * Address we were told to bind to exclusively (IPv4). 244 * Address we were told to bind to exclusively (IPv4).
367 */ 245 */
368 char *bind_address; 246 char *bind4_address;
369 247
370 /** 248 /**
371 * Address we were told to bind to exclusively (IPv6). 249 * Address we were told to bind to exclusively (IPv6).
@@ -383,28 +261,47 @@ struct Plugin
383 struct GNUNET_NETWORK_FDSet *rs; 261 struct GNUNET_NETWORK_FDSet *rs;
384 262
385 /** 263 /**
386 * Probes in flight 264 * The read socket for IPv4
387 */ 265 */
388 struct UDP_NAT_Probes *probes; 266 struct GNUNET_NETWORK_Handle *sockv4;
389 267
390 /** 268 /**
391 * socket that we transmit all IPv4 data with 269 * The read socket for IPv6
392 */ 270 */
393 struct UDP_Sock_Info udp_sockv4; 271 struct GNUNET_NETWORK_Handle *sockv6;
394 272
395 /** 273 /**
396 * socket that we transmit all IPv6 data with 274 * expected delay for ACKs
397 */ 275 */
398 struct UDP_Sock_Info udp_sockv6; 276 struct GNUNET_TIME_Relative last_expected_delay;
277
278 /**
279 * Port we listen on.
280 */
281 uint16_t port;
282
283 /**
284 * Port we advertise on.
285 */
286 uint16_t aport;
399 287
400}; 288};
401 289
402 290
403/** 291/**
404 * Forward declaration. 292 * Lookup the session for the given peer.
293 *
294 * @param plugin the plugin
295 * @param peer peer's identity
296 * @return NULL if we have no session
405 */ 297 */
406static void 298struct PeerSession *
407udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result); 299find_session (struct Plugin *plugin,
300 const struct GNUNET_PeerIdentity *peer)
301{
302 return GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
303 &peer->hashPubKey);
304}
408 305
409 306
410/** 307/**
@@ -417,34 +314,26 @@ udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int
417static void 314static void
418udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) 315udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
419{ 316{
420 /** TODO: Implement! */ 317 struct Plugin *plugin = cls;
421 return; 318 struct PeerSession *session;
422}
423
424
425struct PeerSession *
426find_session (struct Plugin *plugin,
427 const struct GNUNET_PeerIdentity *peer)
428{
429 struct PeerSession *pos;
430
431 pos = plugin->sessions;
432 while (pos != NULL)
433 {
434 if (memcmp(&pos->target, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
435 return pos;
436 pos = pos->next;
437 }
438 319
439 return pos; 320 session = find_session (plugin, target);
321 if (NULL == session)
322 return;
323 GNUNET_assert (GNUNET_OK ==
324 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
325 &target->hashPubKey,
326 session));
327 plugin->last_expected_delay = GNUNET_FRAGMENT_context_destroy (session->frag);
328 session->cont (session->cont_cls, target, GNUNET_SYSERR);
329 GNUNET_free (session);
440} 330}
441 331
442 332
443/** 333/**
444 * Actually send out the message, assume we've got the address and 334 * Actually send out the message.
445 * send_handle squared away!
446 * 335 *
447 * @param cls closure 336 * @param plugin the plugin
448 * @param send_handle which handle to send message on 337 * @param send_handle which handle to send message on
449 * @param target who should receive this message (ignored by UDP) 338 * @param target who should receive this message (ignored by UDP)
450 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together 339 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
@@ -461,117 +350,69 @@ find_session (struct Plugin *plugin,
461 * @return the number of bytes written 350 * @return the number of bytes written
462 */ 351 */
463static ssize_t 352static ssize_t
464udp_real_send (void *cls, 353udp_send (struct Plugin *plugin,
465 struct GNUNET_NETWORK_Handle *send_handle, 354 const struct sockaddr *sa,
466 const struct GNUNET_PeerIdentity *target, 355 const struct GNUNET_MessageHeader *msg)
467 const char *msgbuf,
468 size_t msgbuf_size,
469 unsigned int priority,
470 struct GNUNET_TIME_Relative timeout,
471 const void *addr,
472 size_t addrlen,
473 GNUNET_TRANSPORT_TransmitContinuation cont,
474 void *cont_cls)
475{ 356{
476 struct Plugin *plugin = cls;
477 struct UDPMessage *message;
478 int ssize;
479 ssize_t sent; 357 ssize_t sent;
480 struct sockaddr_in a4; 358 size_t slen;
481 struct sockaddr_in6 a6;
482 const struct IPv4UdpAddress *t4;
483 const struct IPv6UdpAddress *t6;
484 const void *sb;
485 size_t sbs;
486 359
487 if (send_handle == NULL) 360 switch (sa->sa_family)
488 { 361 {
489 /* failed to open send socket for AF */ 362 case AF_INET:
490 if (cont != NULL) 363 sent =
491 cont (cont_cls, target, GNUNET_SYSERR); 364 GNUNET_NETWORK_socket_sendto (plugin->sockv4,
365 msg,
366 ntohs (msg->size),
367 sa,
368 slen = sizeof (struct sockaddr_in));
369 break;
370 case AF_INET6:
371 sent =
372 GNUNET_NETWORK_socket_sendto (plugin->sockv6,
373 msg,
374 ntohs (msg->size),
375 sa,
376 slen = sizeof (struct sockaddr_in6));
377 break;
378 default:
379 GNUNET_break (0);
492 return 0; 380 return 0;
493 } 381 }
494 if ((addr == NULL) || (addrlen == 0)) 382 if (GNUNET_SYSERR == sent)
495 { 383 GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
384 "sendto");
496#if DEBUG_UDP 385#if DEBUG_UDP
497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
498 "udp_real_send called without address, returning!\n"); 387 "UDP transmited %u-byte message to %s (%d: %s)\n",
388 (unsigned int) ntohs (msg->size),
389 GNUNET_a2s (sa, slen),
390 (int) sent,
391 (sent < 0) ? STRERROR (errno) : "ok");
499#endif 392#endif
500 if (cont != NULL) 393 return sent;
501 cont (cont_cls, target, GNUNET_SYSERR); 394}
502 return 0; /* Can never send if we don't have an address!! */
503 }
504
505 /* Build the message to be sent */
506 message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size);
507 ssize = sizeof (struct UDPMessage) + msgbuf_size;
508 395
509 message->header.size = htons (ssize);
510 message->header.type = htons (0);
511 memcpy (&message->sender, plugin->env->my_identity,
512 sizeof (struct GNUNET_PeerIdentity));
513 memcpy (&message[1], msgbuf, msgbuf_size);
514 396
515 if (addrlen == sizeof (struct IPv6UdpAddress)) 397/**
516 { 398 * Function that is called with messages created by the fragmentation
517 t6 = addr; 399 * module. In the case of the 'proc' callback of the
518 memset (&a6, 0, sizeof (a6)); 400 * GNUNET_FRAGMENT_context_create function, this function must
519#if HAVE_SOCKADDR_IN_SIN_LEN 401 * eventually call 'GNUNET_FRAGMENT_context_transmission_done'.
520 a6.sin6_len = sizeof (a6); 402 *
521#endif 403 * @param cls closure, the 'struct PeerSession'
522 a6.sin6_family = AF_INET6; 404 * @param msg the message that was created
523 a6.sin6_port = t6->u6_port; 405 */
524 memcpy (&a6.sin6_addr, 406static void
525 &t6->ipv6_addr, 407send_fragment (void *cls,
526 sizeof (struct in6_addr)); 408 const struct GNUNET_MessageHeader *msg)
527 sb = &a6; 409{
528 sbs = sizeof (a6); 410 struct PeerSession *session = cls;
529 }
530 else if (addrlen == sizeof (struct IPv4UdpAddress))
531 {
532 t4 = addr;
533 memset (&a4, 0, sizeof (a4));
534#if HAVE_SOCKADDR_IN_SIN_LEN
535 a4.sin_len = sizeof (a4);
536#endif
537 a4.sin_family = AF_INET;
538 a4.sin_port = t4->u4_port;
539 a4.sin_addr.s_addr = t4->ipv4_addr;
540 sb = &a4;
541 sbs = sizeof (a4);
542 }
543 else
544 {
545 GNUNET_break_op (0);
546 GNUNET_free (message);
547 return -1;
548 }
549
550 /* Actually send the message */
551 sent =
552 GNUNET_NETWORK_socket_sendto (send_handle, message, ssize,
553 sb,
554 sbs);
555 if (GNUNET_SYSERR == sent)
556 GNUNET_log_strerror(GNUNET_ERROR_TYPE_DEBUG, "sendto");
557 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
558 "UDP transmit %u-byte message to %s (%d: %s)\n",
559 (unsigned int) ssize,
560 GNUNET_a2s (sb, sbs),
561 (int) sent,
562 (sent < 0) ? STRERROR (errno) : "ok");
563 if (cont != NULL)
564 {
565 if (sent == GNUNET_SYSERR)
566 cont (cont_cls, target, GNUNET_SYSERR);
567 else
568 {
569 cont (cont_cls, target, GNUNET_OK);
570 }
571 }
572 411
573 GNUNET_free (message); 412 udp_send (session->plugin,
574 return sent; 413 session->sock_addr,
414 msg);
415 GNUNET_FRAGMENT_context_transmission_done (session->frag);
575} 416}
576 417
577 418
@@ -585,8 +426,8 @@ udp_real_send (void *cls,
585 * @param msgbuf_size the size of the msgbuf to send 426 * @param msgbuf_size the size of the msgbuf to send
586 * @param priority how important is the message (ignored by UDP) 427 * @param priority how important is the message (ignored by UDP)
587 * @param timeout when should we time out (give up) if we can not transmit? 428 * @param timeout when should we time out (give up) if we can not transmit?
588 * @param session identifier used for this session (can be NULL) 429 * @param session identifier used for this session (NULL for UDP)
589 * @param addr the addr to send the message to, needs to be a sockaddr for us 430 * @param addr the addr to send the message to
590 * @param addrlen the len of addr 431 * @param addrlen the len of addr
591 * @param force_address not used, we had better have an address to send to 432 * @param force_address not used, we had better have an address to send to
592 * because we are stateless!! 433 * because we are stateless!!
@@ -601,474 +442,514 @@ udp_real_send (void *cls,
601 */ 442 */
602static ssize_t 443static ssize_t
603udp_plugin_send (void *cls, 444udp_plugin_send (void *cls,
604 const struct GNUNET_PeerIdentity *target, 445 const struct GNUNET_PeerIdentity *target,
605 const char *msgbuf, 446 const char *msgbuf,
606 size_t msgbuf_size, 447 size_t msgbuf_size,
607 unsigned int priority, 448 unsigned int priority,
608 struct GNUNET_TIME_Relative timeout, 449 struct GNUNET_TIME_Relative timeout,
609 struct Session *session, 450 struct Session *session,
610 const void *addr, 451 const void *addr,
611 size_t addrlen, 452 size_t addrlen,
612 int force_address, 453 int force_address,
613 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) 454 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
614{ 455{
615 struct Plugin *plugin = cls; 456 struct Plugin *plugin = cls;
616 ssize_t sent;
617 struct MessageQueue *temp_message;
618 struct PeerSession *peer_session; 457 struct PeerSession *peer_session;
619 int other_peer_natd;
620 const struct IPv4UdpAddress *t4; 458 const struct IPv4UdpAddress *t4;
621 struct sockaddr_in sin4; 459 const struct IPv6UdpAddress *t6;
460 struct sockaddr_in *v4;
461 struct sockaddr_in6 *v6;
462 size_t mlen = msgbuf_size + sizeof (struct UDPMessage);
463 char mbuf[mlen];
464 struct UDPMessage *udp;
622 465
623 if (force_address == GNUNET_SYSERR) 466 if (force_address == GNUNET_SYSERR)
624 return GNUNET_SYSERR; 467 return GNUNET_SYSERR;
625 GNUNET_assert (NULL == session); 468 GNUNET_assert (NULL == session);
626 469 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
627 other_peer_natd = GNUNET_NO;
628 if (addrlen == sizeof(struct IPv4UdpAddress))
629 { 470 {
630 t4 = addr; 471 GNUNET_break (0);
631 if (ntohs(t4->u4_port) == 0) 472 return GNUNET_SYSERR;
632 other_peer_natd = GNUNET_YES;
633 }
634 else if (addrlen != sizeof(struct IPv6UdpAddress))
635 {
636 GNUNET_break_op(0);
637 return -1; /* Must have an address to send to */
638 } 473 }
639 474 switch (addrlen)
640 sent = 0;
641 if ( (other_peer_natd == GNUNET_YES) &&
642 (addrlen == sizeof(struct IPv4UdpAddress)) )
643 { 475 {
644 peer_session = find_session(plugin, target); 476 case sizeof(struct IPv4UdpAddress):
645 if (peer_session == NULL) /* We have a new peer to add */ 477 t4 = addr;
646 { 478 peer_session = GNUNET_malloc (sizeof (struct PeerSession) + sizeof (struct sockaddr_in));
647 /* 479 v4 = (struct sockaddr_in*) &peer_session[1];
648 * The first time, we can assume we have no knowledge of a 480 v4->sin_family = AF_INET;
649 * working port for this peer, call the ICMP/UDP message sender 481#if HAVE_SOCKADDR_IN_SIN_LEN
650 * and wait... 482 v4->sin_len = sizeof (struct sockaddr_in);
651 */
652 peer_session = GNUNET_malloc(sizeof(struct PeerSession));
653 peer_session->connect_addr = GNUNET_malloc(addrlen);
654 memcpy(peer_session->connect_addr, addr, addrlen);
655 peer_session->connect_alen = addrlen;
656 peer_session->plugin = plugin;
657 peer_session->sock = NULL;
658 memcpy(&peer_session->target, target, sizeof(struct GNUNET_PeerIdentity));
659 peer_session->expecting_welcome = GNUNET_YES;
660
661 peer_session->next = plugin->sessions;
662 plugin->sessions = peer_session;
663
664 peer_session->messages = GNUNET_malloc(sizeof(struct MessageQueue));
665 peer_session->messages->msgbuf = GNUNET_malloc(msgbuf_size);
666 memcpy(peer_session->messages->msgbuf, msgbuf, msgbuf_size);
667 peer_session->messages->msgbuf_size = msgbuf_size;
668 peer_session->messages->timeout = GNUNET_TIME_relative_to_absolute(timeout);
669 peer_session->messages->cont = cont;
670 peer_session->messages->cont_cls = cont_cls;
671#if DEBUG_UDP
672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
673 _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target));
674#endif 483#endif
675 memset (&sin4, 0, sizeof (sin4)); 484 v4->sin_port = t4->u4_port;
676 sin4.sin_family = AF_INET; 485 v4->sin_addr.s_addr = t4->ipv4_addr;
486 break;
487 case sizeof(struct IPv6UdpAddress):
488 t6 = addr;
489 peer_session = GNUNET_malloc (sizeof (struct PeerSession) + sizeof (struct sockaddr_in6));
490 v6 = (struct sockaddr_in6*) &peer_session[1];
491 v6->sin6_family = AF_INET6;
677#if HAVE_SOCKADDR_IN_SIN_LEN 492#if HAVE_SOCKADDR_IN_SIN_LEN
678 sin4.sin_len = sizeof (sin4); 493 v6->sin6_len = sizeof (struct sockaddr_in6);
679#endif 494#endif
680 sin4.sin_port = t4->u4_port; 495 v6->sin6_port = t6->u6_port;
681 sin4.sin_addr.s_addr = t4->ipv4_addr; 496 v6->sin6_addr = t6->ipv6_addr;
682 GNUNET_NAT_run_client (plugin->nat, &sin4); 497 break;
683 } 498 default:
684 else 499 /* Must have a valid address to send to */
685 { 500 GNUNET_break_op(0);
686 if (peer_session->expecting_welcome == GNUNET_NO) /* We are "connected" */ 501 return GNUNET_SYSERR;
687 {
688 sent = udp_real_send(cls,
689 peer_session->sock,
690 target,
691 msgbuf, msgbuf_size,
692 priority, timeout,
693 peer_session->connect_addr, peer_session->connect_alen,
694 cont, cont_cls);
695 }
696 else /* Haven't gotten a response from this peer, queue message */
697 {
698 temp_message = GNUNET_malloc(sizeof(struct MessageQueue));
699 temp_message->msgbuf = GNUNET_malloc(msgbuf_size);
700 memcpy(temp_message->msgbuf, msgbuf, msgbuf_size);
701 temp_message->msgbuf_size = msgbuf_size;
702 temp_message->timeout = GNUNET_TIME_relative_to_absolute(timeout);
703 temp_message->cont = cont;
704 temp_message->cont_cls = cont_cls;
705 temp_message->next = peer_session->messages;
706 peer_session->messages = temp_message;
707 }
708 }
709 } 502 }
710 else if (other_peer_natd == GNUNET_NO) /* Other peer not behind a NAT, so we can just send the message as is */ 503 udp = (struct UDPMessage*) mbuf;
504 udp->header.size = htons (mlen);
505 udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE);
506 udp->reserved = htonl (0);
507 udp->sender = *plugin->env->my_identity;
508 memcpy (&udp[1], msgbuf, msgbuf_size);
509 peer_session->target = *target;
510 peer_session->plugin = plugin;
511 peer_session->sock_addr = (const struct sockaddr*) &peer_session[1];
512 peer_session->cont = cont;
513 peer_session->cont_cls = cont_cls;
514 if (mlen <= UDP_MTU)
711 { 515 {
712 sent = udp_real_send(cls, 516 mlen = udp_send (plugin,
713 (addrlen == sizeof (struct IPv4UdpAddress)) ? plugin->udp_sockv4.desc : plugin->udp_sockv6.desc, 517 peer_session->sock_addr,
714 target, 518 &udp->header);
715 msgbuf, msgbuf_size, 519 cont (cont_cls, target, (mlen > 0) ? GNUNET_OK : GNUNET_SYSERR);
716 priority, timeout, addr, addrlen, 520 GNUNET_free (peer_session);
717 cont, cont_cls);
718 } 521 }
719 else /* Other peer is NAT'd, but we don't want to play with them (or can't!) */ 522 else
720 { 523 {
721 return GNUNET_SYSERR; 524 GNUNET_assert (GNUNET_OK ==
525 GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
526 &target->hashPubKey,
527 peer_session,
528 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
529 peer_session->frag = GNUNET_FRAGMENT_context_create (plugin->env->stats,
530 UDP_MTU,
531 &plugin->tracker,
532 plugin->last_expected_delay,
533 &udp->header,
534 &send_fragment,
535 peer_session);
722 } 536 }
723 537 return mlen;
724 /* When GNUNET_SYSERR is returned from udp_real_send, we will still call
725 * the callback so must not return GNUNET_SYSERR!
726 * If we did, then transport context would get freed twice. */
727 if (sent == GNUNET_SYSERR)
728 return 0;
729 return sent;
730} 538}
731 539
732 540
733/** 541/**
734 * Send UDP probe messages or UDP keepalive messages, depending on the 542 * Closure for 'process_inbound_tokenized_messages'
735 * state of the connection. 543 */
544struct SourceInformation
545{
546 /**
547 * Sender identity.
548 */
549 struct GNUNET_PeerIdentity sender;
550
551 /**
552 * Source address.
553 */
554 const void *arg;
555
556 /**
557 * Number of bytes in source address.
558 */
559 size_t args;
560};
561
562
563/**
564 * Message tokenizer has broken up an incomming message. Pass it on
565 * to the service.
736 * 566 *
737 * @param cls closure for this call (should be the main Plugin) 567 * @param cls the 'struct Plugin'
738 * @param tc task context for running this 568 * @param client the 'struct SourceInformation'
569 * @param hdr the actual message
739 */ 570 */
740static void 571static void
741send_udp_probe_message (void *cls, 572process_inbound_tokenized_messages (void *cls,
742 const struct GNUNET_SCHEDULER_TaskContext *tc) 573 void *client,
574 const struct GNUNET_MessageHeader *hdr)
743{ 575{
744 struct UDP_NAT_Probes *probe = cls; 576 struct Plugin *plugin = cls;
745 struct UDP_NAT_ProbeMessage message; 577 struct SourceInformation* si = client;
746 struct Plugin *plugin = probe->plugin; 578 struct GNUNET_TRANSPORT_ATS_Information distance[2];
747
748 memset (&message, 0, sizeof (message));
749 message.header.size = htons(sizeof(struct UDP_NAT_ProbeMessage));
750 message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE);
751 /* If they gave us a port, use that. If not, try our port. */
752 if (ntohs(probe->addr.u4_port) == 0)
753 probe->addr.u4_port = htons(plugin->port);
754 579
755#if DEBUG_UDP 580 /* setup ATS */
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 581 distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
757 _("Sending a probe to port %d\n"), ntohs(probe->addr.u4_port)); 582 distance[0].value = htonl (1);
758#endif 583 distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
759 probe->count++; 584 distance[1].value = htonl (0);
760 udp_real_send(plugin, 585
761 plugin->udp_sockv4.desc, 586 plugin->env->receive (plugin->env->cls,
762 NULL, 587 &si->sender,
763 (char *)&message, ntohs(message.header.size), 0, 588 hdr,
764 GNUNET_TIME_relative_get_unit(), 589 distance, 2,
765 &probe->addr, sizeof(struct IPv4UdpAddress), 590 NULL,
766 &udp_probe_continuation, probe); 591 si->arg, si->args);
767} 592}
768 593
769 594
770/** 595/**
771 * Continuation for probe sends. If the last probe was sent 596 * We've received a UDP Message. Process it (pass contents to main service).
772 * "successfully", schedule sending of another one. If not, 597 *
773 * FIXME... 598 * @param plugin plugin context
599 * @param msg the message
600 * @param sender_addr sender address
601 * @param sender_addr_len number of bytes in sender_addr
774 */ 602 */
775static void 603static void
776udp_probe_continuation (void *cls, 604process_udp_message (struct Plugin *plugin,
777 const struct GNUNET_PeerIdentity *target, 605 const struct UDPMessage *msg,
778 int result) 606 const struct sockaddr *sender_addr,
607 socklen_t sender_addr_len)
779{ 608{
780 struct UDP_NAT_Probes *probe = cls; 609 struct SourceInformation si;
781 /*struct Plugin *plugin = probe->plugin;*/ 610 struct IPv4UdpAddress u4;
782 611 struct IPv6UdpAddress u6;
783 if ((result == GNUNET_OK) && (probe->count < MAX_PROBES)) 612 const void *arg;
613 size_t args;
614
615 if (0 != ntohl (msg->reserved))
784 { 616 {
785#if DEBUG_UDP 617 GNUNET_break_op (0);
786 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 618 return;
787 _("Scheduling next probe for 10000 milliseconds\n"));
788#endif
789 probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
790 &send_udp_probe_message, probe);
791 } 619 }
792 else /* Destroy the probe context. */ 620 if (ntohs (msg->header.size) < sizeof (struct GNUNET_MessageHeader) + sizeof (struct UDPMessage))
793 { 621 {
622 GNUNET_break_op (0);
623 return;
624 }
625
626 /* convert address */
627 switch (sender_addr->sa_family)
628 {
629 case AF_INET:
630 GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in));
631 u4.ipv4_addr = ((struct sockaddr_in *) sender_addr)->sin_addr.s_addr;
632 u4.u4_port = ((struct sockaddr_in *) sender_addr)->sin_port;
633 arg = &u4;
634 args = sizeof (u4);
635 break;
636 case AF_INET6:
637 GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in6));
638 u6.ipv6_addr = ((struct sockaddr_in6*) sender_addr)->sin6_addr;
639 u6.u6_port = ((struct sockaddr_in6 *) sender_addr)->sin6_port;
640 arg = &u6;
641 args = sizeof (u6);
642 break;
643 default:
644 GNUNET_break (0);
645 return;
646 }
794#if DEBUG_UDP 647#if DEBUG_UDP
795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 648 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
796 _("Sending probe didn't go well...\n")); 649 "udp",
650 "Received message with %u bytes from peer `%s' at `%s'\n",
651 (unsigned int) ntohs (msg->header.size),
652 GNUNET_i2s (&msg->sender),
653 GNUNET_a2s (sender_addr, sender_addr_len));
797#endif 654#endif
798 } 655
656 /* iterate over all embedded messages */
657 si.sender = msg->sender;
658 si.arg = arg;
659 si.args = args;
660 GNUNET_SERVER_mst_receive (plugin->mst,
661 &si,
662 (const char*) &msg[1],
663 ntohs (msg->header.size) - sizeof (struct UDPMessage),
664 GNUNET_YES,
665 GNUNET_NO);
799} 666}
800 667
801 668
802/** 669/**
803 * FIXME. 670 * Process a defragmented message.
671 *
672 * @param cls the 'struct ReceiveContext'
673 * @param msg the message
804 */ 674 */
805static void 675static void
806udp_plugin_reversal_callback (void *cls, 676fragment_msg_proc (void *cls,
807 const struct sockaddr *addr, 677 const struct GNUNET_MessageHeader *msg)
808 socklen_t addrlen)
809{ 678{
810 struct Plugin *plugin = cls; 679 struct ReceiveContext *rc = cls;
811 struct UDP_NAT_Probes *temp_probe;
812 const struct sockaddr_in *inaddr;
813 680
814 if (sizeof (struct sockaddr_in) != addrlen) 681 if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE)
815 { 682 {
816 GNUNET_break (0); 683 GNUNET_break (0);
817 return; 684 return;
818 } 685 }
819 inaddr = (const struct sockaddr_in *) addr; 686 if (ntohs (msg->size) < sizeof(struct UDPMessage))
820 temp_probe = GNUNET_malloc(sizeof(struct UDP_NAT_Probes)); 687 {
821 temp_probe->addr.ipv4_addr = inaddr->sin_addr.s_addr; 688 GNUNET_break (0);
822 temp_probe->addr.u4_port = inaddr->sin_port; 689 return;
823 temp_probe->next = plugin->probes; 690 }
824 temp_probe->plugin = plugin; 691 process_udp_message (rc->plugin,
825 temp_probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500), 692 (const struct UDPMessage*) msg,
826 &send_udp_probe_message, 693 rc->src_addr,
827 temp_probe); 694 rc->addr_len);
828 plugin->probes = temp_probe; 695}
829}
830 696
831 697
832/** 698/**
833 * Demultiplexer for UDP NAT messages 699 * Transmit an acknowledgement.
834 * 700 *
835 * @param plugin the main plugin for this transport 701 * @param cls the 'struct ReceiveContext'
836 * @param sender from which peer the message was received 702 * @param id message ID (unused)
837 * @param currhdr pointer to the header of the message 703 * @param msg ack to transmit
838 * @param sender_addr the address from which the message was received
839 * @param fromlen the length of the address
840 * @param sockinfo which socket did we receive the message on
841 */ 704 */
842static void 705static void
843udp_demultiplexer(struct Plugin *plugin, 706ack_proc (void *cls,
844 struct GNUNET_PeerIdentity *sender, 707 uint32_t id,
845 const struct GNUNET_MessageHeader *currhdr, 708 const struct GNUNET_MessageHeader *msg)
846 const void *sender_addr,
847 size_t fromlen, struct UDP_Sock_Info *sockinfo)
848{ 709{
849 struct UDP_NAT_ProbeMessageReply *outgoing_probe_reply; 710 struct ReceiveContext *rc = cls;
850 struct PeerSession *peer_session; 711 size_t msize = sizeof (struct UDPMessage) + ntohs (msg->size);
851 struct MessageQueue *pending_message; 712 char buf[msize];
852 struct MessageQueue *pending_message_temp; 713 struct UDPMessage *udp;
853 uint16_t incoming_port; 714
854 struct GNUNET_TRANSPORT_ATS_Information distance[2];
855 if (memcmp(sender, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
856 {
857#if DEBUG_UDP 715#if DEBUG_UDP
858 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", 716 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
859 _("Received a message from myself, dropping!!!\n")); 717 "udp",
718 "Sending ACK to `%s'\n",
719 GNUNET_a2s (rc->src_addr,
720 (rc->src_addr->sa_family == AF_INET)
721 ? sizeof (struct sockaddr_in)
722 : sizeof (struct sockaddr_in6)));
860#endif 723#endif
861 return; 724 udp = (struct UDPMessage*) buf;
862 } 725 udp->header.size = htons ((uint16_t) msize);
726 udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK);
727 udp->reserved = htonl (0);
728 udp->sender = *rc->plugin->env->my_identity;
729 memcpy (&udp[1], msg, ntohs (msg->size));
730 (void) udp_send (rc->plugin,
731 rc->src_addr,
732 &udp->header);
733}
863 734
864 incoming_port = 0; 735
865 GNUNET_assert(sender_addr != NULL); /* Can recvfrom have a NULL address? */ 736/**
866 if (fromlen == sizeof(struct IPv4UdpAddress)) 737 * Closure for 'find_receive_context'.
867 { 738 */
868 incoming_port = ntohs(((struct IPv4UdpAddress *)sender_addr)->u4_port); 739struct FindReceiveContext
869 } 740{
870 else if (fromlen == sizeof(struct IPv6UdpAddress)) 741 /**
742 * Where to store the result.
743 */
744 struct ReceiveContext *rc;
745
746 /**
747 * Address to find.
748 */
749 const struct sockaddr *addr;
750
751 /**
752 * Number of bytes in 'addr'.
753 */
754 socklen_t addr_len;
755};
756
757
758/**
759 * Scan the heap for a receive context with the given address.
760 *
761 * @param cls the 'struct FindReceiveContext'
762 * @param node internal node of the heap
763 * @param element value stored at the node (a 'struct ReceiveContext')
764 * @param cost cost associated with the node
765 * @return GNUNET_YES if we should continue to iterate,
766 * GNUNET_NO if not.
767 */
768static int
769find_receive_context (void *cls,
770 struct GNUNET_CONTAINER_HeapNode *node,
771 void *element,
772 GNUNET_CONTAINER_HeapCostType cost)
773{
774 struct FindReceiveContext *frc = cls;
775 struct ReceiveContext *e = element;
776
777 if ( (frc->addr_len == e->addr_len) &&
778 (0 == memcmp (frc->addr,
779 e->src_addr,
780 frc->addr_len) ) )
871 { 781 {
872 incoming_port = ntohs(((struct IPv6UdpAddress *)sender_addr)->u6_port); 782 frc->rc = e;
783 return GNUNET_NO;
873 } 784 }
785 return GNUNET_YES;
786}
874 787
875 switch (ntohs(currhdr->type))
876 {
877 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE:
878 /* Send probe reply */
879 outgoing_probe_reply = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageReply));
880 outgoing_probe_reply->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageReply));
881 outgoing_probe_reply->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY);
882 788
883#if DEBUG_UDP 789/**
884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 790 * Read and process a message from the given socket.
885 _("Received a probe on listen port %d, sent_from port %d\n"), 791 *
886 sockinfo->port, incoming_port); 792 * @param plugin the overall plugin
887#endif 793 * @param rsock socket to read from
888 794 */
889 udp_real_send(plugin, sockinfo->desc, NULL, 795static void
890 (char *)outgoing_probe_reply, 796udp_read (struct Plugin *plugin,
891 ntohs(outgoing_probe_reply->header.size), 0, 797 struct GNUNET_NETWORK_Handle *rsock)
892 GNUNET_TIME_relative_get_unit(), 798{
893 sender_addr, fromlen, 799 socklen_t fromlen;
894 NULL, NULL); 800 char addr[32];
801 char buf[65536];
802 ssize_t ret;
803 const struct GNUNET_MessageHeader *msg;
804 const struct GNUNET_MessageHeader *ack;
805 struct PeerSession *peer_session;
806 const struct UDPMessage *udp;
807 struct ReceiveContext *rc;
808 struct GNUNET_TIME_Absolute now;
809 struct FindReceiveContext frc;
895 810
811 fromlen = sizeof (addr);
812 memset (&addr, 0, sizeof(addr));
813 ret = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
814 (struct sockaddr *)&addr, &fromlen);
815 if (ret < sizeof (struct GNUNET_MessageHeader))
816 {
817 GNUNET_break_op (0);
818 return;
819 }
896#if DEBUG_UDP 820#if DEBUG_UDP
897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
898 _("Sent PROBE REPLY to port %d on outgoing port %d\n"), 822 "UDP received %u-byte message from `%s'\n",
899 incoming_port, sockinfo->port); 823 (unsigned int) ret,
824 GNUNET_a2s ((const struct sockaddr*) addr, fromlen));
900#endif 825#endif
901 GNUNET_free(outgoing_probe_reply); 826 msg = (const struct GNUNET_MessageHeader *) buf;
902 break; 827 if (ret != ntohs (msg->size))
903 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY: 828 {
904 /* Check for existing probe, check ports returned, send confirmation if all is well */ 829 GNUNET_break_op (0);
830 return;
831 }
832 switch (ntohs (msg->type))
833 {
834 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE:
835 if (ntohs (msg->size) < sizeof (struct UDPMessage))
836 {
837 GNUNET_break_op (0);
838 return;
839 }
840 process_udp_message (plugin,
841 (const struct UDPMessage *) msg,
842 (const struct sockaddr*) addr,
843 fromlen);
844 return;
845 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
846 if (ntohs (msg->size) < sizeof (struct UDPMessage) + sizeof (struct GNUNET_MessageHeader))
847 {
848 GNUNET_break_op (0);
849 return;
850 }
851 udp = (const struct UDPMessage *) msg;
852 if (ntohl (udp->reserved) != 0)
853 {
854 GNUNET_break_op (0);
855 return;
856 }
857 ack = (const struct GNUNET_MessageHeader*) &udp[1];
858 if (ntohs (ack->size) != ntohs (msg->size) - sizeof (struct UDPMessage))
859 {
860 GNUNET_break_op (0);
861 return;
862 }
905#if DEBUG_UDP 863#if DEBUG_UDP
906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
907 _("Received PROBE REPLY from port %d on incoming port %d\n"), incoming_port, sockinfo->port); 865 "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
908#endif 866 (unsigned int) ntohs (msg->size),
909 if (fromlen == sizeof(struct IPv4UdpAddress)) 867 GNUNET_i2s (&udp->sender),
910 { 868 GNUNET_a2s ((const struct sockaddr*) addr, fromlen));
911 /* FIXME! */
912#if 0
913 struct UDP_NAT_ProbeMessageConfirmation *outgoing_probe_confirmation;
914 struct UDP_NAT_Probes *outgoing_probe;
915 outgoing_probe = find_probe(plugin, &addr_buf[0]);
916 if (outgoing_probe != NULL)
917 {
918#if DEBUG_UDP
919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
920 _("Sending confirmation that we were reached!\n"));
921#endif 869#endif
922 outgoing_probe_confirmation = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
923 outgoing_probe_confirmation->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
924 outgoing_probe_confirmation->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM);
925 udp_real_send(plugin, sockinfo->desc, NULL,
926 (char *)outgoing_probe_confirmation,
927 ntohs(outgoing_probe_confirmation->header.size), 0,
928 GNUNET_TIME_relative_get_unit(),
929 sender_addr, fromlen, NULL, NULL);
930
931 if (outgoing_probe->task != GNUNET_SCHEDULER_NO_TASK)
932 {
933 GNUNET_SCHEDULER_cancel(outgoing_probe->task);
934 outgoing_probe->task = GNUNET_SCHEDULER_NO_TASK;
935 /* Schedule task to timeout and remove probe if confirmation not received */
936 }
937 GNUNET_free(outgoing_probe_confirmation);
938 }
939 else
940 {
941#if DEBUG_UDP
942 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
943 _("Received a probe reply, but have no record of a sent probe!\n"));
944#endif
945 }
946#endif
947 }
948 else
949 {
950#if DEBUG_UDP
951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
952 _("Received a probe reply, but sender address size is WRONG (should be %d, is %d)!\n"), sizeof(struct IPv4UdpAddress), fromlen);
953#endif
954 }
955 break;
956 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM:
957 peer_session = find_session(plugin, sender);
958#if DEBUG_UDP
959 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
960 _("Looking up peer session for peer %s\n"), GNUNET_i2s(sender));
961#endif
962 if (peer_session == NULL) /* Shouldn't this NOT happen? */
963 {
964#if DEBUG_UDP
965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
966 _("Peer not in list, adding (THIS MAY BE A MISTAKE) %s\n"), GNUNET_i2s(sender));
967#endif
968 peer_session = GNUNET_malloc(sizeof(struct PeerSession));
969 peer_session->connect_addr = GNUNET_malloc(fromlen);
970 memcpy(peer_session->connect_addr, sender_addr, fromlen);
971 peer_session->connect_alen = fromlen;
972 peer_session->plugin = plugin;
973 peer_session->sock = sockinfo->desc;
974 memcpy(&peer_session->target, sender, sizeof(struct GNUNET_PeerIdentity));
975 peer_session->expecting_welcome = GNUNET_NO;
976
977 peer_session->next = plugin->sessions;
978 plugin->sessions = peer_session;
979
980 peer_session->messages = NULL;
981 }
982 else if (peer_session->expecting_welcome == GNUNET_YES)
983 {
984 peer_session->expecting_welcome = GNUNET_NO;
985 peer_session->sock = sockinfo->desc;
986 if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress))
987 {
988 ((struct IPv4UdpAddress *)peer_session->connect_addr)->u4_port = htons(incoming_port);
989 }
990 else if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress))
991 {
992 ((struct IPv6UdpAddress *)peer_session->connect_addr)->u6_port = htons(incoming_port);
993 }
994 870
871 peer_session = find_session (plugin, &udp->sender);
872 if (NULL == peer_session)
873 {
995#if DEBUG_UDP 874#if DEBUG_UDP
996 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
997 _("Received a probe confirmation, will send to peer on port %d\n"), incoming_port); 876 "Session for ACK not found, dropping ACK!\n");
998#endif
999 if (peer_session->messages != NULL)
1000 {
1001#if DEBUG_UDP
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 _("Received a probe confirmation, sending queued messages.\n"));
1004#endif
1005 pending_message = peer_session->messages;
1006 int count = 0;
1007 while (pending_message != NULL)
1008 {
1009#if DEBUG_UDP
1010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1011 _("sending queued message %d\n"), count);
1012#endif
1013 udp_real_send(plugin,
1014 peer_session->sock,
1015 &peer_session->target,
1016 pending_message->msgbuf,
1017 pending_message->msgbuf_size, 0,
1018 GNUNET_TIME_relative_get_unit(),
1019 peer_session->connect_addr,
1020 peer_session->connect_alen,
1021 pending_message->cont,
1022 pending_message->cont_cls);
1023
1024 pending_message_temp = pending_message;
1025 pending_message = pending_message->next;
1026 GNUNET_free(pending_message_temp->msgbuf);
1027 GNUNET_free(pending_message_temp);
1028#if DEBUG_UDP
1029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1030 _("finished sending queued message %d\n"), count);
1031#endif
1032 count++;
1033 }
1034 }
1035
1036 }
1037 else
1038 {
1039#if DEBUG_UDP
1040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1041 _("Received probe confirmation for already confirmed peer!\n"));
1042#endif 877#endif
1043 } 878 return;
1044 /* Received confirmation, add peer with address/port specified */ 879 }
1045 break; 880 if (GNUNET_OK !=
1046 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_KEEPALIVE: 881 GNUNET_FRAGMENT_process_ack (peer_session->frag,
1047 /* Once we've sent NAT_PROBE_CONFIRM change to sending keepalives */ 882 ack))
1048 /* If we receive these just ignore! */ 883 return;
1049 break; 884 GNUNET_assert (GNUNET_OK ==
1050 default: 885 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
1051 886 &udp->sender.hashPubKey,
887 peer_session));
888 GNUNET_FRAGMENT_context_destroy (peer_session->frag);
889 peer_session->cont (peer_session->cont_cls,
890 &udp->sender,
891 GNUNET_OK);
892 GNUNET_free (peer_session);
893 return;
894 case GNUNET_MESSAGE_TYPE_FRAGMENT:
895 frc.rc = NULL;
896 frc.addr = (const struct sockaddr*) addr;
897 frc.addr_len = fromlen;
898 GNUNET_CONTAINER_heap_iterate (plugin->defrags,
899 &find_receive_context,
900 &frc);
901 now = GNUNET_TIME_absolute_get ();
902 rc = frc.rc;
903 if (rc == NULL)
904 {
905 /* need to create a new RC */
906 rc = GNUNET_malloc (sizeof (struct ReceiveContext) + fromlen);
907 memcpy (&rc[1], addr, fromlen);
908 rc->src_addr = (const struct sockaddr*) &rc[1];
909 rc->addr_len = fromlen;
910 rc->plugin = plugin;
911 rc->defrag = GNUNET_DEFRAGMENT_context_create (plugin->env->stats,
912 UDP_MTU,
913 UDP_MAX_MESSAGES_IN_DEFRAG,
914 rc,
915 &fragment_msg_proc,
916 &ack_proc);
917 rc->hnode = GNUNET_CONTAINER_heap_insert (plugin->defrags,
918 rc,
919 (GNUNET_CONTAINER_HeapCostType) now.abs_value);
920 }
1052#if DEBUG_UDP 921#if DEBUG_UDP
1053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1054 "Sending message type %d to transport!\n", 923 "UDP processes %u-byte fragment from `%s'\n",
1055 ntohs(currhdr->type)); 924 (unsigned int) ntohs (msg->size),
925 GNUNET_a2s ((const struct sockaddr*) addr, fromlen));
1056#endif 926#endif
1057 927
1058 distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE); 928 if (GNUNET_OK ==
1059 distance[0].value = htonl (UDP_DIRECT_DISTANCE); 929 GNUNET_DEFRAGMENT_process_fragment (rc->defrag,
1060 distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR); 930 msg))
1061 distance[1].value = htonl (0); 931 {
1062 932 /* keep this 'rc' from expiring */
1063 plugin->env->receive (plugin->env->cls, sender, currhdr, 933 GNUNET_CONTAINER_heap_update_cost (plugin->defrags,
1064 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, 934 rc->hnode,
1065 NULL, sender_addr, fromlen); 935 (GNUNET_CONTAINER_HeapCostType) now.abs_value);
1066 } 936 }
1067 937 if (GNUNET_CONTAINER_heap_get_size (plugin->defrags) > UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG)
938 {
939 /* remove 'rc' that was inactive the longest */
940 rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags);
941 GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
942 GNUNET_free (rc);
943 }
944 return;
945 default:
946 GNUNET_break_op (0);
947 return;
948 }
1068} 949}
1069 950
1070 951
1071/* 952/**
1072 * We have been notified that our writeset has something to read. We don't 953 * We have been notified that our writeset has something to read. We don't
1073 * know which socket needs to be read, so we have to check each one 954 * know which socket needs to be read, so we have to check each one
1074 * Then reschedule this function to be called again once more is available. 955 * Then reschedule this function to be called again once more is available.
@@ -1081,124 +962,29 @@ udp_plugin_select (void *cls,
1081 const struct GNUNET_SCHEDULER_TaskContext *tc) 962 const struct GNUNET_SCHEDULER_TaskContext *tc)
1082{ 963{
1083 struct Plugin *plugin = cls; 964 struct Plugin *plugin = cls;
1084 char buf[65536];
1085 struct UDPMessage *msg;
1086 struct GNUNET_PeerIdentity sender;
1087 socklen_t fromlen;
1088 char addr[32];
1089 ssize_t ret;
1090 int offset;
1091 int tsize;
1092 char *msgbuf;
1093 const struct GNUNET_MessageHeader *currhdr;
1094 struct IPv4UdpAddress t4;
1095 struct IPv6UdpAddress t6;
1096 const struct sockaddr_in *s4;
1097 const struct sockaddr_in6 *s6;
1098 const void *ca;
1099 size_t calen;
1100 struct UDP_Sock_Info *udp_sock;
1101 uint16_t csize;
1102 965
1103 plugin->select_task = GNUNET_SCHEDULER_NO_TASK; 966 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1104 if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) 967 if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1105 return; 968 return;
1106 udp_sock = NULL;
1107 if (GNUNET_NETWORK_fdset_isset (tc->read_ready, 969 if (GNUNET_NETWORK_fdset_isset (tc->read_ready,
1108 plugin->udp_sockv4.desc)) 970 plugin->sockv4))
1109 udp_sock = &plugin->udp_sockv4; 971 udp_read (plugin, plugin->sockv4);
1110 else if (GNUNET_NETWORK_fdset_isset (tc->read_ready, 972 if (GNUNET_NETWORK_fdset_isset (tc->read_ready,
1111 plugin->udp_sockv6.desc)) 973 plugin->sockv6))
1112 udp_sock = &plugin->udp_sockv6; 974 udp_read (plugin, plugin->sockv6);
1113 if (NULL == udp_sock)
1114 {
1115 GNUNET_break (0);
1116 return;
1117 }
1118 fromlen = sizeof (addr);
1119 memset (&addr, 0, sizeof(addr));
1120 ret =
1121 GNUNET_NETWORK_socket_recvfrom (udp_sock->desc, buf, sizeof (buf),
1122 (struct sockaddr *)&addr, &fromlen);
1123
1124 if (AF_INET == ((struct sockaddr *)addr)->sa_family)
1125 {
1126 s4 = (const struct sockaddr_in*) &addr;
1127 t4.u4_port = s4->sin_port;
1128 t4.ipv4_addr = s4->sin_addr.s_addr;
1129 ca = &t4;
1130 calen = sizeof (t4);
1131 }
1132 else if (AF_INET6 == ((struct sockaddr *)addr)->sa_family)
1133 {
1134 s6 = (const struct sockaddr_in6*) &addr;
1135 t6.u6_port = s6->sin6_port;
1136 memcpy (&t6.ipv6_addr,
1137 &s6->sin6_addr,
1138 sizeof (struct in6_addr));
1139 ca = &t6;
1140 calen = sizeof (t6);
1141 }
1142 else
1143 {
1144 GNUNET_break (0);
1145 ca = NULL;
1146 calen = 0;
1147 }
1148 if (ret < sizeof (struct UDPMessage))
1149 {
1150 GNUNET_break_op (0);
1151 plugin->select_task =
1152 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1153 GNUNET_SCHEDULER_NO_TASK,
1154 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1155 NULL, &udp_plugin_select, plugin);
1156 return;
1157 }
1158 msg = (struct UDPMessage *) buf;
1159 csize = ntohs (msg->header.size);
1160 if ( (csize < sizeof (struct UDPMessage)) ||
1161 (csize > ret) )
1162 {
1163 GNUNET_break_op (0);
1164 plugin->select_task =
1165 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1166 GNUNET_SCHEDULER_NO_TASK,
1167 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1168 NULL, &udp_plugin_select, plugin);
1169 return;
1170 }
1171 msgbuf = (char *)&msg[1];
1172 memcpy (&sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
1173 offset = 0;
1174 tsize = csize - sizeof (struct UDPMessage);
1175 while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize)
1176 {
1177 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
1178 csize = ntohs (currhdr->size);
1179 if ( (csize < sizeof (struct GNUNET_MessageHeader)) ||
1180 (csize > tsize - offset) )
1181 {
1182 GNUNET_break_op (0);
1183 break;
1184 }
1185 udp_demultiplexer(plugin, &sender, currhdr,
1186 ca, calen, udp_sock);
1187 offset += csize;
1188 }
1189 plugin->select_task = 975 plugin->select_task =
1190 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 976 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1191 GNUNET_SCHEDULER_NO_TASK, 977 GNUNET_SCHEDULER_NO_TASK,
1192 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, 978 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1193 NULL, &udp_plugin_select, plugin); 979 NULL, &udp_plugin_select, plugin);
1194 980
1195} 981}
1196 982
1197 983
1198/** 984/**
1199 * Check if the given port is plausible (must be either 985 * Check if the given port is plausible (must be either our listen
1200 * our listen port or our advertised port). If it is 986 * port or our advertised port). If it is neither, we return
1201 * neither, we return GNUNET_SYSERR. 987 * GNUNET_SYSERR.
1202 * 988 *
1203 * @param plugin global variables 989 * @param plugin global variables
1204 * @param in_port port number to check 990 * @param in_port port number to check
@@ -1207,9 +993,8 @@ udp_plugin_select (void *cls,
1207static int 993static int
1208check_port (struct Plugin *plugin, uint16_t in_port) 994check_port (struct Plugin *plugin, uint16_t in_port)
1209{ 995{
1210 if (in_port == 0) 996 if ( (in_port == plugin->port) ||
1211 return GNUNET_OK; 997 (in_port == plugin->aport) )
1212 if (in_port == plugin->port)
1213 return GNUNET_OK; 998 return GNUNET_OK;
1214 return GNUNET_SYSERR; 999 return GNUNET_SYSERR;
1215} 1000}
@@ -1320,7 +1105,10 @@ udp_address_to_string (void *cls,
1320 sb = &a4; 1105 sb = &a4;
1321 } 1106 }
1322 else 1107 else
1323 return NULL; 1108 {
1109 GNUNET_break_op (0);
1110 return NULL;
1111 }
1324 inet_ntop (af, sb, buf, INET6_ADDRSTRLEN); 1112 inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
1325 GNUNET_snprintf (rbuf, 1113 GNUNET_snprintf (rbuf,
1326 sizeof (rbuf), 1114 sizeof (rbuf),
@@ -1331,9 +1119,33 @@ udp_address_to_string (void *cls,
1331} 1119}
1332 1120
1333 1121
1122/**
1123 * Closure for 'append_port'.
1124 */
1125struct PrettyPrinterContext
1126{
1127 /**
1128 * Function to call with the result.
1129 */
1130 GNUNET_TRANSPORT_AddressStringCallback asc;
1131
1132 /**
1133 * Clsoure for 'asc'.
1134 */
1135 void *asc_cls;
1136
1137 /**
1138 * Port to add after the IP address.
1139 */
1140 uint16_t port;
1141};
1142
1334 1143
1335/** 1144/**
1336 * Append our port and forward the result. 1145 * Append our port and forward the result.
1146 *
1147 * @param cls a 'struct PrettyPrinterContext'
1148 * @param hostname result from DNS resolver
1337 */ 1149 */
1338static void 1150static void
1339append_port (void *cls, const char *hostname) 1151append_port (void *cls, const char *hostname)
@@ -1343,13 +1155,14 @@ append_port (void *cls, const char *hostname)
1343 1155
1344 if (hostname == NULL) 1156 if (hostname == NULL)
1345 { 1157 {
1346 ret = strdup(udp_address_to_string(NULL, ppc->addr, ppc->addr_len)); 1158 ppc->asc (NULL, ret);
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error in name resolution: `%s'\n",ret);
1348 ppc->asc (ppc->asc_cls, ret);
1349 GNUNET_free (ppc); 1159 GNUNET_free (ppc);
1350 return; 1160 return;
1351 } 1161 }
1352 GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port); 1162 GNUNET_asprintf (&ret,
1163 "%s:%d",
1164 hostname,
1165 ppc->port);
1353 ppc->asc (ppc->asc_cls, ret); 1166 ppc->asc (ppc->asc_cls, ret);
1354 GNUNET_free (ret); 1167 GNUNET_free (ret);
1355} 1168}
@@ -1393,6 +1206,9 @@ udp_plugin_address_pretty_printer (void *cls,
1393 u6 = addr; 1206 u6 = addr;
1394 memset (&a6, 0, sizeof (a6)); 1207 memset (&a6, 0, sizeof (a6));
1395 a6.sin6_family = AF_INET6; 1208 a6.sin6_family = AF_INET6;
1209#if HAVE_SOCKADDR_IN_SIN_LEN
1210 a6.sin6_len = sizeof (a6);
1211#endif
1396 a6.sin6_port = u6->u6_port; 1212 a6.sin6_port = u6->u6_port;
1397 memcpy (&a6.sin6_addr, 1213 memcpy (&a6.sin6_addr,
1398 &u6->ipv6_addr, 1214 &u6->ipv6_addr,
@@ -1406,6 +1222,9 @@ udp_plugin_address_pretty_printer (void *cls,
1406 u4 = addr; 1222 u4 = addr;
1407 memset (&a4, 0, sizeof (a4)); 1223 memset (&a4, 0, sizeof (a4));
1408 a4.sin_family = AF_INET; 1224 a4.sin_family = AF_INET;
1225#if HAVE_SOCKADDR_IN_SIN_LEN
1226 a4.sin_len = sizeof (a4);
1227#endif
1409 a4.sin_port = u4->u4_port; 1228 a4.sin_port = u4->u4_port;
1410 a4.sin_addr.s_addr = u4->ipv4_addr; 1229 a4.sin_addr.s_addr = u4->ipv4_addr;
1411 port = ntohs (u4->u4_port); 1230 port = ntohs (u4->u4_port);
@@ -1419,16 +1238,14 @@ udp_plugin_address_pretty_printer (void *cls,
1419 asc (asc_cls, NULL); 1238 asc (asc_cls, NULL);
1420 return; 1239 return;
1421 } 1240 }
1422 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext) + addrlen); 1241 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
1423 ppc->asc = asc; 1242 ppc->asc = asc;
1424 ppc->asc_cls = asc_cls; 1243 ppc->asc_cls = asc_cls;
1425 ppc->port = port; 1244 ppc->port = port;
1426 ppc->addr = &ppc[1];
1427 ppc->addr_len = addrlen;
1428 memcpy(ppc->addr, addr, addrlen);
1429 GNUNET_RESOLVER_hostname_get (sb, 1245 GNUNET_RESOLVER_hostname_get (sb,
1430 sbs, 1246 sbs,
1431 !numeric, timeout, &append_port, ppc); 1247 !numeric, timeout,
1248 &append_port, ppc);
1432} 1249}
1433 1250
1434 1251
@@ -1443,9 +1260,9 @@ udp_plugin_address_pretty_printer (void *cls,
1443 */ 1260 */
1444static void 1261static void
1445udp_nat_port_map_callback (void *cls, 1262udp_nat_port_map_callback (void *cls,
1446 int add_remove, 1263 int add_remove,
1447 const struct sockaddr *addr, 1264 const struct sockaddr *addr,
1448 socklen_t addrlen) 1265 socklen_t addrlen)
1449{ 1266{
1450 struct Plugin *plugin = cls; 1267 struct Plugin *plugin = cls;
1451 struct IPv4UdpAddress u4; 1268 struct IPv4UdpAddress u4;
@@ -1486,13 +1303,16 @@ udp_nat_port_map_callback (void *cls,
1486/** 1303/**
1487 * The exported method. Makes the core api available via a global and 1304 * The exported method. Makes the core api available via a global and
1488 * returns the udp transport API. 1305 * returns the udp transport API.
1306 *
1307 * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
1308 * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
1489 */ 1309 */
1490void * 1310void *
1491libgnunet_plugin_transport_udp_init (void *cls) 1311libgnunet_plugin_transport_udp_init (void *cls)
1492{ 1312{
1493 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; 1313 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1494 unsigned long long mtu;
1495 unsigned long long port; 1314 unsigned long long port;
1315 unsigned long long aport;
1496 struct GNUNET_TRANSPORT_PluginFunctions *api; 1316 struct GNUNET_TRANSPORT_PluginFunctions *api;
1497 struct Plugin *plugin; 1317 struct Plugin *plugin;
1498 int sockets_created; 1318 int sockets_created;
@@ -1503,13 +1323,26 @@ libgnunet_plugin_transport_udp_init (void *cls)
1503 socklen_t addrlens[2]; 1323 socklen_t addrlens[2];
1504 socklen_t addrlen; 1324 socklen_t addrlen;
1505 unsigned int tries; 1325 unsigned int tries;
1326 unsigned long long udp_max_bps;
1506 1327
1507 if (GNUNET_OK != 1328 if (GNUNET_OK !=
1508 GNUNET_CONFIGURATION_get_value_number (env->cfg, 1329 GNUNET_CONFIGURATION_get_value_number (env->cfg,
1509 "transport-udp", 1330 "transport-udp",
1510 "PORT", 1331 "PORT",
1511 &port)) 1332 &port))
1512 port = UDP_NAT_DEFAULT_PORT; 1333 port = 2086;
1334 if (GNUNET_OK !=
1335 GNUNET_CONFIGURATION_get_value_number (env->cfg,
1336 "transport-udp",
1337 "MAX_BPS",
1338 &udp_max_bps))
1339 udp_max_bps = 1024 * 1024 * 100; /* 100 MB/s == infinity for practical purposes */
1340 if (GNUNET_OK !=
1341 GNUNET_CONFIGURATION_get_value_number (env->cfg,
1342 "transport-udp",
1343 "ADVERTISED_PORT",
1344 &aport))
1345 aport = port;
1513 if (port > 65535) 1346 if (port > 65535)
1514 { 1347 {
1515 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1348 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1519,14 +1352,16 @@ libgnunet_plugin_transport_udp_init (void *cls)
1519 65535); 1352 65535);
1520 return NULL; 1353 return NULL;
1521 } 1354 }
1355 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1356 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1522 1357
1523 mtu = 1240;
1524 if (mtu < 1200)
1525 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1526 _("MTU %llu for `%s' is probably too low!\n"), mtu,
1527 "UDP");
1528 plugin = GNUNET_malloc (sizeof (struct Plugin)); 1358 plugin = GNUNET_malloc (sizeof (struct Plugin));
1359 GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
1360 GNUNET_BANDWIDTH_value_init ((uint32_t) udp_max_bps),
1361 30);
1362 plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
1529 plugin->port = port; 1363 plugin->port = port;
1364 plugin->aport = aport;
1530 plugin->env = env; 1365 plugin->env = env;
1531 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 1366 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1532 api->cls = plugin; 1367 api->cls = plugin;
@@ -1540,43 +1375,63 @@ libgnunet_plugin_transport_udp_init (void *cls)
1540 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, 1375 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg,
1541 "transport-udp", 1376 "transport-udp",
1542 "BINDTO", 1377 "BINDTO",
1543 &plugin->bind_address)) 1378 &plugin->bind4_address))
1544 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 1379 {
1545 "Binding udp plugin to specific address: `%s'\n", 1380 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1546 plugin->bind_address); 1381 "Binding udp plugin to specific address: `%s'\n",
1382 plugin->bind4_address);
1383 if (1 != inet_pton(AF_INET,
1384 plugin->bind4_address,
1385 &serverAddrv4.sin_addr))
1386 {
1387 GNUNET_free (plugin->bind4_address);
1388 GNUNET_free (plugin);
1389 return NULL;
1390 }
1391 }
1392
1547 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, 1393 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg,
1548 "transport-udp", 1394 "transport-udp",
1549 "BINDTO6", 1395 "BINDTO6",
1550 &plugin->bind6_address)) 1396 &plugin->bind6_address))
1551 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 1397 {
1552 "Binding udp plugin to specific address: `%s'\n", 1398 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1553 plugin->bind6_address); 1399 "Binding udp plugin to specific address: `%s'\n",
1400 plugin->bind6_address);
1401 if (1 != inet_pton(AF_INET6,
1402 plugin->bind6_address,
1403 &serverAddrv6.sin6_addr))
1404 {
1405 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1406 _("Invalid IPv6 address: `%s'\n"),
1407 plugin->bind6_address);
1408 GNUNET_free_non_null (plugin->bind4_address);
1409 GNUNET_free (plugin->bind6_address);
1410 GNUNET_free (plugin);
1411 return NULL;
1412 }
1413 }
1554 1414
1415 plugin->defrags = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1416 plugin->sessions = GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG * 2);
1555 sockets_created = 0; 1417 sockets_created = 0;
1556 if ( (GNUNET_YES != 1418 if ( (GNUNET_YES !=
1557 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, 1419 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg,
1558 "gnunetd", 1420 "nat",
1559 "DISABLEV6"))) 1421 "DISABLEV6")))
1560 { 1422 {
1561 plugin->udp_sockv6.desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0); 1423 plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
1562 if (NULL == plugin->udp_sockv6.desc) 1424 if (NULL == plugin->sockv6)
1563 { 1425 {
1564 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", "socket"); 1426 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
1565 } 1427 }
1566 else 1428 else
1567 { 1429 {
1568 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1569#if HAVE_SOCKADDR_IN_SIN_LEN 1430#if HAVE_SOCKADDR_IN_SIN_LEN
1570 serverAddrv6.sin6_len = sizeof (serverAddrv6); 1431 serverAddrv6.sin6_len = sizeof (serverAddrv6);
1571#endif 1432#endif
1572
1573 serverAddrv6.sin6_family = AF_INET6; 1433 serverAddrv6.sin6_family = AF_INET6;
1574 serverAddrv6.sin6_addr = in6addr_any; 1434 serverAddrv6.sin6_addr = in6addr_any;
1575 if (plugin->bind6_address != NULL)
1576 {
1577 if (1 != inet_pton(AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
1578 return 0;
1579 }
1580 serverAddrv6.sin6_port = htons (plugin->port); 1435 serverAddrv6.sin6_port = htons (plugin->port);
1581 addrlen = sizeof (serverAddrv6); 1436 addrlen = sizeof (serverAddrv6);
1582 serverAddr = (struct sockaddr *) &serverAddrv6; 1437 serverAddr = (struct sockaddr *) &serverAddrv6;
@@ -1586,7 +1441,8 @@ libgnunet_plugin_transport_udp_init (void *cls)
1586 ntohs(serverAddrv6.sin6_port)); 1441 ntohs(serverAddrv6.sin6_port));
1587#endif 1442#endif
1588 tries = 0; 1443 tries = 0;
1589 while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv6.desc, serverAddr, addrlen) != 1444 while (GNUNET_NETWORK_socket_bind (plugin->sockv6,
1445 serverAddr, addrlen) !=
1590 GNUNET_OK) 1446 GNUNET_OK)
1591 { 1447 {
1592 serverAddrv6.sin6_port 1448 serverAddrv6.sin6_port
@@ -1599,14 +1455,13 @@ libgnunet_plugin_transport_udp_init (void *cls)
1599 tries++; 1455 tries++;
1600 if (tries > 10) 1456 if (tries > 10)
1601 { 1457 {
1602 GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc); 1458 GNUNET_NETWORK_socket_close (plugin->sockv6);
1603 plugin->udp_sockv6.desc = NULL; 1459 plugin->sockv6 = NULL;
1604 break; 1460 break;
1605 } 1461 }
1606 } 1462 }
1607 if (plugin->udp_sockv6.desc != NULL) 1463 if (plugin->sockv6 != NULL)
1608 { 1464 {
1609 plugin->udp_sockv6.port = ntohs(serverAddrv6.sin6_port);
1610 addrs[sockets_created] = (struct sockaddr*) &serverAddrv6; 1465 addrs[sockets_created] = (struct sockaddr*) &serverAddrv6;
1611 addrlens[sockets_created] = sizeof (serverAddrv6); 1466 addrlens[sockets_created] = sizeof (serverAddrv6);
1612 sockets_created++; 1467 sockets_created++;
@@ -1614,24 +1469,20 @@ libgnunet_plugin_transport_udp_init (void *cls)
1614 } 1469 }
1615 } 1470 }
1616 1471
1617 plugin->udp_sockv4.desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0); 1472 plugin->mst = GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages,
1618 if (NULL == plugin->udp_sockv4.desc) 1473 plugin);
1474 plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
1475 if (NULL == plugin->sockv4)
1619 { 1476 {
1620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "socket"); 1477 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
1621 } 1478 }
1622 else 1479 else
1623 { 1480 {
1624 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1625#if HAVE_SOCKADDR_IN_SIN_LEN 1481#if HAVE_SOCKADDR_IN_SIN_LEN
1626 serverAddrv4.sin_len = sizeof (serverAddrv4); 1482 serverAddrv4.sin_len = sizeof (serverAddrv4);
1627#endif 1483#endif
1628 serverAddrv4.sin_family = AF_INET; 1484 serverAddrv4.sin_family = AF_INET;
1629 serverAddrv4.sin_addr.s_addr = INADDR_ANY; 1485 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1630 if (plugin->bind_address != NULL)
1631 {
1632 if (1 != inet_pton(AF_INET, plugin->bind_address, &serverAddrv4.sin_addr))
1633 return 0;
1634 }
1635 serverAddrv4.sin_port = htons (plugin->port); 1486 serverAddrv4.sin_port = htons (plugin->port);
1636 addrlen = sizeof (serverAddrv4); 1487 addrlen = sizeof (serverAddrv4);
1637 serverAddr = (struct sockaddr *) &serverAddrv4; 1488 serverAddr = (struct sockaddr *) &serverAddrv4;
@@ -1641,7 +1492,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
1641 ntohs(serverAddrv4.sin_port)); 1492 ntohs(serverAddrv4.sin_port));
1642#endif 1493#endif
1643 tries = 0; 1494 tries = 0;
1644 while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv4.desc, serverAddr, addrlen) != 1495 while (GNUNET_NETWORK_socket_bind (plugin->sockv4, serverAddr, addrlen) !=
1645 GNUNET_OK) 1496 GNUNET_OK)
1646 { 1497 {
1647 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */ 1498 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
@@ -1653,14 +1504,13 @@ libgnunet_plugin_transport_udp_init (void *cls)
1653 tries++; 1504 tries++;
1654 if (tries > 10) 1505 if (tries > 10)
1655 { 1506 {
1656 GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc); 1507 GNUNET_NETWORK_socket_close (plugin->sockv4);
1657 plugin->udp_sockv4.desc = NULL; 1508 plugin->sockv4 = NULL;
1658 break; 1509 break;
1659 } 1510 }
1660 } 1511 }
1661 if (plugin->udp_sockv4.desc != NULL) 1512 if (plugin->sockv4 != NULL)
1662 { 1513 {
1663 plugin->udp_sockv4.port = ntohs(serverAddrv4.sin_port);
1664 addrs[sockets_created] = (struct sockaddr*) &serverAddrv4; 1514 addrs[sockets_created] = (struct sockaddr*) &serverAddrv4;
1665 addrlens[sockets_created] = sizeof (serverAddrv4); 1515 addrlens[sockets_created] = sizeof (serverAddrv4);
1666 sockets_created++; 1516 sockets_created++;
@@ -1669,12 +1519,12 @@ libgnunet_plugin_transport_udp_init (void *cls)
1669 1519
1670 plugin->rs = GNUNET_NETWORK_fdset_create (); 1520 plugin->rs = GNUNET_NETWORK_fdset_create ();
1671 GNUNET_NETWORK_fdset_zero (plugin->rs); 1521 GNUNET_NETWORK_fdset_zero (plugin->rs);
1672 if (NULL != plugin->udp_sockv4.desc) 1522 if (NULL != plugin->sockv4)
1673 GNUNET_NETWORK_fdset_set (plugin->rs, 1523 GNUNET_NETWORK_fdset_set (plugin->rs,
1674 plugin->udp_sockv4.desc); 1524 plugin->sockv4);
1675 if (NULL != plugin->udp_sockv6.desc) 1525 if (NULL != plugin->sockv6)
1676 GNUNET_NETWORK_fdset_set (plugin->rs, 1526 GNUNET_NETWORK_fdset_set (plugin->rs,
1677 plugin->udp_sockv6.desc); 1527 plugin->sockv6);
1678 1528
1679 plugin->select_task = 1529 plugin->select_task =
1680 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 1530 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
@@ -1690,33 +1540,75 @@ libgnunet_plugin_transport_udp_init (void *cls)
1690 sockets_created, 1540 sockets_created,
1691 (const struct sockaddr**) addrs, addrlens, 1541 (const struct sockaddr**) addrs, addrlens,
1692 &udp_nat_port_map_callback, 1542 &udp_nat_port_map_callback,
1693 &udp_plugin_reversal_callback, 1543 NULL,
1694 plugin); 1544 plugin);
1695 return api; 1545 return api;
1696} 1546}
1697 1547
1698 1548
1549/**
1550 * Destroy a session, plugin is being unloaded.
1551 *
1552 * @param cls unused
1553 * @param key hash of public key of target peer
1554 * @param value a 'struct PeerSession*' to clean up
1555 * @return GNUNET_OK (continue to iterate)
1556 */
1557static int
1558destroy_session (void *cls,
1559 const GNUNET_HashCode *key,
1560 void *value)
1561{
1562 struct PeerSession *peer_session = value;
1563
1564 GNUNET_FRAGMENT_context_destroy (peer_session->frag);
1565 GNUNET_free (peer_session);
1566 return GNUNET_OK;
1567}
1568
1569
1570/**
1571 * Shutdown the plugin.
1572 *
1573 * @param cls our 'struct GNUNET_TRANSPORT_PluginFunctions'
1574 * @return NULL
1575 */
1699void * 1576void *
1700libgnunet_plugin_transport_udp_done (void *cls) 1577libgnunet_plugin_transport_udp_done (void *cls)
1701{ 1578{
1702 struct GNUNET_TRANSPORT_PluginFunctions *api = cls; 1579 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1703 struct Plugin *plugin = api->cls; 1580 struct Plugin *plugin = api->cls;
1704 1581 struct ReceiveContext *rc;
1582
1583 /* FIXME: clean up heap and hashmap */
1584 GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions,
1585 &destroy_session,
1586 NULL);
1587 GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
1588 plugin->sessions = NULL;
1589 while (NULL != (rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags)))
1590 {
1591 GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
1592 GNUNET_free (rc);
1593 }
1594 GNUNET_CONTAINER_heap_destroy (plugin->defrags);
1595
1705 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK) 1596 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
1706 { 1597 {
1707 GNUNET_SCHEDULER_cancel (plugin->select_task); 1598 GNUNET_SCHEDULER_cancel (plugin->select_task);
1708 plugin->select_task = GNUNET_SCHEDULER_NO_TASK; 1599 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1709 } 1600 }
1710 if (plugin->udp_sockv4.desc != NULL) 1601 if (plugin->sockv4 != NULL)
1711 { 1602 {
1712 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc)); 1603 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4));
1713 plugin->udp_sockv4.desc = NULL; 1604 plugin->sockv4 = NULL;
1714 } 1605 }
1715 if (plugin->udp_sockv6.desc != NULL) 1606 if (plugin->sockv6 != NULL)
1716 { 1607 {
1717 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc)); 1608 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6));
1718 plugin->udp_sockv6.desc = NULL; 1609 plugin->sockv6 = NULL;
1719 } 1610 }
1611 GNUNET_SERVER_mst_destroy (plugin->mst);
1720 GNUNET_NETWORK_fdset_destroy (plugin->rs); 1612 GNUNET_NETWORK_fdset_destroy (plugin->rs);
1721 GNUNET_NAT_unregister (plugin->nat); 1613 GNUNET_NAT_unregister (plugin->nat);
1722 plugin->nat = NULL; 1614 plugin->nat = NULL;