diff options
Diffstat (limited to 'src/transport/plugin_transport_udp.c')
-rw-r--r-- | src/transport/plugin_transport_udp.c | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c new file mode 100644 index 000000000..ccaf9fbd1 --- /dev/null +++ b/src/transport/plugin_transport_udp.c | |||
@@ -0,0 +1,592 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2001, 2002, 2003, 2004, 2005, 2008 Christian Grothoff (and other contributing authors) | ||
4 | |||
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 | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file transports/udp.c | ||
23 | * @brief Implementation of the UDP transport service | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util.h" | ||
29 | #include "gnunet_protocols.h" | ||
30 | #include "gnunet_transport.h" | ||
31 | #include "gnunet_stats_service.h" | ||
32 | #include "gnunet_upnp_service.h" | ||
33 | #include "ip.h" | ||
34 | |||
35 | #define DEBUG_UDP GNUNET_YES | ||
36 | |||
37 | /** | ||
38 | * The default maximum size of each outbound UDP message, | ||
39 | * optimal value for Ethernet (10 or 100 MBit). | ||
40 | */ | ||
41 | #define MESSAGE_SIZE 1472 | ||
42 | |||
43 | /** | ||
44 | * Message-Packet header. | ||
45 | */ | ||
46 | typedef struct | ||
47 | { | ||
48 | /** | ||
49 | * size of the message, in bytes, including this header. | ||
50 | */ | ||
51 | GNUNET_MessageHeader header; | ||
52 | |||
53 | /** | ||
54 | * What is the identity of the sender (GNUNET_hash of public key) | ||
55 | */ | ||
56 | GNUNET_PeerIdentity sender; | ||
57 | |||
58 | } UDPMessage; | ||
59 | |||
60 | #define MY_TRANSPORT_NAME "UDP" | ||
61 | #include "common.c" | ||
62 | |||
63 | /* *********** globals ************* */ | ||
64 | |||
65 | static int stat_bytesReceived; | ||
66 | |||
67 | static int stat_bytesSent; | ||
68 | |||
69 | static int stat_bytesDropped; | ||
70 | |||
71 | static int stat_udpConnected; | ||
72 | |||
73 | /** | ||
74 | * thread that listens for inbound messages | ||
75 | */ | ||
76 | static struct GNUNET_SelectHandle *selector; | ||
77 | |||
78 | /** | ||
79 | * the socket that we transmit all data with | ||
80 | */ | ||
81 | static struct GNUNET_SocketHandle *udp_sock; | ||
82 | |||
83 | static struct GNUNET_LoadMonitor *load_monitor; | ||
84 | |||
85 | |||
86 | /** | ||
87 | * The socket of session has data waiting, process! | ||
88 | * | ||
89 | * This function may only be called if the tcplock is | ||
90 | * already held by the caller. | ||
91 | */ | ||
92 | static int | ||
93 | select_message_handler (void *mh_cls, | ||
94 | struct GNUNET_SelectHandle *sh, | ||
95 | struct GNUNET_SocketHandle *sock, | ||
96 | void *sock_ctx, const GNUNET_MessageHeader * msg) | ||
97 | { | ||
98 | unsigned int len; | ||
99 | GNUNET_TransportPacket *mp; | ||
100 | const UDPMessage *um; | ||
101 | |||
102 | len = ntohs (msg->size); | ||
103 | if (len <= sizeof (UDPMessage)) | ||
104 | { | ||
105 | GNUNET_GE_LOG (coreAPI->ectx, | ||
106 | GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, | ||
107 | _("Received malformed message via %s. Ignored.\n"), | ||
108 | "UDP"); | ||
109 | return GNUNET_SYSERR; | ||
110 | } | ||
111 | um = (const UDPMessage *) msg; | ||
112 | mp = GNUNET_malloc (sizeof (GNUNET_TransportPacket)); | ||
113 | mp->msg = GNUNET_malloc (len - sizeof (UDPMessage)); | ||
114 | memcpy (mp->msg, &um[1], len - sizeof (UDPMessage)); | ||
115 | mp->sender = um->sender; | ||
116 | mp->size = len - sizeof (UDPMessage); | ||
117 | mp->tsession = NULL; | ||
118 | coreAPI->receive (mp); | ||
119 | if (stats != NULL) | ||
120 | stats->change (stat_bytesReceived, len); | ||
121 | return GNUNET_OK; | ||
122 | } | ||
123 | |||
124 | static void * | ||
125 | select_accept_handler (void *ah_cls, | ||
126 | struct GNUNET_SelectHandle *sh, | ||
127 | struct GNUNET_SocketHandle *sock, | ||
128 | const void *addr, unsigned int addr_len) | ||
129 | { | ||
130 | static int nonnullpointer; | ||
131 | |||
132 | if (GNUNET_NO != is_rejected_tester (addr, addr_len)) | ||
133 | return NULL; | ||
134 | return &nonnullpointer; | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * Select has been forced to close a connection. | ||
139 | * Free the associated context. | ||
140 | */ | ||
141 | static void | ||
142 | select_close_handler (void *ch_cls, | ||
143 | struct GNUNET_SelectHandle *sh, | ||
144 | struct GNUNET_SocketHandle *sock, void *sock_ctx) | ||
145 | { | ||
146 | /* do nothing */ | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * Establish a connection to a remote node. | ||
151 | * | ||
152 | * @param hello the hello-Message for the target node | ||
153 | * @param tsessionPtr the session handle that is to be set | ||
154 | * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed | ||
155 | */ | ||
156 | static int | ||
157 | udp_connect (const GNUNET_MessageHello * hello, | ||
158 | GNUNET_TSession ** tsessionPtr, int may_reuse) | ||
159 | { | ||
160 | GNUNET_TSession *tsession; | ||
161 | |||
162 | tsession = GNUNET_malloc (sizeof (GNUNET_TSession)); | ||
163 | memset (tsession, 0, sizeof (GNUNET_TSession)); | ||
164 | tsession->internal = GNUNET_malloc (GNUNET_sizeof_hello (hello)); | ||
165 | memcpy (tsession->internal, hello, GNUNET_sizeof_hello (hello)); | ||
166 | tsession->ttype = myAPI.protocol_number; | ||
167 | tsession->peer = hello->senderIdentity; | ||
168 | *tsessionPtr = tsession; | ||
169 | if (stats != NULL) | ||
170 | stats->change (stat_udpConnected, 1); | ||
171 | return GNUNET_OK; | ||
172 | } | ||
173 | |||
174 | /** | ||
175 | * A (core) Session is to be associated with a transport session. The | ||
176 | * transport service may want to know in order to call back on the | ||
177 | * core if the connection is being closed. | ||
178 | * | ||
179 | * @param tsession the session handle passed along | ||
180 | * from the call to receive that was made by the transport | ||
181 | * layer | ||
182 | * @return GNUNET_OK if the session could be associated, | ||
183 | * GNUNET_SYSERR if not. | ||
184 | */ | ||
185 | int | ||
186 | udp_associate (GNUNET_TSession * tsession) | ||
187 | { | ||
188 | return GNUNET_SYSERR; /* UDP connections can never be associated */ | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * Disconnect from a remote node. | ||
193 | * | ||
194 | * @param tsession the session that is closed | ||
195 | * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed | ||
196 | */ | ||
197 | static int | ||
198 | udp_disconnect (GNUNET_TSession * tsession) | ||
199 | { | ||
200 | if (tsession != NULL) | ||
201 | { | ||
202 | if (tsession->internal != NULL) | ||
203 | GNUNET_free (tsession->internal); | ||
204 | GNUNET_free (tsession); | ||
205 | if (stats != NULL) | ||
206 | stats->change (stat_udpConnected, -1); | ||
207 | } | ||
208 | return GNUNET_OK; | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * Shutdown the server process (stop receiving inbound traffic). Maybe | ||
213 | * restarted later! | ||
214 | */ | ||
215 | static int | ||
216 | udp_transport_server_stop () | ||
217 | { | ||
218 | GNUNET_GE_ASSERT (coreAPI->ectx, udp_sock != NULL); | ||
219 | if (selector != NULL) | ||
220 | { | ||
221 | GNUNET_select_destroy (selector); | ||
222 | selector = NULL; | ||
223 | } | ||
224 | GNUNET_socket_destroy (udp_sock); | ||
225 | udp_sock = NULL; | ||
226 | return GNUNET_OK; | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * Test if the transport would even try to send | ||
231 | * a message of the given size and importance | ||
232 | * for the given session.<br> | ||
233 | * This function is used to check if the core should | ||
234 | * even bother to construct (and encrypt) this kind | ||
235 | * of message. | ||
236 | * | ||
237 | * @return GNUNET_YES if the transport would try (i.e. queue | ||
238 | * the message or call the OS to send), | ||
239 | * GNUNET_NO if the transport would just drop the message, | ||
240 | * GNUNET_SYSERR if the size/session is invalid | ||
241 | */ | ||
242 | static int | ||
243 | udp_test_would_try (GNUNET_TSession * tsession, unsigned int size, | ||
244 | int important) | ||
245 | { | ||
246 | const GNUNET_MessageHello *hello; | ||
247 | |||
248 | if (udp_sock == NULL) | ||
249 | return GNUNET_SYSERR; | ||
250 | if (size == 0) | ||
251 | { | ||
252 | GNUNET_GE_BREAK (coreAPI->ectx, 0); | ||
253 | return GNUNET_SYSERR; | ||
254 | } | ||
255 | if (size > myAPI.mtu) | ||
256 | { | ||
257 | GNUNET_GE_BREAK (coreAPI->ectx, 0); | ||
258 | return GNUNET_SYSERR; | ||
259 | } | ||
260 | hello = (const GNUNET_MessageHello *) tsession->internal; | ||
261 | if (hello == NULL) | ||
262 | return GNUNET_SYSERR; | ||
263 | return GNUNET_YES; | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * Create a UDP socket. If possible, use IPv6, otherwise | ||
268 | * try IPv4. Update available_protocols accordingly. | ||
269 | */ | ||
270 | static int | ||
271 | udp_create_socket () | ||
272 | { | ||
273 | int s; | ||
274 | |||
275 | available_protocols = VERSION_AVAILABLE_NONE; | ||
276 | s = -1; | ||
277 | if (GNUNET_YES != | ||
278 | GNUNET_GC_get_configuration_value_yesno (cfg, "GNUNETD", "DISABLE-IPV6", | ||
279 | GNUNET_YES)) | ||
280 | { | ||
281 | #ifndef MINGW | ||
282 | s = SOCKET (PF_INET6, SOCK_DGRAM, 17); | ||
283 | #else | ||
284 | s = win_ols_socket (PF_INET6, SOCK_DGRAM, 17); | ||
285 | #endif | ||
286 | } | ||
287 | if (s < 0) | ||
288 | { | ||
289 | #ifndef MINGW | ||
290 | s = SOCKET (PF_INET, SOCK_DGRAM, 17); | ||
291 | #else | ||
292 | s = win_ols_socket (PF_INET, SOCK_DGRAM, 17); | ||
293 | #endif | ||
294 | if (s < 0) | ||
295 | { | ||
296 | GNUNET_GE_LOG_STRERROR (coreAPI->ectx, | ||
297 | GNUNET_GE_ERROR | GNUNET_GE_ADMIN | | ||
298 | GNUNET_GE_BULK, "socket"); | ||
299 | return GNUNET_SYSERR; | ||
300 | } | ||
301 | available_protocols = VERSION_AVAILABLE_IPV4; | ||
302 | } | ||
303 | else | ||
304 | { | ||
305 | available_protocols = VERSION_AVAILABLE_IPV6 | VERSION_AVAILABLE_IPV4; | ||
306 | } | ||
307 | return s; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * Send a message to the specified remote node. | ||
312 | * | ||
313 | * @param tsession the GNUNET_MessageHello identifying the remote node | ||
314 | * @param message what to send | ||
315 | * @param size the size of the message | ||
316 | * @return GNUNET_SYSERR on error, GNUNET_OK on success | ||
317 | */ | ||
318 | static int | ||
319 | udp_send (GNUNET_TSession * tsession, | ||
320 | const void *message, const unsigned int size, int important) | ||
321 | { | ||
322 | const GNUNET_MessageHello *hello; | ||
323 | const HostAddress *haddr; | ||
324 | UDPMessage *mp; | ||
325 | struct sockaddr_in serverAddrv4; | ||
326 | struct sockaddr_in6 serverAddrv6; | ||
327 | struct sockaddr *serverAddr; | ||
328 | socklen_t addrlen; | ||
329 | unsigned short available; | ||
330 | int ok; | ||
331 | int ssize; | ||
332 | size_t sent; | ||
333 | |||
334 | GNUNET_GE_ASSERT (NULL, tsession != NULL); | ||
335 | if (udp_sock == NULL) | ||
336 | return GNUNET_SYSERR; | ||
337 | if (size == 0) | ||
338 | { | ||
339 | GNUNET_GE_BREAK (coreAPI->ectx, 0); | ||
340 | return GNUNET_SYSERR; | ||
341 | } | ||
342 | if (size > myAPI.mtu) | ||
343 | { | ||
344 | GNUNET_GE_BREAK (coreAPI->ectx, 0); | ||
345 | return GNUNET_SYSERR; | ||
346 | } | ||
347 | hello = (const GNUNET_MessageHello *) tsession->internal; | ||
348 | if (hello == NULL) | ||
349 | return GNUNET_SYSERR; | ||
350 | |||
351 | haddr = (const HostAddress *) &hello[1]; | ||
352 | available = ntohs (haddr->availability) & available_protocols; | ||
353 | if (available == VERSION_AVAILABLE_NONE) | ||
354 | return GNUNET_SYSERR; | ||
355 | if (available == (VERSION_AVAILABLE_IPV4 | VERSION_AVAILABLE_IPV6)) | ||
356 | { | ||
357 | if (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 2) == 0) | ||
358 | available = VERSION_AVAILABLE_IPV4; | ||
359 | else | ||
360 | available = VERSION_AVAILABLE_IPV6; | ||
361 | } | ||
362 | ssize = size + sizeof (UDPMessage); | ||
363 | mp = GNUNET_malloc (ssize); | ||
364 | mp->header.size = htons (ssize); | ||
365 | mp->header.type = 0; | ||
366 | mp->sender = *(coreAPI->my_identity); | ||
367 | memcpy (&mp[1], message, size); | ||
368 | ok = GNUNET_SYSERR; | ||
369 | |||
370 | if ((available & VERSION_AVAILABLE_IPV4) > 0) | ||
371 | { | ||
372 | memset (&serverAddrv4, 0, sizeof (serverAddrv4)); | ||
373 | serverAddrv4.sin_family = AF_INET; | ||
374 | serverAddrv4.sin_port = haddr->port; | ||
375 | memcpy (&serverAddrv4.sin_addr, &haddr->ipv4, sizeof (struct in_addr)); | ||
376 | addrlen = sizeof (serverAddrv4); | ||
377 | serverAddr = (struct sockaddr *) &serverAddrv4; | ||
378 | } | ||
379 | else | ||
380 | { | ||
381 | memset (&serverAddrv6, 0, sizeof (serverAddrv6)); | ||
382 | serverAddrv6.sin6_family = AF_INET; | ||
383 | serverAddrv6.sin6_port = haddr->port; | ||
384 | memcpy (&serverAddrv6.sin6_addr, &haddr->ipv6, | ||
385 | sizeof (struct in6_addr)); | ||
386 | addrlen = sizeof (serverAddrv6); | ||
387 | serverAddr = (struct sockaddr *) &serverAddrv6; | ||
388 | } | ||
389 | #ifndef MINGW | ||
390 | if (GNUNET_YES == GNUNET_socket_send_to (udp_sock, | ||
391 | GNUNET_NC_NONBLOCKING, | ||
392 | mp, | ||
393 | ssize, &sent, | ||
394 | (const char *) serverAddr, | ||
395 | addrlen)) | ||
396 | #else | ||
397 | sent = | ||
398 | win_ols_sendto (udp_sock, mp, ssize, (const char *) serverAddr, addrlen); | ||
399 | if (sent != SOCKET_ERROR) | ||
400 | #endif | ||
401 | { | ||
402 | ok = GNUNET_OK; | ||
403 | if (stats != NULL) | ||
404 | stats->change (stat_bytesSent, sent); | ||
405 | } | ||
406 | else | ||
407 | { | ||
408 | if (stats != NULL) | ||
409 | stats->change (stat_bytesDropped, ssize); | ||
410 | } | ||
411 | GNUNET_free (mp); | ||
412 | return ok; | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * Start the server process to receive inbound traffic. | ||
417 | * | ||
418 | * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed | ||
419 | */ | ||
420 | static int | ||
421 | udp_transport_server_start () | ||
422 | { | ||
423 | struct sockaddr_in serverAddrv4; | ||
424 | struct sockaddr_in6 serverAddrv6; | ||
425 | struct sockaddr *serverAddr; | ||
426 | socklen_t addrlen; | ||
427 | int sock; | ||
428 | const int on = 1; | ||
429 | unsigned short port; | ||
430 | |||
431 | GNUNET_GE_ASSERT (coreAPI->ectx, selector == NULL); | ||
432 | /* initialize UDP network */ | ||
433 | port = get_port (); | ||
434 | if (port != 0) | ||
435 | { | ||
436 | sock = udp_create_socket (); | ||
437 | if (sock < 0) | ||
438 | return GNUNET_SYSERR; | ||
439 | if (SETSOCKOPT (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) | ||
440 | { | ||
441 | GNUNET_GE_DIE_STRERROR (coreAPI->ectx, | ||
442 | GNUNET_GE_FATAL | GNUNET_GE_ADMIN | | ||
443 | GNUNET_GE_IMMEDIATE, "setsockopt"); | ||
444 | return GNUNET_SYSERR; | ||
445 | } | ||
446 | if (available_protocols == VERSION_AVAILABLE_IPV4) | ||
447 | { | ||
448 | memset (&serverAddrv4, 0, sizeof (serverAddrv4)); | ||
449 | serverAddrv4.sin_family = AF_INET; | ||
450 | serverAddrv4.sin_addr.s_addr = INADDR_ANY; | ||
451 | serverAddrv4.sin_port = htons (port); | ||
452 | addrlen = sizeof (serverAddrv4); | ||
453 | serverAddr = (struct sockaddr *) &serverAddrv4; | ||
454 | } | ||
455 | else | ||
456 | { | ||
457 | memset (&serverAddrv6, 0, sizeof (serverAddrv6)); | ||
458 | serverAddrv6.sin6_family = AF_INET6; | ||
459 | serverAddrv6.sin6_addr = in6addr_any; | ||
460 | serverAddrv6.sin6_port = htons (port); | ||
461 | addrlen = sizeof (serverAddrv6); | ||
462 | serverAddr = (struct sockaddr *) &serverAddrv6; | ||
463 | } | ||
464 | if (BIND (sock, serverAddr, addrlen) < 0) | ||
465 | { | ||
466 | GNUNET_GE_LOG_STRERROR (coreAPI->ectx, | ||
467 | GNUNET_GE_FATAL | GNUNET_GE_ADMIN | | ||
468 | GNUNET_GE_IMMEDIATE, "bind"); | ||
469 | GNUNET_GE_LOG (coreAPI->ectx, | ||
470 | GNUNET_GE_FATAL | GNUNET_GE_ADMIN | | ||
471 | GNUNET_GE_IMMEDIATE, | ||
472 | _("Failed to bind to %s port %d.\n"), | ||
473 | MY_TRANSPORT_NAME, port); | ||
474 | if (0 != CLOSE (sock)) | ||
475 | GNUNET_GE_LOG_STRERROR (coreAPI->ectx, | ||
476 | GNUNET_GE_ERROR | GNUNET_GE_USER | | ||
477 | GNUNET_GE_ADMIN | GNUNET_GE_BULK, | ||
478 | "close"); | ||
479 | return GNUNET_SYSERR; | ||
480 | } | ||
481 | selector = GNUNET_select_create ("udp", GNUNET_YES, coreAPI->ectx, load_monitor, sock, addrlen, 0, /* timeout */ | ||
482 | &select_message_handler, | ||
483 | NULL, | ||
484 | &select_accept_handler, | ||
485 | NULL, | ||
486 | &select_close_handler, | ||
487 | NULL, 64 * 1024, | ||
488 | 16 /* max sockets */ ); | ||
489 | if (selector == NULL) | ||
490 | return GNUNET_SYSERR; | ||
491 | } | ||
492 | sock = udp_create_socket (); | ||
493 | if (sock == -1) | ||
494 | { | ||
495 | GNUNET_GE_LOG_STRERROR (coreAPI->ectx, | ||
496 | GNUNET_GE_ERROR | GNUNET_GE_ADMIN | | ||
497 | GNUNET_GE_BULK, "socket"); | ||
498 | GNUNET_select_destroy (selector); | ||
499 | selector = NULL; | ||
500 | return GNUNET_SYSERR; | ||
501 | } | ||
502 | udp_sock = GNUNET_socket_create (coreAPI->ectx, load_monitor, sock); | ||
503 | GNUNET_GE_ASSERT (coreAPI->ectx, udp_sock != NULL); | ||
504 | return GNUNET_OK; | ||
505 | } | ||
506 | |||
507 | /** | ||
508 | * The exported method. Makes the core api available via a global and | ||
509 | * returns the udp transport API. | ||
510 | */ | ||
511 | GNUNET_TransportAPI * | ||
512 | inittransport_udp (GNUNET_CoreAPIForTransport * core) | ||
513 | { | ||
514 | unsigned long long mtu; | ||
515 | |||
516 | cfg = core->cfg; | ||
517 | load_monitor = core->load_monitor; | ||
518 | GNUNET_GE_ASSERT (coreAPI->ectx, sizeof (UDPMessage) == 68); | ||
519 | GNUNET_GE_ASSERT (coreAPI->ectx, sizeof (HostAddress) == 24); | ||
520 | coreAPI = core; | ||
521 | if (-1 == GNUNET_GC_get_configuration_value_number (cfg, | ||
522 | "UDP", | ||
523 | "MTU", | ||
524 | sizeof (UDPMessage) | ||
525 | + | ||
526 | GNUNET_P2P_MESSAGE_OVERHEAD | ||
527 | + | ||
528 | sizeof | ||
529 | (GNUNET_MessageHeader) + | ||
530 | 32, 65500, | ||
531 | MESSAGE_SIZE, &mtu)) | ||
532 | { | ||
533 | return NULL; | ||
534 | } | ||
535 | if (mtu < 1200) | ||
536 | GNUNET_GE_LOG (coreAPI->ectx, | ||
537 | GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_IMMEDIATE, | ||
538 | _("MTU %llu for `%s' is probably too low!\n"), mtu, "UDP"); | ||
539 | lock = GNUNET_mutex_create (GNUNET_NO); | ||
540 | if (0 != | ||
541 | GNUNET_GC_attach_change_listener (cfg, &reload_configuration, NULL)) | ||
542 | { | ||
543 | GNUNET_mutex_destroy (lock); | ||
544 | lock = NULL; | ||
545 | return NULL; | ||
546 | } | ||
547 | if (GNUNET_GC_get_configuration_value_yesno (cfg, "UDP", "UPNP", GNUNET_YES) | ||
548 | == GNUNET_YES) | ||
549 | { | ||
550 | upnp = coreAPI->service_request ("upnp"); | ||
551 | if (upnp == NULL) | ||
552 | GNUNET_GE_LOG (coreAPI->ectx, | ||
553 | GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_IMMEDIATE, | ||
554 | "The UPnP service could not be loaded. To disable UPnP, set the " | ||
555 | "configuration option \"UPNP\" in section \"%s\" to \"NO\"\n", | ||
556 | "UDP"); | ||
557 | } | ||
558 | stats = coreAPI->service_request ("stats"); | ||
559 | if (stats != NULL) | ||
560 | { | ||
561 | stat_bytesReceived | ||
562 | = stats->create (gettext_noop ("# bytes received via UDP")); | ||
563 | stat_bytesSent = stats->create (gettext_noop ("# bytes sent via UDP")); | ||
564 | stat_bytesDropped | ||
565 | = stats->create (gettext_noop ("# bytes dropped by UDP (outgoing)")); | ||
566 | stat_udpConnected | ||
567 | = stats->create (gettext_noop ("# UDP connections (right now)")); | ||
568 | } | ||
569 | myAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_UDP; | ||
570 | myAPI.mtu = mtu - sizeof (UDPMessage); | ||
571 | myAPI.cost = 20000; | ||
572 | myAPI.hello_verify = &verify_hello; | ||
573 | myAPI.hello_create = &create_hello; | ||
574 | myAPI.connect = &udp_connect; | ||
575 | myAPI.send = &udp_send; | ||
576 | myAPI.associate = &udp_associate; | ||
577 | myAPI.disconnect = &udp_disconnect; | ||
578 | myAPI.server_start = &udp_transport_server_start; | ||
579 | myAPI.server_stop = &udp_transport_server_stop; | ||
580 | myAPI.hello_to_address = &hello_to_address; | ||
581 | myAPI.send_now_test = &udp_test_would_try; | ||
582 | |||
583 | return &myAPI; | ||
584 | } | ||
585 | |||
586 | void | ||
587 | donetransport_udp () | ||
588 | { | ||
589 | do_shutdown (); | ||
590 | } | ||
591 | |||
592 | /* end of udp.c */ | ||