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