aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2012-02-13 11:57:40 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2012-02-13 11:57:40 +0000
commitf89a942814ab1eb72334dafb80120ee146e42783 (patch)
treee30ffca8c2f9dea385cc9892dee44378bcd4a077
parent7eaa96c073b94a0f0d0968c578d493db75a0e020 (diff)
downloadgnunet-f89a942814ab1eb72334dafb80120ee146e42783.tar.gz
gnunet-f89a942814ab1eb72334dafb80120ee146e42783.zip
adding rewritten udp plugin
-rw-r--r--src/transport/Makefile.am3
-rw-r--r--src/transport/gnunet-service-transport_neighbours.c9
-rw-r--r--src/transport/plugin_transport_udp.c2971
-rw-r--r--src/transport/plugin_transport_udp.h (renamed from src/transport/plugin_transport_udp_new.h)0
-rw-r--r--src/transport/plugin_transport_udp_broadcasting.c (renamed from src/transport/plugin_transport_udp_new_broadcasting.c)2
5 files changed, 1216 insertions, 1769 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 2fe7d8416..988e2fed7 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -187,7 +187,8 @@ libgnunet_plugin_transport_wlan_la_LDFLAGS = \
187 $(GN_PLUGIN_LDFLAGS) 187 $(GN_PLUGIN_LDFLAGS)
188 188
189libgnunet_plugin_transport_udp_la_SOURCES = \ 189libgnunet_plugin_transport_udp_la_SOURCES = \
190 plugin_transport_udp.c 190 plugin_transport_udp.c \
191 plugin_transport_udp_broadcasting.c
191libgnunet_plugin_transport_udp_la_LIBADD = \ 192libgnunet_plugin_transport_udp_la_LIBADD = \
192 $(top_builddir)/src/hello/libgnunethello.la \ 193 $(top_builddir)/src/hello/libgnunethello.la \
193 $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ 194 $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c
index a6f42052c..6fd5f7e61 100644
--- a/src/transport/gnunet-service-transport_neighbours.c
+++ b/src/transport/gnunet-service-transport_neighbours.c
@@ -637,7 +637,6 @@ send_with_session (struct NeighbourMapEntry *n,
637} 637}
638 638
639 639
640
641static ssize_t 640static ssize_t
642send_with_plugin (const struct GNUNET_PeerIdentity *target, const char *msgbuf, 641send_with_plugin (const struct GNUNET_PeerIdentity *target, const char *msgbuf,
643 size_t msgbuf_size, uint32_t priority, 642 size_t msgbuf_size, uint32_t priority,
@@ -1561,7 +1560,7 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
1561 return GNUNET_NO; 1560 return GNUNET_NO;
1562 } 1561 }
1563 1562
1564 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1565 "Obtained new session %p for peer `%s' and address '%s'\n", 1564 "Obtained new session %p for peer `%s' and address '%s'\n",
1566 n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address)); 1565 n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
1567 /* Telling ATS about new session */ 1566 /* Telling ATS about new session */
@@ -1569,15 +1568,11 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
1569 } 1568 }
1570 else 1569 else
1571 { 1570 {
1572 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1571 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1573 "Using existing session %p for peer `%s' and address '%s'\n", 1572 "Using existing session %p for peer `%s' and address '%s'\n",
1574 n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address)); 1573 n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
1575 n->session = session; 1574 n->session = session;
1576 } 1575 }
1577 /* remove this dummy */
1578 if (NULL != NULL) send_with_plugin (NULL, NULL, 0,
1579 UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, NULL,
1580 NULL, GNUNET_YES, NULL, NULL);
1581#else 1576#else
1582 n->session = session; 1577 n->session = session;
1583 1578
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index cae033c45..3f04e3b9f 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -20,12 +20,13 @@
20 20
21/** 21/**
22 * @file transport/plugin_transport_udp.c 22 * @file transport/plugin_transport_udp.c
23 * @brief Implementation of the UDP NAT punching 23 * @brief Implementation of the UDP transport protocol
24 * transport service
25 * @author Christian Grothoff 24 * @author Christian Grothoff
26 * @author Nathan Evans 25 * @author Nathan Evans
26 * @author Matthias Wachs
27 */ 27 */
28#include "platform.h" 28#include "platform.h"
29#include "plugin_transport_udp.h"
29#include "gnunet_hello_lib.h" 30#include "gnunet_hello_lib.h"
30#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
31#include "gnunet_fragmentation_lib.h" 32#include "gnunet_fragmentation_lib.h"
@@ -42,14 +43,6 @@
42#define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__) 43#define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
43 44
44 45
45#define DEBUG_UDP GNUNET_EXTRA_LOGGING
46
47/**
48 * MTU for fragmentation subsystem. Should be conservative since
49 * all communicating peers MUST work with this MTU.
50 */
51#define UDP_MTU 1400
52
53/** 46/**
54 * Number of messages we can defragment in parallel. We only really 47 * Number of messages we can defragment in parallel. We only really
55 * defragment 1 message at a time, but if messages get re-ordered, we 48 * defragment 1 message at a time, but if messages get re-ordered, we
@@ -70,172 +63,125 @@
70#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128 63#define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
71 64
72 65
73GNUNET_NETWORK_STRUCT_BEGIN
74 66
75/** 67/**
76 * UDP Message-Packet header (after defragmentation). 68 * Closure for 'append_port'.
77 */ 69 */
78struct UDPMessage 70struct PrettyPrinterContext
79{ 71{
80 /** 72 /**
81 * Message header. 73 * Function to call with the result.
82 */ 74 */
83 struct GNUNET_MessageHeader header; 75 GNUNET_TRANSPORT_AddressStringCallback asc;
84 76
85 /** 77 /**
86 * Always zero for now. 78 * Clsoure for 'asc'.
87 */ 79 */
88 uint32_t reserved; 80 void *asc_cls;
89 81
90 /** 82 /**
91 * What is the identity of the sender 83 * Port to add after the IP address.
92 */ 84 */
93 struct GNUNET_PeerIdentity sender; 85 uint16_t port;
94
95}; 86};
96 87
97/** 88struct Session
98 * UDP ACK Message-Packet header (after defragmentation).
99 */
100struct UDP_ACK_Message
101{ 89{
102 /** 90 /**
103 * Message header. 91 * Which peer is this session for?
104 */ 92 */
105 struct GNUNET_MessageHeader header; 93 struct GNUNET_PeerIdentity target;
106 94
107 /** 95 /**
108 * Desired delay for flow control 96 * Address of the other peer
109 */ 97 */
110 uint32_t delay; 98 const struct sockaddr *sock_addr;
99
100 size_t addrlen;
111 101
112 /** 102 /**
113 * What is the identity of the sender 103 * Desired delay for next sending we send to other peer
114 */ 104 */
115 struct GNUNET_PeerIdentity sender; 105 struct GNUNET_TIME_Relative flow_delay_for_other_peer;
116};
117
118
119struct UDP_Beacon_Message
120{
121 /**
122 * Message header.
123 */
124 struct GNUNET_MessageHeader header;
125
126 /**
127 * What is the identity of the sender
128 */
129 struct GNUNET_PeerIdentity sender;
130};
131
132 106
133/**
134 * Network format for IPv4 addresses.
135 */
136struct IPv4UdpAddress
137{
138 /** 107 /**
139 * IPv4 address, in network byte order. 108 * Desired delay for next sending we received from other peer
140 */ 109 */
141 uint32_t ipv4_addr GNUNET_PACKED; 110 struct GNUNET_TIME_Absolute flow_delay_from_other_peer;
142 111
143 /** 112 /**
144 * Port number, in network byte order. 113 * expected delay for ACKs
145 */ 114 */
146 uint16_t u4_port GNUNET_PACKED; 115 struct GNUNET_TIME_Relative last_expected_delay;
147};
148
149 116
150/**
151 * Network format for IPv6 addresses.
152 */
153struct IPv6UdpAddress
154{
155 117
156 /** 118 struct GNUNET_ATS_Information ats;
157 * IPv6 address.
158 */
159 struct in6_addr ipv6_addr GNUNET_PACKED;
160 119
161 /** 120 struct FragmentationContext * frag_ctx;
162 * Port number, in network byte order.
163 */
164 uint16_t u6_port GNUNET_PACKED;
165}; 121};
166GNUNET_NETWORK_STRUCT_END
167 122
168/* Forward definition */ 123
169struct Plugin; 124struct SessionCompareContext
125{
126 struct Session *res;
127 const struct GNUNET_HELLO_Address *addr;
128};
170 129
171 130
172/** 131/**
173 * Session with another peer. FIXME: why not make this into 132 * Closure for 'process_inbound_tokenized_messages'
174 * a regular 'struct Session' and pass it around!?
175 */ 133 */
176struct Session 134struct SourceInformation
177{ 135{
178
179 /** 136 /**
180 * Which peer is this session for? 137 * Sender identity.
181 */ 138 */
182 struct GNUNET_PeerIdentity target; 139 struct GNUNET_PeerIdentity sender;
183 140
184 /** 141 /**
185 * Pointer to the global plugin struct. 142 * Source address.
186 */ 143 */
187 struct Plugin *plugin; 144 const void *arg;
188 145
189 /** 146 /**
190 * Address of the other peer 147 * Number of bytes in source address.
191 */ 148 */
192 const struct sockaddr *sock_addr; 149 size_t args;
193
194 size_t addrlen;
195 150
196 /** 151 struct Session *session;
197 * ATS network type in NBO 152};
198 */
199 uint32_t ats_address_network_type;
200 153
201 /**
202 * Function to call upon completion of the transmission.
203 */
204 GNUNET_TRANSPORT_TransmitContinuation cont;
205 154
155/**
156 * Closure for 'find_receive_context'.
157 */
158struct FindReceiveContext
159{
206 /** 160 /**
207 * Closure for 'cont'. 161 * Where to store the result.
208 */ 162 */
209 void *cont_cls; 163 struct DefragContext *rc;
210 164
211 /** 165 /**
212 * Current outgoing message to this peer. 166 * Address to find.
213 */ 167 */
214 struct GNUNET_FRAGMENT_Context *frag; 168 const struct sockaddr *addr;
215
216 struct GNUNET_TIME_Absolute valid_until;
217
218 GNUNET_SCHEDULER_TaskIdentifier invalidation_task;
219
220 GNUNET_SCHEDULER_TaskIdentifier delayed_cont_task;
221 169
222 /** 170 /**
223 * Desired delay for next sending we send to other peer 171 * Number of bytes in 'addr'.
224 */ 172 */
225 struct GNUNET_TIME_Relative flow_delay_for_other_peer; 173 socklen_t addr_len;
226 174
227 /** 175 struct Session *session;
228 * Desired delay for next sending we received from other peer
229 */
230 struct GNUNET_TIME_Absolute flow_delay_from_other_peer;
231}; 176};
232 177
233 178
179
234/** 180/**
235 * Data structure to track defragmentation contexts based 181 * Data structure to track defragmentation contexts based
236 * on the source of the UDP traffic. 182 * on the source of the UDP traffic.
237 */ 183 */
238struct ReceiveContext 184struct DefragContext
239{ 185{
240 186
241 /** 187 /**
@@ -263,298 +209,311 @@ struct ReceiveContext
263 * Length of 'src_addr' 209 * Length of 'src_addr'
264 */ 210 */
265 size_t addr_len; 211 size_t addr_len;
266
267 struct GNUNET_PeerIdentity id;
268
269}; 212};
270 213
271struct BroadcastAddress
272{
273 struct BroadcastAddress *next;
274 struct BroadcastAddress *prev;
275
276 void *addr;
277 socklen_t addrlen;
278};
279 214
280 215
281/** 216/**
282 * Encapsulation of all of the state of the plugin. 217 * Closure for 'process_inbound_tokenized_messages'
283 */ 218 */
284struct Plugin 219struct FragmentationContext
285{ 220{
221 struct FragmentationContext * next;
222 struct FragmentationContext * prev;
286 223
287 /** 224 struct Plugin * plugin;
288 * Our environment. 225 struct GNUNET_FRAGMENT_Context * frag;
289 */ 226 struct Session * session;
290 struct GNUNET_TRANSPORT_PluginEnvironment *env;
291
292 /**
293 * Session of peers with whom we are currently connected,
294 * map of peer identity to 'struct PeerSession'.
295 */
296 struct GNUNET_CONTAINER_MultiHashMap *sessions;
297
298 /**
299 * Session of peers with whom we are currently connected,
300 * map of peer identity to 'struct PeerSession'.
301 */
302 struct GNUNET_CONTAINER_MultiHashMap *inbound_sessions;
303
304 /**
305 * Heap with all of our defragmentation activities.
306 */
307 struct GNUNET_CONTAINER_Heap *defrags;
308
309 /**
310 * ID of select task
311 */
312 GNUNET_SCHEDULER_TaskIdentifier select_task;
313
314 /**
315 * Tokenizer for inbound messages.
316 */
317 struct GNUNET_SERVER_MessageStreamTokenizer *mst;
318
319 /**
320 * Bandwidth tracker to limit global UDP traffic.
321 */
322 struct GNUNET_BANDWIDTH_Tracker tracker;
323
324 /**
325 * Address we were told to bind to exclusively (IPv4).
326 */
327 char *bind4_address;
328
329 /**
330 * Address we were told to bind to exclusively (IPv6).
331 */
332 char *bind6_address;
333
334 /**
335 * Handle to NAT traversal support.
336 */
337 struct GNUNET_NAT_Handle *nat;
338
339 /**
340 * FD Read set
341 */
342 struct GNUNET_NETWORK_FDSet *rs;
343 227
344 /** 228 struct GNUNET_TIME_Absolute timeout;
345 * The read socket for IPv4
346 */
347 struct GNUNET_NETWORK_Handle *sockv4;
348 229
349 /**
350 * The read socket for IPv6
351 */
352 struct GNUNET_NETWORK_Handle *sockv6;
353
354 /**
355 * Beacon broadcasting
356 * -------------------
357 */
358 230
359 /** 231 /**
360 * Broadcast interval 232 * Function to call upon completion of the transmission.
361 */ 233 */
362 struct GNUNET_TIME_Relative broadcast_interval; 234 GNUNET_TRANSPORT_TransmitContinuation cont;
363 235
364 /** 236 /**
365 * Broadcast with IPv4 237 * Closure for 'cont'.
366 */ 238 */
367 int broadcast_ipv4; 239 void *cont_cls;
368 240
369 /** 241 size_t bytes_to_send;
370 * Broadcast with IPv6 242};
371 */
372 int broadcast_ipv6;
373 243
374 244
375 /** 245struct UDPMessageWrapper
376 * Tokenizer for inbound messages. 246{
377 */ 247 struct Session *session;
378 struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_ipv6_mst; 248 struct UDPMessageWrapper *prev;
379 struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_ipv4_mst; 249 struct UDPMessageWrapper *next;
250 char *udp;
251 size_t msg_size;
380 252
381 /** 253 struct GNUNET_TIME_Absolute timeout;
382 * ID of select broadcast task
383 */
384 GNUNET_SCHEDULER_TaskIdentifier send_ipv4_broadcast_task;
385 254
386 /** 255 /**
387 * ID of select broadcast task 256 * Function to call upon completion of the transmission.
388 */ 257 */
389 GNUNET_SCHEDULER_TaskIdentifier send_ipv6_broadcast_task; 258 GNUNET_TRANSPORT_TransmitContinuation cont;
390 259
391 /** 260 /**
392 * IPv6 multicast address 261 * Closure for 'cont'.
393 */ 262 */
394 struct sockaddr_in6 ipv6_multicast_address; 263 void *cont_cls;
395 264
396 /** 265 struct FragmentationContext *frag_ctx;
397 * DLL of IPv4 broadcast addresses
398 */
399 struct BroadcastAddress *ipv4_broadcast_tail;
400 struct BroadcastAddress *ipv4_broadcast_head;
401 266
267};
402 268
403 /**
404 * expected delay for ACKs
405 */
406 struct GNUNET_TIME_Relative last_expected_delay;
407 269
270/**
271 * UDP ACK Message-Packet header (after defragmentation).
272 */
273struct UDP_ACK_Message
274{
408 /** 275 /**
409 * Port we broadcasting on. 276 * Message header.
410 */ 277 */
411 uint16_t broadcast_port; 278 struct GNUNET_MessageHeader header;
412 279
413 /** 280 /**
414 * Port we listen on. 281 * Desired delay for flow control
415 */ 282 */
416 uint16_t port; 283 uint32_t delay;
417 284
418 /** 285 /**
419 * Port we advertise on. 286 * What is the identity of the sender
420 */ 287 */
421 uint16_t aport; 288 struct GNUNET_PeerIdentity sender;
422 289
423}; 290};
424 291
425struct PeerSessionIteratorContext
426{
427 struct Session *result;
428 const void *addr;
429 size_t addrlen;
430};
431 292
432 293
433/** 294/**
434 * Lookup the session for the given peer. 295 * Function called for a quick conversion of the binary address to
296 * a numeric address. Note that the caller must not free the
297 * address and that the next call to this function is allowed
298 * to override the address again.
435 * 299 *
436 * @param plugin the plugin 300 * @param cls closure
437 * @param peer peer's identity 301 * @param addr binary address
438 * @return NULL if we have no session 302 * @param addrlen length of the address
303 * @return string representing the same address
439 */ 304 */
440static struct Session * 305const char *
441find_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *peer) 306udp_address_to_string (void *cls, const void *addr, size_t addrlen)
442{
443 return GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
444 &peer->hashPubKey);
445}
446
447
448static int
449inbound_session_iterator (void *cls, const GNUNET_HashCode * key, void *value)
450{ 307{
451 struct PeerSessionIteratorContext *psc = cls; 308 static char rbuf[INET6_ADDRSTRLEN + 10];
452 struct Session *s = value; 309 char buf[INET6_ADDRSTRLEN];
310 const void *sb;
311 struct in_addr a4;
312 struct in6_addr a6;
313 const struct IPv4UdpAddress *t4;
314 const struct IPv6UdpAddress *t6;
315 int af;
316 uint16_t port;
453 317
454 if (s->addrlen == psc->addrlen) 318 if (addrlen == sizeof (struct IPv6UdpAddress))
455 { 319 {
456 if (0 == memcmp (&s[1], psc->addr, s->addrlen)) 320 t6 = addr;
457 psc->result = s; 321 af = AF_INET6;
322 port = ntohs (t6->u6_port);
323 memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
324 sb = &a6;
458 } 325 }
459 if (psc->result != NULL) 326 else if (addrlen == sizeof (struct IPv4UdpAddress))
460 return GNUNET_NO; 327 {
461 return GNUNET_YES; 328 t4 = addr;
329 af = AF_INET;
330 port = ntohs (t4->u4_port);
331 memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
332 sb = &a4;
333 }
334 else
335 {
336 GNUNET_break_op (0);
337 return NULL;
338 }
339 inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
340 GNUNET_snprintf (rbuf, sizeof (rbuf), (af == AF_INET6) ? "[%s]:%u" : "%s:%u",
341 buf, port);
342 return rbuf;
462} 343}
463 344
345
464/** 346/**
465 * Lookup the session for the given peer. 347 * Append our port and forward the result.
466 * 348 *
467 * @param plugin the plugin 349 * @param cls a 'struct PrettyPrinterContext'
468 * @param peer peer's identity 350 * @param hostname result from DNS resolver
469 * @param addr address
470 * @param addrlen address length
471 * @return NULL if we have no session
472 */ 351 */
473static struct Session * 352static void
474find_inbound_session (struct Plugin *plugin, 353append_port (void *cls, const char *hostname)
475 const struct GNUNET_PeerIdentity *peer, const void *addr,
476 size_t addrlen)
477{ 354{
478 struct PeerSessionIteratorContext psc; 355 struct PrettyPrinterContext *ppc = cls;
479 356 char *ret;
480 psc.result = NULL;
481 psc.addrlen = addrlen;
482 psc.addr = addr;
483 357
484 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->inbound_sessions, 358 if (hostname == NULL)
485 &peer->hashPubKey, 359 {
486 &inbound_session_iterator, &psc); 360 ppc->asc (ppc->asc_cls, NULL);
487 return psc.result; 361 GNUNET_free (ppc);
362 return;
363 }
364 GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
365 ppc->asc (ppc->asc_cls, ret);
366 GNUNET_free (ret);
488} 367}
489 368
490 369
491static int 370/**
492inbound_session_by_addr_iterator (void *cls, const GNUNET_HashCode * key, 371 * Convert the transports address to a nice, human-readable
493 void *value) 372 * format.
373 *
374 * @param cls closure
375 * @param type name of the transport that generated the address
376 * @param addr one of the addresses of the host, NULL for the last address
377 * the specific address format depends on the transport
378 * @param addrlen length of the address
379 * @param numeric should (IP) addresses be displayed in numeric form?
380 * @param timeout after how long should we give up?
381 * @param asc function to call on each string
382 * @param asc_cls closure for asc
383 */
384static void
385udp_plugin_address_pretty_printer (void *cls, const char *type,
386 const void *addr, size_t addrlen,
387 int numeric,
388 struct GNUNET_TIME_Relative timeout,
389 GNUNET_TRANSPORT_AddressStringCallback asc,
390 void *asc_cls)
494{ 391{
495 struct PeerSessionIteratorContext *psc = cls; 392 struct PrettyPrinterContext *ppc;
496 struct Session *s = value; 393 const void *sb;
394 size_t sbs;
395 struct sockaddr_in a4;
396 struct sockaddr_in6 a6;
397 const struct IPv4UdpAddress *u4;
398 const struct IPv6UdpAddress *u6;
399 uint16_t port;
497 400
498 if (s->addrlen == psc->addrlen) 401 if (addrlen == sizeof (struct IPv6UdpAddress))
499 { 402 {
500 if (0 == memcmp (&s[1], psc->addr, s->addrlen)) 403 u6 = addr;
501 psc->result = s; 404 memset (&a6, 0, sizeof (a6));
405 a6.sin6_family = AF_INET6;
406#if HAVE_SOCKADDR_IN_SIN_LEN
407 a6.sin6_len = sizeof (a6);
408#endif
409 a6.sin6_port = u6->u6_port;
410 memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof (struct in6_addr));
411 port = ntohs (u6->u6_port);
412 sb = &a6;
413 sbs = sizeof (a6);
414 }
415 else if (addrlen == sizeof (struct IPv4UdpAddress))
416 {
417 u4 = addr;
418 memset (&a4, 0, sizeof (a4));
419 a4.sin_family = AF_INET;
420#if HAVE_SOCKADDR_IN_SIN_LEN
421 a4.sin_len = sizeof (a4);
422#endif
423 a4.sin_port = u4->u4_port;
424 a4.sin_addr.s_addr = u4->ipv4_addr;
425 port = ntohs (u4->u4_port);
426 sb = &a4;
427 sbs = sizeof (a4);
502 } 428 }
503 if (psc->result != NULL)
504 return GNUNET_NO;
505 else 429 else
506 return GNUNET_YES; 430 {
507}; 431 /* invalid address */
432 GNUNET_break_op (0);
433 asc (asc_cls, NULL);
434 return;
435 }
436 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
437 ppc->asc = asc;
438 ppc->asc_cls = asc_cls;
439 ppc->port = port;
440 GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
441}
442
508 443
509/** 444/**
510 * Lookup the session for the given peer just by address. 445 * Check if the given port is plausible (must be either our listen
446 * port or our advertised port). If it is neither, we return
447 * GNUNET_SYSERR.
511 * 448 *
512 * @param plugin the plugin 449 * @param plugin global variables
513 * @param addr address 450 * @param in_port port number to check
514 * @param addrlen address length 451 * @return GNUNET_OK if port is either open_port or adv_port
515 * @return NULL if we have no session
516 */ 452 */
517static struct Session * 453static int
518find_inbound_session_by_addr (struct Plugin *plugin, const void *addr, 454check_port (struct Plugin *plugin, uint16_t in_port)
519 size_t addrlen)
520{ 455{
521 struct PeerSessionIteratorContext psc; 456 if ((in_port == plugin->port) || (in_port == plugin->aport))
522 457 return GNUNET_OK;
523 psc.result = NULL; 458 return GNUNET_SYSERR;
524 psc.addrlen = addrlen;
525 psc.addr = addr;
526
527 GNUNET_CONTAINER_multihashmap_iterate (plugin->inbound_sessions,
528 &inbound_session_by_addr_iterator,
529 &psc);
530 return psc.result;
531} 459}
532 460
533 461
462
534/** 463/**
535 * Destroy a session, plugin is being unloaded. 464 * Function that will be called to check if a binary address for this
465 * plugin is well-formed and corresponds to an address for THIS peer
466 * (as per our configuration). Naturally, if absolutely necessary,
467 * plugins can be a bit conservative in their answer, but in general
468 * plugins should make sure that the address does not redirect
469 * traffic to a 3rd party that might try to man-in-the-middle our
470 * traffic.
471 *
472 * @param cls closure, should be our handle to the Plugin
473 * @param addr pointer to the address
474 * @param addrlen length of addr
475 * @return GNUNET_OK if this is a plausible address for this peer
476 * and transport, GNUNET_SYSERR if not
536 * 477 *
537 * @param cls unused
538 * @param key hash of public key of target peer
539 * @param value a 'struct PeerSession*' to clean up
540 * @return GNUNET_OK (continue to iterate)
541 */ 478 */
542static int 479static int
543destroy_session (void *cls, const GNUNET_HashCode * key, void *value) 480udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
544{ 481{
545 struct Session *peer_session = value; 482 struct Plugin *plugin = cls;
483 struct IPv4UdpAddress *v4;
484 struct IPv6UdpAddress *v6;
546 485
547 GNUNET_assert (GNUNET_YES == 486 if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
548 GNUNET_CONTAINER_multihashmap_remove (peer_session-> 487 (addrlen != sizeof (struct IPv6UdpAddress)))
549 plugin->sessions, 488 {
550 &peer_session-> 489 GNUNET_break_op (0);
551 target.hashPubKey, 490 return GNUNET_SYSERR;
552 peer_session)); 491 }
553 if (peer_session->frag != NULL) 492 if (addrlen == sizeof (struct IPv4UdpAddress))
554 GNUNET_FRAGMENT_context_destroy (peer_session->frag); 493 {
555 if (GNUNET_SCHEDULER_NO_TASK != peer_session->delayed_cont_task) 494 v4 = (struct IPv4UdpAddress *) addr;
556 GNUNET_SCHEDULER_cancel (peer_session->delayed_cont_task); 495 if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port)))
557 GNUNET_free (peer_session); 496 return GNUNET_SYSERR;
497 if (GNUNET_OK !=
498 GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr,
499 sizeof (struct in_addr)))
500 return GNUNET_SYSERR;
501 }
502 else
503 {
504 v6 = (struct IPv6UdpAddress *) addr;
505 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
506 {
507 GNUNET_break_op (0);
508 return GNUNET_SYSERR;
509 }
510 if (GNUNET_OK != check_port (plugin, ntohs (v6->u6_port)))
511 return GNUNET_SYSERR;
512 if (GNUNET_OK !=
513 GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr,
514 sizeof (struct in6_addr)))
515 return GNUNET_SYSERR;
516 }
558 return GNUNET_OK; 517 return GNUNET_OK;
559} 518}
560 519
@@ -568,16 +527,48 @@ destroy_session (void *cls, const GNUNET_HashCode * key, void *value)
568 * @return GNUNET_OK (continue to iterate) 527 * @return GNUNET_OK (continue to iterate)
569 */ 528 */
570static int 529static int
571destroy_inbound_session (void *cls, const GNUNET_HashCode * key, void *value) 530disconnect_and_free_it (void *cls, const GNUNET_HashCode * key, void *value)
572{ 531{
532 struct Plugin *plugin = cls;
573 struct Session *s = value; 533 struct Session *s = value;
534 struct UDPMessageWrapper *udpw;
535
536#if DEBUG_UDP
537 LOG (GNUNET_ERROR_TYPE_DEBUG,
538 "Session %p to peer `%s' address ended \n",
539 s,
540 GNUNET_i2s (&s->target),
541 GNUNET_a2s (s->sock_addr, s->addrlen));
542#endif
543 plugin->env->session_end (plugin->env->cls, &s->target, s);
544
545 if (s->frag_ctx != NULL)
546 {
547 GNUNET_FRAGMENT_context_destroy(s->frag_ctx->frag);
548 GNUNET_free (s->frag_ctx);
549 s->frag_ctx = NULL;
550 }
551
552 udpw = plugin->msg_head;
553 while (udpw != NULL)
554 {
555 if (udpw->session == s)
556 {
557 GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
558
559 if (udpw->cont != NULL)
560 udpw->cont (udpw->cont_cls, &s->target, GNUNET_SYSERR);
561 GNUNET_free (udpw);
562 }
563 udpw = plugin->msg_head;
564 }
565
566 GNUNET_assert (GNUNET_YES ==
567 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
568 &s->target.hashPubKey,
569 s));
570
574 571
575 if (s->invalidation_task != GNUNET_SCHEDULER_NO_TASK)
576 GNUNET_SCHEDULER_cancel (s->invalidation_task);
577 if (GNUNET_SCHEDULER_NO_TASK != s->delayed_cont_task)
578 GNUNET_SCHEDULER_cancel (s->delayed_cont_task);
579 GNUNET_CONTAINER_multihashmap_remove (s->plugin->inbound_sessions,
580 &s->target.hashPubKey, s);
581 GNUNET_free (s); 572 GNUNET_free (s);
582 return GNUNET_OK; 573 return GNUNET_OK;
583} 574}
@@ -594,40 +585,31 @@ static void
594udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) 585udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
595{ 586{
596 struct Plugin *plugin = cls; 587 struct Plugin *plugin = cls;
597 struct Session *session; 588 GNUNET_assert (plugin != NULL);
598 589
599 session = find_session (plugin, target); 590 GNUNET_assert (target != NULL);
600 if (NULL == session) 591#if DEBUG_UDP
601 return; 592 LOG (GNUNET_ERROR_TYPE_DEBUG,
602 GNUNET_assert (GNUNET_OK == 593 "Disconnecting from peer `%s'\n", GNUNET_i2s (target));
603 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions, 594#endif
604 &target->hashPubKey, 595 /* Clean up sessions */
605 session)); 596 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->sessions, &target->hashPubKey, &disconnect_and_free_it, plugin);
606
607 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->inbound_sessions,
608 &target->hashPubKey,
609 &destroy_inbound_session, NULL);
610 plugin->last_expected_delay = GNUNET_FRAGMENT_context_destroy (session->frag);
611 if (GNUNET_SCHEDULER_NO_TASK != session->delayed_cont_task)
612 GNUNET_SCHEDULER_cancel (session->delayed_cont_task);
613 if (session->cont != NULL)
614 session->cont (session->cont_cls, target, GNUNET_SYSERR);
615 GNUNET_free (session);
616}
617 597
598 LOG (GNUNET_ERROR_TYPE_DEBUG,
599 "FREEED SESSIONS from peer `%s'\n", GNUNET_i2s (target));
600}
618 601
619static struct Session * 602static struct Session *
620create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target, 603create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
621 const void *addr, size_t addrlen, 604 const void *addr, size_t addrlen,
622 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) 605 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
623{ 606{
624 struct Session *peer_session; 607 struct Session *s;
625 const struct IPv4UdpAddress *t4; 608 const struct IPv4UdpAddress *t4;
626 const struct IPv6UdpAddress *t6; 609 const struct IPv6UdpAddress *t6;
627 struct sockaddr_in *v4; 610 struct sockaddr_in *v4;
628 struct sockaddr_in6 *v6; 611 struct sockaddr_in6 *v6;
629 size_t len; 612 size_t len;
630 struct GNUNET_ATS_Information ats;
631 613
632 switch (addrlen) 614 switch (addrlen)
633 { 615 {
@@ -637,17 +619,16 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
637 return NULL; 619 return NULL;
638 } 620 }
639 t4 = addr; 621 t4 = addr;
640 peer_session = 622 s = GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in));
641 GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in));
642 len = sizeof (struct sockaddr_in); 623 len = sizeof (struct sockaddr_in);
643 v4 = (struct sockaddr_in *) &peer_session[1]; 624 v4 = (struct sockaddr_in *) &s[1];
644 v4->sin_family = AF_INET; 625 v4->sin_family = AF_INET;
645#if HAVE_SOCKADDR_IN_SIN_LEN 626#if HAVE_SOCKADDR_IN_SIN_LEN
646 v4->sin_len = sizeof (struct sockaddr_in); 627 v4->sin_len = sizeof (struct sockaddr_in);
647#endif 628#endif
648 v4->sin_port = t4->u4_port; 629 v4->sin_port = t4->u4_port;
649 v4->sin_addr.s_addr = t4->ipv4_addr; 630 v4->sin_addr.s_addr = t4->ipv4_addr;
650 ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) v4, sizeof (struct sockaddr_in)); 631 s->ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) v4, sizeof (struct sockaddr_in));
651 break; 632 break;
652 case sizeof (struct IPv6UdpAddress): 633 case sizeof (struct IPv6UdpAddress):
653 if (NULL == plugin->sockv6) 634 if (NULL == plugin->sockv6)
@@ -655,17 +636,17 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
655 return NULL; 636 return NULL;
656 } 637 }
657 t6 = addr; 638 t6 = addr;
658 peer_session = 639 s =
659 GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in6)); 640 GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in6));
660 len = sizeof (struct sockaddr_in6); 641 len = sizeof (struct sockaddr_in6);
661 v6 = (struct sockaddr_in6 *) &peer_session[1]; 642 v6 = (struct sockaddr_in6 *) &s[1];
662 v6->sin6_family = AF_INET6; 643 v6->sin6_family = AF_INET6;
663#if HAVE_SOCKADDR_IN_SIN_LEN 644#if HAVE_SOCKADDR_IN_SIN_LEN
664 v6->sin6_len = sizeof (struct sockaddr_in6); 645 v6->sin6_len = sizeof (struct sockaddr_in6);
665#endif 646#endif
666 v6->sin6_port = t6->u6_port; 647 v6->sin6_port = t6->u6_port;
667 v6->sin6_addr = t6->ipv6_addr; 648 v6->sin6_addr = t6->ipv6_addr;
668 ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) v6, sizeof (struct sockaddr_in6)); 649 s->ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) v6, sizeof (struct sockaddr_in6));
669 break; 650 break;
670 default: 651 default:
671 /* Must have a valid address to send to */ 652 /* Must have a valid address to send to */
@@ -673,41 +654,62 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
673 return NULL; 654 return NULL;
674 } 655 }
675 656
676 peer_session->ats_address_network_type = ats.value; 657 s->addrlen = len;
677 peer_session->valid_until = GNUNET_TIME_absolute_get_zero (); 658 s->target = *target;
678 peer_session->invalidation_task = GNUNET_SCHEDULER_NO_TASK; 659 s->sock_addr = (const struct sockaddr *) &s[1];
679 peer_session->addrlen = len; 660 s->flow_delay_for_other_peer = GNUNET_TIME_relative_get_zero();
680 peer_session->target = *target; 661 s->flow_delay_from_other_peer = GNUNET_TIME_absolute_get_zero();
681 peer_session->plugin = plugin; 662 s->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
682 peer_session->sock_addr = (const struct sockaddr *) &peer_session[1];
683 peer_session->cont = cont;
684 peer_session->cont_cls = cont_cls;
685 663
686 return peer_session; 664 return s;
687} 665}
688 666
689
690static int session_cmp_it (void *cls, 667static int session_cmp_it (void *cls,
691 const GNUNET_HashCode * key, 668 const GNUNET_HashCode * key,
692 void *value) 669 void *value)
693{ 670{
694 int res = GNUNET_OK; 671 struct SessionCompareContext * cctx = cls;
695 /* 672 const struct GNUNET_HELLO_Address *address = cctx->addr;
696 struct GNUNET_HELLO_Address *address = cls;
697 struct Session *s = value; 673 struct Session *s = value;
698 674
699 struct IPv4UdpAddress * u4 = NULL; 675 socklen_t s_addrlen = s->addrlen;
700 struct IPv4UdpAddress * u6 = NULL;
701
702 676
677#if VERBOSE_UDP
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing address %s <-> %s\n",
679 udp_address_to_string (NULL, (void *) address->address, address->address_length),
680 GNUNET_a2s (s->sock_addr, s->addrlen));
681#endif
703 682
704 if ((s->addrlen == address->address_length) && 683 if ((address->address_length == sizeof (struct IPv4UdpAddress)) &&
705 (0 == memcmp (s->sock_addr, address->address, address->address_length))) 684 (s_addrlen == sizeof (struct sockaddr_in)))
706 { 685 {
686 struct IPv4UdpAddress * u4 = NULL;
687 u4 = (struct IPv4UdpAddress *) address->address;
688 const struct sockaddr_in *s4 = (const struct sockaddr_in *) s->sock_addr;
689 if ((0 == memcmp ((const void *) &u4->ipv4_addr,(const void *) &s4->sin_addr, sizeof (struct in_addr))) &&
690 (u4->u4_port == s4->sin_port))
691 {
692 cctx->res = s;
693 return GNUNET_NO;
694 }
707 695
708 } 696 }
709*/ 697 if ((address->address_length == sizeof (struct IPv6UdpAddress)) &&
710 return res; 698 (s_addrlen == sizeof (struct sockaddr_in6)))
699 {
700 struct IPv6UdpAddress * u6 = NULL;
701 u6 = (struct IPv6UdpAddress *) address->address;
702 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) s->sock_addr;
703 if ((0 == memcmp (&u6->ipv6_addr, &s6->sin6_addr, sizeof (struct in6_addr))) &&
704 (u6->u6_port == s6->sin6_port))
705 {
706 cctx->res = s;
707 return GNUNET_NO;
708 }
709 }
710
711
712 return GNUNET_YES;
711} 713}
712 714
713 715
@@ -719,7 +721,6 @@ static int session_cmp_it (void *cls,
719 * @param address the address 721 * @param address the address
720 * @return the session or NULL of max connections exceeded 722 * @return the session or NULL of max connections exceeded
721 */ 723 */
722
723static struct Session * 724static struct Session *
724udp_plugin_get_session (void *cls, 725udp_plugin_get_session (void *cls,
725 const struct GNUNET_HELLO_Address *address) 726 const struct GNUNET_HELLO_Address *address)
@@ -739,7 +740,20 @@ udp_plugin_get_session (void *cls,
739 } 740 }
740 741
741 /* check if session already exists */ 742 /* check if session already exists */
742 GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessions, &address->peer.hashPubKey, session_cmp_it, (void *) address); 743 struct SessionCompareContext cctx;
744 cctx.addr = address;
745 cctx.res = NULL;
746#if VERBOSE_UDP
747 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for existing session for peer `%s' `%s' \n", GNUNET_i2s (&address->peer), udp_address_to_string(NULL, address->address, address->address_length));
748#endif
749 GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessions, &address->peer.hashPubKey, session_cmp_it, &cctx);
750 if (cctx.res != NULL)
751 {
752#if VERBOSE_UDP
753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res);
754#endif
755 return cctx.res;
756 }
743 757
744 /* otherwise create new */ 758 /* otherwise create new */
745 s = create_session (plugin, 759 s = create_session (plugin,
@@ -747,11 +761,60 @@ udp_plugin_get_session (void *cls,
747 address->address, 761 address->address,
748 address->address_length, 762 address->address_length,
749 NULL, NULL); 763 NULL, NULL);
764#if VERBOSE
765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
766 "Creating new session %p for peer `%s' address `%s'\n",
767 s,
768 GNUNET_i2s(&address->peer),
769 udp_address_to_string(NULL,address->address,address->address_length));
770#endif
771 GNUNET_assert (GNUNET_OK ==
772 GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
773 &s->target.hashPubKey,
774 s,
775 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
750 776
751 return s; 777 return s;
752} 778}
753 779
754/** 780/**
781 * Function that is called with messages created by the fragmentation
782 * module. In the case of the 'proc' callback of the
783 * GNUNET_FRAGMENT_context_create function, this function must
784 * eventually call 'GNUNET_FRAGMENT_context_transmission_done'.
785 *
786 * @param cls closure, the 'struct FragmentationContext'
787 * @param msg the message that was created
788 */
789static void
790enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
791{
792 struct FragmentationContext *frag_ctx = cls;
793 struct Plugin *plugin = frag_ctx->plugin;
794 struct UDPMessageWrapper * udpw;
795
796 size_t msg_len = ntohs (msg->size);
797
798#if VERBOSE_UDP
799 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Enqueuing fragment with %u bytes %u\n", msg_len , sizeof (struct UDPMessageWrapper));
800#endif
801
802 udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + msg_len);
803 udpw->session = frag_ctx->session;
804 udpw->udp = (char *) &udpw[1];
805
806 udpw->msg_size = msg_len;
807 udpw->cont = frag_ctx->cont;
808 udpw->cont_cls = frag_ctx->cont_cls;
809 udpw->timeout = frag_ctx->timeout;
810 udpw->frag_ctx = frag_ctx;
811 memcpy (udpw->udp, msg, msg_len);
812
813 GNUNET_CONTAINER_DLL_insert(plugin->msg_head, plugin->msg_tail, udpw);
814}
815
816
817/**
755 * Function that can be used by the transport service to transmit 818 * Function that can be used by the transport service to transmit
756 * a message using the plugin. Note that in the case of a 819 * a message using the plugin. Note that in the case of a
757 * peer disconnecting, the continuation MUST be called 820 * peer disconnecting, the continuation MUST be called
@@ -780,146 +843,20 @@ udp_plugin_get_session (void *cls,
780 */ 843 */
781static ssize_t 844static ssize_t
782udp_plugin_send (void *cls, 845udp_plugin_send (void *cls,
783 struct Session *session, 846 struct Session *s,
784 const char *msgbuf, size_t msgbuf_size, 847 const char *msgbuf, size_t msgbuf_size,
785 unsigned int priority, 848 unsigned int priority,
786 struct GNUNET_TIME_Relative to, 849 struct GNUNET_TIME_Relative to,
787 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) 850 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
788{ 851{
789 ssize_t sent = -1;
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "To be implemented\n");
791 GNUNET_break (0);
792 return sent;
793}
794
795
796/**
797 * Actually send out the message.
798 *
799 * @param plugin the plugin
800 * @param sa the address to send the message to
801 * @param msg message to transmit
802 * @return the number of bytes written
803 */
804static ssize_t
805udp_send (struct Plugin *plugin, const struct sockaddr *sa,
806 const struct GNUNET_MessageHeader *msg)
807{
808 ssize_t sent;
809 size_t slen;
810
811 switch (sa->sa_family)
812 {
813 case AF_INET:
814 if (NULL == plugin->sockv4)
815 return 0;
816 sent =
817 GNUNET_NETWORK_socket_sendto (plugin->sockv4, msg, ntohs (msg->size),
818 sa, slen = sizeof (struct sockaddr_in));
819 break;
820 case AF_INET6:
821 if (NULL == plugin->sockv6)
822 return 0;
823 sent =
824 GNUNET_NETWORK_socket_sendto (plugin->sockv6, msg, ntohs (msg->size),
825 sa, slen = sizeof (struct sockaddr_in6));
826 break;
827 default:
828 GNUNET_break (0);
829 return 0;
830 }
831 if (GNUNET_SYSERR == sent)
832 {
833 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
834 LOG (GNUNET_ERROR_TYPE_ERROR,
835 "UDP transmited %u-byte message to %s (%d: %s)\n",
836 (unsigned int) ntohs (msg->size), GNUNET_a2s (sa, slen), (int) sent,
837 (sent < 0) ? STRERROR (errno) : "ok");
838
839 }
840 LOG (GNUNET_ERROR_TYPE_DEBUG,
841 "UDP transmited %u-byte message to %s (%d: %s)\n",
842 (unsigned int) ntohs (msg->size), GNUNET_a2s (sa, slen), (int) sent,
843 (sent < 0) ? STRERROR (errno) : "ok");
844 return sent;
845}
846
847
848/**
849 * Function that is called with messages created by the fragmentation
850 * module. In the case of the 'proc' callback of the
851 * GNUNET_FRAGMENT_context_create function, this function must
852 * eventually call 'GNUNET_FRAGMENT_context_transmission_done'.
853 *
854 * @param cls closure, the 'struct PeerSession'
855 * @param msg the message that was created
856 */
857static void
858send_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
859{
860 struct Session *session = cls;
861
862 udp_send (session->plugin, session->sock_addr, msg);
863 GNUNET_FRAGMENT_context_transmission_done (session->frag);
864}
865
866
867static const char *
868udp_address_to_string (void *cls, const void *addr, size_t addrlen);
869
870
871static void
872udp_call_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
873{
874 struct Session *s = cls;
875 GNUNET_TRANSPORT_TransmitContinuation cont = s->cont;
876
877 s->delayed_cont_task = GNUNET_SCHEDULER_NO_TASK;
878 s->cont = NULL;
879 cont (s->cont_cls, &s->target, GNUNET_OK);
880}
881
882
883/**
884 * Function that can be used by the transport service to transmit
885 * a message using the plugin.
886 *
887 * @param cls closure
888 * @param target who should receive this message (ignored by UDP)
889 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
890 * @param msgbuf_size the size of the msgbuf to send
891 * @param priority how important is the message (ignored by UDP)
892 * @param timeout when should we time out (give up) if we can not transmit?
893 * @param session identifier used for this session (NULL for UDP)
894 * @param addr the addr to send the message to
895 * @param addrlen the len of addr
896 * @param force_address not used, we had better have an address to send to
897 * because we are stateless!!
898 * @param cont continuation to call once the message has
899 * been transmitted (or if the transport is ready
900 * for the next transmission call; or if the
901 * peer disconnected...)
902 * @param cont_cls closure for cont
903 *
904 * @return the number of bytes written (may return 0 and the message can
905 * still be transmitted later!)
906 */
907static ssize_t
908udp_plugin_send_old (void *cls, const struct GNUNET_PeerIdentity *target,
909 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
910 struct GNUNET_TIME_Relative timeout, struct Session *session,
911 const void *addr, size_t addrlen, int force_address,
912 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
913{
914 struct Plugin *plugin = cls; 852 struct Plugin *plugin = cls;
915 struct Session *peer_session;
916 struct Session *s;
917 const struct IPv4UdpAddress *t4;
918 const struct IPv6UdpAddress *t6;
919 size_t mlen = msgbuf_size + sizeof (struct UDPMessage); 853 size_t mlen = msgbuf_size + sizeof (struct UDPMessage);
920 char mbuf[mlen]; 854
855 struct UDPMessageWrapper * udpw;
921 struct UDPMessage *udp; 856 struct UDPMessage *udp;
922 struct GNUNET_TIME_Relative delta; 857 char mbuf[mlen];
858 GNUNET_assert (plugin != NULL);
859 GNUNET_assert (s != NULL);
923 860
924 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 861 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
925 { 862 {
@@ -927,83 +864,17 @@ udp_plugin_send_old (void *cls, const struct GNUNET_PeerIdentity *target,
927 return GNUNET_SYSERR; 864 return GNUNET_SYSERR;
928 } 865 }
929 866
930 LOG (GNUNET_ERROR_TYPE_DEBUG, 867 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains_value(plugin->sessions, &s->target.hashPubKey, s))
931 "UDP transmits %u-byte message to `%s' using address `%s' session 0x%X mode %i\n",
932 msgbuf_size, GNUNET_i2s (target), udp_address_to_string (NULL, addr,
933 addrlen),
934 session, force_address);
935
936 if ((force_address == GNUNET_SYSERR) && (session == NULL))
937 return GNUNET_SYSERR;
938
939 s = NULL;
940 /* safety check: comparing address to address stored in session */
941 if ((session != NULL) && (addr != NULL) && (addrlen != 0))
942 { 868 {
943 s = session; 869 GNUNET_break (0);
944 GNUNET_assert (GNUNET_YES ==
945 GNUNET_CONTAINER_multihashmap_contains_value
946 (plugin->inbound_sessions, &target->hashPubKey, s));
947
948 if (0 != memcmp (&s->target, target, sizeof (struct GNUNET_PeerIdentity)))
949 return GNUNET_SYSERR;
950 switch (addrlen)
951 {
952 case sizeof (struct IPv4UdpAddress):
953 if (NULL == plugin->sockv4)
954 {
955 if (cont != NULL)
956 cont (cont_cls, target, GNUNET_SYSERR);
957 return GNUNET_SYSERR;
958 }
959 t4 = addr;
960 if (s->addrlen != (sizeof (struct sockaddr_in)))
961 return GNUNET_SYSERR;
962 struct sockaddr_in *a4 = (struct sockaddr_in *) s->sock_addr;
963
964 GNUNET_assert (a4->sin_port == t4->u4_port);
965 GNUNET_assert (0 ==
966 memcmp (&a4->sin_addr, &t4->ipv4_addr,
967 sizeof (struct in_addr)));
968 LOG (GNUNET_ERROR_TYPE_DEBUG, "Session 0x%X successfully checked!\n",
969 session);
970 break;
971 case sizeof (struct IPv6UdpAddress):
972 if (NULL == plugin->sockv6)
973 {
974 if (cont != NULL)
975 cont (cont_cls, target, GNUNET_SYSERR);
976 return GNUNET_SYSERR;
977 }
978 t6 = addr;
979 GNUNET_assert (s->addrlen == sizeof (struct sockaddr_in6));
980 struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) s->sock_addr;
981
982 GNUNET_assert (a6->sin6_port == t6->u6_port);
983 GNUNET_assert (0 ==
984 memcmp (&a6->sin6_addr, &t6->ipv6_addr,
985 sizeof (struct in6_addr)));
986 LOG (GNUNET_ERROR_TYPE_DEBUG, "Session 0x%X successfully checked!\n",
987 session);
988 break;
989 default:
990 /* Must have a valid address to send to */
991 GNUNET_break_op (0);
992 }
993 }
994//session_invalid:
995 if ((addr == NULL) || (addrlen == 0))
996 return GNUNET_SYSERR; 870 return GNUNET_SYSERR;
997 peer_session = create_session (plugin, target, addr, addrlen, cont, cont_cls);
998 if (peer_session == NULL)
999 {
1000 if (cont != NULL)
1001 cont (cont_cls, target, GNUNET_SYSERR);
1002 return GNUNET_SYSERR;;
1003 } 871 }
1004 872
1005 873 LOG (GNUNET_ERROR_TYPE_DEBUG,
1006 874 "UDP transmits %u-byte message to `%s' using address `%s'\n",
875 msgbuf_size,
876 GNUNET_i2s (&s->target),
877 GNUNET_a2s(s->sock_addr, s->addrlen));
1007 878
1008 /* Message */ 879 /* Message */
1009 udp = (struct UDPMessage *) mbuf; 880 udp = (struct UDPMessage *) mbuf;
@@ -1011,69 +882,129 @@ udp_plugin_send_old (void *cls, const struct GNUNET_PeerIdentity *target,
1011 udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE); 882 udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE);
1012 udp->reserved = htonl (0); 883 udp->reserved = htonl (0);
1013 udp->sender = *plugin->env->my_identity; 884 udp->sender = *plugin->env->my_identity;
1014 memcpy (&udp[1], msgbuf, msgbuf_size);
1015 885
1016 if (s != NULL)
1017 delta = GNUNET_TIME_absolute_get_remaining (s->flow_delay_from_other_peer);
1018 else
1019 delta = GNUNET_TIME_UNIT_ZERO;
1020 if (mlen <= UDP_MTU) 886 if (mlen <= UDP_MTU)
1021 { 887 {
1022 mlen = udp_send (plugin, peer_session->sock_addr, &udp->header); 888 udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + mlen);
1023 if (cont != NULL) 889 udpw->session = s;
1024 { 890 udpw->udp = (char *) &udpw[1];
1025 if ((delta.rel_value > 0) && (mlen > 0)) 891 udpw->msg_size = mlen;
1026 { 892 udpw->timeout = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), to);
1027 s->cont = cont; 893 udpw->cont = cont;
1028 s->cont_cls = cont_cls; 894 udpw->cont_cls = cont_cls;
1029 s->delayed_cont_task = 895 udpw->frag_ctx = NULL;
1030 GNUNET_SCHEDULER_add_delayed (delta, &udp_call_continuation, s); 896
1031 } 897 memcpy (udpw->udp, udp, sizeof (struct UDPMessage));
1032 else 898 memcpy (&udpw->udp[sizeof (struct UDPMessage)], msgbuf, msgbuf_size);
1033 cont (cont_cls, target, (mlen > 0) ? GNUNET_OK : GNUNET_SYSERR); 899
1034 } 900 GNUNET_CONTAINER_DLL_insert(plugin->msg_head, plugin->msg_tail, udpw);
1035 GNUNET_free_non_null (peer_session);
1036 } 901 }
1037 else 902 else
1038 { 903 {
1039 GNUNET_assert (GNUNET_OK == 904 LOG (GNUNET_ERROR_TYPE_DEBUG,
1040 GNUNET_CONTAINER_multihashmap_put (plugin->sessions, 905 "UDP has to fragment message \n");
1041 &target->hashPubKey, 906 if (s->frag_ctx != NULL)
1042 peer_session, 907 return GNUNET_SYSERR;
1043 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 908 memcpy (&udp[1], msgbuf, msgbuf_size);
1044 peer_session->frag = 909 struct FragmentationContext * frag_ctx = GNUNET_malloc(sizeof (struct FragmentationContext));
1045 GNUNET_FRAGMENT_context_create (plugin->env->stats, UDP_MTU, 910
1046 &plugin->tracker, 911 frag_ctx->plugin = plugin;
1047 plugin->last_expected_delay, 912 frag_ctx->session = s;
1048 &udp->header, &send_fragment, 913 frag_ctx->cont = cont;
1049 peer_session); 914 frag_ctx->cont_cls = cont_cls;
915 frag_ctx->timeout = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), to);
916 frag_ctx->bytes_to_send = mlen;
917 frag_ctx->frag = GNUNET_FRAGMENT_context_create (plugin->env->stats,
918 UDP_MTU,
919 &plugin->tracker,
920 s->last_expected_delay,
921 &udp->header,
922 &enqueue_fragment,
923 frag_ctx);
924
925 s->frag_ctx = frag_ctx;
926
1050 } 927 }
1051 return mlen; 928 return mlen;
1052} 929}
1053 930
931static ssize_t udp_plugin_send_wrapper (void *cls,
932 const struct
933 GNUNET_PeerIdentity *
934 target,
935 const char *msgbuf,
936 size_t msgbuf_size,
937 uint32_t priority,
938 struct
939 GNUNET_TIME_Relative
940 timeout,
941 struct Session * session,
942 const void *addr,
943 size_t addrlen,
944 int force_address,
945 GNUNET_TRANSPORT_TransmitContinuation
946 cont, void *cont_cls)
947{
948 int ret;
949 struct Session * s = NULL;
950 struct GNUNET_HELLO_Address * ha = NULL;
951
952 ha = GNUNET_HELLO_address_allocate(target, "", addr,addrlen);
953 GNUNET_assert (ha != NULL);
954 s = udp_plugin_get_session(cls, ha);
955 GNUNET_assert (s != NULL);
956 GNUNET_free (ha);
957 ret = udp_plugin_send (cls, s, msgbuf, msgbuf_size, priority, timeout, cont, cont_cls);
958
959 return ret;
960}
961
1054 962
1055/** 963/**
1056 * Closure for 'process_inbound_tokenized_messages' 964 * Our external IP address/port mapping has changed.
965 *
966 * @param cls closure, the 'struct LocalAddrList'
967 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
968 * the previous (now invalid) one
969 * @param addr either the previous or the new public IP address
970 * @param addrlen actual lenght of the address
1057 */ 971 */
1058struct SourceInformation 972static void
973udp_nat_port_map_callback (void *cls, int add_remove,
974 const struct sockaddr *addr, socklen_t addrlen)
1059{ 975{
1060 /** 976 struct Plugin *plugin = cls;
1061 * Sender identity. 977 struct IPv4UdpAddress u4;
1062 */ 978 struct IPv6UdpAddress u6;
1063 struct GNUNET_PeerIdentity sender; 979 void *arg;
1064
1065 /**
1066 * Source address.
1067 */
1068 const void *arg;
1069
1070 /**
1071 * Number of bytes in source address.
1072 */
1073 size_t args; 980 size_t args;
1074 981
1075 struct Session *session; 982 /* convert 'addr' to our internal format */
1076}; 983 switch (addr->sa_family)
984 {
985 case AF_INET:
986 GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
987 u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
988 u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
989 arg = &u4;
990 args = sizeof (u4);
991 break;
992 case AF_INET6:
993 GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
994 memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
995 sizeof (struct in6_addr));
996 u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
997 arg = &u6;
998 args = sizeof (u6);
999 break;
1000 default:
1001 GNUNET_break (0);
1002 return;
1003 }
1004 /* modify our published address list */
1005 plugin->env->notify_address (plugin->env->cls, add_remove, arg, args);
1006}
1007
1077 1008
1078 1009
1079/** 1010/**
@@ -1090,44 +1021,26 @@ process_inbound_tokenized_messages (void *cls, void *client,
1090{ 1021{
1091 struct Plugin *plugin = cls; 1022 struct Plugin *plugin = cls;
1092 struct SourceInformation *si = client; 1023 struct SourceInformation *si = client;
1093 struct GNUNET_ATS_Information atsi[2]; 1024 struct GNUNET_ATS_Information ats[2];
1094 struct GNUNET_TIME_Relative delay; 1025 struct GNUNET_TIME_Relative delay;
1095 1026
1027 GNUNET_assert (si->session != NULL);
1096 /* setup ATS */ 1028 /* setup ATS */
1097 atsi[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); 1029 ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
1098 atsi[0].value = htonl (1); 1030 ats[0].value = htonl (1);
1099 atsi[1].type = htonl (GNUNET_ATS_NETWORK_TYPE); 1031 ats[1] = si->session->ats;
1100 atsi[1].value = si->session->ats_address_network_type; 1032 GNUNET_break (ntohl(ats[1].value) != GNUNET_ATS_NET_UNSPECIFIED);
1101 GNUNET_break (ntohl(si->session->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); 1033
1102 1034 delay = plugin->env->receive (plugin->env->cls,
1103 1035 &si->sender,
1104 LOG (GNUNET_ERROR_TYPE_DEBUG, "Giving Session %X %s to transport\n", 1036 hdr,
1105 si->session, GNUNET_i2s (&si->session->target)); 1037 (const struct GNUNET_ATS_Information *) &ats, 2,
1106 delay = 1038 NULL,
1107 plugin->env->receive (plugin->env->cls, &si->sender, hdr, 1039 si->arg,
1108 (const struct GNUNET_ATS_Information *) &atsi, 2, 1040 si->args);
1109 si->session, si->arg, si->args);
1110 si->session->flow_delay_for_other_peer = delay; 1041 si->session->flow_delay_for_other_peer = delay;
1111} 1042}
1112 1043
1113static void
1114invalidation_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1115{
1116 struct Session *s = cls;
1117
1118 s->invalidation_task = GNUNET_SCHEDULER_NO_TASK;
1119 LOG (GNUNET_ERROR_TYPE_DEBUG, "Session %X (`%s') is now invalid\n", s,
1120 GNUNET_a2s (s->sock_addr, s->addrlen));
1121
1122 s->plugin->env->session_end (s->plugin->env->cls, &s->target, s);
1123 GNUNET_assert (GNUNET_YES ==
1124 GNUNET_CONTAINER_multihashmap_remove (s->
1125 plugin->inbound_sessions,
1126 &s->target.hashPubKey,
1127 s));
1128 GNUNET_free (s);
1129}
1130
1131 1044
1132/** 1045/**
1133 * We've received a UDP Message. Process it (pass contents to main service). 1046 * We've received a UDP Message. Process it (pass contents to main service).
@@ -1143,6 +1056,7 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
1143 socklen_t sender_addr_len) 1056 socklen_t sender_addr_len)
1144{ 1057{
1145 struct SourceInformation si; 1058 struct SourceInformation si;
1059 struct Session * s = NULL;
1146 struct IPv4UdpAddress u4; 1060 struct IPv4UdpAddress u4;
1147 struct IPv6UdpAddress u6; 1061 struct IPv6UdpAddress u6;
1148 struct GNUNET_ATS_Information ats; 1062 struct GNUNET_ATS_Information ats;
@@ -1191,56 +1105,16 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
1191 GNUNET_a2s (sender_addr, sender_addr_len)); 1105 GNUNET_a2s (sender_addr, sender_addr_len));
1192#endif 1106#endif
1193 1107
1194 /* create a session for inbound connections */ 1108 struct GNUNET_HELLO_Address * address = GNUNET_HELLO_address_allocate(&msg->sender, "udp", arg, args);
1195 const struct UDPMessage *udp_msg = (const struct UDPMessage *) msg; 1109 s = udp_plugin_get_session(plugin, address);
1196 1110 GNUNET_free (address);
1197 LOG (GNUNET_ERROR_TYPE_DEBUG,
1198 "Lookup inbound UDP sessions for peer `%s' address `%s'\n",
1199 GNUNET_i2s (&udp_msg->sender), udp_address_to_string (NULL, arg, args));
1200
1201 struct Session *s = NULL;
1202
1203 s = find_inbound_session (plugin, &udp_msg->sender, sender_addr,
1204 sender_addr_len);
1205 1111
1206 if (s != NULL)
1207 {
1208 LOG (GNUNET_ERROR_TYPE_DEBUG,
1209 "Found existing inbound UDP sessions 0x%X for peer `%s' address `%s'\n",
1210 s, GNUNET_i2s (&s->target), udp_address_to_string (NULL, arg, args));
1211 }
1212 else
1213 {
1214 s = create_session (plugin, &udp_msg->sender, arg, args, NULL, NULL);
1215 ats = plugin->env->get_address_type (plugin->env->cls, sender_addr, sender_addr_len);
1216 s->ats_address_network_type = ats.value;
1217 LOG (GNUNET_ERROR_TYPE_DEBUG,
1218 "Creating inbound UDP sessions 0x%X for peer `%s' address `%s'\n", s,
1219 GNUNET_i2s (&s->target), udp_address_to_string (NULL, arg, args));
1220
1221 GNUNET_assert (GNUNET_OK ==
1222 GNUNET_CONTAINER_multihashmap_put (plugin->inbound_sessions,
1223 &s->target.hashPubKey, s,
1224 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1225 }
1226 s->valid_until =
1227 GNUNET_TIME_relative_to_absolute
1228 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1229 if (s->invalidation_task != GNUNET_SCHEDULER_NO_TASK)
1230 {
1231 GNUNET_SCHEDULER_cancel (s->invalidation_task);
1232 s->invalidation_task = GNUNET_SCHEDULER_NO_TASK;
1233 LOG (GNUNET_ERROR_TYPE_DEBUG, "Rescheduling %X' `%s'\n", s,
1234 udp_address_to_string (NULL, arg, args));
1235 }
1236 s->invalidation_task =
1237 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1238 &invalidation_task, s);
1239 /* iterate over all embedded messages */ 1112 /* iterate over all embedded messages */
1113 si.session = s;
1240 si.sender = msg->sender; 1114 si.sender = msg->sender;
1241 si.arg = arg; 1115 si.arg = arg;
1242 si.args = args; 1116 si.args = args;
1243 si.session = s; 1117
1244 GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1], 1118 GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1],
1245 ntohs (msg->header.size) - 1119 ntohs (msg->header.size) -
1246 sizeof (struct UDPMessage), GNUNET_YES, GNUNET_NO); 1120 sizeof (struct UDPMessage), GNUNET_YES, GNUNET_NO);
@@ -1248,6 +1122,33 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
1248 1122
1249 1123
1250/** 1124/**
1125 * Scan the heap for a receive context with the given address.
1126 *
1127 * @param cls the 'struct FindReceiveContext'
1128 * @param node internal node of the heap
1129 * @param element value stored at the node (a 'struct ReceiveContext')
1130 * @param cost cost associated with the node
1131 * @return GNUNET_YES if we should continue to iterate,
1132 * GNUNET_NO if not.
1133 */
1134static int
1135find_receive_context (void *cls, struct GNUNET_CONTAINER_HeapNode *node,
1136 void *element, GNUNET_CONTAINER_HeapCostType cost)
1137{
1138 struct FindReceiveContext *frc = cls;
1139 struct DefragContext *e = element;
1140
1141 if ((frc->addr_len == e->addr_len) &&
1142 (0 == memcmp (frc->addr, e->src_addr, frc->addr_len)))
1143 {
1144 frc->rc = e;
1145 return GNUNET_NO;
1146 }
1147 return GNUNET_YES;
1148}
1149
1150
1151/**
1251 * Process a defragmented message. 1152 * Process a defragmented message.
1252 * 1153 *
1253 * @param cls the 'struct ReceiveContext' 1154 * @param cls the 'struct ReceiveContext'
@@ -1256,7 +1157,7 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
1256static void 1157static void
1257fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg) 1158fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
1258{ 1159{
1259 struct ReceiveContext *rc = cls; 1160 struct DefragContext *rc = cls;
1260 1161
1261 if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE) 1162 if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE)
1262 { 1163 {
@@ -1272,6 +1173,28 @@ fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
1272 rc->src_addr, rc->addr_len); 1173 rc->src_addr, rc->addr_len);
1273} 1174}
1274 1175
1176struct LookupContext
1177{
1178 const struct sockaddr * addr;
1179 size_t addrlen;
1180
1181 struct Session *res;
1182};
1183
1184static int
1185lookup_session_by_addr_it (void *cls, const GNUNET_HashCode * key, void *value)
1186{
1187 struct LookupContext *l_ctx = cls;
1188 struct Session * s = value;
1189
1190 if ((s->addrlen == l_ctx->addrlen) &&
1191 (0 == memcmp (s->sock_addr, l_ctx->addr, s->addrlen)))
1192 {
1193 l_ctx->res = s;
1194 return GNUNET_NO;
1195 }
1196 return GNUNET_YES;
1197}
1275 1198
1276/** 1199/**
1277 * Transmit an acknowledgement. 1200 * Transmit an acknowledgement.
@@ -1283,24 +1206,27 @@ fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
1283static void 1206static void
1284ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg) 1207ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
1285{ 1208{
1286 struct ReceiveContext *rc = cls; 1209 struct DefragContext *rc = cls;
1287 1210
1288 size_t msize = sizeof (struct UDP_ACK_Message) + ntohs (msg->size); 1211 size_t msize = sizeof (struct UDP_ACK_Message) + ntohs (msg->size);
1289 char buf[msize];
1290 struct UDP_ACK_Message *udp_ack; 1212 struct UDP_ACK_Message *udp_ack;
1291 uint32_t delay = 0; 1213 uint32_t delay = 0;
1292 1214 struct UDPMessageWrapper *udpw;
1293 struct Session *s; 1215 struct Session *s;
1294 1216
1295 s = find_inbound_session_by_addr (rc->plugin, rc->src_addr, rc->addr_len); 1217 struct LookupContext l_ctx;
1296 if (s != NULL) 1218 l_ctx.addr = rc->src_addr;
1297 { 1219 l_ctx.addrlen = rc->addr_len;
1298 if (s->flow_delay_for_other_peer.rel_value <= UINT32_MAX) 1220 l_ctx.res = NULL;
1299 delay = s->flow_delay_for_other_peer.rel_value; 1221 GNUNET_CONTAINER_multihashmap_iterate (rc->plugin->sessions,
1300 else 1222 &lookup_session_by_addr_it,
1301 delay = UINT32_MAX; 1223 &l_ctx);
1302 } 1224 s = l_ctx.res;
1303 1225
1226 GNUNET_assert (s != NULL);
1227
1228 if (s->flow_delay_for_other_peer.rel_value <= UINT32_MAX)
1229 delay = s->flow_delay_for_other_peer.rel_value;
1304 1230
1305#if DEBUG_UDP 1231#if DEBUG_UDP
1306 LOG (GNUNET_ERROR_TYPE_DEBUG, 1232 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -1311,88 +1237,199 @@ ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
1311 sockaddr_in6)), 1237 sockaddr_in6)),
1312 delay); 1238 delay);
1313#endif 1239#endif
1314 udp_ack = (struct UDP_ACK_Message *) buf; 1240 udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + msize);
1241 udpw->cont = NULL;
1242 udpw->cont_cls = NULL;
1243 udpw->frag_ctx = NULL;
1244 udpw->msg_size = msize;
1245 udpw->session = s;
1246 udpw->timeout = GNUNET_TIME_absolute_get_forever();
1247 udpw->udp = (char *)&udpw[1];
1248
1249 udp_ack = (struct UDP_ACK_Message *) udpw->udp;
1315 udp_ack->header.size = htons ((uint16_t) msize); 1250 udp_ack->header.size = htons ((uint16_t) msize);
1316 udp_ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK); 1251 udp_ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK);
1317 udp_ack->delay = htonl (delay); 1252 udp_ack->delay = htonl (delay);
1318 udp_ack->sender = *rc->plugin->env->my_identity; 1253 udp_ack->sender = *rc->plugin->env->my_identity;
1319 memcpy (&udp_ack[1], msg, ntohs (msg->size)); 1254 memcpy (&udp_ack[1], msg, ntohs (msg->size));
1320 (void) udp_send (rc->plugin, rc->src_addr, &udp_ack->header); 1255
1256 GNUNET_CONTAINER_DLL_insert(rc->plugin->msg_head, rc->plugin->msg_tail, udpw);
1321} 1257}
1322 1258
1323 1259
1324/** 1260static void read_process_msg (struct Plugin *plugin,
1325 * Closure for 'find_receive_context'. 1261 const struct GNUNET_MessageHeader *msg,
1326 */ 1262 char *addr,
1327struct FindReceiveContext 1263 socklen_t fromlen)
1328{ 1264{
1329 /** 1265 if (ntohs (msg->size) < sizeof (struct UDPMessage))
1330 * Where to store the result. 1266 {
1331 */ 1267 GNUNET_break_op (0);
1332 struct ReceiveContext *rc; 1268 return;
1269 }
1270 process_udp_message (plugin, (const struct UDPMessage *) msg,
1271 (const struct sockaddr *) addr, fromlen);
1272 return;
1273}
1333 1274
1334 /** 1275static void read_process_ack (struct Plugin *plugin,
1335 * Address to find. 1276 const struct GNUNET_MessageHeader *msg,
1336 */ 1277 char *addr,
1337 const struct sockaddr *addr; 1278 socklen_t fromlen)
1279{
1280 const struct GNUNET_MessageHeader *ack;
1281 const struct UDP_ACK_Message *udp_ack;
1282 struct LookupContext l_ctx;
1283 struct Session *s = NULL;
1284 struct GNUNET_TIME_Relative flow_delay;
1338 1285
1339 /** 1286 if (ntohs (msg->size) <
1340 * Number of bytes in 'addr'. 1287 sizeof (struct UDP_ACK_Message) + sizeof (struct GNUNET_MessageHeader))
1341 */ 1288 {
1342 socklen_t addr_len; 1289 GNUNET_break_op (0);
1290 return;
1291 }
1343 1292
1344 struct Session *session; 1293 udp_ack = (const struct UDP_ACK_Message *) msg;
1345};
1346 1294
1295 l_ctx.addr = (const struct sockaddr *) addr;
1296 l_ctx.addrlen = fromlen;
1297 l_ctx.res = NULL;
1298 GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions,
1299 &lookup_session_by_addr_it,
1300 &l_ctx);
1301 s = l_ctx.res;
1347 1302
1348/** 1303 if ((s == NULL) || (s->frag_ctx == NULL))
1349 * Scan the heap for a receive context with the given address. 1304 return;
1350 *
1351 * @param cls the 'struct FindReceiveContext'
1352 * @param node internal node of the heap
1353 * @param element value stored at the node (a 'struct ReceiveContext')
1354 * @param cost cost associated with the node
1355 * @return GNUNET_YES if we should continue to iterate,
1356 * GNUNET_NO if not.
1357 */
1358static int
1359find_receive_context (void *cls, struct GNUNET_CONTAINER_HeapNode *node,
1360 void *element, GNUNET_CONTAINER_HeapCostType cost)
1361{
1362 struct FindReceiveContext *frc = cls;
1363 struct ReceiveContext *e = element;
1364 1305
1365 if ((frc->addr_len == e->addr_len) && 1306 flow_delay.rel_value = (uint64_t) ntohl (udp_ack->delay);
1366 (0 == memcmp (frc->addr, e->src_addr, frc->addr_len))) 1307 LOG (GNUNET_ERROR_TYPE_DEBUG, "We received a sending delay of %llu\n",
1308 flow_delay.rel_value);
1309 s->flow_delay_from_other_peer =
1310 GNUNET_TIME_relative_to_absolute (flow_delay);
1311
1312 ack = (const struct GNUNET_MessageHeader *) &udp_ack[1];
1313 if (ntohs (ack->size) !=
1314 ntohs (msg->size) - sizeof (struct UDP_ACK_Message))
1367 { 1315 {
1368 frc->rc = e; 1316 GNUNET_break_op (0);
1369 return GNUNET_NO; 1317 return;
1370 } 1318 }
1371 return GNUNET_YES; 1319
1320 if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (s->frag_ctx->frag, ack))
1321 {
1322#if DEBUG_UDP
1323 LOG (GNUNET_ERROR_TYPE_DEBUG,
1324 "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
1325 (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
1326 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1327#endif
1328 return;
1329 }
1330
1331#if DEBUG_UDP
1332 LOG (GNUNET_ERROR_TYPE_DEBUG,
1333 "FULL MESSAGE ACKed\n",
1334 (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
1335 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1336#endif
1337 s->last_expected_delay = GNUNET_FRAGMENT_context_destroy (s->frag_ctx->frag);
1338
1339 struct UDPMessageWrapper * udpw = plugin->msg_head;
1340 while (udpw!= NULL)
1341 {
1342 if ((udpw->frag_ctx != NULL) && (udpw->frag_ctx == s->frag_ctx))
1343 {
1344 GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
1345 GNUNET_free (udpw);
1346 }
1347 udpw = udpw->next;
1348 }
1349
1350 if (s->frag_ctx->cont != NULL)
1351 s->frag_ctx->cont
1352 (s->frag_ctx->cont_cls, &udp_ack->sender, GNUNET_OK);
1353 GNUNET_free (s->frag_ctx);
1354 s->frag_ctx = NULL;
1355 return;
1372} 1356}
1373 1357
1374struct Mstv4Context 1358static void read_process_fragment (struct Plugin *plugin,
1359 const struct GNUNET_MessageHeader *msg,
1360 char *addr,
1361 socklen_t fromlen)
1375{ 1362{
1376 struct Plugin *plugin; 1363 struct DefragContext *d_ctx;
1364 struct GNUNET_TIME_Absolute now;
1365 struct FindReceiveContext frc;
1377 1366
1378 struct IPv4UdpAddress addr;
1379 /**
1380 * ATS network type in NBO
1381 */
1382 uint32_t ats_address_network_type;
1383};
1384 1367
1385struct Mstv6Context 1368 frc.rc = NULL;
1386{ 1369 frc.addr = (const struct sockaddr *) addr;
1387 struct Plugin *plugin; 1370 frc.addr_len = fromlen;
1388 1371
1389 struct IPv6UdpAddress addr; 1372#if DEBUG_UDP
1390 /** 1373 LOG (GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte fragment from `%s'\n",
1391 * ATS network type in NBO 1374 (unsigned int) ntohs (msg->size),
1392 */ 1375 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1393 uint32_t ats_address_network_type; 1376#endif
1394}; 1377
1378 /* Lookup existing receive context for this address */
1379 GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs,
1380 &find_receive_context,
1381 &frc);
1382 now = GNUNET_TIME_absolute_get ();
1383 d_ctx = frc.rc;
1395 1384
1385 if (d_ctx == NULL)
1386 {
1387 /* Create a new defragmentation context */
1388 d_ctx = GNUNET_malloc (sizeof (struct DefragContext) + fromlen);
1389 memcpy (&d_ctx[1], addr, fromlen);
1390 d_ctx->src_addr = (const struct sockaddr *) &d_ctx[1];
1391 d_ctx->addr_len = fromlen;
1392 d_ctx->plugin = plugin;
1393 d_ctx->defrag =
1394 GNUNET_DEFRAGMENT_context_create (plugin->env->stats, UDP_MTU,
1395 UDP_MAX_MESSAGES_IN_DEFRAG, d_ctx,
1396 &fragment_msg_proc, &ack_proc);
1397 d_ctx->hnode =
1398 GNUNET_CONTAINER_heap_insert (plugin->defrag_ctxs, d_ctx,
1399 (GNUNET_CONTAINER_HeapCostType)
1400 now.abs_value);
1401#if DEBUG_UDP
1402 LOG (GNUNET_ERROR_TYPE_DEBUG, "Created new defragmentation context for %u-byte fragment from `%s'\n",
1403 (unsigned int) ntohs (msg->size),
1404 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1405#endif
1406 }
1407 else
1408 {
1409#if DEBUG_UDP
1410 LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing defragmentation context for %u-byte fragment from `%s'\n",
1411 (unsigned int) ntohs (msg->size),
1412 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1413#endif
1414 }
1415
1416 if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (d_ctx->defrag, msg))
1417 {
1418 /* keep this 'rc' from expiring */
1419 GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs, d_ctx->hnode,
1420 (GNUNET_CONTAINER_HeapCostType)
1421 now.abs_value);
1422 }
1423 if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) >
1424 UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG)
1425 {
1426 /* remove 'rc' that was inactive the longest */
1427 d_ctx = GNUNET_CONTAINER_heap_remove_root (plugin->defrag_ctxs);
1428 GNUNET_assert (NULL != d_ctx);
1429 GNUNET_DEFRAGMENT_context_destroy (d_ctx->defrag);
1430 GNUNET_free (d_ctx);
1431 }
1432}
1396 1433
1397/** 1434/**
1398 * Read and process a message from the given socket. 1435 * Read and process a message from the given socket.
@@ -1401,29 +1438,20 @@ struct Mstv6Context
1401 * @param rsock socket to read from 1438 * @param rsock socket to read from
1402 */ 1439 */
1403static void 1440static void
1404udp_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock) 1441udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
1405{ 1442{
1406 socklen_t fromlen; 1443 socklen_t fromlen;
1407 char addr[32]; 1444 char addr[32];
1408 char buf[65536]; 1445 char buf[65536];
1409 ssize_t ret; 1446 ssize_t size;
1410 const struct GNUNET_MessageHeader *msg; 1447 const struct GNUNET_MessageHeader *msg;
1411 const struct GNUNET_MessageHeader *ack;
1412 struct Session *peer_session;
1413 const struct UDP_ACK_Message *udp_ack;
1414 struct ReceiveContext *rc;
1415 struct GNUNET_TIME_Absolute now;
1416 struct FindReceiveContext frc;
1417 struct Session *s = NULL;
1418 struct GNUNET_TIME_Relative flow_delay;
1419 struct GNUNET_ATS_Information ats;
1420 1448
1421 fromlen = sizeof (addr); 1449 fromlen = sizeof (addr);
1422 memset (&addr, 0, sizeof (addr)); 1450 memset (&addr, 0, sizeof (addr));
1423 ret = 1451 size = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
1424 GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
1425 (struct sockaddr *) &addr, &fromlen); 1452 (struct sockaddr *) &addr, &fromlen);
1426 if (ret < sizeof (struct GNUNET_MessageHeader)) 1453
1454 if (size < sizeof (struct GNUNET_MessageHeader))
1427 { 1455 {
1428 GNUNET_break_op (0); 1456 GNUNET_break_op (0);
1429 return; 1457 return;
@@ -1431,863 +1459,216 @@ udp_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
1431 msg = (const struct GNUNET_MessageHeader *) buf; 1459 msg = (const struct GNUNET_MessageHeader *) buf;
1432 1460
1433 LOG (GNUNET_ERROR_TYPE_DEBUG, 1461 LOG (GNUNET_ERROR_TYPE_DEBUG,
1434 "UDP received %u-byte message from `%s' type %i\n", (unsigned int) ret, 1462 "UDP received %u-byte message from `%s' type %i\n", (unsigned int) size,
1435 GNUNET_a2s ((const struct sockaddr *) addr, fromlen), ntohs (msg->type)); 1463 GNUNET_a2s ((const struct sockaddr *) addr, fromlen), ntohs (msg->type));
1436 1464
1437 if (ret != ntohs (msg->size)) 1465 if (size != ntohs (msg->size))
1438 { 1466 {
1439 GNUNET_break_op (0); 1467 GNUNET_break_op (0);
1440 return; 1468 return;
1441 } 1469 }
1470
1442 switch (ntohs (msg->type)) 1471 switch (ntohs (msg->type))
1443 { 1472 {
1444 case GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON: 1473 case GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON:
1445 { 1474 udp_broadcast_receive (plugin, &buf, size, addr, fromlen);
1446 if (fromlen == sizeof (struct sockaddr_in))
1447 {
1448 LOG (GNUNET_ERROR_TYPE_DEBUG,
1449 "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n",
1450 ret, GNUNET_a2s ((const struct sockaddr *) &addr, fromlen));
1451
1452 struct Mstv4Context *mc;
1453
1454 mc = GNUNET_malloc (sizeof (struct Mstv4Context));
1455 struct sockaddr_in *av4 = (struct sockaddr_in *) &addr;
1456
1457 mc->addr.ipv4_addr = av4->sin_addr.s_addr;
1458 mc->addr.u4_port = av4->sin_port;
1459 ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &addr, fromlen);
1460 mc->ats_address_network_type = ats.value;
1461 if (GNUNET_OK !=
1462 GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, ret,
1463 GNUNET_NO, GNUNET_NO))
1464 GNUNET_free (mc);
1465 }
1466 else if (fromlen == sizeof (struct sockaddr_in6))
1467 {
1468 LOG (GNUNET_ERROR_TYPE_DEBUG,
1469 "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n",
1470 ret, GNUNET_a2s ((const struct sockaddr *) &addr, fromlen));
1471
1472 struct Mstv6Context *mc;
1473
1474 mc = GNUNET_malloc (sizeof (struct Mstv6Context));
1475 struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) &addr;
1476
1477 mc->addr.ipv6_addr = av6->sin6_addr;
1478 mc->addr.u6_port = av6->sin6_port;
1479 ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &addr, fromlen);
1480 mc->ats_address_network_type = ats.value;
1481
1482 if (GNUNET_OK !=
1483 GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, ret,
1484 GNUNET_NO, GNUNET_NO))
1485 GNUNET_free (mc);
1486 }
1487 return; 1475 return;
1488 } 1476
1489 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE: 1477 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE:
1490 if (ntohs (msg->size) < sizeof (struct UDPMessage)) 1478 read_process_msg (plugin, msg, addr, fromlen);
1491 {
1492 GNUNET_break_op (0);
1493 return;
1494 }
1495 process_udp_message (plugin, (const struct UDPMessage *) msg,
1496 (const struct sockaddr *) addr, fromlen);
1497 return; 1479 return;
1498 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
1499
1500 if (ntohs (msg->size) <
1501 sizeof (struct UDP_ACK_Message) + sizeof (struct GNUNET_MessageHeader))
1502 {
1503 GNUNET_break_op (0);
1504 return;
1505 }
1506 udp_ack = (const struct UDP_ACK_Message *) msg;
1507 s = find_inbound_session (plugin, &udp_ack->sender, addr, fromlen);
1508 if (s != NULL)
1509 {
1510 flow_delay.rel_value = (uint64_t) ntohl (udp_ack->delay);
1511 1480
1512 LOG (GNUNET_ERROR_TYPE_DEBUG, "We received a sending delay of %llu\n", 1481 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
1513 flow_delay.rel_value); 1482 read_process_ack (plugin, msg, addr, fromlen);;
1514
1515 s->flow_delay_from_other_peer =
1516 GNUNET_TIME_relative_to_absolute (flow_delay);
1517 }
1518 ack = (const struct GNUNET_MessageHeader *) &udp_ack[1];
1519 if (ntohs (ack->size) !=
1520 ntohs (msg->size) - sizeof (struct UDP_ACK_Message))
1521 {
1522 GNUNET_break_op (0);
1523 return;
1524 }
1525#if DEBUG_UDP
1526 LOG (GNUNET_ERROR_TYPE_DEBUG,
1527 "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
1528 (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
1529 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1530#endif
1531
1532 peer_session = find_session (plugin, &udp_ack->sender);
1533 if (NULL == peer_session)
1534 {
1535#if DEBUG_UDP
1536 LOG (GNUNET_ERROR_TYPE_DEBUG,
1537 "Session for ACK not found, dropping ACK!\n");
1538#endif
1539 return;
1540 }
1541 if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (peer_session->frag, ack))
1542 return;
1543 GNUNET_assert (GNUNET_OK ==
1544 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
1545 &udp_ack->
1546 sender.hashPubKey,
1547 peer_session));
1548 plugin->last_expected_delay =
1549 GNUNET_FRAGMENT_context_destroy (peer_session->frag);
1550 if (peer_session->cont != NULL)
1551 peer_session->cont (peer_session->cont_cls, &udp_ack->sender, GNUNET_OK);
1552 GNUNET_free (peer_session);
1553 return; 1483 return;
1554 case GNUNET_MESSAGE_TYPE_FRAGMENT:
1555 frc.rc = NULL;
1556 frc.addr = (const struct sockaddr *) addr;
1557 frc.addr_len = fromlen;
1558 GNUNET_CONTAINER_heap_iterate (plugin->defrags, &find_receive_context,
1559 &frc);
1560 now = GNUNET_TIME_absolute_get ();
1561 rc = frc.rc;
1562 if (rc == NULL)
1563 {
1564 /* need to create a new RC */
1565 rc = GNUNET_malloc (sizeof (struct ReceiveContext) + fromlen);
1566 memcpy (&rc[1], addr, fromlen);
1567 rc->src_addr = (const struct sockaddr *) &rc[1];
1568 rc->addr_len = fromlen;
1569 rc->plugin = plugin;
1570 rc->defrag =
1571 GNUNET_DEFRAGMENT_context_create (plugin->env->stats, UDP_MTU,
1572 UDP_MAX_MESSAGES_IN_DEFRAG, rc,
1573 &fragment_msg_proc, &ack_proc);
1574 rc->hnode =
1575 GNUNET_CONTAINER_heap_insert (plugin->defrags, rc,
1576 (GNUNET_CONTAINER_HeapCostType)
1577 now.abs_value);
1578 }
1579#if DEBUG_UDP
1580 LOG (GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte fragment from `%s'\n",
1581 (unsigned int) ntohs (msg->size),
1582 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1583#endif
1584 1484
1585 if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (rc->defrag, msg)) 1485 case GNUNET_MESSAGE_TYPE_FRAGMENT:
1586 { 1486 read_process_fragment (plugin, msg, addr, fromlen);
1587 /* keep this 'rc' from expiring */
1588 GNUNET_CONTAINER_heap_update_cost (plugin->defrags, rc->hnode,
1589 (GNUNET_CONTAINER_HeapCostType)
1590 now.abs_value);
1591 }
1592 if (GNUNET_CONTAINER_heap_get_size (plugin->defrags) >
1593 UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG)
1594 {
1595 /* remove 'rc' that was inactive the longest */
1596 rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags);
1597 GNUNET_assert (NULL != rc);
1598 GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
1599 GNUNET_free (rc);
1600 }
1601 return; 1487 return;
1488
1602 default: 1489 default:
1603 GNUNET_break_op (0); 1490 GNUNET_break_op (0);
1604 return; 1491 return;
1605 } 1492 }
1606} 1493}
1607 1494
1608 1495size_t
1609/** 1496udp_select_send (struct Plugin *plugin)
1610 * We have been notified that our writeset has something to read. We don't
1611 * know which socket needs to be read, so we have to check each one
1612 * Then reschedule this function to be called again once more is available.
1613 *
1614 * @param cls the plugin handle
1615 * @param tc the scheduling context (for rescheduling this function again)
1616 */
1617static void
1618udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1619{
1620 struct Plugin *plugin = cls;
1621
1622 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1623 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1624 return;
1625 if ((NULL != plugin->sockv4) &&
1626 (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4)))
1627 udp_read (plugin, plugin->sockv4);
1628 if ((NULL != plugin->sockv6) &&
1629 (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv6)))
1630 udp_read (plugin, plugin->sockv6);
1631 plugin->select_task =
1632 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1633 GNUNET_SCHEDULER_NO_TASK,
1634 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1635 NULL, &udp_plugin_select, plugin);
1636
1637}
1638
1639
1640void
1641broadcast_ipv4_mst_cb (void *cls, void *client,
1642 const struct GNUNET_MessageHeader *message)
1643{
1644 struct Plugin *plugin = cls;
1645 struct Mstv4Context *mc = client;
1646 const struct GNUNET_MessageHeader *hello;
1647 struct UDP_Beacon_Message *msg;
1648
1649 msg = (struct UDP_Beacon_Message *) message;
1650
1651 if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
1652 ntohs (msg->header.type))
1653 return;
1654
1655 LOG (GNUNET_ERROR_TYPE_DEBUG,
1656 "Received beacon with %u bytes from peer `%s' via address `%s'\n",
1657 ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
1658 udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
1659
1660 struct GNUNET_ATS_Information atsi[2];
1661
1662 /* setup ATS */
1663 atsi[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
1664 atsi[0].value = htonl (1);
1665 atsi[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
1666 atsi[1].value = mc->ats_address_network_type;
1667 GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED);
1668
1669 hello = (struct GNUNET_MessageHeader *) &msg[1];
1670 plugin->env->receive (plugin->env->cls, &msg->sender, hello,
1671 (const struct GNUNET_ATS_Information *) &atsi, 2, NULL,
1672 (const char *) &mc->addr, sizeof (mc->addr));
1673
1674 GNUNET_STATISTICS_update (plugin->env->stats,
1675 _
1676 ("# IPv4 broadcast HELLO beacons received via udp"),
1677 1, GNUNET_NO);
1678 GNUNET_free (mc);
1679}
1680
1681
1682void
1683broadcast_ipv6_mst_cb (void *cls, void *client,
1684 const struct GNUNET_MessageHeader *message)
1685{
1686
1687 struct Plugin *plugin = cls;
1688 struct Mstv6Context *mc = client;
1689 const struct GNUNET_MessageHeader *hello;
1690 struct UDP_Beacon_Message *msg;
1691
1692 msg = (struct UDP_Beacon_Message *) message;
1693
1694 if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
1695 ntohs (msg->header.type))
1696 return;
1697
1698 LOG (GNUNET_ERROR_TYPE_DEBUG,
1699 "Received beacon with %u bytes from peer `%s' via address `%s'\n",
1700 ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
1701 udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
1702
1703 struct GNUNET_ATS_Information atsi[2];
1704
1705 /* setup ATS */
1706 atsi[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
1707 atsi[0].value = htonl (1);
1708 atsi[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
1709 atsi[1].value = mc->ats_address_network_type;
1710 GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED);
1711
1712 hello = (struct GNUNET_MessageHeader *) &msg[1];
1713 plugin->env->receive (plugin->env->cls, &msg->sender, hello,
1714 (const struct GNUNET_ATS_Information *) &atsi, 2, NULL,
1715 (const char *) &mc->addr, sizeof (mc->addr));
1716
1717 GNUNET_STATISTICS_update (plugin->env->stats,
1718 _
1719 ("# IPv6 multicast HELLO beacons received via udp"),
1720 1, GNUNET_NO);
1721 GNUNET_free (mc);
1722}
1723
1724
1725static void
1726udp_ipv4_broadcast_send (void *cls,
1727 const struct GNUNET_SCHEDULER_TaskContext *tc)
1728{ 1497{
1729 struct Plugin *plugin = cls; 1498 ssize_t sent;
1730 int sent; 1499 size_t slen;
1731 uint16_t msg_size; 1500 struct GNUNET_TIME_Absolute max;
1732 uint16_t hello_size; 1501 struct GNUNET_TIME_Absolute ;
1733 char buf[65536];
1734
1735 const struct GNUNET_MessageHeader *hello;
1736 struct UDP_Beacon_Message *msg;
1737 struct BroadcastAddress *baddr;
1738
1739 plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
1740 1502
1741 hello = plugin->env->get_our_hello (); 1503 struct UDPMessageWrapper *udpw = plugin->msg_head;
1742 hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello); 1504 const struct sockaddr * sa = udpw->session->sock_addr;
1743 msg_size = hello_size + sizeof (struct UDP_Beacon_Message);
1744 1505
1745 if (hello_size < (sizeof (struct GNUNET_MessageHeader)) || 1506 max = GNUNET_TIME_absolute_max(udpw->timeout, GNUNET_TIME_absolute_get());
1746 (msg_size > (UDP_MTU)))
1747 return;
1748 1507
1749 msg = (struct UDP_Beacon_Message *) buf; 1508 while (udpw != NULL)
1750 msg->sender = *(plugin->env->my_identity);
1751 msg->header.size = ntohs (msg_size);
1752 msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON);
1753 memcpy (&msg[1], hello, hello_size);
1754 sent = 0;
1755
1756 baddr = plugin->ipv4_broadcast_head;
1757 /* just IPv4 */
1758 while ((baddr != NULL) && (baddr->addrlen == sizeof (struct sockaddr_in)))
1759 { 1509 {
1760 struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr; 1510 if (max.abs_value != udpw->timeout.abs_value)
1511 {
1512 /* Message timed out */
1761 1513
1762 addr->sin_port = htons (plugin->port); 1514 if (udpw->cont != NULL)
1515 udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
1516 if (udpw->frag_ctx != NULL)
1517 {
1518#if DEBUG_UDP
1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fragmented message for peer `%s' with size %u timed out\n",
1520 GNUNET_i2s(&udpw->session->target), udpw->frag_ctx->bytes_to_send);
1521#endif
1522 udpw->session->last_expected_delay = GNUNET_FRAGMENT_context_destroy(udpw->frag_ctx->frag);
1523 GNUNET_free (udpw->frag_ctx);
1524 udpw->session->frag_ctx = NULL;
1525 }
1526 else
1527 {
1528#if DEBUG_UDP
1529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' with size %u timed out\n",
1530 GNUNET_i2s(&udpw->session->target), udpw->msg_size);
1531#endif
1532 }
1763 1533
1764 sent = 1534 GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
1765 GNUNET_NETWORK_socket_sendto (plugin->sockv4, msg, msg_size, 1535 GNUNET_free (udpw);
1766 (const struct sockaddr *) addr, 1536 udpw = plugin->msg_head;
1767 baddr->addrlen); 1537 }
1768 if (sent == GNUNET_SYSERR)
1769 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
1770 else 1538 else
1771 LOG (GNUNET_ERROR_TYPE_DEBUG, 1539 {
1772 "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent, 1540 struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_remaining (udpw->session->flow_delay_from_other_peer);
1773 GNUNET_a2s (baddr->addr, baddr->addrlen)); 1541 if (delta.rel_value == 0)
1774 baddr = baddr->next; 1542 {
1775 } 1543 /* this message is not delayed */
1776 1544 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' (%u bytes) is not delayed \n",
1777 plugin->send_ipv4_broadcast_task = 1545 GNUNET_i2s(&udpw->session->target), udpw->msg_size);
1778 GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, 1546 break;
1779 &udp_ipv4_broadcast_send, plugin); 1547 }
1780} 1548 else
1781 1549 {
1782static void 1550 /* this message is delayed, try next */
1783udp_ipv6_broadcast_send (void *cls, 1551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' (%u bytes) is delayed for %llu \n",
1784 const struct GNUNET_SCHEDULER_TaskContext *tc) 1552 GNUNET_i2s(&udpw->session->target), udpw->msg_size,
1785{ 1553 delta);
1786 struct Plugin *plugin = cls; 1554 udpw = udpw->next;
1787 int sent; 1555 }
1788 uint16_t msg_size; 1556 }
1789 uint16_t hello_size;
1790 char buf[65536];
1791
1792 const struct GNUNET_MessageHeader *hello;
1793 struct UDP_Beacon_Message *msg;
1794
1795 plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
1796
1797 hello = plugin->env->get_our_hello ();
1798 hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1799 msg_size = hello_size + sizeof (struct UDP_Beacon_Message);
1800
1801 if (hello_size < (sizeof (struct GNUNET_MessageHeader)) ||
1802 (msg_size > (UDP_MTU)))
1803 return;
1804
1805 msg = (struct UDP_Beacon_Message *) buf;
1806 msg->sender = *(plugin->env->my_identity);
1807 msg->header.size = ntohs (msg_size);
1808 msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON);
1809 memcpy (&msg[1], hello, hello_size);
1810 sent = 0;
1811
1812 sent =
1813 GNUNET_NETWORK_socket_sendto (plugin->sockv6, msg, msg_size,
1814 (const struct sockaddr *)
1815 &plugin->ipv6_multicast_address,
1816 sizeof (struct sockaddr_in6));
1817 if (sent == GNUNET_SYSERR)
1818 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
1819 else
1820 LOG (GNUNET_ERROR_TYPE_DEBUG,
1821 "Sending IPv6 HELLO beacon broadcast with %i bytes to address %s\n",
1822 sent,
1823 GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address,
1824 sizeof (struct sockaddr_in6)));
1825
1826
1827
1828 plugin->send_ipv6_broadcast_task =
1829 GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
1830 &udp_ipv6_broadcast_send, plugin);
1831}
1832
1833/**
1834 * Check if the given port is plausible (must be either our listen
1835 * port or our advertised port). If it is neither, we return
1836 * GNUNET_SYSERR.
1837 *
1838 * @param plugin global variables
1839 * @param in_port port number to check
1840 * @return GNUNET_OK if port is either open_port or adv_port
1841 */
1842static int
1843check_port (struct Plugin *plugin, uint16_t in_port)
1844{
1845 if ((in_port == plugin->port) || (in_port == plugin->aport))
1846 return GNUNET_OK;
1847 return GNUNET_SYSERR;
1848}
1849
1850 1557
1851/** 1558 }
1852 * Function that will be called to check if a binary address for this
1853 * plugin is well-formed and corresponds to an address for THIS peer
1854 * (as per our configuration). Naturally, if absolutely necessary,
1855 * plugins can be a bit conservative in their answer, but in general
1856 * plugins should make sure that the address does not redirect
1857 * traffic to a 3rd party that might try to man-in-the-middle our
1858 * traffic.
1859 *
1860 * @param cls closure, should be our handle to the Plugin
1861 * @param addr pointer to the address
1862 * @param addrlen length of addr
1863 * @return GNUNET_OK if this is a plausible address for this peer
1864 * and transport, GNUNET_SYSERR if not
1865 *
1866 */
1867static int
1868udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
1869{
1870 struct Plugin *plugin = cls;
1871 struct IPv4UdpAddress *v4;
1872 struct IPv6UdpAddress *v6;
1873 1559
1874 if ((addrlen != sizeof (struct IPv4UdpAddress)) && 1560 if (udpw == NULL)
1875 (addrlen != sizeof (struct IPv6UdpAddress)))
1876 { 1561 {
1877 GNUNET_break_op (0); 1562 /* No message left */
1878 return GNUNET_SYSERR; 1563 return 0;
1879 } 1564 }
1880 if (addrlen == sizeof (struct IPv4UdpAddress)) 1565
1566 switch (sa->sa_family)
1881 { 1567 {
1882 v4 = (struct IPv4UdpAddress *) addr; 1568 case AF_INET:
1883 if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port))) 1569 if (NULL == plugin->sockv4)
1884 return GNUNET_SYSERR; 1570 return 0;
1885 if (GNUNET_OK != 1571 sent =
1886 GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr, 1572 GNUNET_NETWORK_socket_sendto (plugin->sockv4, udpw->udp, udpw->msg_size,
1887 sizeof (struct in_addr))) 1573 sa, slen = sizeof (struct sockaddr_in));
1888 return GNUNET_SYSERR; 1574 break;
1575 case AF_INET6:
1576 if (NULL == plugin->sockv6)
1577 return 0;
1578 sent =
1579 GNUNET_NETWORK_socket_sendto (plugin->sockv6, udpw->udp, udpw->msg_size,
1580 sa, slen = sizeof (struct sockaddr_in6));
1581 break;
1582 default:
1583 GNUNET_break (0);
1584 return 0;
1889 } 1585 }
1890 else 1586 if (GNUNET_SYSERR == sent)
1891 { 1587 {
1892 v6 = (struct IPv6UdpAddress *) addr; 1588 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
1893 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr)) 1589 LOG (GNUNET_ERROR_TYPE_DEBUG,
1894 { 1590 "UDP transmitted %u-byte message to %s (%d: %s)\n",
1895 GNUNET_break_op (0); 1591 (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen), (int) sent,
1896 return GNUNET_SYSERR; 1592 (sent < 0) ? STRERROR (errno) : "ok");
1897 } 1593 if (udpw->cont != NULL)
1898 if (GNUNET_OK != check_port (plugin, ntohs (v6->u6_port))) 1594 udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
1899 return GNUNET_SYSERR;
1900 if (GNUNET_OK !=
1901 GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr,
1902 sizeof (struct in6_addr)))
1903 return GNUNET_SYSERR;
1904 } 1595 }
1905 return GNUNET_OK; 1596 LOG (GNUNET_ERROR_TYPE_DEBUG,
1906} 1597 "UDP transmitted %u-byte message to %s (%d: %s)\n",
1907 1598 (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen), (int) sent,
1908 1599 (sent < 0) ? STRERROR (errno) : "ok");
1909/**
1910 * Function called for a quick conversion of the binary address to
1911 * a numeric address. Note that the caller must not free the
1912 * address and that the next call to this function is allowed
1913 * to override the address again.
1914 *
1915 * @param cls closure
1916 * @param addr binary address
1917 * @param addrlen length of the address
1918 * @return string representing the same address
1919 */
1920static const char *
1921udp_address_to_string (void *cls, const void *addr, size_t addrlen)
1922{
1923 static char rbuf[INET6_ADDRSTRLEN + 10];
1924 char buf[INET6_ADDRSTRLEN];
1925 const void *sb;
1926 struct in_addr a4;
1927 struct in6_addr a6;
1928 const struct IPv4UdpAddress *t4;
1929 const struct IPv6UdpAddress *t6;
1930 int af;
1931 uint16_t port;
1932 1600
1933 if (addrlen == sizeof (struct IPv6UdpAddress)) 1601 /* This was just a message fragment */
1602 if (udpw->frag_ctx != NULL)
1934 { 1603 {
1935 t6 = addr; 1604 GNUNET_FRAGMENT_context_transmission_done (udpw->frag_ctx->frag);
1936 af = AF_INET6;
1937 port = ntohs (t6->u6_port);
1938 memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
1939 sb = &a6;
1940 }
1941 else if (addrlen == sizeof (struct IPv4UdpAddress))
1942 {
1943 t4 = addr;
1944 af = AF_INET;
1945 port = ntohs (t4->u4_port);
1946 memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
1947 sb = &a4;
1948 } 1605 }
1606 /* This was a complete message*/
1949 else 1607 else
1950 { 1608 {
1951 GNUNET_break_op (0); 1609 if (udpw->cont != NULL)
1952 return NULL; 1610 udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_OK);
1953 } 1611 }
1954 inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
1955 GNUNET_snprintf (rbuf, sizeof (rbuf), (af == AF_INET6) ? "[%s]:%u" : "%s:%u",
1956 buf, port);
1957 return rbuf;
1958}
1959
1960
1961/**
1962 * Closure for 'append_port'.
1963 */
1964struct PrettyPrinterContext
1965{
1966 /**
1967 * Function to call with the result.
1968 */
1969 GNUNET_TRANSPORT_AddressStringCallback asc;
1970 1612
1971 /** 1613 GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
1972 * Clsoure for 'asc'. 1614 GNUNET_free (udpw);
1973 */
1974 void *asc_cls;
1975 1615
1976 /** 1616 return sent;
1977 * Port to add after the IP address.
1978 */
1979 uint16_t port;
1980};
1981
1982
1983/**
1984 * Append our port and forward the result.
1985 *
1986 * @param cls a 'struct PrettyPrinterContext'
1987 * @param hostname result from DNS resolver
1988 */
1989static void
1990append_port (void *cls, const char *hostname)
1991{
1992 struct PrettyPrinterContext *ppc = cls;
1993 char *ret;
1994
1995 if (hostname == NULL)
1996 {
1997 ppc->asc (ppc->asc_cls, NULL);
1998 GNUNET_free (ppc);
1999 return;
2000 }
2001 GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
2002 ppc->asc (ppc->asc_cls, ret);
2003 GNUNET_free (ret);
2004} 1617}
2005 1618
2006
2007/** 1619/**
2008 * Convert the transports address to a nice, human-readable 1620 * We have been notified that our readset has something to read. We don't
2009 * format. 1621 * know which socket needs to be read, so we have to check each one
1622 * Then reschedule this function to be called again once more is available.
2010 * 1623 *
2011 * @param cls closure 1624 * @param cls the plugin handle
2012 * @param type name of the transport that generated the address 1625 * @param tc the scheduling context (for rescheduling this function again)
2013 * @param addr one of the addresses of the host, NULL for the last address
2014 * the specific address format depends on the transport
2015 * @param addrlen length of the address
2016 * @param numeric should (IP) addresses be displayed in numeric form?
2017 * @param timeout after how long should we give up?
2018 * @param asc function to call on each string
2019 * @param asc_cls closure for asc
2020 */ 1626 */
2021static void 1627static void
2022udp_plugin_address_pretty_printer (void *cls, const char *type, 1628udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2023 const void *addr, size_t addrlen,
2024 int numeric,
2025 struct GNUNET_TIME_Relative timeout,
2026 GNUNET_TRANSPORT_AddressStringCallback asc,
2027 void *asc_cls)
2028{ 1629{
2029 struct PrettyPrinterContext *ppc; 1630 struct Plugin *plugin = cls;
2030 const void *sb;
2031 size_t sbs;
2032 struct sockaddr_in a4;
2033 struct sockaddr_in6 a6;
2034 const struct IPv4UdpAddress *u4;
2035 const struct IPv6UdpAddress *u6;
2036 uint16_t port;
2037 1631
2038 if (addrlen == sizeof (struct IPv6UdpAddress)) 1632 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
2039 { 1633 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
2040 u6 = addr;
2041 memset (&a6, 0, sizeof (a6));
2042 a6.sin6_family = AF_INET6;
2043#if HAVE_SOCKADDR_IN_SIN_LEN
2044 a6.sin6_len = sizeof (a6);
2045#endif
2046 a6.sin6_port = u6->u6_port;
2047 memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof (struct in6_addr));
2048 port = ntohs (u6->u6_port);
2049 sb = &a6;
2050 sbs = sizeof (a6);
2051 }
2052 else if (addrlen == sizeof (struct IPv4UdpAddress))
2053 {
2054 u4 = addr;
2055 memset (&a4, 0, sizeof (a4));
2056 a4.sin_family = AF_INET;
2057#if HAVE_SOCKADDR_IN_SIN_LEN
2058 a4.sin_len = sizeof (a4);
2059#endif
2060 a4.sin_port = u4->u4_port;
2061 a4.sin_addr.s_addr = u4->ipv4_addr;
2062 port = ntohs (u4->u4_port);
2063 sb = &a4;
2064 sbs = sizeof (a4);
2065 }
2066 else
2067 {
2068 /* invalid address */
2069 GNUNET_break_op (0);
2070 asc (asc_cls, NULL);
2071 return; 1634 return;
2072 }
2073 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
2074 ppc->asc = asc;
2075 ppc->asc_cls = asc_cls;
2076 ppc->port = port;
2077 GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
2078}
2079
2080 1635
2081/** 1636 if ((tc->reason & GNUNET_SCHEDULER_REASON_READ_READY) != 0)
2082 * Our external IP address/port mapping has changed.
2083 *
2084 * @param cls closure, the 'struct LocalAddrList'
2085 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
2086 * the previous (now invalid) one
2087 * @param addr either the previous or the new public IP address
2088 * @param addrlen actual lenght of the address
2089 */
2090static void
2091udp_nat_port_map_callback (void *cls, int add_remove,
2092 const struct sockaddr *addr, socklen_t addrlen)
2093{
2094 struct Plugin *plugin = cls;
2095 struct IPv4UdpAddress u4;
2096 struct IPv6UdpAddress u6;
2097 void *arg;
2098 size_t args;
2099
2100 /* convert 'addr' to our internal format */
2101 switch (addr->sa_family)
2102 { 1637 {
2103 case AF_INET: 1638 if ((NULL != plugin->sockv4) &&
2104 GNUNET_assert (addrlen == sizeof (struct sockaddr_in)); 1639 (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4)))
2105 u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; 1640 udp_select_read (plugin, plugin->sockv4);
2106 u4.u4_port = ((struct sockaddr_in *) addr)->sin_port; 1641 if ((NULL != plugin->sockv6) &&
2107 arg = &u4; 1642 (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv6)))
2108 args = sizeof (u4); 1643 udp_select_read (plugin, plugin->sockv6);
2109 break;
2110 case AF_INET6:
2111 GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
2112 memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
2113 sizeof (struct in6_addr));
2114 u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
2115 arg = &u6;
2116 args = sizeof (u6);
2117 break;
2118 default:
2119 GNUNET_break (0);
2120 return;
2121 } 1644 }
2122 /* modify our published address list */
2123 plugin->env->notify_address (plugin->env->cls, add_remove, arg, args);
2124}
2125 1645
2126 1646 if ((tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY) != 0)
2127static int
2128iface_proc (void *cls, const char *name, int isDefault,
2129 const struct sockaddr *addr, const struct sockaddr *broadcast_addr,
2130 const struct sockaddr *netmask, socklen_t addrlen)
2131{
2132 struct Plugin *plugin = cls;
2133
2134 if (addr != NULL)
2135 { 1647 {
2136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ", 1648 if (plugin->msg_head != NULL)
2137 GNUNET_a2s (addr, addrlen), name, addr); 1649 udp_select_send (plugin);
2138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1650 }
2139 "broadcast address %s for interface %s %p\n ",
2140 GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr);
2141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
2142 GNUNET_a2s (netmask, addrlen), name, netmask);
2143 1651
1652 plugin->select_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1653 GNUNET_SCHEDULER_NO_TASK,
1654 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1655 plugin->ws, &udp_plugin_select, plugin);
2144 1656
2145 /* Collecting broadcast addresses */
2146 if (broadcast_addr != NULL)
2147 {
2148 struct BroadcastAddress *ba =
2149 GNUNET_malloc (sizeof (struct BroadcastAddress));
2150 ba->addr = GNUNET_malloc (addrlen);
2151 memcpy (ba->addr, broadcast_addr, addrlen);
2152 ba->addrlen = addrlen;
2153 GNUNET_CONTAINER_DLL_insert (plugin->ipv4_broadcast_head,
2154 plugin->ipv4_broadcast_tail, ba);
2155 }
2156 }
2157 return GNUNET_OK;
2158} 1657}
2159 1658
2160 1659
2161/** 1660static int
2162 * The exported method. Makes the core api available via a global and 1661setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct sockaddr_in *serverAddrv4)
2163 * returns the udp transport API.
2164 *
2165 * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
2166 * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
2167 */
2168void *
2169libgnunet_plugin_transport_udp_init (void *cls)
2170{ 1662{
2171 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; 1663 int tries;
2172 unsigned long long port; 1664 int sockets_created = 0;
2173 unsigned long long aport;
2174 struct GNUNET_TRANSPORT_PluginFunctions *api;
2175 struct Plugin *plugin;
2176 int sockets_created;
2177 int broadcast;
2178 struct GNUNET_TIME_Relative interval;
2179 struct sockaddr_in serverAddrv4;
2180 struct sockaddr_in6 serverAddrv6;
2181 struct sockaddr *serverAddr; 1665 struct sockaddr *serverAddr;
2182 struct sockaddr *addrs[2]; 1666 struct sockaddr *addrs[2];
2183 socklen_t addrlens[2]; 1667 socklen_t addrlens[2];
2184 socklen_t addrlen; 1668 socklen_t addrlen;
2185 unsigned int tries;
2186 unsigned long long udp_max_bps;
2187
2188 if (GNUNET_OK !=
2189 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT",
2190 &port))
2191 port = 2086;
2192
2193 broadcast =
2194 GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp",
2195 "BROADCAST");
2196 if (broadcast == GNUNET_SYSERR)
2197 broadcast = GNUNET_NO;
2198
2199 if (GNUNET_SYSERR ==
2200 GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-udp",
2201 "BROADCAST_INTERVAL", &interval))
2202 interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
2203
2204 if (GNUNET_OK !=
2205 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
2206 "MAX_BPS", &udp_max_bps))
2207 udp_max_bps = 1024 * 1024 * 50; /* 50 MB/s == infinity for practical purposes */
2208 if (GNUNET_OK !=
2209 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
2210 "ADVERTISED_PORT", &aport))
2211 aport = port;
2212 if (port > 65535)
2213 {
2214 LOG (GNUNET_ERROR_TYPE_WARNING,
2215 _("Given `%s' option is out of range: %llu > %u\n"), "PORT", port,
2216 65535);
2217 return NULL;
2218 }
2219 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
2220 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
2221
2222 plugin = GNUNET_malloc (sizeof (struct Plugin));
2223 GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
2224 GNUNET_BANDWIDTH_value_init ((uint32_t)
2225 udp_max_bps), 30);
2226 plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
2227 plugin->port = port;
2228 plugin->aport = aport;
2229 plugin->env = env;
2230 plugin->broadcast_interval = interval;
2231 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2232 api->cls = plugin;
2233
2234 api->send = &udp_plugin_send_old;
2235 api->disconnect = &udp_disconnect;
2236 api->address_pretty_printer = &udp_plugin_address_pretty_printer;
2237 api->address_to_string = &udp_address_to_string;
2238 api->check_address = &udp_plugin_check_address;
2239
2240 api->get_session = &udp_plugin_get_session;
2241 api->send_with_session = &udp_plugin_send;
2242
2243 if (GNUNET_YES ==
2244 GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
2245 "BINDTO", &plugin->bind4_address))
2246 {
2247 LOG (GNUNET_ERROR_TYPE_DEBUG,
2248 "Binding udp plugin to specific address: `%s'\n",
2249 plugin->bind4_address);
2250 if (1 != inet_pton (AF_INET, plugin->bind4_address, &serverAddrv4.sin_addr))
2251 {
2252 GNUNET_free (plugin->bind4_address);
2253 GNUNET_free (plugin);
2254 GNUNET_free (api);
2255 return NULL;
2256 }
2257 }
2258
2259 if (GNUNET_YES ==
2260 GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
2261 "BINDTO6", &plugin->bind6_address))
2262 {
2263 LOG (GNUNET_ERROR_TYPE_DEBUG,
2264 "Binding udp plugin to specific address: `%s'\n",
2265 plugin->bind6_address);
2266 if (1 !=
2267 inet_pton (AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
2268 {
2269 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid IPv6 address: `%s'\n"),
2270 plugin->bind6_address);
2271 GNUNET_free_non_null (plugin->bind4_address);
2272 GNUNET_free (plugin->bind6_address);
2273 GNUNET_free (plugin);
2274 GNUNET_free (api);
2275 return NULL;
2276 }
2277 }
2278 1669
2279 plugin->defrags = 1670 /* Create IPv6 socket */
2280 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 1671 if (plugin->enable_ipv6 == GNUNET_YES)
2281 plugin->sessions =
2282 GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
2283 * 2);
2284 plugin->inbound_sessions =
2285 GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
2286 * 2);
2287 sockets_created = 0;
2288 if ((GNUNET_YES !=
2289 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "nat",
2290 "DISABLEV6")))
2291 { 1672 {
2292 plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0); 1673 plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
2293 if (NULL == plugin->sockv6) 1674 if (NULL == plugin->sockv6)
@@ -2299,24 +1680,24 @@ libgnunet_plugin_transport_udp_init (void *cls)
2299#if HAVE_SOCKADDR_IN_SIN_LEN 1680#if HAVE_SOCKADDR_IN_SIN_LEN
2300 serverAddrv6.sin6_len = sizeof (serverAddrv6); 1681 serverAddrv6.sin6_len = sizeof (serverAddrv6);
2301#endif 1682#endif
2302 serverAddrv6.sin6_family = AF_INET6; 1683 serverAddrv6->sin6_family = AF_INET6;
2303 serverAddrv6.sin6_addr = in6addr_any; 1684 serverAddrv6->sin6_addr = in6addr_any;
2304 serverAddrv6.sin6_port = htons (plugin->port); 1685 serverAddrv6->sin6_port = htons (plugin->port);
2305 addrlen = sizeof (serverAddrv6); 1686 addrlen = sizeof (struct sockaddr_in6);
2306 serverAddr = (struct sockaddr *) &serverAddrv6; 1687 serverAddr = (struct sockaddr *) serverAddrv6;
2307#if DEBUG_UDP 1688#if DEBUG_UDP
2308 LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 port %d\n", 1689 LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 port %d\n",
2309 ntohs (serverAddrv6.sin6_port)); 1690 ntohs (serverAddrv6->sin6_port));
2310#endif 1691#endif
2311 tries = 0; 1692 tries = 0;
2312 while (GNUNET_NETWORK_socket_bind (plugin->sockv6, serverAddr, addrlen) != 1693 while (GNUNET_NETWORK_socket_bind (plugin->sockv6, serverAddr, addrlen) !=
2313 GNUNET_OK) 1694 GNUNET_OK)
2314 { 1695 {
2315 serverAddrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */ 1696 serverAddrv6->sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
2316#if DEBUG_UDP 1697#if DEBUG_UDP
2317 LOG (GNUNET_ERROR_TYPE_DEBUG, 1698 LOG (GNUNET_ERROR_TYPE_DEBUG,
2318 "IPv6 Binding failed, trying new port %d\n", 1699 "IPv6 Binding failed, trying new port %d\n",
2319 ntohs (serverAddrv6.sin6_port)); 1700 ntohs (serverAddrv6->sin6_port));
2320#endif 1701#endif
2321 tries++; 1702 tries++;
2322 if (tries > 10) 1703 if (tries > 10)
@@ -2328,15 +1709,19 @@ libgnunet_plugin_transport_udp_init (void *cls)
2328 } 1709 }
2329 if (plugin->sockv6 != NULL) 1710 if (plugin->sockv6 != NULL)
2330 { 1711 {
2331 addrs[sockets_created] = (struct sockaddr *) &serverAddrv6; 1712#if DEBUG_UDP
2332 addrlens[sockets_created] = sizeof (serverAddrv6); 1713 LOG (GNUNET_ERROR_TYPE_DEBUG,
1714 "IPv6 socket created on port %d\n",
1715 ntohs (serverAddrv6->sin6_port));
1716#endif
1717 addrs[sockets_created] = (struct sockaddr *) serverAddrv6;
1718 addrlens[sockets_created] = sizeof (struct sockaddr_in6);
2333 sockets_created++; 1719 sockets_created++;
2334 } 1720 }
2335 } 1721 }
2336 } 1722 }
2337 1723
2338 plugin->mst = 1724 /* Create IPv4 socket */
2339 GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, plugin);
2340 plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0); 1725 plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
2341 if (NULL == plugin->sockv4) 1726 if (NULL == plugin->sockv4)
2342 { 1727 {
@@ -2347,23 +1732,24 @@ libgnunet_plugin_transport_udp_init (void *cls)
2347#if HAVE_SOCKADDR_IN_SIN_LEN 1732#if HAVE_SOCKADDR_IN_SIN_LEN
2348 serverAddrv4.sin_len = sizeof (serverAddrv4); 1733 serverAddrv4.sin_len = sizeof (serverAddrv4);
2349#endif 1734#endif
2350 serverAddrv4.sin_family = AF_INET; 1735 serverAddrv4->sin_family = AF_INET;
2351 serverAddrv4.sin_addr.s_addr = INADDR_ANY; 1736 serverAddrv4->sin_addr.s_addr = INADDR_ANY;
2352 serverAddrv4.sin_port = htons (plugin->port); 1737 serverAddrv4->sin_port = htons (plugin->port);
2353 addrlen = sizeof (serverAddrv4); 1738 addrlen = sizeof (struct sockaddr_in);
2354 serverAddr = (struct sockaddr *) &serverAddrv4; 1739 serverAddr = (struct sockaddr *) serverAddrv4;
1740
2355#if DEBUG_UDP 1741#if DEBUG_UDP
2356 LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 port %d\n", 1742 LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 port %d\n",
2357 ntohs (serverAddrv4.sin_port)); 1743 ntohs (serverAddrv4->sin_port));
2358#endif 1744#endif
2359 tries = 0; 1745 tries = 0;
2360 while (GNUNET_NETWORK_socket_bind (plugin->sockv4, serverAddr, addrlen) != 1746 while (GNUNET_NETWORK_socket_bind (plugin->sockv4, serverAddr, addrlen) !=
2361 GNUNET_OK) 1747 GNUNET_OK)
2362 { 1748 {
2363 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */ 1749 serverAddrv4->sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
2364#if DEBUG_UDP 1750#if DEBUG_UDP
2365 LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Binding failed, trying new port %d\n", 1751 LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Binding failed, trying new port %d\n",
2366 ntohs (serverAddrv4.sin_port)); 1752 ntohs (serverAddrv4->sin_port));
2367#endif 1753#endif
2368 tries++; 1754 tries++;
2369 if (tries > 10) 1755 if (tries > 10)
@@ -2375,210 +1761,242 @@ libgnunet_plugin_transport_udp_init (void *cls)
2375 } 1761 }
2376 if (plugin->sockv4 != NULL) 1762 if (plugin->sockv4 != NULL)
2377 { 1763 {
2378 addrs[sockets_created] = (struct sockaddr *) &serverAddrv4; 1764 addrs[sockets_created] = (struct sockaddr *) serverAddrv4;
2379 addrlens[sockets_created] = sizeof (serverAddrv4); 1765 addrlens[sockets_created] = sizeof (struct sockaddr_in);
2380 sockets_created++; 1766 sockets_created++;
2381 } 1767 }
2382 } 1768 }
2383 1769
1770 /* Create file descriptors */
2384 plugin->rs = GNUNET_NETWORK_fdset_create (); 1771 plugin->rs = GNUNET_NETWORK_fdset_create ();
1772 plugin->ws = GNUNET_NETWORK_fdset_create ();
2385 GNUNET_NETWORK_fdset_zero (plugin->rs); 1773 GNUNET_NETWORK_fdset_zero (plugin->rs);
1774 GNUNET_NETWORK_fdset_zero (plugin->ws);
2386 if (NULL != plugin->sockv4) 1775 if (NULL != plugin->sockv4)
1776 {
2387 GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv4); 1777 GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv4);
1778 GNUNET_NETWORK_fdset_set (plugin->ws, plugin->sockv4);
1779 }
2388 if (NULL != plugin->sockv6) 1780 if (NULL != plugin->sockv6)
1781 {
2389 GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv6); 1782 GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv6);
1783 GNUNET_NETWORK_fdset_set (plugin->ws, plugin->sockv6);
1784 }
1785
1786 if (sockets_created == 0)
1787 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
2390 1788
2391 plugin->select_task = 1789 plugin->select_task =
2392 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 1790 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2393 GNUNET_SCHEDULER_NO_TASK, 1791 GNUNET_SCHEDULER_NO_TASK,
2394 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, 1792 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
2395 NULL, &udp_plugin_select, plugin); 1793 plugin->ws, &udp_plugin_select, plugin);
2396
2397
2398
2399 if (broadcast)
2400 {
2401 /* create IPv4 broadcast socket */
2402 plugin->broadcast_ipv4 = GNUNET_NO;
2403 if (plugin->sockv4 != NULL)
2404 {
2405 int yes = 1;
2406 1794
2407 if (GNUNET_NETWORK_socket_setsockopt 1795 plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
2408 (plugin->sockv4, SOL_SOCKET, SO_BROADCAST, &yes, 1796 GNUNET_NO, plugin->port,
2409 sizeof (int)) != GNUNET_OK) 1797 sockets_created,
2410 {
2411 LOG (GNUNET_ERROR_TYPE_WARNING,
2412 _
2413 ("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"),
2414 ntohs (serverAddrv4.sin_port));
2415 }
2416 else
2417 {
2418 GNUNET_OS_network_interfaces_list (iface_proc, plugin);
2419 plugin->send_ipv4_broadcast_task =
2420 GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, plugin);
2421
2422 plugin->broadcast_ipv4_mst =
2423 GNUNET_SERVER_mst_create (broadcast_ipv4_mst_cb, plugin);
2424
2425 LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Broadcasting running\n");
2426 plugin->broadcast_ipv4 = GNUNET_YES;
2427 }
2428 }
2429
2430 plugin->broadcast_ipv6 = GNUNET_NO;
2431 if (plugin->sockv6 != NULL)
2432 {
2433 memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6));
2434 GNUNET_assert (1 ==
2435 inet_pton (AF_INET6, "FF05::13B",
2436 &plugin->ipv6_multicast_address.sin6_addr));
2437
2438 plugin->ipv6_multicast_address.sin6_family = AF_INET6;
2439 plugin->ipv6_multicast_address.sin6_port = htons (plugin->port);
2440
2441 plugin->broadcast_ipv6_mst =
2442 GNUNET_SERVER_mst_create (broadcast_ipv6_mst_cb, plugin);
2443
2444 /* Create IPv6 multicast request */
2445 struct ipv6_mreq multicastRequest;
2446
2447 multicastRequest.ipv6mr_multiaddr =
2448 plugin->ipv6_multicast_address.sin6_addr;
2449 /* TODO: 0 selects the "best" interface, tweak to use all interfaces
2450 *
2451 * http://tools.ietf.org/html/rfc2553#section-5.2:
2452 *
2453 * IPV6_JOIN_GROUP
2454 *
2455 * Join a multicast group on a specified local interface. If the
2456 * interface index is specified as 0, the kernel chooses the local
2457 * interface. For example, some kernels look up the multicast
2458 * group in the normal IPv6 routing table and using the resulting
2459 * interface.
2460 * */
2461 multicastRequest.ipv6mr_interface = 0;
2462
2463 /* Join the multicast group */
2464 if (GNUNET_NETWORK_socket_setsockopt
2465 (plugin->sockv6, IPPROTO_IPV6, IPV6_JOIN_GROUP,
2466 (char *) &multicastRequest, sizeof (multicastRequest)) != GNUNET_OK)
2467 {
2468 LOG (GNUNET_ERROR_TYPE_WARNING,
2469 "Failed to join IPv6 multicast group: IPv6 broadcasting not running\n");
2470 }
2471 else
2472 {
2473#if DEBUG_UDP
2474 LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 broadcasting running\n");
2475#endif
2476 plugin->send_ipv6_broadcast_task =
2477 GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, plugin);
2478 plugin->broadcast_ipv6 = GNUNET_YES;
2479 }
2480 }
2481 }
2482
2483 if (sockets_created == 0)
2484 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
2485 plugin->nat =
2486 GNUNET_NAT_register (env->cfg, GNUNET_NO, port, sockets_created,
2487 (const struct sockaddr **) addrs, addrlens, 1798 (const struct sockaddr **) addrs, addrlens,
2488 &udp_nat_port_map_callback, NULL, plugin); 1799 &udp_nat_port_map_callback, NULL, plugin);
2489 return api; 1800
1801 return sockets_created;
2490} 1802}
2491 1803
1804
2492/** 1805/**
2493 * Shutdown the plugin. 1806 * The exported method. Makes the core api available via a global and
1807 * returns the udp transport API.
2494 * 1808 *
2495 * @param cls our 'struct GNUNET_TRANSPORT_PluginFunctions' 1809 * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
2496 * @return NULL 1810 * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
2497 */ 1811 */
2498void * 1812void *
2499libgnunet_plugin_transport_udp_done (void *cls) 1813libgnunet_plugin_transport_udp_init (void *cls)
2500{ 1814{
2501 struct GNUNET_TRANSPORT_PluginFunctions *api = cls; 1815 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2502 struct Plugin *plugin = api->cls; 1816 struct GNUNET_TRANSPORT_PluginFunctions *api;
2503 struct ReceiveContext *rc; 1817 struct Plugin *plugin;
2504 1818
2505 /* FIXME: clean up heap and hashmap */ 1819 unsigned long long port;
2506 GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &destroy_session, 1820 unsigned long long aport;
2507 NULL); 1821 unsigned long long broadcast;
2508 GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions); 1822 unsigned long long udp_max_bps;
2509 plugin->sessions = NULL; 1823 unsigned long long enable_v6;
2510 GNUNET_CONTAINER_multihashmap_iterate (plugin->inbound_sessions, 1824 char * bind4_address;
2511 &destroy_inbound_session, NULL); 1825 char * bind6_address;
2512 GNUNET_CONTAINER_multihashmap_destroy (plugin->inbound_sessions); 1826 struct GNUNET_TIME_Relative interval;
2513 plugin->inbound_sessions = NULL; 1827
2514 while (NULL != (rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags))) 1828 struct sockaddr_in serverAddrv4;
1829 struct sockaddr_in6 serverAddrv6;
1830
1831 int res;
1832
1833 /* Get port number */
1834 if (GNUNET_OK !=
1835 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT",
1836 &port))
1837 port = 2086;
1838 if (GNUNET_OK !=
1839 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
1840 "ADVERTISED_PORT", &aport))
1841 aport = port;
1842 if (port > 65535)
2515 { 1843 {
2516 GNUNET_DEFRAGMENT_context_destroy (rc->defrag); 1844 LOG (GNUNET_ERROR_TYPE_WARNING,
2517 GNUNET_free (rc); 1845 _("Given `%s' option is out of range: %llu > %u\n"), "PORT", port,
1846 65535);
1847 return NULL;
2518 } 1848 }
2519 GNUNET_CONTAINER_heap_destroy (plugin->defrags);
2520 1849
2521 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK) 1850 /* Protocols */
1851 if ((GNUNET_YES ==
1852 GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "nat",
1853 "DISABLEV6")))
2522 { 1854 {
2523 GNUNET_SCHEDULER_cancel (plugin->select_task); 1855 enable_v6 = GNUNET_NO;
2524 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
2525 } 1856 }
1857 else
1858 enable_v6 = GNUNET_YES;
1859
1860
1861 /* Addresses */
1862 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1863 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
2526 1864
2527 if (plugin->broadcast_ipv4) 1865 if (GNUNET_YES ==
1866 GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
1867 "BINDTO", &bind4_address))
2528 { 1868 {
2529 if (plugin->send_ipv4_broadcast_task != GNUNET_SCHEDULER_NO_TASK) 1869 LOG (GNUNET_ERROR_TYPE_DEBUG,
1870 "Binding udp plugin to specific address: `%s'\n",
1871 bind4_address);
1872 if (1 != inet_pton (AF_INET, bind4_address, &serverAddrv4.sin_addr))
2530 { 1873 {
2531 GNUNET_SCHEDULER_cancel (plugin->send_ipv4_broadcast_task); 1874 GNUNET_free (bind4_address);
2532 plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK; 1875 return NULL;
2533 } 1876 }
1877 }
2534 1878
2535 if (plugin->broadcast_ipv4_mst != NULL) 1879 if (GNUNET_YES ==
2536 GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst); 1880 GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
2537 1881 "BINDTO6", &bind6_address))
2538 while (plugin->ipv4_broadcast_head != NULL) 1882 {
1883 LOG (GNUNET_ERROR_TYPE_DEBUG,
1884 "Binding udp plugin to specific address: `%s'\n",
1885 bind6_address);
1886 if (1 !=
1887 inet_pton (AF_INET6, bind6_address, &serverAddrv6.sin6_addr))
2539 { 1888 {
2540 struct BroadcastAddress *p = plugin->ipv4_broadcast_head; 1889 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid IPv6 address: `%s'\n"),
2541 1890 bind6_address);
2542 GNUNET_CONTAINER_DLL_remove (plugin->ipv4_broadcast_head, 1891 GNUNET_free_non_null (bind4_address);
2543 plugin->ipv4_broadcast_tail, p); 1892 GNUNET_free (bind6_address);
2544 GNUNET_free (p->addr); 1893 return NULL;
2545 GNUNET_free (p);
2546 } 1894 }
2547 } 1895 }
2548 1896
2549 if (plugin->broadcast_ipv6) 1897
1898 /* Enable neighbour discovery */
1899 broadcast = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp",
1900 "BROADCAST");
1901 if (broadcast == GNUNET_SYSERR)
1902 broadcast = GNUNET_NO;
1903
1904 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-udp",
1905 "BROADCAST_INTERVAL", &interval))
2550 { 1906 {
2551 /* Create IPv6 multicast request */ 1907 interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
2552 struct ipv6_mreq multicastRequest; 1908 }
2553 1909
2554 multicastRequest.ipv6mr_multiaddr = 1910 /* Maximum datarate */
2555 plugin->ipv6_multicast_address.sin6_addr; 1911 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
2556 multicastRequest.ipv6mr_interface = 0; 1912 "MAX_BPS", &udp_max_bps))
1913 {
1914 udp_max_bps = 1024 * 1024 * 50; /* 50 MB/s == infinity for practical purposes */
1915 }
2557 1916
2558 /* Join the multicast address */ 1917 plugin = GNUNET_malloc (sizeof (struct Plugin));
2559 if (GNUNET_NETWORK_socket_setsockopt 1918 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2560 (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
2561 (char *) &multicastRequest, sizeof (multicastRequest)) != GNUNET_OK)
2562 {
2563 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, setsockopt);
2564 }
2565 else
2566 {
2567#if DEBUG_UDP
2568 LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 Broadcasting stopped\n");
2569#endif
2570 }
2571 1919
2572 if (plugin->send_ipv6_broadcast_task != GNUNET_SCHEDULER_NO_TASK) 1920 GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
2573 { 1921 GNUNET_BANDWIDTH_value_init ((uint32_t)udp_max_bps), 30);
2574 GNUNET_SCHEDULER_cancel (plugin->send_ipv6_broadcast_task); 1922
2575 plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK; 1923
2576 } 1924 plugin->sessions = GNUNET_CONTAINER_multihashmap_create (10);
2577 if (plugin->broadcast_ipv6_mst != NULL) 1925 plugin->defrag_ctxs = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2578 GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst); 1926 plugin->mst = GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, plugin);
1927 plugin->port = port;
1928 plugin->aport = aport;
1929 plugin->broadcast_interval = interval;
1930 plugin->enable_ipv6 = enable_v6;
1931 plugin->env = env;
1932
1933 api->cls = plugin;
1934 api->send = NULL;
1935 api->disconnect = &udp_disconnect;
1936 api->address_pretty_printer = &udp_plugin_address_pretty_printer;
1937 api->address_to_string = &udp_address_to_string;
1938 api->check_address = &udp_plugin_check_address;
1939 api->get_session = &udp_plugin_get_session;
1940 api->send = &udp_plugin_send_wrapper;
1941 api->send_with_session = &udp_plugin_send;
1942
1943 LOG (GNUNET_ERROR_TYPE_DEBUG, "Setting up sockets\n");
1944 res = setup_sockets (plugin, &serverAddrv6, &serverAddrv4);
1945 if ((res == 0) || ((plugin->sockv4 == NULL) && (plugin->sockv6 == NULL)))
1946 {
1947 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to create network sockets, plugin failed\n");
1948 GNUNET_free (plugin);
1949 GNUNET_free (api);
1950 return NULL;
2579 } 1951 }
2580 1952
1953 LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting broadcasting\n");
1954 if (broadcast == GNUNET_YES)
1955 setup_broadcast (plugin, &serverAddrv6, &serverAddrv4);
1956
1957
1958 GNUNET_free_non_null (bind4_address);
1959 GNUNET_free_non_null (bind6_address);
1960 return api;
1961}
1962
1963int heap_cleanup_iterator (void *cls,
1964 struct GNUNET_CONTAINER_HeapNode *
1965 node, void *element,
1966 GNUNET_CONTAINER_HeapCostType
1967 cost)
1968{
1969 struct DefragContext * d_ctx = element;
1970
1971 GNUNET_CONTAINER_heap_remove_node (node);
1972 GNUNET_DEFRAGMENT_context_destroy(d_ctx->defrag);
1973 GNUNET_free (d_ctx);
1974
1975 return GNUNET_YES;
1976}
1977
2581 1978
1979/**
1980 * The exported method. Makes the core api available via a global and
1981 * returns the udp transport API.
1982 *
1983 * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
1984 * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
1985 */
1986void *
1987libgnunet_plugin_transport_udp_done (void *cls)
1988{
1989 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1990 struct Plugin *plugin = api->cls;
1991 stop_broadcast (plugin);
1992
1993 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
1994 {
1995 GNUNET_SCHEDULER_cancel (plugin->select_task);
1996 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1997 }
1998
1999 /* Closing sockets */
2582 if (plugin->sockv4 != NULL) 2000 if (plugin->sockv4 != NULL)
2583 { 2001 {
2584 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4)); 2002 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4));
@@ -2589,15 +2007,48 @@ libgnunet_plugin_transport_udp_done (void *cls)
2589 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6)); 2007 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6));
2590 plugin->sockv6 = NULL; 2008 plugin->sockv6 = NULL;
2591 } 2009 }
2592
2593 GNUNET_SERVER_mst_destroy (plugin->mst);
2594 GNUNET_NETWORK_fdset_destroy (plugin->rs); 2010 GNUNET_NETWORK_fdset_destroy (plugin->rs);
2595 2011 GNUNET_NETWORK_fdset_destroy (plugin->ws);
2596 GNUNET_NAT_unregister (plugin->nat); 2012 GNUNET_NAT_unregister (plugin->nat);
2013
2014 if (plugin->defrag_ctxs != NULL)
2015 {
2016 GNUNET_CONTAINER_heap_iterate(plugin->defrag_ctxs,
2017 heap_cleanup_iterator, NULL);
2018 GNUNET_CONTAINER_heap_destroy(plugin->defrag_ctxs);
2019 plugin->defrag_ctxs = NULL;
2020 }
2021 if (plugin->mst != NULL)
2022 {
2023 GNUNET_SERVER_mst_destroy(plugin->mst);
2024 plugin->mst = NULL;
2025 }
2026
2027 /* Clean up leftover messages */
2028 struct UDPMessageWrapper *udpw = plugin->msg_head;
2029 while (udpw != NULL)
2030 {
2031 struct UDPMessageWrapper *tmp = udpw->next;
2032 GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
2033 if (udpw->cont != NULL)
2034 udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
2035 GNUNET_free (udpw);
2036 udpw = tmp;
2037 }
2038
2039 /* Clean up sessions */
2040#if DEBUG_UDP
2041 LOG (GNUNET_ERROR_TYPE_DEBUG,
2042 "Cleaning up sessions\n");
2043#endif
2044 GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &disconnect_and_free_it, plugin);
2045 GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
2046
2597 plugin->nat = NULL; 2047 plugin->nat = NULL;
2598 GNUNET_free (plugin); 2048 GNUNET_free (plugin);
2599 GNUNET_free (api); 2049 GNUNET_free (api);
2600 return NULL; 2050 return NULL;
2601} 2051}
2602 2052
2053
2603/* end of plugin_transport_udp.c */ 2054/* end of plugin_transport_udp.c */
diff --git a/src/transport/plugin_transport_udp_new.h b/src/transport/plugin_transport_udp.h
index d3eb192a1..d3eb192a1 100644
--- a/src/transport/plugin_transport_udp_new.h
+++ b/src/transport/plugin_transport_udp.h
diff --git a/src/transport/plugin_transport_udp_new_broadcasting.c b/src/transport/plugin_transport_udp_broadcasting.c
index 3c2d82675..e33af26be 100644
--- a/src/transport/plugin_transport_udp_new_broadcasting.c
+++ b/src/transport/plugin_transport_udp_broadcasting.c
@@ -25,7 +25,7 @@
25 * @author Matthias Wachs 25 * @author Matthias Wachs
26 */ 26 */
27#include "platform.h" 27#include "platform.h"
28#include "plugin_transport_udp_new.h" 28#include "plugin_transport_udp.h"
29#include "gnunet_hello_lib.h" 29#include "gnunet_hello_lib.h"
30#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
31#include "gnunet_fragmentation_lib.h" 31#include "gnunet_fragmentation_lib.h"