aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/plugin_transport_tcp.c500
1 files changed, 258 insertions, 242 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 313cbf7f0..f39b1edf6 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2002--2014 Christian Grothoff (and other contributing authors) 3 Copyright (C) 2002--2015 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
@@ -227,7 +227,7 @@ struct PendingMessage
227 GNUNET_TRANSPORT_TransmitContinuation transmit_cont; 227 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
228 228
229 /** 229 /**
230 * Closure for transmit_cont. 230 * Closure for @e transmit_cont.
231 */ 231 */
232 void *transmit_cont_cls; 232 void *transmit_cont_cls;
233 233
@@ -239,7 +239,7 @@ struct PendingMessage
239 /** 239 /**
240 * So that the gnunet-service-transport can group messages together, 240 * So that the gnunet-service-transport can group messages together,
241 * these pending messages need to accept a message buffer and size 241 * these pending messages need to accept a message buffer and size
242 * instead of just a GNUNET_MessageHeader. 242 * instead of just a `struct GNUNET_MessageHeader`.
243 */ 243 */
244 size_t message_size; 244 size_t message_size;
245 245
@@ -349,6 +349,64 @@ struct Session
349 349
350 350
351/** 351/**
352 * Context for address to string conversion, closure
353 * for #append_port().
354 */
355struct PrettyPrinterContext
356{
357 /**
358 * DLL
359 */
360 struct PrettyPrinterContext *next;
361
362 /**
363 * DLL
364 */
365 struct PrettyPrinterContext *prev;
366
367 /**
368 * Our plugin.
369 */
370 struct Plugin *plugin;
371
372 /**
373 * Timeout task
374 */
375 struct GNUNET_SCHEDULER_Task *timeout_task;
376
377 /**
378 * Resolver handle
379 */
380 struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
381
382 /**
383 * Function to call with the result.
384 */
385 GNUNET_TRANSPORT_AddressStringCallback asc;
386
387 /**
388 * Clsoure for @e asc.
389 */
390 void *asc_cls;
391
392 /**
393 * IPv6 address
394 */
395 int ipv6;
396
397 /**
398 * Options
399 */
400 uint32_t options;
401
402 /**
403 * Port to add after the IP address.
404 */
405 uint16_t port;
406};
407
408
409/**
352 * Encapsulation of all of the state of the plugin. 410 * Encapsulation of all of the state of the plugin.
353 */ 411 */
354struct Plugin 412struct Plugin
@@ -420,6 +478,21 @@ struct Plugin
420 void *sic_cls; 478 void *sic_cls;
421 479
422 /** 480 /**
481 * ID of task used to update our addresses when one expires.
482 */
483 struct GNUNET_SCHEDULER_Task *address_update_task;
484
485 /**
486 * Running pretty printers: head
487 */
488 struct PrettyPrinterContext *ppc_dll_head;
489
490 /**
491 * Running pretty printers: tail
492 */
493 struct PrettyPrinterContext *ppc_dll_tail;
494
495 /**
423 * Welcome message used by this peer. 496 * Welcome message used by this peer.
424 */ 497 */
425 struct WelcomeMessage my_welcome; 498 struct WelcomeMessage my_welcome;
@@ -435,11 +508,6 @@ struct Plugin
435 unsigned long long cur_connections; 508 unsigned long long cur_connections;
436 509
437 /** 510 /**
438 * ID of task used to update our addresses when one expires.
439 */
440 struct GNUNET_SCHEDULER_Task * address_update_task;
441
442 /**
443 * Address options 511 * Address options
444 */ 512 */
445 uint32_t myoptions; 513 uint32_t myoptions;
@@ -493,53 +561,6 @@ notify_session_monitor (struct Plugin *plugin,
493 561
494 562
495/** 563/**
496 * Function called for a quick conversion of the binary address to
497 * a numeric address. Note that the caller must not free the
498 * address and that the next call to this function is allowed
499 * to override the address again.
500 *
501 * @param cls closure (`struct Plugin *`)
502 * @param addr binary address
503 * @param addrlen length of @a addr
504 * @return string representing the same address
505 */
506static const char *
507tcp_plugin_address_to_string (void *cls,
508 const void *addr,
509 size_t addrlen);
510
511
512/**
513 * Function to check if an inbound connection is acceptable.
514 * Mostly used to limit the total number of open connections
515 * we can have.
516 *
517 * @param cls the `struct Plugin`
518 * @param ucred credentials, if available, otherwise NULL
519 * @param addr address
520 * @param addrlen length of @a addr
521 * @return #GNUNET_YES to allow, #GNUNET_NO to deny, #GNUNET_SYSERR
522 * for unknown address family (will be denied).
523 */
524static int
525plugin_tcp_access_check (void *cls,
526 const struct GNUNET_CONNECTION_Credentials *ucred,
527 const struct sockaddr *addr,
528 socklen_t addrlen)
529{
530 struct Plugin *plugin = cls;
531
532 LOG (GNUNET_ERROR_TYPE_DEBUG,
533 "Accepting new incoming TCP connection from `%s'\n",
534 GNUNET_a2s (addr, addrlen));
535 if (plugin->cur_connections >= plugin->max_connections)
536 return GNUNET_NO;
537 plugin->cur_connections++;
538 return GNUNET_YES;
539}
540
541
542/**
543 * Our external IP address/port mapping has changed. 564 * Our external IP address/port mapping has changed.
544 * 565 *
545 * @param cls closure, the `struct Plugin` 566 * @param cls closure, the `struct Plugin`
@@ -697,7 +718,7 @@ tcp_plugin_string_to_address (void *cls,
697 address = NULL; 718 address = NULL;
698 plugin = NULL; 719 plugin = NULL;
699 optionstr = NULL; 720 optionstr = NULL;
700 if ((NULL == addr) || (addrlen == 0)) 721 if ((NULL == addr) || (0 == addrlen))
701 { 722 {
702 GNUNET_break(0); 723 GNUNET_break(0);
703 return GNUNET_SYSERR; 724 return GNUNET_SYSERR;
@@ -733,9 +754,10 @@ tcp_plugin_string_to_address (void *cls,
733 address[0] = '\0'; 754 address[0] = '\0';
734 address++; 755 address++;
735 756
736 if (GNUNET_OK 757 if (GNUNET_OK !=
737 != GNUNET_STRINGS_to_address_ip (address, strlen (address), 758 GNUNET_STRINGS_to_address_ip (address,
738 &socket_address)) 759 strlen (address),
760 &socket_address))
739 { 761 {
740 GNUNET_break(0); 762 GNUNET_break(0);
741 GNUNET_free(plugin); 763 GNUNET_free(plugin);
@@ -829,14 +851,16 @@ tcp_plugin_disconnect_session (void *cls,
829 session)) 851 session))
830 { 852 {
831 GNUNET_STATISTICS_update (session->plugin->env->stats, 853 GNUNET_STATISTICS_update (session->plugin->env->stats,
832 gettext_noop ("# TCP sessions active"), -1, GNUNET_NO); 854 gettext_noop ("# TCP sessions active"),
855 -1,
856 GNUNET_NO);
833 } 857 }
834 else 858 else
835 { 859 {
836 GNUNET_assert(GNUNET_YES == 860 GNUNET_assert (GNUNET_YES ==
837 GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns, 861 GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns,
838 &session->target, 862 &session->target,
839 session)); 863 session));
840 } 864 }
841 if (NULL != session->client) 865 if (NULL != session->client)
842 GNUNET_SERVER_client_set_user_context (session->client, 866 GNUNET_SERVER_client_set_user_context (session->client,
@@ -931,7 +955,7 @@ tcp_plugin_query_keepalive_factor (void *cls)
931 955
932 956
933/** 957/**
934 * Session was idle, so disconnect it 958 * Session was idle for too long, so disconnect it
935 * 959 *
936 * @param cls the `struct Session` of the idle session 960 * @param cls the `struct Session` of the idle session
937 * @param tc scheduler context 961 * @param tc scheduler context
@@ -963,19 +987,20 @@ session_timeout (void *cls,
963 GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 987 GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
964 GNUNET_YES)); 988 GNUNET_YES));
965 /* call session destroy function */ 989 /* call session destroy function */
966 tcp_plugin_disconnect_session (s->plugin, s); 990 tcp_plugin_disconnect_session (s->plugin,
991 s);
967} 992}
968 993
969 994
970/** 995/**
971 * Increment session timeout due to activity 996 * Increment session timeout due to activity.
972 * 997 *
973 * @param s session to increment timeout for 998 * @param s session to increment timeout for
974 */ 999 */
975static void 1000static void
976reschedule_session_timeout (struct Session *s) 1001reschedule_session_timeout (struct Session *s)
977{ 1002{
978 GNUNET_assert(NULL != s->timeout_task); 1003 GNUNET_assert (NULL != s->timeout_task);
979 s->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1004 s->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
980} 1005}
981 1006
@@ -1021,7 +1046,7 @@ create_session (struct Plugin *plugin,
1021 session->expecting_welcome = GNUNET_YES; 1046 session->expecting_welcome = GNUNET_YES;
1022 session->scope = GNUNET_ATS_NET_UNSPECIFIED; 1047 session->scope = GNUNET_ATS_NET_UNSPECIFIED;
1023 pm = GNUNET_malloc (sizeof (struct PendingMessage) + 1048 pm = GNUNET_malloc (sizeof (struct PendingMessage) +
1024 sizeof (struct WelcomeMessage)); 1049 sizeof (struct WelcomeMessage));
1025 pm->msg = (const char *) &pm[1]; 1050 pm->msg = (const char *) &pm[1];
1026 pm->message_size = sizeof(struct WelcomeMessage); 1051 pm->message_size = sizeof(struct WelcomeMessage);
1027 memcpy (&pm[1], 1052 memcpy (&pm[1],
@@ -1029,7 +1054,8 @@ create_session (struct Plugin *plugin,
1029 sizeof(struct WelcomeMessage)); 1054 sizeof(struct WelcomeMessage));
1030 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; 1055 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1031 GNUNET_STATISTICS_update (plugin->env->stats, 1056 GNUNET_STATISTICS_update (plugin->env->stats,
1032 gettext_noop ("# bytes currently in TCP buffers"), pm->message_size, 1057 gettext_noop ("# bytes currently in TCP buffers"),
1058 pm->message_size,
1033 GNUNET_NO); 1059 GNUNET_NO);
1034 GNUNET_CONTAINER_DLL_insert (session->pending_messages_head, 1060 GNUNET_CONTAINER_DLL_insert (session->pending_messages_head,
1035 session->pending_messages_tail, 1061 session->pending_messages_tail,
@@ -1085,7 +1111,9 @@ process_pending_messages (struct Session *session);
1085 * @return number of bytes written to @a buf 1111 * @return number of bytes written to @a buf
1086 */ 1112 */
1087static size_t 1113static size_t
1088do_transmit (void *cls, size_t size, void *buf) 1114do_transmit (void *cls,
1115 size_t size,
1116 void *buf)
1089{ 1117{
1090 struct Session *session = cls; 1118 struct Session *session = cls;
1091 struct GNUNET_PeerIdentity pid; 1119 struct GNUNET_PeerIdentity pid;
@@ -1270,7 +1298,7 @@ process_pending_messages (struct Session *session)
1270 * @param cls closure 1298 * @param cls closure
1271 * @param session which session must be used 1299 * @param session which session must be used
1272 * @param msgbuf the message to transmit 1300 * @param msgbuf the message to transmit
1273 * @param msgbuf_size number of bytes in 'msgbuf' 1301 * @param msgbuf_size number of bytes in @a msgbuf
1274 * @param priority how important is the message (most plugins will 1302 * @param priority how important is the message (most plugins will
1275 * ignore message priority and just FIFO) 1303 * ignore message priority and just FIFO)
1276 * @param to how long to wait at most for the transmission (does not 1304 * @param to how long to wait at most for the transmission (does not
@@ -1360,9 +1388,9 @@ tcp_plugin_send (void *cls,
1360 GNUNET_TRANSPORT_SS_HANDSHAKE); 1388 GNUNET_TRANSPORT_SS_HANDSHAKE);
1361 return msgbuf_size; 1389 return msgbuf_size;
1362 } 1390 }
1363 LOG(GNUNET_ERROR_TYPE_ERROR, 1391 LOG (GNUNET_ERROR_TYPE_ERROR,
1364 "Invalid session %p\n", 1392 "Invalid session %p\n",
1365 session); 1393 session);
1366 if (NULL != cont) 1394 if (NULL != cont)
1367 cont (cont_cls, 1395 cont (cont_cls,
1368 &session->target, 1396 &session->target,
@@ -1464,7 +1492,7 @@ tcp_plugin_update_session_timeout (void *cls,
1464 * Task to signal the server that we can continue 1492 * Task to signal the server that we can continue
1465 * receiving from the TCP client now. 1493 * receiving from the TCP client now.
1466 * 1494 *
1467 * @param cls the `struct Session*` 1495 * @param cls the `struct Session *`
1468 * @param tc task context (unused) 1496 * @param tc task context (unused)
1469 */ 1497 */
1470static void 1498static void
@@ -1475,8 +1503,8 @@ delayed_done (void *cls,
1475 1503
1476 session->receive_delay_task = NULL; 1504 session->receive_delay_task = NULL;
1477 reschedule_session_timeout (session); 1505 reschedule_session_timeout (session);
1478 1506 GNUNET_SERVER_receive_done (session->client,
1479 GNUNET_SERVER_receive_done (session->client, GNUNET_OK); 1507 GNUNET_OK);
1480} 1508}
1481 1509
1482 1510
@@ -1565,10 +1593,10 @@ tcp_plugin_get_session (void *cls,
1565 1593
1566 si_ctx.address = address; 1594 si_ctx.address = address;
1567 si_ctx.result = NULL; 1595 si_ctx.result = NULL;
1568
1569 GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap, 1596 GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap,
1570 &address->peer, 1597 &address->peer,
1571 &session_lookup_it, &si_ctx); 1598 &session_lookup_it,
1599 &si_ctx);
1572 if (NULL != si_ctx.result) 1600 if (NULL != si_ctx.result)
1573 { 1601 {
1574 session = si_ctx.result; 1602 session = si_ctx.result;
@@ -1632,7 +1660,8 @@ tcp_plugin_get_session (void *cls,
1632 sbs); 1660 sbs);
1633 GNUNET_break (net_type != GNUNET_ATS_NET_UNSPECIFIED); 1661 GNUNET_break (net_type != GNUNET_ATS_NET_UNSPECIFIED);
1634 1662
1635 if ((is_natd == GNUNET_YES) && (addrlen == sizeof(struct IPv6TcpAddress))) 1663 if ( (is_natd == GNUNET_YES) &&
1664 (addrlen == sizeof(struct IPv6TcpAddress)) )
1636 { 1665 {
1637 /* NAT client only works with IPv4 addresses */ 1666 /* NAT client only works with IPv4 addresses */
1638 return NULL; 1667 return NULL;
@@ -1644,10 +1673,10 @@ tcp_plugin_get_session (void *cls,
1644 return NULL; 1673 return NULL;
1645 } 1674 }
1646 1675
1647 if ((is_natd == GNUNET_YES) 1676 if ( (is_natd == GNUNET_YES) &&
1648 && (GNUNET_YES 1677 (GNUNET_YES ==
1649 == GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns, 1678 GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
1650 &address->peer))) 1679 &address->peer)))
1651 { 1680 {
1652 /* Only do one NAT punch attempt per peer identity */ 1681 /* Only do one NAT punch attempt per peer identity */
1653 return NULL; 1682 return NULL;
@@ -1696,8 +1725,6 @@ tcp_plugin_get_session (void *cls,
1696 } 1725 }
1697 1726
1698 /* create new outbound session */ 1727 /* create new outbound session */
1699 GNUNET_assert(plugin->cur_connections <= plugin->max_connections);
1700
1701 if (0 != (options & TCP_OPTIONS_TCP_STEALTH)) 1728 if (0 != (options & TCP_OPTIONS_TCP_STEALTH))
1702 { 1729 {
1703#ifdef TCP_STEALTH 1730#ifdef TCP_STEALTH
@@ -1749,15 +1776,6 @@ tcp_plugin_get_session (void *cls,
1749 GNUNET_a2s (sb, sbs)); 1776 GNUNET_a2s (sb, sbs));
1750 return NULL; 1777 return NULL;
1751 } 1778 }
1752 plugin->cur_connections++;
1753 if (plugin->cur_connections == plugin->max_connections)
1754 {
1755 GNUNET_STATISTICS_update (plugin->env->stats,
1756 gettext_noop ("# TCP service suspended"),
1757 1,
1758 GNUNET_NO);
1759 GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */
1760 }
1761 LOG (GNUNET_ERROR_TYPE_DEBUG, 1779 LOG (GNUNET_ERROR_TYPE_DEBUG,
1762 "Asked to transmit to `%4s', creating fresh session using address `%s'.\n", 1780 "Asked to transmit to `%4s', creating fresh session using address `%s'.\n",
1763 GNUNET_i2s (&address->peer), 1781 GNUNET_i2s (&address->peer),
@@ -1781,6 +1799,16 @@ tcp_plugin_get_session (void *cls,
1781} 1799}
1782 1800
1783 1801
1802/**
1803 * We have been asked to destroy all connections to a particular peer.
1804 * This function is called on each applicable session and must tear it
1805 * down.
1806 *
1807 * @param cls the `struct Plugin *`
1808 * @param key the peer which the session belongs to (unused)
1809 * @param value the `struct Session`
1810 * @return #GNUNET_YES (continue to iterate)
1811 */
1784static int 1812static int
1785session_disconnect_it (void *cls, 1813session_disconnect_it (void *cls,
1786 const struct GNUNET_PeerIdentity *key, 1814 const struct GNUNET_PeerIdentity *key,
@@ -1821,9 +1849,9 @@ tcp_plugin_disconnect (void *cls,
1821{ 1849{
1822 struct Plugin *plugin = cls; 1850 struct Plugin *plugin = cls;
1823 1851
1824 LOG(GNUNET_ERROR_TYPE_DEBUG, 1852 LOG (GNUNET_ERROR_TYPE_DEBUG,
1825 "Disconnecting peer `%4s'\n", 1853 "Disconnecting peer `%4s'\n",
1826 GNUNET_i2s (target)); 1854 GNUNET_i2s (target));
1827 GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap, 1855 GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap,
1828 target, 1856 target,
1829 &session_disconnect_it, 1857 &session_disconnect_it,
@@ -1836,70 +1864,11 @@ tcp_plugin_disconnect (void *cls,
1836 1864
1837 1865
1838/** 1866/**
1839 * Running pretty printers: head 1867 * We are processing an address pretty printing request and finished
1840 */ 1868 * the IP resolution (if applicable). Append our port and forward the
1841static struct PrettyPrinterContext *ppc_dll_head; 1869 * result. If called with @a hostname NULL, we are done and should
1842 1870 * clean up the pretty printer (otherwise, there might be multiple
1843/** 1871 * hostnames for the IP address and we might receive more).
1844 * Running pretty printers: tail
1845 */
1846static struct PrettyPrinterContext *ppc_dll_tail;
1847
1848/**
1849 * Context for address to string conversion, closure
1850 * for #append_port().
1851 */
1852struct PrettyPrinterContext
1853{
1854 /**
1855 * DLL
1856 */
1857 struct PrettyPrinterContext *next;
1858
1859 /**
1860 * DLL
1861 */
1862 struct PrettyPrinterContext *prev;
1863
1864 /**
1865 * Timeout task
1866 */
1867 struct GNUNET_SCHEDULER_Task * timeout_task;
1868
1869 /**
1870 * Resolver handle
1871 */
1872 struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
1873
1874 /**
1875 * Function to call with the result.
1876 */
1877 GNUNET_TRANSPORT_AddressStringCallback asc;
1878
1879 /**
1880 * Clsoure for @e asc.
1881 */
1882 void *asc_cls;
1883
1884 /**
1885 * Port to add after the IP address.
1886 */
1887 uint16_t port;
1888
1889 /**
1890 * IPv6 address
1891 */
1892 int ipv6;
1893
1894 /**
1895 * Options
1896 */
1897 uint32_t options;
1898};
1899
1900
1901/**
1902 * Append our port and forward the result.
1903 * 1872 *
1904 * @param cls the `struct PrettyPrinterContext *` 1873 * @param cls the `struct PrettyPrinterContext *`
1905 * @param hostname hostname part of the address 1874 * @param hostname hostname part of the address
@@ -1909,14 +1878,15 @@ append_port (void *cls,
1909 const char *hostname) 1878 const char *hostname)
1910{ 1879{
1911 struct PrettyPrinterContext *ppc = cls; 1880 struct PrettyPrinterContext *ppc = cls;
1881 struct Plugin *plugin = ppc->plugin;
1912 char *ret; 1882 char *ret;
1913 1883
1914 if (NULL == hostname) 1884 if (NULL == hostname)
1915 { 1885 {
1916 /* Final call, done */ 1886 /* Final call, done */
1917 ppc->resolver_handle = NULL; 1887 ppc->resolver_handle = NULL;
1918 GNUNET_CONTAINER_DLL_remove (ppc_dll_head, 1888 GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
1919 ppc_dll_tail, 1889 plugin->ppc_dll_tail,
1920 ppc); 1890 ppc);
1921 ppc->asc (ppc->asc_cls, 1891 ppc->asc (ppc->asc_cls,
1922 NULL, 1892 NULL,
@@ -1946,10 +1916,9 @@ append_port (void *cls,
1946 1916
1947 1917
1948/** 1918/**
1949 * Convert the transports address to a nice, human-readable 1919 * Convert the transports address to a nice, human-readable format.
1950 * format.
1951 * 1920 *
1952 * @param cls closure 1921 * @param cls closure with the `struct Plugin`
1953 * @param type name of the transport that generated the address 1922 * @param type name of the transport that generated the address
1954 * @param addr one of the addresses of the host, NULL for the last address 1923 * @param addr one of the addresses of the host, NULL for the last address
1955 * the specific address format depends on the transport 1924 * the specific address format depends on the transport
@@ -1969,6 +1938,7 @@ tcp_plugin_address_pretty_printer (void *cls,
1969 GNUNET_TRANSPORT_AddressStringCallback asc, 1938 GNUNET_TRANSPORT_AddressStringCallback asc,
1970 void *asc_cls) 1939 void *asc_cls)
1971{ 1940{
1941 struct Plugin *plugin = cls;
1972 struct PrettyPrinterContext *ppc; 1942 struct PrettyPrinterContext *ppc;
1973 const void *sb; 1943 const void *sb;
1974 size_t sbs; 1944 size_t sbs;
@@ -2011,6 +1981,7 @@ tcp_plugin_address_pretty_printer (void *cls,
2011 return; 1981 return;
2012 } 1982 }
2013 ppc = GNUNET_new (struct PrettyPrinterContext); 1983 ppc = GNUNET_new (struct PrettyPrinterContext);
1984 ppc->plugin = plugin;
2014 if (addrlen == sizeof(struct IPv6TcpAddress)) 1985 if (addrlen == sizeof(struct IPv6TcpAddress))
2015 ppc->ipv6 = GNUNET_YES; 1986 ppc->ipv6 = GNUNET_YES;
2016 else 1987 else
@@ -2030,8 +2001,8 @@ tcp_plugin_address_pretty_printer (void *cls,
2030 GNUNET_free (ppc); 2001 GNUNET_free (ppc);
2031 return; 2002 return;
2032 } 2003 }
2033 GNUNET_CONTAINER_DLL_insert (ppc_dll_head, 2004 GNUNET_CONTAINER_DLL_insert (plugin->ppc_dll_head,
2034 ppc_dll_tail, 2005 plugin->ppc_dll_tail,
2035 ppc); 2006 ppc);
2036} 2007}
2037 2008
@@ -2047,13 +2018,16 @@ tcp_plugin_address_pretty_printer (void *cls,
2047 * @return #GNUNET_OK if port is either open_port or adv_port 2018 * @return #GNUNET_OK if port is either open_port or adv_port
2048 */ 2019 */
2049static int 2020static int
2050check_port (struct Plugin *plugin, uint16_t in_port) 2021check_port (struct Plugin *plugin,
2022 uint16_t in_port)
2051{ 2023{
2052 if ((in_port == plugin->adv_port) || (in_port == plugin->open_port)) 2024 if ( (in_port == plugin->adv_port) ||
2025 (in_port == plugin->open_port) )
2053 return GNUNET_OK; 2026 return GNUNET_OK;
2054 return GNUNET_SYSERR; 2027 return GNUNET_SYSERR;
2055} 2028}
2056 2029
2030
2057/** 2031/**
2058 * Function that will be called to check if a binary address for this 2032 * Function that will be called to check if a binary address for this
2059 * plugin is well-formed and corresponds to an address for THIS peer 2033 * plugin is well-formed and corresponds to an address for THIS peer
@@ -2065,66 +2039,73 @@ check_port (struct Plugin *plugin, uint16_t in_port)
2065 * 2039 *
2066 * @param cls closure, our `struct Plugin *` 2040 * @param cls closure, our `struct Plugin *`
2067 * @param addr pointer to the address 2041 * @param addr pointer to the address
2068 * @param addrlen length of addr 2042 * @param addrlen length of @a addr
2069 * @return #GNUNET_OK if this is a plausible address for this peer 2043 * @return #GNUNET_OK if this is a plausible address for this peer
2070 * and transport, #GNUNET_SYSERR if not 2044 * and transport, #GNUNET_SYSERR if not
2071 */ 2045 */
2072static int 2046static int
2073tcp_plugin_check_address (void *cls, const void *addr, size_t addrlen) 2047tcp_plugin_check_address (void *cls,
2048 const void *addr,
2049 size_t addrlen)
2074{ 2050{
2075 struct Plugin *plugin = cls; 2051 struct Plugin *plugin = cls;
2076 struct IPv4TcpAddress *v4; 2052 const struct IPv4TcpAddress *v4;
2077 struct IPv6TcpAddress *v6; 2053 const struct IPv6TcpAddress *v6;
2078 2054
2079 if ((addrlen != sizeof(struct IPv4TcpAddress)) 2055 if ( (addrlen != sizeof(struct IPv4TcpAddress)) &&
2080 && (addrlen != sizeof(struct IPv6TcpAddress))) 2056 (addrlen != sizeof(struct IPv6TcpAddress)) )
2081 { 2057 {
2082 GNUNET_break_op(0); 2058 GNUNET_break_op (0);
2083 return GNUNET_SYSERR; 2059 return GNUNET_SYSERR;
2084 } 2060 }
2085 2061
2086 if (addrlen == sizeof(struct IPv4TcpAddress)) 2062 if (addrlen == sizeof(struct IPv4TcpAddress))
2087 { 2063 {
2088 v4 = (struct IPv4TcpAddress *) addr; 2064 v4 = (const struct IPv4TcpAddress *) addr;
2089 if (0 != memcmp (&v4->options, 2065 if (0 != memcmp (&v4->options,
2090 &plugin->myoptions, 2066 &plugin->myoptions,
2091 sizeof(uint32_t))) 2067 sizeof(uint32_t)))
2092 { 2068 {
2093 GNUNET_break(0); 2069 GNUNET_break (0);
2094 return GNUNET_SYSERR; 2070 return GNUNET_SYSERR;
2095 } 2071 }
2096 if (GNUNET_OK != check_port (plugin, ntohs (v4->t4_port))) 2072 if (GNUNET_OK != check_port (plugin,
2073 ntohs (v4->t4_port)))
2097 return GNUNET_SYSERR; 2074 return GNUNET_SYSERR;
2098 if (GNUNET_OK 2075 if (GNUNET_OK !=
2099 != GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr, 2076 GNUNET_NAT_test_address (plugin->nat,
2100 sizeof(struct in_addr))) 2077 &v4->ipv4_addr,
2078 sizeof (struct in_addr)))
2101 return GNUNET_SYSERR; 2079 return GNUNET_SYSERR;
2102 } 2080 }
2103 else 2081 else
2104 { 2082 {
2105 v6 = (struct IPv6TcpAddress *) addr; 2083 v6 = (const struct IPv6TcpAddress *) addr;
2106 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr)) 2084 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
2107 { 2085 {
2108 GNUNET_break_op(0); 2086 GNUNET_break_op (0);
2109 return GNUNET_SYSERR; 2087 return GNUNET_SYSERR;
2110 } 2088 }
2111 if (0 != memcmp (&v6->options, 2089 if (0 != memcmp (&v6->options,
2112 &plugin->myoptions, 2090 &plugin->myoptions,
2113 sizeof (uint32_t))) 2091 sizeof (uint32_t)))
2114 { 2092 {
2115 GNUNET_break(0); 2093 GNUNET_break (0);
2116 return GNUNET_SYSERR; 2094 return GNUNET_SYSERR;
2117 } 2095 }
2118 if (GNUNET_OK != check_port (plugin, ntohs (v6->t6_port))) 2096 if (GNUNET_OK != check_port (plugin,
2097 ntohs (v6->t6_port)))
2119 return GNUNET_SYSERR; 2098 return GNUNET_SYSERR;
2120 if (GNUNET_OK 2099 if (GNUNET_OK !=
2121 != GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr, 2100 GNUNET_NAT_test_address (plugin->nat,
2122 sizeof(struct in6_addr))) 2101 &v6->ipv6_addr,
2102 sizeof(struct in6_addr)))
2123 return GNUNET_SYSERR; 2103 return GNUNET_SYSERR;
2124 } 2104 }
2125 return GNUNET_OK; 2105 return GNUNET_OK;
2126} 2106}
2127 2107
2108
2128/** 2109/**
2129 * We've received a nat probe from this peer via TCP. Finish 2110 * We've received a nat probe from this peer via TCP. Finish
2130 * creating the client session and resume sending of queued 2111 * creating the client session and resume sending of queued
@@ -2175,7 +2156,7 @@ handle_tcp_nat_probe (void *cls,
2175 2156
2176 session = GNUNET_CONTAINER_multipeermap_get (plugin->nat_wait_conns, 2157 session = GNUNET_CONTAINER_multipeermap_get (plugin->nat_wait_conns,
2177 &tcp_nat_probe->clientIdentity); 2158 &tcp_nat_probe->clientIdentity);
2178 if (session == NULL) 2159 if (NULL == session)
2179 { 2160 {
2180 LOG (GNUNET_ERROR_TYPE_DEBUG, 2161 LOG (GNUNET_ERROR_TYPE_DEBUG,
2181 "Did NOT find session for NAT probe!\n"); 2162 "Did NOT find session for NAT probe!\n");
@@ -2185,25 +2166,34 @@ handle_tcp_nat_probe (void *cls,
2185 LOG (GNUNET_ERROR_TYPE_DEBUG, 2166 LOG (GNUNET_ERROR_TYPE_DEBUG,
2186 "Found session for NAT probe!\n"); 2167 "Found session for NAT probe!\n");
2187 2168
2188 if (session->nat_connection_timeout != NULL) 2169 if (NULL != session->nat_connection_timeout)
2189 { 2170 {
2190 GNUNET_SCHEDULER_cancel (session->nat_connection_timeout); 2171 GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
2191 session->nat_connection_timeout = NULL; 2172 session->nat_connection_timeout = NULL;
2192 } 2173 }
2193 2174
2194 if (GNUNET_OK != GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) 2175 if (GNUNET_OK !=
2176 GNUNET_SERVER_client_get_address (client,
2177 &vaddr,
2178 &alen))
2195 { 2179 {
2196 GNUNET_break(0); 2180 GNUNET_break(0);
2197 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 2181 GNUNET_SERVER_receive_done (client,
2182 GNUNET_SYSERR);
2198 tcp_plugin_disconnect_session (plugin, 2183 tcp_plugin_disconnect_session (plugin,
2199 session); 2184 session);
2200 return; 2185 return;
2201 } 2186 }
2202 GNUNET_assert( 2187 GNUNET_assert (GNUNET_YES ==
2203 GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity, session) == GNUNET_YES); 2188 GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns,
2204 GNUNET_SERVER_client_set_user_context(client, session); 2189 &tcp_nat_probe->clientIdentity,
2205 GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap, &session->target, 2190 session));
2206 session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 2191 GNUNET_SERVER_client_set_user_context (client,
2192 session);
2193 (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
2194 &session->target,
2195 session,
2196 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2207 session->last_activity = GNUNET_TIME_absolute_get (); 2197 session->last_activity = GNUNET_TIME_absolute_get ();
2208 LOG (GNUNET_ERROR_TYPE_DEBUG, 2198 LOG (GNUNET_ERROR_TYPE_DEBUG,
2209 "Found address `%s' for incoming connection\n", 2199 "Found address `%s' for incoming connection\n",
@@ -2244,14 +2234,17 @@ handle_tcp_nat_probe (void *cls,
2244 session); 2234 session);
2245 return; 2235 return;
2246 } 2236 }
2247 GNUNET_free(vaddr); 2237 GNUNET_free (vaddr);
2248 GNUNET_break(NULL == session->client); 2238 GNUNET_break (NULL == session->client);
2249 GNUNET_SERVER_client_keep (client); 2239 GNUNET_SERVER_client_keep (client);
2250 session->client = client; 2240 session->client = client;
2251 GNUNET_STATISTICS_update (plugin->env->stats, 2241 GNUNET_STATISTICS_update (plugin->env->stats,
2252 gettext_noop ("# TCP sessions active"), 1, GNUNET_NO); 2242 gettext_noop ("# TCP sessions active"),
2243 1,
2244 GNUNET_NO);
2253 process_pending_messages (session); 2245 process_pending_messages (session);
2254 GNUNET_SERVER_receive_done (client, GNUNET_OK); 2246 GNUNET_SERVER_receive_done (client,
2247 GNUNET_OK);
2255} 2248}
2256 2249
2257 2250
@@ -2324,18 +2317,6 @@ handle_tcp_welcome (void *cls,
2324 else 2317 else
2325 { 2318 {
2326 GNUNET_SERVER_client_keep (client); 2319 GNUNET_SERVER_client_keep (client);
2327 if (NULL != plugin->service) /* Otherwise value is incremented in tcp_access_check */
2328 plugin->cur_connections++;
2329 if (plugin->cur_connections == plugin->max_connections)
2330 {
2331 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2332 _("TCP connection limit reached, suspending server\n"));
2333 GNUNET_STATISTICS_update (plugin->env->stats,
2334 gettext_noop ("# TCP service suspended"),
2335 1,
2336 GNUNET_NO);
2337 GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */
2338 }
2339 if (GNUNET_OK == 2320 if (GNUNET_OK ==
2340 GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) 2321 GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
2341 { 2322 {
@@ -2480,7 +2461,7 @@ handle_tcp_data (void *cls,
2480 GNUNET_free_non_null (vaddr); 2461 GNUNET_free_non_null (vaddr);
2481 return; 2462 return;
2482 } 2463 }
2483 else if (GNUNET_YES == session->expecting_welcome) 2464 if (GNUNET_YES == session->expecting_welcome)
2484 { 2465 {
2485 /* Session is expecting WELCOME message */ 2466 /* Session is expecting WELCOME message */
2486 void *vaddr; 2467 void *vaddr;
@@ -2537,8 +2518,36 @@ handle_tcp_data (void *cls,
2537 2518
2538 2519
2539/** 2520/**
2540 * Functions with this signature are called whenever a peer 2521 * Function called whenever a peer is connected on the "SERVER" level.
2541 * is disconnected on the network level. 2522 * Increments number of active connections and suspends server if we
2523 * have reached the limit.
2524 *
2525 * @param cls closure
2526 * @param client identification of the client
2527 */
2528static void
2529connect_notify (void *cls,
2530 struct GNUNET_SERVER_Client *client)
2531{
2532 struct Plugin *plugin = cls;
2533
2534 plugin->cur_connections++;
2535 if (plugin->cur_connections != plugin->max_connections)
2536 return;
2537 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2538 _("TCP connection limit reached, suspending server\n"));
2539 GNUNET_STATISTICS_update (plugin->env->stats,
2540 gettext_noop ("# TCP service suspended"),
2541 1,
2542 GNUNET_NO);
2543 GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */
2544}
2545
2546
2547/**
2548 * Function called whenever a peer is disconnected on the "SERVER"
2549 * level. Cleans up the connection, decrements number of active
2550 * connections and if applicable resumes listening.
2542 * 2551 *
2543 * @param cls closure 2552 * @param cls closure
2544 * @param client identification of the client 2553 * @param client identification of the client
@@ -2570,24 +2579,21 @@ disconnect_notify (void *cls,
2570 GNUNET_NO); 2579 GNUNET_NO);
2571 GNUNET_SERVER_resume (plugin->server); /* Resume server */ 2580 GNUNET_SERVER_resume (plugin->server); /* Resume server */
2572 } 2581 }
2573 2582 GNUNET_assert (plugin->cur_connections >= 1);
2574 if (plugin->cur_connections < 1) 2583 plugin->cur_connections--;
2575 GNUNET_break(0);
2576 else
2577 plugin->cur_connections--;
2578
2579 GNUNET_STATISTICS_update (session->plugin->env->stats, 2584 GNUNET_STATISTICS_update (session->plugin->env->stats,
2580 gettext_noop ("# network-level TCP disconnect events"), 2585 gettext_noop ("# network-level TCP disconnect events"),
2581 1, 2586 1,
2582 GNUNET_NO); 2587 GNUNET_NO);
2583 tcp_plugin_disconnect_session (plugin, session); 2588 tcp_plugin_disconnect_session (plugin,
2589 session);
2584} 2590}
2585 2591
2586 2592
2587/** 2593/**
2588 * We can now send a probe message, copy into buffer to really send. 2594 * We can now send a probe message, copy into buffer to really send.
2589 * 2595 *
2590 * @param cls closure, a struct TCPProbeContext 2596 * @param cls closure, a `struct TCPProbeContext`
2591 * @param size max size to copy 2597 * @param size max size to copy
2592 * @param buf buffer to copy message to 2598 * @param buf buffer to copy message to
2593 * @return number of bytes copied into @a buf 2599 * @return number of bytes copied into @a buf
@@ -2605,18 +2611,20 @@ notify_send_probe (void *cls,
2605 GNUNET_CONTAINER_DLL_remove (plugin->probe_head, 2611 GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
2606 plugin->probe_tail, 2612 plugin->probe_tail,
2607 tcp_probe_ctx); 2613 tcp_probe_ctx);
2608 if (buf == NULL) 2614 if (NULL == buf)
2609 { 2615 {
2610 GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock); 2616 GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock);
2611 GNUNET_free(tcp_probe_ctx); 2617 GNUNET_free(tcp_probe_ctx);
2612 return 0; 2618 return 0;
2613 } 2619 }
2614 GNUNET_assert(size >= sizeof(tcp_probe_ctx->message)); 2620 GNUNET_assert(size >= sizeof(tcp_probe_ctx->message));
2615 memcpy (buf, &tcp_probe_ctx->message, sizeof(tcp_probe_ctx->message)); 2621 memcpy (buf,
2622 &tcp_probe_ctx->message,
2623 sizeof(tcp_probe_ctx->message));
2616 GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server, 2624 GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server,
2617 tcp_probe_ctx->sock); 2625 tcp_probe_ctx->sock);
2618 ret = sizeof(tcp_probe_ctx->message); 2626 ret = sizeof(tcp_probe_ctx->message);
2619 GNUNET_free(tcp_probe_ctx); 2627 GNUNET_free (tcp_probe_ctx);
2620 return ret; 2628 return ret;
2621} 2629}
2622 2630
@@ -2643,8 +2651,10 @@ try_connection_reversal (void *cls,
2643 * We have received an ICMP response, ostensibly from a peer 2651 * We have received an ICMP response, ostensibly from a peer
2644 * that wants to connect to us! Send a message to establish a connection. 2652 * that wants to connect to us! Send a message to establish a connection.
2645 */ 2653 */
2646 sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen); 2654 sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET,
2647 if (sock == NULL) 2655 addr,
2656 addrlen);
2657 if (NULL == sock)
2648 { 2658 {
2649 /* failed for some odd reason (out of sockets?); ignore attempt */ 2659 /* failed for some odd reason (out of sockets?); ignore attempt */
2650 return; 2660 return;
@@ -2674,7 +2684,7 @@ try_connection_reversal (void *cls,
2674/** 2684/**
2675 * Function obtain the network type for a session 2685 * Function obtain the network type for a session
2676 * 2686 *
2677 * @param cls closure ('struct Plugin*') 2687 * @param cls closure (`struct Plugin *`)
2678 * @param session the session 2688 * @param session the session
2679 * @return the network type in HBO or #GNUNET_SYSERR 2689 * @return the network type in HBO or #GNUNET_SYSERR
2680 */ 2690 */
@@ -2965,9 +2975,11 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2965 goto die; 2975 goto die;
2966 } 2976 }
2967 plugin->server 2977 plugin->server
2968 = GNUNET_SERVER_create_with_sockets (&plugin_tcp_access_check, 2978 = GNUNET_SERVER_create_with_sockets (NULL,
2969 plugin, NULL, 2979 plugin,
2970 idle_timeout, GNUNET_YES); 2980 NULL,
2981 idle_timeout,
2982 GNUNET_YES);
2971 } 2983 }
2972 plugin->handlers = GNUNET_malloc (sizeof (my_handlers)); 2984 plugin->handlers = GNUNET_malloc (sizeof (my_handlers));
2973 memcpy (plugin->handlers, my_handlers, sizeof(my_handlers)); 2985 memcpy (plugin->handlers, my_handlers, sizeof(my_handlers));
@@ -2976,6 +2988,9 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2976 2988
2977 GNUNET_SERVER_add_handlers (plugin->server, 2989 GNUNET_SERVER_add_handlers (plugin->server,
2978 plugin->handlers); 2990 plugin->handlers);
2991 GNUNET_SERVER_connect_notify (plugin->server,
2992 &connect_notify,
2993 plugin);
2979 GNUNET_SERVER_disconnect_notify (plugin->server, 2994 GNUNET_SERVER_disconnect_notify (plugin->server,
2980 &disconnect_notify, 2995 &disconnect_notify,
2981 plugin); 2996 plugin);
@@ -2994,7 +3009,6 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2994 _("TCP transport advertises itself as being on port %llu\n"), 3009 _("TCP transport advertises itself as being on port %llu\n"),
2995 aport); 3010 aport);
2996 /* Initially set connections to 0 */ 3011 /* Initially set connections to 0 */
2997 GNUNET_assert(NULL != plugin->env->stats);
2998 GNUNET_STATISTICS_set (plugin->env->stats, 3012 GNUNET_STATISTICS_set (plugin->env->stats,
2999 gettext_noop ("# TCP sessions active"), 3013 gettext_noop ("# TCP sessions active"),
3000 0, 3014 0,
@@ -3045,14 +3059,16 @@ libgnunet_plugin_transport_tcp_done (void *cls)
3045 &session_disconnect_it, 3059 &session_disconnect_it,
3046 plugin); 3060 plugin);
3047 3061
3048 for (cur = ppc_dll_head; NULL != cur; cur = next) 3062 for (cur = plugin->ppc_dll_head; NULL != cur; cur = next)
3049 { 3063 {
3050 next = cur->next; 3064 next = cur->next;
3051 GNUNET_CONTAINER_DLL_remove (ppc_dll_head, 3065 GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
3052 ppc_dll_tail, 3066 plugin->ppc_dll_tail,
3053 cur); 3067 cur);
3054 GNUNET_RESOLVER_request_cancel (cur->resolver_handle); 3068 GNUNET_RESOLVER_request_cancel (cur->resolver_handle);
3055 cur->asc (cur->asc_cls, NULL, GNUNET_OK); 3069 cur->asc (cur->asc_cls,
3070 NULL,
3071 GNUNET_OK);
3056 GNUNET_free (cur); 3072 GNUNET_free (cur);
3057 } 3073 }
3058 3074