aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transport/plugin_transport_udp.c227
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 */
1378static void
1379udp_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
1410static void
1411udp_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 */
1445static void
1446udp_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);