diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/transport/plugin_transport_udp.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c index ad5b165b1..5ef974942 100644 --- a/src/transport/plugin_transport_udp.c +++ b/src/transport/plugin_transport_udp.c | |||
@@ -323,11 +323,42 @@ struct Plugin | |||
323 | struct GNUNET_NETWORK_Handle *sockv6; | 323 | struct GNUNET_NETWORK_Handle *sockv6; |
324 | 324 | ||
325 | /** | 325 | /** |
326 | * Broadcast? | ||
327 | */ | ||
328 | int broadcast; | ||
329 | |||
330 | /** | ||
331 | * The read socket for IPv4 | ||
332 | */ | ||
333 | struct GNUNET_NETWORK_Handle *sockv4_broadcast; | ||
334 | |||
335 | /** | ||
336 | * ID of select broadcast task | ||
337 | */ | ||
338 | GNUNET_SCHEDULER_TaskIdentifier select_broadcast_task; | ||
339 | |||
340 | /** | ||
341 | * ID of select broadcast task | ||
342 | */ | ||
343 | GNUNET_SCHEDULER_TaskIdentifier send_broadcast_task; | ||
344 | |||
345 | /** | ||
346 | * FD Read set | ||
347 | */ | ||
348 | struct GNUNET_NETWORK_FDSet *broadcast_rs; | ||
349 | |||
350 | |||
351 | /** | ||
326 | * expected delay for ACKs | 352 | * expected delay for ACKs |
327 | */ | 353 | */ |
328 | struct GNUNET_TIME_Relative last_expected_delay; | 354 | struct GNUNET_TIME_Relative last_expected_delay; |
329 | 355 | ||
330 | /** | 356 | /** |
357 | * Port we broadcasting on. | ||
358 | */ | ||
359 | uint16_t broadcast_port; | ||
360 | |||
361 | /** | ||
331 | * Port we listen on. | 362 | * Port we listen on. |
332 | */ | 363 | */ |
333 | uint16_t port; | 364 | uint16_t port; |
@@ -1339,6 +1370,101 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1339 | 1370 | ||
1340 | 1371 | ||
1341 | /** | 1372 | /** |
1373 | * Read and process a message from the given socket. | ||
1374 | * | ||
1375 | * @param plugin the overall plugin | ||
1376 | * @param rsock socket to read from | ||
1377 | */ | ||
1378 | static void | ||
1379 | udp_broadcast_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock) | ||
1380 | { | ||
1381 | socklen_t fromlen; | ||
1382 | char addr[32]; | ||
1383 | char buf[65536]; | ||
1384 | ssize_t ret; | ||
1385 | const struct GNUNET_MessageHeader *msg; | ||
1386 | |||
1387 | fromlen = sizeof (addr); | ||
1388 | memset (&addr, 0, sizeof (addr)); | ||
1389 | ret = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf), | ||
1390 | (struct sockaddr *) &addr, &fromlen); | ||
1391 | if (ret < sizeof (struct GNUNET_MessageHeader)) | ||
1392 | { | ||
1393 | GNUNET_break_op (0); | ||
1394 | return; | ||
1395 | } | ||
1396 | msg = (const struct GNUNET_MessageHeader *) buf; | ||
1397 | |||
1398 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1399 | "UDP received %u-byte message from `%s' type %i\n", (unsigned int) ret, | ||
1400 | GNUNET_a2s ((const struct sockaddr *) addr, fromlen), ntohs(msg->type)); | ||
1401 | |||
1402 | if (ret != ntohs (msg->size)) | ||
1403 | { | ||
1404 | GNUNET_break_op (0); | ||
1405 | return; | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | |||
1410 | static void | ||
1411 | udp_broadcast_send (void *cls, | ||
1412 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1413 | { | ||
1414 | struct Plugin * plugin = cls; | ||
1415 | struct GNUNET_MessageHeader msg; | ||
1416 | int sent; | ||
1417 | |||
1418 | plugin->send_broadcast_task = GNUNET_SCHEDULER_NO_TASK; | ||
1419 | |||
1420 | struct sockaddr_in baddr; | ||
1421 | baddr.sin_family = AF_INET; | ||
1422 | baddr.sin_port = htons (plugin->broadcast_port); | ||
1423 | baddr.sin_addr.s_addr=htonl(-1); /* send message to 255.255.255.255 */ | ||
1424 | |||
1425 | msg.size = htons(sizeof (struct GNUNET_MessageHeader)); | ||
1426 | msg.type = htons (500); | ||
1427 | |||
1428 | sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4_broadcast, &msg, ntohs (msg.size), | ||
1429 | (const struct sockaddr *) &baddr, sizeof (struct sockaddr_in)); | ||
1430 | |||
1431 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1432 | "Sent broadcast with %i bytes\n", sent); | ||
1433 | plugin->send_broadcast_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, &udp_broadcast_send, plugin); | ||
1434 | |||
1435 | } | ||
1436 | |||
1437 | /** | ||
1438 | * We have been notified that our writeset has something to read. We don't | ||
1439 | * know which socket needs to be read, so we have to check each one | ||
1440 | * Then reschedule this function to be called again once more is available. | ||
1441 | * | ||
1442 | * @param cls the plugin handle | ||
1443 | * @param tc the scheduling context (for rescheduling this function again) | ||
1444 | */ | ||
1445 | static void | ||
1446 | udp_plugin_broadcast_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1447 | { | ||
1448 | struct Plugin *plugin = cls; | ||
1449 | |||
1450 | plugin->select_broadcast_task = GNUNET_SCHEDULER_NO_TASK; | ||
1451 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
1452 | return; | ||
1453 | |||
1454 | if ((NULL != plugin->sockv4_broadcast) && | ||
1455 | (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4_broadcast))) | ||
1456 | udp_broadcast_read (plugin, plugin->sockv4_broadcast); | ||
1457 | |||
1458 | plugin->select_broadcast_task = | ||
1459 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
1460 | GNUNET_SCHEDULER_NO_TASK, | ||
1461 | GNUNET_TIME_UNIT_FOREVER_REL, plugin->broadcast_rs, | ||
1462 | NULL, &udp_plugin_broadcast_select, plugin); | ||
1463 | } | ||
1464 | |||
1465 | |||
1466 | |||
1467 | /** | ||
1342 | * Check if the given port is plausible (must be either our listen | 1468 | * Check if the given port is plausible (must be either our listen |
1343 | * port or our advertised port). If it is neither, we return | 1469 | * port or our advertised port). If it is neither, we return |
1344 | * GNUNET_SYSERR. | 1470 | * GNUNET_SYSERR. |
@@ -1645,9 +1771,11 @@ libgnunet_plugin_transport_udp_init (void *cls) | |||
1645 | struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; | 1771 | struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; |
1646 | unsigned long long port; | 1772 | unsigned long long port; |
1647 | unsigned long long aport; | 1773 | unsigned long long aport; |
1774 | unsigned long long bport; | ||
1648 | struct GNUNET_TRANSPORT_PluginFunctions *api; | 1775 | struct GNUNET_TRANSPORT_PluginFunctions *api; |
1649 | struct Plugin *plugin; | 1776 | struct Plugin *plugin; |
1650 | int sockets_created; | 1777 | int sockets_created; |
1778 | int broadcast; | ||
1651 | struct sockaddr_in serverAddrv4; | 1779 | struct sockaddr_in serverAddrv4; |
1652 | struct sockaddr_in6 serverAddrv6; | 1780 | struct sockaddr_in6 serverAddrv6; |
1653 | struct sockaddr *serverAddr; | 1781 | struct sockaddr *serverAddr; |
@@ -1661,6 +1789,16 @@ libgnunet_plugin_transport_udp_init (void *cls) | |||
1661 | GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT", | 1789 | GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT", |
1662 | &port)) | 1790 | &port)) |
1663 | port = 2086; | 1791 | port = 2086; |
1792 | |||
1793 | broadcast = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp", "BROADCAST"); | ||
1794 | if (broadcast == GNUNET_SYSERR) | ||
1795 | broadcast = GNUNET_NO; | ||
1796 | |||
1797 | if (GNUNET_OK != | ||
1798 | GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "BROADCAST_PORT", | ||
1799 | &bport)) | ||
1800 | bport = 20086; | ||
1801 | |||
1664 | if (GNUNET_OK != | 1802 | if (GNUNET_OK != |
1665 | GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", | 1803 | GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", |
1666 | "MAX_BPS", &udp_max_bps)) | 1804 | "MAX_BPS", &udp_max_bps)) |
@@ -1686,6 +1824,8 @@ libgnunet_plugin_transport_udp_init (void *cls) | |||
1686 | plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS; | 1824 | plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS; |
1687 | plugin->port = port; | 1825 | plugin->port = port; |
1688 | plugin->aport = aport; | 1826 | plugin->aport = aport; |
1827 | plugin->broadcast_port = bport; | ||
1828 | plugin->broadcast = broadcast; | ||
1689 | plugin->env = env; | 1829 | plugin->env = env; |
1690 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); | 1830 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); |
1691 | api->cls = plugin; | 1831 | api->cls = plugin; |
@@ -1850,6 +1990,70 @@ libgnunet_plugin_transport_udp_init (void *cls) | |||
1850 | GNUNET_SCHEDULER_NO_TASK, | 1990 | GNUNET_SCHEDULER_NO_TASK, |
1851 | GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, | 1991 | GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, |
1852 | NULL, &udp_plugin_select, plugin); | 1992 | NULL, &udp_plugin_select, plugin); |
1993 | |||
1994 | |||
1995 | /* create broadcast socket */ | ||
1996 | if (broadcast) | ||
1997 | { | ||
1998 | plugin->sockv4_broadcast = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0); | ||
1999 | if (NULL == plugin->sockv4_broadcast) | ||
2000 | { | ||
2001 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket"); | ||
2002 | } | ||
2003 | else | ||
2004 | { | ||
2005 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
2006 | serverAddrv4.sin_len = sizeof (serverAddrv4); | ||
2007 | #endif | ||
2008 | serverAddrv4.sin_family = AF_INET; | ||
2009 | serverAddrv4.sin_addr.s_addr = INADDR_ANY; | ||
2010 | serverAddrv4.sin_port = htons (plugin->broadcast_port); | ||
2011 | addrlen = sizeof (serverAddrv4); | ||
2012 | serverAddr = (struct sockaddr *) &serverAddrv4; | ||
2013 | #if DEBUG_UDP | ||
2014 | #endif | ||
2015 | LOG (GNUNET_ERROR_TYPE_ERROR, "Binding Broadcast to IPv4 port %d\n", | ||
2016 | ntohs (serverAddrv4.sin_port)); | ||
2017 | |||
2018 | tries = 0; | ||
2019 | while (GNUNET_NETWORK_socket_bind (plugin->sockv4_broadcast, serverAddr, addrlen) != GNUNET_OK) | ||
2020 | { | ||
2021 | serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */ | ||
2022 | #if DEBUG_UDP | ||
2023 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2024 | "IPv4 Binding failed, trying new port %d\n", | ||
2025 | ntohs (serverAddrv4.sin_port)); | ||
2026 | #endif | ||
2027 | tries++; | ||
2028 | if (tries > 10) | ||
2029 | { | ||
2030 | GNUNET_NETWORK_socket_close (plugin->sockv4_broadcast); | ||
2031 | plugin->sockv4_broadcast = NULL; | ||
2032 | break; | ||
2033 | } | ||
2034 | } | ||
2035 | if (plugin->sockv4_broadcast != NULL) | ||
2036 | { | ||
2037 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("UDP Broadcast sockets on port %u \n"), bport); | ||
2038 | int yes = 1; | ||
2039 | if (GNUNET_NETWORK_socket_setsockopt (plugin->sockv4_broadcast, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(int)) != GNUNET_OK) | ||
2040 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "BROAD CASD socket"); | ||
2041 | } | ||
2042 | } | ||
2043 | |||
2044 | plugin->broadcast_rs = GNUNET_NETWORK_fdset_create (); | ||
2045 | if (NULL != plugin->sockv4_broadcast) | ||
2046 | GNUNET_NETWORK_fdset_set (plugin->broadcast_rs, plugin->sockv4_broadcast); | ||
2047 | |||
2048 | plugin->select_broadcast_task = | ||
2049 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
2050 | GNUNET_SCHEDULER_NO_TASK, | ||
2051 | GNUNET_TIME_UNIT_FOREVER_REL, plugin->broadcast_rs, | ||
2052 | NULL, &udp_plugin_broadcast_select, plugin); | ||
2053 | |||
2054 | plugin->send_broadcast_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, &udp_broadcast_send, plugin); | ||
2055 | } | ||
2056 | |||
1853 | if (sockets_created == 0) | 2057 | if (sockets_created == 0) |
1854 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n")); | 2058 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n")); |
1855 | plugin->nat = | 2059 | plugin->nat = |
@@ -1903,8 +2107,31 @@ libgnunet_plugin_transport_udp_done (void *cls) | |||
1903 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6)); | 2107 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6)); |
1904 | plugin->sockv6 = NULL; | 2108 | plugin->sockv6 = NULL; |
1905 | } | 2109 | } |
2110 | |||
2111 | if (plugin->broadcast) | ||
2112 | { | ||
2113 | if (plugin->select_broadcast_task != GNUNET_SCHEDULER_NO_TASK) | ||
2114 | { | ||
2115 | GNUNET_SCHEDULER_cancel (plugin->select_broadcast_task); | ||
2116 | plugin->select_broadcast_task = GNUNET_SCHEDULER_NO_TASK; | ||
2117 | } | ||
2118 | if (plugin->send_broadcast_task != GNUNET_SCHEDULER_NO_TASK) | ||
2119 | { | ||
2120 | GNUNET_SCHEDULER_cancel (plugin->send_broadcast_task ); | ||
2121 | plugin->send_broadcast_task = GNUNET_SCHEDULER_NO_TASK; | ||
2122 | } | ||
2123 | |||
2124 | if (plugin->sockv4_broadcast != NULL) | ||
2125 | { | ||
2126 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4_broadcast)); | ||
2127 | plugin->sockv4_broadcast = NULL; | ||
2128 | } | ||
2129 | GNUNET_NETWORK_fdset_destroy (plugin->broadcast_rs); | ||
2130 | } | ||
2131 | |||
1906 | GNUNET_SERVER_mst_destroy (plugin->mst); | 2132 | GNUNET_SERVER_mst_destroy (plugin->mst); |
1907 | GNUNET_NETWORK_fdset_destroy (plugin->rs); | 2133 | GNUNET_NETWORK_fdset_destroy (plugin->rs); |
2134 | |||
1908 | GNUNET_NAT_unregister (plugin->nat); | 2135 | GNUNET_NAT_unregister (plugin->nat); |
1909 | plugin->nat = NULL; | 2136 | plugin->nat = NULL; |
1910 | GNUNET_free (plugin); | 2137 | GNUNET_free (plugin); |