diff options
-rw-r--r-- | doc/handbook/chapters/developer.texi | 118 | ||||
-rw-r--r-- | doc/handbook/chapters/installation.texi | 31 | ||||
-rw-r--r-- | doc/handbook/chapters/user.texi | 41 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/ats/Makefile.am | 2 | ||||
-rw-r--r-- | src/ats/test_ats2_lib.conf | 13 | ||||
-rw-r--r-- | src/include/gnunet_container_lib.h | 2 | ||||
-rw-r--r-- | src/include/gnunet_mq_lib.h | 45 | ||||
-rw-r--r-- | src/include/gnunet_protocols.h | 5 | ||||
-rw-r--r-- | src/transport/gnunet-service-tng.c | 565 | ||||
-rw-r--r-- | src/util/mq.c | 44 |
11 files changed, 792 insertions, 76 deletions
diff --git a/doc/handbook/chapters/developer.texi b/doc/handbook/chapters/developer.texi index d9c92247b..2da262b34 100644 --- a/doc/handbook/chapters/developer.texi +++ b/doc/handbook/chapters/developer.texi | |||
@@ -7743,6 +7743,7 @@ record types. | |||
7743 | * The GNS Client-Service Protocol:: | 7743 | * The GNS Client-Service Protocol:: |
7744 | * Hijacking the DNS-Traffic using gnunet-service-dns:: | 7744 | * Hijacking the DNS-Traffic using gnunet-service-dns:: |
7745 | * Serving DNS lookups via GNS on W32:: | 7745 | * Serving DNS lookups via GNS on W32:: |
7746 | * Importing DNS Zones into GNS:: | ||
7746 | @end menu | 7747 | @end menu |
7747 | 7748 | ||
7748 | @node libgnunetgns | 7749 | @node libgnunetgns |
@@ -8073,6 +8074,119 @@ applications that use alternative means of resolving names (such as | |||
8073 | sending queries to a DNS server directly by themselves). | 8074 | sending queries to a DNS server directly by themselves). |
8074 | This includes some of well known utilities, like "ping" and "nslookup". | 8075 | This includes some of well known utilities, like "ping" and "nslookup". |
8075 | 8076 | ||
8077 | @node Importing DNS Zones into GNS | ||
8078 | @subsection Importing DNS Zones into GNS | ||
8079 | |||
8080 | @c %**end of header | ||
8081 | |||
8082 | This section discusses the challenges and problems faced when writing the | ||
8083 | ascension tool. It also takes a look at possible improvements in the future. | ||
8084 | |||
8085 | @menu | ||
8086 | * Conversions between DNS and GNS:: | ||
8087 | * DNS Zone Size:: | ||
8088 | * Performance:: | ||
8089 | @end menu | ||
8090 | |||
8091 | @node Conversions between DNS and GNS | ||
8092 | @subsubsection Conversions between DNS and GNS | ||
8093 | |||
8094 | The differences between the two name systems lies in the details | ||
8095 | and is not always transparent. For instance an SRV record is converted to a | ||
8096 | gnunet only BOX record. | ||
8097 | |||
8098 | This is done by converting to a BOX record from an existing SRV record: | ||
8099 | |||
8100 | @example | ||
8101 | # SRV | ||
8102 | # _service._proto.name. TTL class SRV priority weight port target | ||
8103 | _sip._tcp.example.com. 14000 IN SRV 0 0 5060 www.example.com. | ||
8104 | # BOX | ||
8105 | # TTL BOX flags port protocol recordtype priority weight port target | ||
8106 | 14000 BOX n 5060 6 33 0 0 5060 www.example.com | ||
8107 | @end example | ||
8108 | |||
8109 | Other records that have such a transformation is the MX record type, as well as | ||
8110 | the SOA record type. | ||
8111 | |||
8112 | Transformation of a SOA record into GNS works as described in the following | ||
8113 | example. Very important to note are the rname and mname keys. | ||
8114 | @example | ||
8115 | # BIND syntax for a clean SOA record | ||
8116 | @ IN SOA master.example.com. hostmaster.example.com. ( | ||
8117 | 2017030300 ; serial | ||
8118 | 3600 ; refresh | ||
8119 | 1800 ; retry | ||
8120 | 604800 ; expire | ||
8121 | 600 ) ; ttl | ||
8122 | # Recordline for adding the record | ||
8123 | gnunet-namestore -z example.com -a -n @ -t SOA -V rname=master.example.com \ | ||
8124 | mname=hostmaster.example.com 2017030300,3600,1800,604800,600 -e 7200s | ||
8125 | @end example | ||
8126 | |||
8127 | The transformation of MX records is done in a simple way. | ||
8128 | @example | ||
8129 | # mail.example.com. 3600 IN MX 10 mail.example.com. | ||
8130 | gnunet-namestore -z example.com -n mail -R 3600 MX n 10,mail | ||
8131 | @end example | ||
8132 | |||
8133 | Finally, one of the biggest struggling points were the NS records that are found | ||
8134 | in top level domain zones. The intended behaviour for those is to add GNS2DNS | ||
8135 | records for those so that gnunet-gns can resolve records for those domains on | ||
8136 | its own. This requires migration of the DNS GLUE records as well, provided that | ||
8137 | they are within the same zone. | ||
8138 | |||
8139 | A solution was found by creating a hierarchical zone structure in GNS and linking | ||
8140 | the zones using PKEY records to one another. This allows the resolution of the | ||
8141 | nameservers to work within GNS while not taking control over unwanted zones. | ||
8142 | |||
8143 | @node DNS Zone Size | ||
8144 | @subsubsection DNS Zone Size | ||
8145 | |||
8146 | Another very big problem exists with very large zones. When migrating a small | ||
8147 | zone the delay between adding of records and their expiry is negligible. However | ||
8148 | when working with a TLD zone that has more that 1 million records this delay | ||
8149 | becomes a problem. | ||
8150 | |||
8151 | Records will start to expire well before the zone has finished migrating. This | ||
8152 | causes unwanted anomalies when trying to resolve records. | ||
8153 | |||
8154 | A good solution has not been found yet. One of the idea that floated around was | ||
8155 | that the records should be added with the s (shadow) flag to keep the records | ||
8156 | resolvable even if they expired. However this would introduce the problem of how | ||
8157 | to detect if a record has been removed from the zone and would require deletion | ||
8158 | of said record(s). | ||
8159 | |||
8160 | Another problem that still persists is how to refresh records. Expired records | ||
8161 | are still displayed when calling gnunet-namestore but do not resolve with | ||
8162 | gnunet-gns. When doing incremental zone transfers this becomes especially | ||
8163 | apparent. | ||
8164 | |||
8165 | @node Performance | ||
8166 | @subsubsection Performance | ||
8167 | The performance when migrating a zone using the ascension tool is limited by a | ||
8168 | handful of factors. First of all ascension is written in python3 and calls the | ||
8169 | CLI tools of gnunet. Furthermore all the records that are added to the same | ||
8170 | label are signed using the zones private key. This signing operation is very | ||
8171 | resource heavy and was optimized during development by adding the '-R' | ||
8172 | (Recordline) option to gnunet-namestore. This allows to add multiple records | ||
8173 | at once using the CLI. | ||
8174 | |||
8175 | The result of this was a much faster migration of TLD zones, as most records | ||
8176 | with the same label have two name servers. | ||
8177 | |||
8178 | Another improvement that could be made is with the addition of multiple threads | ||
8179 | when opening the gnunet CLI tools. This could be implemented by simply creating | ||
8180 | more workers in the program but performance improvements were not tested. | ||
8181 | |||
8182 | During the entire development of the ascension tool sqlite was used as a | ||
8183 | database backend. Other backends need to be tested in the future. | ||
8184 | |||
8185 | In conclusion there are many bottlenecks still around in the program, namely the | ||
8186 | signing process and the single threaded implementation. In the future a solution | ||
8187 | that uses the c api would be cleaner and better. | ||
8188 | |||
8189 | |||
8076 | @cindex GNS Namecache | 8190 | @cindex GNS Namecache |
8077 | @node GNS Namecache | 8191 | @node GNS Namecache |
8078 | @section GNS Namecache | 8192 | @section GNS Namecache |
@@ -8768,14 +8882,14 @@ regular expressions. | |||
8768 | 8882 | ||
8769 | Using the REST subsystem, you can expose REST-based APIs or services. | 8883 | Using the REST subsystem, you can expose REST-based APIs or services. |
8770 | The REST service is designed as a pluggable architecture. | 8884 | The REST service is designed as a pluggable architecture. |
8771 | To create a new REST endpoint, simply add a library in the form | 8885 | To create a new REST endpoint, simply add a library in the form |
8772 | ``plugin_rest_*''. | 8886 | ``plugin_rest_*''. |
8773 | The REST service will automatically load all REST plugins on startup. | 8887 | The REST service will automatically load all REST plugins on startup. |
8774 | 8888 | ||
8775 | @strong{Configuration} | 8889 | @strong{Configuration} |
8776 | 8890 | ||
8777 | The REST service can be configured in various ways. | 8891 | The REST service can be configured in various ways. |
8778 | The reference config file can be found in | 8892 | The reference config file can be found in |
8779 | @file{src/rest/rest.conf}: | 8893 | @file{src/rest/rest.conf}: |
8780 | @example | 8894 | @example |
8781 | [rest] | 8895 | [rest] |
diff --git a/doc/handbook/chapters/installation.texi b/doc/handbook/chapters/installation.texi index c05f776f2..bdff20802 100644 --- a/doc/handbook/chapters/installation.texi +++ b/doc/handbook/chapters/installation.texi | |||
@@ -35,7 +35,7 @@ The mandatory libraries and applications are | |||
35 | @item libextractor | 35 | @item libextractor |
36 | @item libidn | 36 | @item libidn |
37 | @item libmicrohttpd @geq{}0.9.52 | 37 | @item libmicrohttpd @geq{}0.9.52 |
38 | @item libnss | 38 | @item libnss |
39 | @item libunistring | 39 | @item libunistring |
40 | @item gettext | 40 | @item gettext |
41 | @item glibc | 41 | @item glibc |
@@ -1427,6 +1427,7 @@ and @code{[transport-https_client]} section of the configuration: | |||
1427 | * GNS Proxy Setup:: | 1427 | * GNS Proxy Setup:: |
1428 | * Setup of the GNS CA:: | 1428 | * Setup of the GNS CA:: |
1429 | * Testing the GNS setup:: | 1429 | * Testing the GNS setup:: |
1430 | * Migrating existing DNS zones into GNS:: | ||
1430 | @end menu | 1431 | @end menu |
1431 | 1432 | ||
1432 | 1433 | ||
@@ -1693,6 +1694,34 @@ configured proxy) should give you a valid SSL certificate for | |||
1693 | @c FIXME: Image does not exist, create it or save it from Drupal? | 1694 | @c FIXME: Image does not exist, create it or save it from Drupal? |
1694 | @c @image{images/gnunethpgns.png,5in,, picture of homepage.gnu in Webbrowser} | 1695 | @c @image{images/gnunethpgns.png,5in,, picture of homepage.gnu in Webbrowser} |
1695 | 1696 | ||
1697 | @node Migrating existing DNS zones into GNS | ||
1698 | @subsubsection Migrating existing DNS zones into GNS | ||
1699 | |||
1700 | To migrate an existing zone into GNS use the ascension tool. | ||
1701 | |||
1702 | Ascension transfers entire zones into GNS by doing incremental zone transfers | ||
1703 | and then adding the records to GNS. | ||
1704 | |||
1705 | You can find the source code here: @code{https://gnunet.org/git/ascension.git/} | ||
1706 | |||
1707 | The software can be installed into a python virtual environment like this: | ||
1708 | @example | ||
1709 | $ python3 -m venv .venv | ||
1710 | $ source .venv/bin/activate | ||
1711 | $ python3 setup.py install | ||
1712 | @end example | ||
1713 | |||
1714 | Or installed globally like this (not recommended): | ||
1715 | @example | ||
1716 | $ sudo python3 setup.py install | ||
1717 | @end example | ||
1718 | |||
1719 | The advantage of using a virtual environment is, that all the dependencies can | ||
1720 | be installed separately in different versions without touching your existing | ||
1721 | python installation and its dependencies. | ||
1722 | |||
1723 | Using the tool is discussed in the user section of the documentation. | ||
1724 | |||
1696 | 1725 | ||
1697 | @node Configuring the GNUnet VPN | 1726 | @node Configuring the GNUnet VPN |
1698 | @subsection Configuring the GNUnet VPN | 1727 | @subsection Configuring the GNUnet VPN |
diff --git a/doc/handbook/chapters/user.texi b/doc/handbook/chapters/user.texi index ea41bbb6c..0703adafc 100644 --- a/doc/handbook/chapters/user.texi +++ b/doc/handbook/chapters/user.texi | |||
@@ -1453,6 +1453,7 @@ the user. This results in non-unique name-value mappings as | |||
1453 | * Using Public Keys as Top Level Domains:: | 1453 | * Using Public Keys as Top Level Domains:: |
1454 | * Resource Records in GNS:: | 1454 | * Resource Records in GNS:: |
1455 | * Synchronizing with legacy DNS:: | 1455 | * Synchronizing with legacy DNS:: |
1456 | * Migrating an existing DNS zone into GNS:: | ||
1456 | @end menu | 1457 | @end menu |
1457 | 1458 | ||
1458 | 1459 | ||
@@ -1891,6 +1892,43 @@ DNS zone and that do not have a local gns service in use, it | |||
1891 | is thus advisable to disable the namecache by setting the | 1892 | is thus advisable to disable the namecache by setting the |
1892 | option ``DISABLE'' to ``YES'' in section ``[namecache]''. | 1893 | option ``DISABLE'' to ``YES'' in section ``[namecache]''. |
1893 | 1894 | ||
1895 | @node Migrating an existing DNS zone into GNS | ||
1896 | @subsection Migrating an existing DNS zone into GNS | ||
1897 | |||
1898 | After installing the tool according to the README file you have the following | ||
1899 | options: | ||
1900 | @example | ||
1901 | Ascension | ||
1902 | |||
1903 | Usage: | ||
1904 | ascension.py <domain> [-d] | ||
1905 | ascension.py <domain> -p <port> [-d] | ||
1906 | ascension.py <domain> -ns <transferns> [-d] | ||
1907 | ascension.py <domain> -ns <transferns> -p <port> [-d] | ||
1908 | ascension.py -h | --help | ||
1909 | ascension.py -v | --version | ||
1910 | |||
1911 | Options: | ||
1912 | <port> Port for zone transfer | ||
1913 | <domain> Domain to migrate | ||
1914 | <transferns> DNS Server that does the zone transfer | ||
1915 | -d --debug Enable debugging | ||
1916 | -h --help Show this screen. | ||
1917 | -v --version Show version. | ||
1918 | @end example | ||
1919 | |||
1920 | To migrate the Syrian top level domain - one of the few top level domains that | ||
1921 | still supports zone transfers - use the following command: | ||
1922 | |||
1923 | @example | ||
1924 | $ ascension sy. -ns ns1.tld.sy. | ||
1925 | @end example | ||
1926 | |||
1927 | The program will continue to run as a daemon and update once the refresh time | ||
1928 | specified in the zones SOA record has elapsed. | ||
1929 | |||
1930 | At this point you might want to write for example a systemd unit file to start | ||
1931 | and enable the service, so that your zone is migrated automatically. | ||
1894 | 1932 | ||
1895 | @node re@:claim Identity Provider | 1933 | @node re@:claim Identity Provider |
1896 | @section re@:claim Identity Provider | 1934 | @section re@:claim Identity Provider |
@@ -1962,7 +2000,7 @@ Further, the "ticket" can be re-used later to retrieve up-to-date attributes in | |||
1962 | 2000 | ||
1963 | To list all given authorizations (tickets) you can execute: | 2001 | To list all given authorizations (tickets) you can execute: |
1964 | @example | 2002 | @example |
1965 | $ gnunet-reclaim -e "friend" -T (TODO there is only a C and REST API for this at this time) | 2003 | $ gnunet-reclaim -e "friend" -T (TODO there is only a C and REST API for this at this time) |
1966 | @end example | 2004 | @end example |
1967 | 2005 | ||
1968 | 2006 | ||
@@ -2292,3 +2330,4 @@ protocol (--tcp or --udp) and you will again receive an IP address | |||
2292 | that will terminate at the respective peer's service. | 2330 | that will terminate at the respective peer's service. |
2293 | 2331 | ||
2294 | 2332 | ||
2333 | |||
diff --git a/src/Makefile.am b/src/Makefile.am index ffb39260c..5fd65141b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -94,11 +94,11 @@ SUBDIRS = \ | |||
94 | datacache \ | 94 | datacache \ |
95 | datastore \ | 95 | datastore \ |
96 | template \ | 96 | template \ |
97 | peerstore \ | ||
97 | ats \ | 98 | ats \ |
98 | nat \ | 99 | nat \ |
99 | nat-auto \ | 100 | nat-auto \ |
100 | fragmentation \ | 101 | fragmentation \ |
101 | peerstore \ | ||
102 | transport \ | 102 | transport \ |
103 | ats-tool \ | 103 | ats-tool \ |
104 | peerinfo-tool \ | 104 | peerinfo-tool \ |
diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am index f113d96e7..4f2a93227 100644 --- a/src/ats/Makefile.am +++ b/src/ats/Makefile.am | |||
@@ -82,6 +82,8 @@ libgnunet_plugin_ats2_simple_la_SOURCES = \ | |||
82 | plugin_ats2_simple.c | 82 | plugin_ats2_simple.c |
83 | libgnunet_plugin_ats2_simple_la_LIBADD = \ | 83 | libgnunet_plugin_ats2_simple_la_LIBADD = \ |
84 | $(top_builddir)/src/hello/libgnunethello.la \ | 84 | $(top_builddir)/src/hello/libgnunethello.la \ |
85 | $(top_builddir)/src/peerstore/libgnunetpeerstore.la \ | ||
86 | $(top_builddir)/src/nt/libgnunetnt.la \ | ||
85 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 87 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
86 | $(top_builddir)/src/util/libgnunetutil.la \ | 88 | $(top_builddir)/src/util/libgnunetutil.la \ |
87 | $(LTLIBINTL) | 89 | $(LTLIBINTL) |
diff --git a/src/ats/test_ats2_lib.conf b/src/ats/test_ats2_lib.conf new file mode 100644 index 000000000..e24f5ea68 --- /dev/null +++ b/src/ats/test_ats2_lib.conf | |||
@@ -0,0 +1,13 @@ | |||
1 | @INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf | ||
2 | @INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf | ||
3 | |||
4 | [ats] | ||
5 | BINARY = gnunet-service-ats-new | ||
6 | |||
7 | [core] | ||
8 | START_ON_DEMAND = NO | ||
9 | IMMEDIATE_START = NO | ||
10 | |||
11 | [transport] | ||
12 | START_ON_DEMAND = NO | ||
13 | IMMEDIATE_START = NO | ||
diff --git a/src/include/gnunet_container_lib.h b/src/include/gnunet_container_lib.h index e7bd4113d..fee851e1c 100644 --- a/src/include/gnunet_container_lib.h +++ b/src/include/gnunet_container_lib.h | |||
@@ -2011,7 +2011,7 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (struct GNUNET_CONTAINER_MultiH | |||
2011 | if (NULL == (element)->next_##mdll) \ | 2011 | if (NULL == (element)->next_##mdll) \ |
2012 | (tail) = (element); \ | 2012 | (tail) = (element); \ |
2013 | else \ | 2013 | else \ |
2014 | (element)->next->prev_##mdll = (element); } while (0) | 2014 | (element)->next_##mdll->prev_##mdll = (element); } while (0) |
2015 | 2015 | ||
2016 | 2016 | ||
2017 | /** | 2017 | /** |
diff --git a/src/include/gnunet_mq_lib.h b/src/include/gnunet_mq_lib.h index 3f67dc365..2a459636a 100644 --- a/src/include/gnunet_mq_lib.h +++ b/src/include/gnunet_mq_lib.h | |||
@@ -528,6 +528,51 @@ struct GNUNET_MQ_MessageHandler | |||
528 | 528 | ||
529 | 529 | ||
530 | /** | 530 | /** |
531 | * Insert code for a "check_" function that verifies that | ||
532 | * a given variable-length message received over the network | ||
533 | * is followed by another variable-length message that fits | ||
534 | * exactly with the given size. If the message @a m | ||
535 | * is not followed by another `struct GNUNET_MessageHeader` | ||
536 | * with a size that adds up to the total size, an error is logged | ||
537 | * and the function is returned with #GNUNET_NO. | ||
538 | * | ||
539 | * @param an IPC message with proper type to determine | ||
540 | * the size, starting with a `struct GNUNET_MessageHeader` | ||
541 | */ | ||
542 | #define GNUNET_MQ_check_boxed_message(m) \ | ||
543 | { \ | ||
544 | const struct GNUNET_MessageHeader *inbox = \ | ||
545 | (const struct GNUNET_MessageHeader *) &m[1]; \ | ||
546 | const struct GNUNET_MessageHeader *hdr = \ | ||
547 | (const struct GNUNET_MessageHeader *) m; \ | ||
548 | uint16_t slen = ntohs (hdr->size) - sizeof (*m); \ | ||
549 | if ( (slen < sizeof (struct GNUNET_MessageHeader))||\ | ||
550 | (slen != ntohs (inbox->size)) ) \ | ||
551 | { \ | ||
552 | GNUNET_break (0); \ | ||
553 | return GNUNET_NO; \ | ||
554 | } \ | ||
555 | } | ||
556 | |||
557 | |||
558 | /** | ||
559 | * Call the message message handler that was registered | ||
560 | * for the type of the given message in the given @a handlers list. | ||
561 | * | ||
562 | * This function is indended to be used for the implementation | ||
563 | * of message queues. | ||
564 | * | ||
565 | * @param handlers a set of handlers | ||
566 | * @param mh message to dispatch | ||
567 | * @return #GNUNET_OK on success, #GNUNET_NO if no handler matched, | ||
568 | * #GNUNET_SYSERR if message was rejected by check function | ||
569 | */ | ||
570 | int | ||
571 | GNUNET_MQ_handle_message (const struct GNUNET_MQ_MessageHandler *handlers, | ||
572 | const struct GNUNET_MessageHeader *mh); | ||
573 | |||
574 | |||
575 | /** | ||
531 | * Create a new envelope. | 576 | * Create a new envelope. |
532 | * | 577 | * |
533 | * @param mhp message header to store the allocated message header in, can be NULL | 578 | * @param mhp message header to store the allocated message header in, can be NULL |
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 8593005d7..a8d716b3f 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -3125,6 +3125,11 @@ extern "C" | |||
3125 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX 1219 | 3125 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX 1219 |
3126 | 3126 | ||
3127 | /** | 3127 | /** |
3128 | * Transport affirming receipt of an ephemeral key. | ||
3129 | */ | ||
3130 | #define GNUNET_MESSAGE_TYPE_TRANSPORT_EPHEMERAL_CONFIRMATION 1220 | ||
3131 | |||
3132 | /** | ||
3128 | * Message sent to indicate to the transport that a monitor | 3133 | * Message sent to indicate to the transport that a monitor |
3129 | * wants to observe certain events. | 3134 | * wants to observe certain events. |
3130 | */ | 3135 | */ |
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 8febbdfff..3cccf5173 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c | |||
@@ -33,7 +33,7 @@ | |||
33 | * transport-to-transport traffic) | 33 | * transport-to-transport traffic) |
34 | * | 34 | * |
35 | * Implement: | 35 | * Implement: |
36 | * - manage fragmentation/defragmentation, retransmission, track RTT, loss, etc. | 36 | * - manage defragmentation, retransmission, track RTT, loss, etc. |
37 | * | 37 | * |
38 | * Easy: | 38 | * Easy: |
39 | * - use ATS bandwidth allocation callback and schedule transmissions! | 39 | * - use ATS bandwidth allocation callback and schedule transmissions! |
@@ -165,8 +165,8 @@ struct TransportBackchannelEncapsulationMessage | |||
165 | 165 | ||
166 | 166 | ||
167 | /** | 167 | /** |
168 | * Message by which a peer confirms that it is using an | 168 | * Body by which a peqer confirms that it is using an ephemeral |
169 | * ephemeral key. | 169 | * key. |
170 | */ | 170 | */ |
171 | struct EphemeralConfirmation | 171 | struct EphemeralConfirmation |
172 | { | 172 | { |
@@ -192,6 +192,37 @@ struct EphemeralConfirmation | |||
192 | 192 | ||
193 | 193 | ||
194 | /** | 194 | /** |
195 | * Message by which a peqer confirms that it is using an ephemeral | ||
196 | * key. | ||
197 | */ | ||
198 | struct EphemeralConfirmationMessage | ||
199 | { | ||
200 | |||
201 | /** | ||
202 | * Message header, type is #GNUNET_MESSAGE_TYPE_TRANSPORT_EPHEMERAL_CONFIRMATION | ||
203 | */ | ||
204 | struct GNUNET_MessageHeader header; | ||
205 | |||
206 | /** | ||
207 | * Must be zero. | ||
208 | */ | ||
209 | uint32_t reserved; | ||
210 | |||
211 | /** | ||
212 | * How long is this signature over the ephemeral key | ||
213 | * valid? | ||
214 | */ | ||
215 | struct GNUNET_TIME_AbsoluteNBO ephemeral_validity; | ||
216 | |||
217 | /** | ||
218 | * Ephemeral key setup by the sender for @e target, used | ||
219 | * to encrypt the payload. | ||
220 | */ | ||
221 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
222 | }; | ||
223 | |||
224 | |||
225 | /** | ||
195 | * Plaintext of the variable-size payload that is encrypted | 226 | * Plaintext of the variable-size payload that is encrypted |
196 | * within a `struct TransportBackchannelEncapsulationMessage` | 227 | * within a `struct TransportBackchannelEncapsulationMessage` |
197 | */ | 228 | */ |
@@ -863,7 +894,12 @@ struct PendingMessage | |||
863 | * Kept in a MDLL of messages from this @a cpm (if @e pmt is #PMT_FRAGMENT_BOX) | 894 | * Kept in a MDLL of messages from this @a cpm (if @e pmt is #PMT_FRAGMENT_BOX) |
864 | */ | 895 | */ |
865 | struct PendingMessage *prev_frag; | 896 | struct PendingMessage *prev_frag; |
866 | 897 | ||
898 | /** | ||
899 | * This message, reliability boxed. Only possibly available if @e pmt is #PMT_CORE. | ||
900 | */ | ||
901 | struct PendingMessage *bpm; | ||
902 | |||
867 | /** | 903 | /** |
868 | * Target of the request. | 904 | * Target of the request. |
869 | */ | 905 | */ |
@@ -1798,6 +1834,36 @@ free_fragment_tree (struct PendingMessage *root) | |||
1798 | 1834 | ||
1799 | 1835 | ||
1800 | /** | 1836 | /** |
1837 | * Release memory associated with @a pm and remove @a pm from associated | ||
1838 | * data structures. @a pm must be a top-level pending message and not | ||
1839 | * a fragment in the tree. The entire tree is freed (if applicable). | ||
1840 | * | ||
1841 | * @param pm the pending message to free | ||
1842 | */ | ||
1843 | static void | ||
1844 | free_pending_message (struct PendingMessage *pm) | ||
1845 | { | ||
1846 | struct TransportClient *tc = pm->client; | ||
1847 | struct Neighbour *target = pm->target; | ||
1848 | |||
1849 | if (NULL != tc) | ||
1850 | { | ||
1851 | GNUNET_CONTAINER_MDLL_remove (client, | ||
1852 | tc->details.core.pending_msg_head, | ||
1853 | tc->details.core.pending_msg_tail, | ||
1854 | pm); | ||
1855 | } | ||
1856 | GNUNET_CONTAINER_MDLL_remove (neighbour, | ||
1857 | target->pending_msg_head, | ||
1858 | target->pending_msg_tail, | ||
1859 | pm); | ||
1860 | free_fragment_tree (pm); | ||
1861 | GNUNET_free_non_null (pm->bpm); | ||
1862 | GNUNET_free (pm); | ||
1863 | } | ||
1864 | |||
1865 | |||
1866 | /** | ||
1801 | * Send a response to the @a pm that we have processed a | 1867 | * Send a response to the @a pm that we have processed a |
1802 | * "send" request with status @a success. We | 1868 | * "send" request with status @a success. We |
1803 | * transmitted @a bytes_physical on the actual wire. | 1869 | * transmitted @a bytes_physical on the actual wire. |
@@ -1829,17 +1895,8 @@ client_send_response (struct PendingMessage *pm, | |||
1829 | som->peer = target->pid; | 1895 | som->peer = target->pid; |
1830 | GNUNET_MQ_send (tc->mq, | 1896 | GNUNET_MQ_send (tc->mq, |
1831 | env); | 1897 | env); |
1832 | GNUNET_CONTAINER_MDLL_remove (client, | ||
1833 | tc->details.core.pending_msg_head, | ||
1834 | tc->details.core.pending_msg_tail, | ||
1835 | pm); | ||
1836 | } | 1898 | } |
1837 | GNUNET_CONTAINER_MDLL_remove (neighbour, | 1899 | free_pending_message (pm); |
1838 | target->pending_msg_head, | ||
1839 | target->pending_msg_tail, | ||
1840 | pm); | ||
1841 | free_fragment_tree (pm); | ||
1842 | GNUNET_free (pm); | ||
1843 | } | 1900 | } |
1844 | 1901 | ||
1845 | 1902 | ||
@@ -2176,36 +2233,291 @@ handle_del_address (void *cls, | |||
2176 | 2233 | ||
2177 | 2234 | ||
2178 | /** | 2235 | /** |
2236 | * Context from #handle_incoming_msg(). Closure for many | ||
2237 | * message handlers below. | ||
2238 | */ | ||
2239 | struct CommunicatorMessageContext | ||
2240 | { | ||
2241 | /** | ||
2242 | * Which communicator provided us with the message. | ||
2243 | */ | ||
2244 | struct TransportClient *tc; | ||
2245 | |||
2246 | /** | ||
2247 | * Additional information for flow control and about the sender. | ||
2248 | */ | ||
2249 | struct GNUNET_TRANSPORT_IncomingMessage im; | ||
2250 | }; | ||
2251 | |||
2252 | |||
2253 | /** | ||
2254 | * Send ACK to communicator (if requested) and free @a cmc. | ||
2255 | * | ||
2256 | * @param cmc context for which we are done handling the message | ||
2257 | */ | ||
2258 | static void | ||
2259 | finish_cmc_handling (struct CommunicatorMessageContext *cmc) | ||
2260 | { | ||
2261 | // FIXME: if (0 != ntohl (im->fc_on)) => send ACK when done to communicator for flow control! | ||
2262 | GNUNET_SERVICE_client_continue (cmc->tc->client); | ||
2263 | |||
2264 | GNUNET_free (cmc); | ||
2265 | } | ||
2266 | |||
2267 | |||
2268 | /** | ||
2269 | * Communicator gave us an unencapsulated message to pass | ||
2270 | * as-is to CORE. Process the request. | ||
2271 | * | ||
2272 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2273 | * @param mh the message that was received | ||
2274 | */ | ||
2275 | static void | ||
2276 | handle_raw_message (void *cls, | ||
2277 | const struct GNUNET_MessageHeader *mh) | ||
2278 | { | ||
2279 | struct CommunicatorMessageContext *cmc = cls; | ||
2280 | |||
2281 | // FIXME: do work! | ||
2282 | finish_cmc_handling (cmc); | ||
2283 | } | ||
2284 | |||
2285 | |||
2286 | /** | ||
2287 | * Communicator gave us a fragment box. Check the message. | ||
2288 | * | ||
2289 | * @param cls a `struct CommunicatorMessageContext` | ||
2290 | * @param fb the send message that was sent | ||
2291 | * @return #GNUNET_YES if message is well-formed | ||
2292 | */ | ||
2293 | static int | ||
2294 | check_fragment_box (void *cls, | ||
2295 | const struct TransportFragmentBox *fb) | ||
2296 | { | ||
2297 | // FIXME! check that off + size-of-payload <= total-length! | ||
2298 | return GNUNET_YES; | ||
2299 | } | ||
2300 | |||
2301 | |||
2302 | /** | ||
2303 | * Communicator gave us a fragment. Process the request. | ||
2304 | * | ||
2305 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2306 | * @param fb the message that was received | ||
2307 | */ | ||
2308 | static void | ||
2309 | handle_fragment_box (void *cls, | ||
2310 | const struct TransportFragmentBox *fb) | ||
2311 | { | ||
2312 | struct CommunicatorMessageContext *cmc = cls; | ||
2313 | |||
2314 | // FIXME: do work! | ||
2315 | finish_cmc_handling (cmc); | ||
2316 | } | ||
2317 | |||
2318 | |||
2319 | /** | ||
2320 | * Communicator gave us a fragment acknowledgement. Process the request. | ||
2321 | * | ||
2322 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2323 | * @param fa the message that was received | ||
2324 | */ | ||
2325 | static void | ||
2326 | handle_fragment_ack (void *cls, | ||
2327 | const struct TransportFragmentAckMessage *fa) | ||
2328 | { | ||
2329 | struct CommunicatorMessageContext *cmc = cls; | ||
2330 | |||
2331 | // FIXME: do work! | ||
2332 | finish_cmc_handling (cmc); | ||
2333 | } | ||
2334 | |||
2335 | |||
2336 | /** | ||
2337 | * Communicator gave us a reliability box. Check the message. | ||
2338 | * | ||
2339 | * @param cls a `struct CommunicatorMessageContext` | ||
2340 | * @param rb the send message that was sent | ||
2341 | * @return #GNUNET_YES if message is well-formed | ||
2342 | */ | ||
2343 | static int | ||
2344 | check_reliability_box (void *cls, | ||
2345 | const struct TransportReliabilityBox *rb) | ||
2346 | { | ||
2347 | GNUNET_MQ_check_boxed_message (rb); | ||
2348 | return GNUNET_YES; | ||
2349 | } | ||
2350 | |||
2351 | |||
2352 | /** | ||
2353 | * Communicator gave us a reliability box. Process the request. | ||
2354 | * | ||
2355 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2356 | * @param rb the message that was received | ||
2357 | */ | ||
2358 | static void | ||
2359 | handle_reliability_box (void *cls, | ||
2360 | const struct TransportReliabilityBox *rb) | ||
2361 | { | ||
2362 | struct CommunicatorMessageContext *cmc = cls; | ||
2363 | |||
2364 | // FIXME: do work! | ||
2365 | finish_cmc_handling (cmc); | ||
2366 | } | ||
2367 | |||
2368 | |||
2369 | /** | ||
2370 | * Communicator gave us a reliability ack. Process the request. | ||
2371 | * | ||
2372 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2373 | * @param ra the message that was received | ||
2374 | */ | ||
2375 | static void | ||
2376 | handle_reliability_ack (void *cls, | ||
2377 | const struct TransportReliabilityAckMessage *ra) | ||
2378 | { | ||
2379 | struct CommunicatorMessageContext *cmc = cls; | ||
2380 | |||
2381 | // FIXME: do work! | ||
2382 | finish_cmc_handling (cmc); | ||
2383 | } | ||
2384 | |||
2385 | |||
2386 | /** | ||
2387 | * Communicator gave us a backchannel encapsulation. Check the message. | ||
2388 | * | ||
2389 | * @param cls a `struct CommunicatorMessageContext` | ||
2390 | * @param be the send message that was sent | ||
2391 | * @return #GNUNET_YES if message is well-formed | ||
2392 | */ | ||
2393 | static int | ||
2394 | check_backchannel_encapsulation (void *cls, | ||
2395 | const struct TransportBackchannelEncapsulationMessage *be) | ||
2396 | { | ||
2397 | // FIXME: do work! | ||
2398 | return GNUNET_YES; | ||
2399 | } | ||
2400 | |||
2401 | |||
2402 | /** | ||
2403 | * Communicator gave us a backchannel encapsulation. Process the request. | ||
2404 | * | ||
2405 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2406 | * @param be the message that was received | ||
2407 | */ | ||
2408 | static void | ||
2409 | handle_backchannel_encapsulation (void *cls, | ||
2410 | const struct TransportBackchannelEncapsulationMessage *be) | ||
2411 | { | ||
2412 | struct CommunicatorMessageContext *cmc = cls; | ||
2413 | |||
2414 | // FIXME: do work! | ||
2415 | finish_cmc_handling (cmc); | ||
2416 | } | ||
2417 | |||
2418 | |||
2419 | /** | ||
2420 | * Communicator gave us an ephemeral confirmation. Process the request. | ||
2421 | * | ||
2422 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2423 | * @param ec the message that was received | ||
2424 | */ | ||
2425 | static void | ||
2426 | handle_ephemeral_confirmation (void *cls, | ||
2427 | const struct EphemeralConfirmationMessage *ec) | ||
2428 | { | ||
2429 | struct CommunicatorMessageContext *cmc = cls; | ||
2430 | |||
2431 | // FIXME: do work! | ||
2432 | finish_cmc_handling (cmc); | ||
2433 | } | ||
2434 | |||
2435 | |||
2436 | /** | ||
2437 | * Communicator gave us a DV learn message. Check the message. | ||
2438 | * | ||
2439 | * @param cls a `struct CommunicatorMessageContext` | ||
2440 | * @param dvl the send message that was sent | ||
2441 | * @return #GNUNET_YES if message is well-formed | ||
2442 | */ | ||
2443 | static int | ||
2444 | check_dv_learn (void *cls, | ||
2445 | const struct TransportDVLearn *dvl) | ||
2446 | { | ||
2447 | // FIXME: do work! | ||
2448 | return GNUNET_YES; | ||
2449 | } | ||
2450 | |||
2451 | |||
2452 | /** | ||
2453 | * Communicator gave us a DV learn message. Process the request. | ||
2454 | * | ||
2455 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2456 | * @param dvl the message that was received | ||
2457 | */ | ||
2458 | static void | ||
2459 | handle_dv_learn (void *cls, | ||
2460 | const struct TransportDVLearn *dvl) | ||
2461 | { | ||
2462 | struct CommunicatorMessageContext *cmc = cls; | ||
2463 | |||
2464 | // FIXME: do work! | ||
2465 | finish_cmc_handling (cmc); | ||
2466 | } | ||
2467 | |||
2468 | |||
2469 | /** | ||
2470 | * Communicator gave us a DV box. Check the message. | ||
2471 | * | ||
2472 | * @param cls a `struct CommunicatorMessageContext` | ||
2473 | * @param dvb the send message that was sent | ||
2474 | * @return #GNUNET_YES if message is well-formed | ||
2475 | */ | ||
2476 | static int | ||
2477 | check_dv_box (void *cls, | ||
2478 | const struct TransportDVBox *dvb) | ||
2479 | { | ||
2480 | // FIXME: do work! | ||
2481 | return GNUNET_YES; | ||
2482 | } | ||
2483 | |||
2484 | |||
2485 | /** | ||
2486 | * Communicator gave us a DV box. Process the request. | ||
2487 | * | ||
2488 | * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) | ||
2489 | * @param dvb the message that was received | ||
2490 | */ | ||
2491 | static void | ||
2492 | handle_dv_box (void *cls, | ||
2493 | const struct TransportDVBox *dvb) | ||
2494 | { | ||
2495 | struct CommunicatorMessageContext *cmc = cls; | ||
2496 | |||
2497 | // FIXME: do work! | ||
2498 | finish_cmc_handling (cmc); | ||
2499 | } | ||
2500 | |||
2501 | |||
2502 | /** | ||
2179 | * Client notified us about transmission from a peer. Process the request. | 2503 | * Client notified us about transmission from a peer. Process the request. |
2180 | * | 2504 | * |
2181 | * @param cls the client | 2505 | * @param cls a `struct TransportClient` which sent us the message |
2182 | * @param obm the send message that was sent | 2506 | * @param obm the send message that was sent |
2507 | * @return #GNUNET_YES if message is well-formed | ||
2183 | */ | 2508 | */ |
2184 | static int | 2509 | static int |
2185 | check_incoming_msg (void *cls, | 2510 | check_incoming_msg (void *cls, |
2186 | const struct GNUNET_TRANSPORT_IncomingMessage *im) | 2511 | const struct GNUNET_TRANSPORT_IncomingMessage *im) |
2187 | { | 2512 | { |
2188 | struct TransportClient *tc = cls; | 2513 | struct TransportClient *tc = cls; |
2189 | uint16_t size; | ||
2190 | const struct GNUNET_MessageHeader *obmm; | ||
2191 | 2514 | ||
2192 | if (CT_COMMUNICATOR != tc->type) | 2515 | if (CT_COMMUNICATOR != tc->type) |
2193 | { | 2516 | { |
2194 | GNUNET_break (0); | 2517 | GNUNET_break (0); |
2195 | return GNUNET_SYSERR; | 2518 | return GNUNET_SYSERR; |
2196 | } | 2519 | } |
2197 | size = ntohs (im->header.size) - sizeof (*im); | 2520 | GNUNET_MQ_check_boxed_message (im); |
2198 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
2199 | { | ||
2200 | GNUNET_break (0); | ||
2201 | return GNUNET_SYSERR; | ||
2202 | } | ||
2203 | obmm = (const struct GNUNET_MessageHeader *) &im[1]; | ||
2204 | if (size != ntohs (obmm->size)) | ||
2205 | { | ||
2206 | GNUNET_break (0); | ||
2207 | return GNUNET_SYSERR; | ||
2208 | } | ||
2209 | return GNUNET_OK; | 2521 | return GNUNET_OK; |
2210 | } | 2522 | } |
2211 | 2523 | ||
@@ -2213,7 +2525,6 @@ check_incoming_msg (void *cls, | |||
2213 | /** | 2525 | /** |
2214 | * Incoming meessage. Process the request. | 2526 | * Incoming meessage. Process the request. |
2215 | * | 2527 | * |
2216 | * @param cls the client | ||
2217 | * @param im the send message that was received | 2528 | * @param im the send message that was received |
2218 | */ | 2529 | */ |
2219 | static void | 2530 | static void |
@@ -2221,8 +2532,61 @@ handle_incoming_msg (void *cls, | |||
2221 | const struct GNUNET_TRANSPORT_IncomingMessage *im) | 2532 | const struct GNUNET_TRANSPORT_IncomingMessage *im) |
2222 | { | 2533 | { |
2223 | struct TransportClient *tc = cls; | 2534 | struct TransportClient *tc = cls; |
2535 | struct CommunicatorMessageContext *cmc = GNUNET_new (struct CommunicatorMessageContext); | ||
2536 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
2537 | GNUNET_MQ_hd_var_size (fragment_box, | ||
2538 | GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT, | ||
2539 | struct TransportFragmentBox, | ||
2540 | &cmc), | ||
2541 | GNUNET_MQ_hd_fixed_size (fragment_ack, | ||
2542 | GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK, | ||
2543 | struct TransportFragmentAckMessage, | ||
2544 | &cmc), | ||
2545 | GNUNET_MQ_hd_var_size (reliability_box, | ||
2546 | GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX, | ||
2547 | struct TransportReliabilityBox, | ||
2548 | &cmc), | ||
2549 | GNUNET_MQ_hd_fixed_size (reliability_ack, | ||
2550 | GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK, | ||
2551 | struct TransportReliabilityAckMessage, | ||
2552 | &cmc), | ||
2553 | GNUNET_MQ_hd_var_size (backchannel_encapsulation, | ||
2554 | GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION, | ||
2555 | struct TransportBackchannelEncapsulationMessage, | ||
2556 | &cmc), | ||
2557 | GNUNET_MQ_hd_fixed_size (ephemeral_confirmation, | ||
2558 | GNUNET_MESSAGE_TYPE_TRANSPORT_EPHEMERAL_CONFIRMATION, | ||
2559 | struct EphemeralConfirmationMessage, | ||
2560 | &cmc), | ||
2561 | GNUNET_MQ_hd_var_size (dv_learn, | ||
2562 | GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, | ||
2563 | struct TransportDVLearn, | ||
2564 | &cmc), | ||
2565 | GNUNET_MQ_hd_var_size (dv_box, | ||
2566 | GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, | ||
2567 | struct TransportDVBox, | ||
2568 | &cmc), | ||
2569 | GNUNET_MQ_handler_end() | ||
2570 | }; | ||
2571 | int ret; | ||
2224 | 2572 | ||
2225 | GNUNET_SERVICE_client_continue (tc->client); | 2573 | cmc->tc = tc; |
2574 | cmc->im = *im; | ||
2575 | ret = GNUNET_MQ_handle_message (handlers, | ||
2576 | (const struct GNUNET_MessageHeader *) &im[1]); | ||
2577 | if (GNUNET_SYSERR == ret) | ||
2578 | { | ||
2579 | GNUNET_break (0); | ||
2580 | GNUNET_SERVICE_client_drop (tc->client); | ||
2581 | GNUNET_free (cmc); | ||
2582 | return; | ||
2583 | } | ||
2584 | if (GNUNET_NO == ret) | ||
2585 | { | ||
2586 | /* unencapsulated 'raw' message */ | ||
2587 | handle_raw_message (&cmc, | ||
2588 | (const struct GNUNET_MessageHeader *) &im[1]); | ||
2589 | } | ||
2226 | } | 2590 | } |
2227 | 2591 | ||
2228 | 2592 | ||
@@ -2269,6 +2633,23 @@ tracker_update_in_cb (void *cls) | |||
2269 | 2633 | ||
2270 | 2634 | ||
2271 | /** | 2635 | /** |
2636 | * If necessary, generates the UUID for a @a pm | ||
2637 | * | ||
2638 | * @param pm pending message to generate UUID for. | ||
2639 | */ | ||
2640 | static void | ||
2641 | set_pending_message_uuid (struct PendingMessage *pm) | ||
2642 | { | ||
2643 | if (pm->msg_uuid_set) | ||
2644 | return; | ||
2645 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
2646 | &pm->msg_uuid, | ||
2647 | sizeof (pm->msg_uuid)); | ||
2648 | pm->msg_uuid_set = GNUNET_YES; | ||
2649 | } | ||
2650 | |||
2651 | |||
2652 | /** | ||
2272 | * Fragment the given @a pm to the given @a mtu. Adds | 2653 | * Fragment the given @a pm to the given @a mtu. Adds |
2273 | * additional fragments to the neighbour as well. If the | 2654 | * additional fragments to the neighbour as well. If the |
2274 | * @a mtu is too small, generates and error for the @a pm | 2655 | * @a mtu is too small, generates and error for the @a pm |
@@ -2284,13 +2665,7 @@ fragment_message (struct PendingMessage *pm, | |||
2284 | { | 2665 | { |
2285 | struct PendingMessage *ff; | 2666 | struct PendingMessage *ff; |
2286 | 2667 | ||
2287 | if (GNUNET_NO == pm->msg_uuid_set) | 2668 | set_pending_message_uuid (pm); |
2288 | { | ||
2289 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
2290 | &pm->msg_uuid, | ||
2291 | sizeof (pm->msg_uuid)); | ||
2292 | pm->msg_uuid_set = GNUNET_YES; | ||
2293 | } | ||
2294 | 2669 | ||
2295 | /* This invariant is established in #handle_add_queue_message() */ | 2670 | /* This invariant is established in #handle_add_queue_message() */ |
2296 | GNUNET_assert (mtu > sizeof (struct TransportFragmentBox)); | 2671 | GNUNET_assert (mtu > sizeof (struct TransportFragmentBox)); |
@@ -2390,24 +2765,50 @@ fragment_message (struct PendingMessage *pm, | |||
2390 | static struct PendingMessage * | 2765 | static struct PendingMessage * |
2391 | reliability_box_message (struct PendingMessage *pm) | 2766 | reliability_box_message (struct PendingMessage *pm) |
2392 | { | 2767 | { |
2393 | if (PMT_CORE != pm->pmt) | 2768 | struct TransportReliabilityBox rbox; |
2394 | { | 2769 | struct PendingMessage *bpm; |
2395 | /* already fragmented or reliability boxed, or control message: do nothing */ | 2770 | char *msg; |
2396 | return pm; | 2771 | |
2397 | } | 2772 | if (PMT_CORE != pm->pmt) |
2398 | 2773 | return pm; /* already fragmented or reliability boxed, or control message: do nothing */ | |
2399 | if (0) // FIXME | 2774 | if (NULL != pm->bpm) |
2775 | return pm->bpm; /* already computed earlier: do nothing */ | ||
2776 | GNUNET_assert (NULL == pm->head_frag); | ||
2777 | if (pm->bytes_msg + sizeof (rbox) > UINT16_MAX) | ||
2400 | { | 2778 | { |
2401 | /* failed hard */ | 2779 | /* failed hard */ |
2402 | // FIMXE: bitch | 2780 | GNUNET_break (0); |
2403 | client_send_response (pm, | 2781 | client_send_response (pm, |
2404 | GNUNET_NO, | 2782 | GNUNET_NO, |
2405 | 0); | 2783 | 0); |
2406 | return NULL; | 2784 | return NULL; |
2407 | } | 2785 | } |
2408 | 2786 | bpm = GNUNET_malloc (sizeof (struct PendingMessage) + | |
2409 | /* FIXME: return boxed PM here! */ | 2787 | sizeof (rbox) + |
2410 | return NULL; | 2788 | pm->bytes_msg); |
2789 | bpm->target = pm->target; | ||
2790 | bpm->frag_parent = pm; | ||
2791 | GNUNET_CONTAINER_MDLL_insert (frag, | ||
2792 | pm->head_frag, | ||
2793 | pm->tail_frag, | ||
2794 | bpm); | ||
2795 | bpm->timeout = pm->timeout; | ||
2796 | bpm->pmt = PMT_RELIABILITY_BOX; | ||
2797 | bpm->bytes_msg = pm->bytes_msg + sizeof (rbox); | ||
2798 | set_pending_message_uuid (bpm); | ||
2799 | rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX); | ||
2800 | rbox.header.size = htons (sizeof (rbox) + pm->bytes_msg); | ||
2801 | rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support | ||
2802 | rbox.msg_uuid = pm->msg_uuid; | ||
2803 | msg = (char *) &bpm[1]; | ||
2804 | memcpy (msg, | ||
2805 | &rbox, | ||
2806 | sizeof (rbox)); | ||
2807 | memcpy (&msg[sizeof (rbox)], | ||
2808 | &pm[1], | ||
2809 | pm->bytes_msg); | ||
2810 | pm->bpm = bpm; | ||
2811 | return bpm; | ||
2411 | } | 2812 | } |
2412 | 2813 | ||
2413 | 2814 | ||
@@ -2542,26 +2943,64 @@ transmit_on_queue (void *cls) | |||
2542 | else if (PMT_CORE != pm->pmt) | 2943 | else if (PMT_CORE != pm->pmt) |
2543 | { | 2944 | { |
2544 | /* This was an acknowledgement of some type, always free */ | 2945 | /* This was an acknowledgement of some type, always free */ |
2545 | 2946 | free_pending_message (pm); | |
2546 | struct Neighbour *neighbour = pm->target; | ||
2547 | GNUNET_CONTAINER_MDLL_remove (neighbour, | ||
2548 | neighbour->pending_msg_head, | ||
2549 | neighbour->pending_msg_tail, | ||
2550 | pm); | ||
2551 | GNUNET_free (pm); | ||
2552 | } | 2947 | } |
2553 | else | 2948 | else |
2554 | { | 2949 | { |
2555 | /* message not finished, waiting for acknowledgement */ | 2950 | /* message not finished, waiting for acknowledgement */ |
2556 | // FIXME: update time by which we might retransmit 's' based on | 2951 | struct Neighbour *neighbour = pm->target; |
2557 | // queue characteristics (i.e. RTT) | 2952 | /* Update time by which we might retransmit 's' based on queue |
2558 | 2953 | characteristics (i.e. RTT); it takes one RTT for the message to | |
2559 | // FIXME: move 'pm' back in the transmission queue (simplistic: to | 2954 | arrive and the ACK to come back in the best case; but the other |
2560 | // the end, better: with position depending on type, timeout, | 2955 | side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before |
2561 | // etc.) | 2956 | retransmitting. Note that in the future this heuristic should |
2957 | likely be improved further (measure RTT stability, consider | ||
2958 | message urgency and size when delaying ACKs, etc.) */ | ||
2959 | s->next_attempt = GNUNET_TIME_relative_to_absolute | ||
2960 | (GNUNET_TIME_relative_multiply (queue->rtt, | ||
2961 | 4)); | ||
2962 | if (s == pm) | ||
2963 | { | ||
2964 | struct PendingMessage *pos; | ||
2965 | |||
2966 | /* re-insert sort in neighbour list */ | ||
2967 | GNUNET_CONTAINER_MDLL_remove (neighbour, | ||
2968 | neighbour->pending_msg_head, | ||
2969 | neighbour->pending_msg_tail, | ||
2970 | pm); | ||
2971 | pos = neighbour->pending_msg_tail; | ||
2972 | while ( (NULL != pos) && | ||
2973 | (pm->next_attempt.abs_value_us > pos->next_attempt.abs_value_us) ) | ||
2974 | pos = pos->prev_neighbour; | ||
2975 | GNUNET_CONTAINER_MDLL_insert_after (neighbour, | ||
2976 | neighbour->pending_msg_head, | ||
2977 | neighbour->pending_msg_tail, | ||
2978 | pos, | ||
2979 | pm); | ||
2980 | } | ||
2981 | else | ||
2982 | { | ||
2983 | /* re-insert sort in fragment list */ | ||
2984 | struct PendingMessage *fp = s->frag_parent; | ||
2985 | struct PendingMessage *pos; | ||
2986 | |||
2987 | GNUNET_CONTAINER_MDLL_remove (frag, | ||
2988 | fp->head_frag, | ||
2989 | fp->tail_frag, | ||
2990 | s); | ||
2991 | pos = fp->tail_frag; | ||
2992 | while ( (NULL != pos) && | ||
2993 | (s->next_attempt.abs_value_us > pos->next_attempt.abs_value_us) ) | ||
2994 | pos = pos->prev_frag; | ||
2995 | GNUNET_CONTAINER_MDLL_insert_after (frag, | ||
2996 | fp->head_frag, | ||
2997 | fp->tail_frag, | ||
2998 | pos, | ||
2999 | s); | ||
3000 | } | ||
2562 | } | 3001 | } |
2563 | 3002 | ||
2564 | /* finally, re-schedule self */ | 3003 | /* finally, re-schedule queue transmission task itself */ |
2565 | schedule_transmit_on_queue (queue); | 3004 | schedule_transmit_on_queue (queue); |
2566 | } | 3005 | } |
2567 | 3006 | ||
diff --git a/src/util/mq.c b/src/util/mq.c index 4dfcb72be..d2f5add19 100644 --- a/src/util/mq.c +++ b/src/util/mq.c | |||
@@ -215,6 +215,35 @@ void | |||
215 | GNUNET_MQ_inject_message (struct GNUNET_MQ_Handle *mq, | 215 | GNUNET_MQ_inject_message (struct GNUNET_MQ_Handle *mq, |
216 | const struct GNUNET_MessageHeader *mh) | 216 | const struct GNUNET_MessageHeader *mh) |
217 | { | 217 | { |
218 | int ret; | ||
219 | |||
220 | ret = GNUNET_MQ_handle_message (mq->handlers, | ||
221 | mh); | ||
222 | if (GNUNET_SYSERR == ret) | ||
223 | { | ||
224 | GNUNET_MQ_inject_error (mq, | ||
225 | GNUNET_MQ_ERROR_MALFORMED); | ||
226 | return; | ||
227 | } | ||
228 | } | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Call the message message handler that was registered | ||
233 | * for the type of the given message in the given @a handlers list. | ||
234 | * | ||
235 | * This function is indended to be used for the implementation | ||
236 | * of message queues. | ||
237 | * | ||
238 | * @param handlers a set of handlers | ||
239 | * @param mh message to dispatch | ||
240 | * @return #GNUNET_OK on success, #GNUNET_NO if no handler matched, | ||
241 | * #GNUNET_SYSERR if message was rejected by check function | ||
242 | */ | ||
243 | int | ||
244 | GNUNET_MQ_handle_message (const struct GNUNET_MQ_MessageHandler *handlers, | ||
245 | const struct GNUNET_MessageHeader *mh) | ||
246 | { | ||
218 | const struct GNUNET_MQ_MessageHandler *handler; | 247 | const struct GNUNET_MQ_MessageHandler *handler; |
219 | int handled = GNUNET_NO; | 248 | int handled = GNUNET_NO; |
220 | uint16_t msize = ntohs (mh->size); | 249 | uint16_t msize = ntohs (mh->size); |
@@ -224,9 +253,9 @@ GNUNET_MQ_inject_message (struct GNUNET_MQ_Handle *mq, | |||
224 | "Received message of type %u and size %u\n", | 253 | "Received message of type %u and size %u\n", |
225 | mtype, msize); | 254 | mtype, msize); |
226 | 255 | ||
227 | if (NULL == mq->handlers) | 256 | if (NULL == handlers) |
228 | goto done; | 257 | goto done; |
229 | for (handler = mq->handlers; NULL != handler->cb; handler++) | 258 | for (handler = handlers; NULL != handler->cb; handler++) |
230 | { | 259 | { |
231 | if (handler->type == mtype) | 260 | if (handler->type == mtype) |
232 | { | 261 | { |
@@ -240,9 +269,7 @@ GNUNET_MQ_inject_message (struct GNUNET_MQ_Handle *mq, | |||
240 | LOG (GNUNET_ERROR_TYPE_ERROR, | 269 | LOG (GNUNET_ERROR_TYPE_ERROR, |
241 | "Received malformed message of type %u\n", | 270 | "Received malformed message of type %u\n", |
242 | (unsigned int) handler->type); | 271 | (unsigned int) handler->type); |
243 | GNUNET_MQ_inject_error (mq, | 272 | return GNUNET_SYSERR; |
244 | GNUNET_MQ_ERROR_MALFORMED); | ||
245 | break; | ||
246 | } | 273 | } |
247 | if ( (NULL == handler->mv) || | 274 | if ( (NULL == handler->mv) || |
248 | (GNUNET_OK == | 275 | (GNUNET_OK == |
@@ -257,17 +284,20 @@ GNUNET_MQ_inject_message (struct GNUNET_MQ_Handle *mq, | |||
257 | LOG (GNUNET_ERROR_TYPE_ERROR, | 284 | LOG (GNUNET_ERROR_TYPE_ERROR, |
258 | "Received malformed message of type %u\n", | 285 | "Received malformed message of type %u\n", |
259 | (unsigned int) handler->type); | 286 | (unsigned int) handler->type); |
260 | GNUNET_MQ_inject_error (mq, | 287 | return GNUNET_SYSERR; |
261 | GNUNET_MQ_ERROR_MALFORMED); | ||
262 | } | 288 | } |
263 | break; | 289 | break; |
264 | } | 290 | } |
265 | } | 291 | } |
266 | done: | 292 | done: |
267 | if (GNUNET_NO == handled) | 293 | if (GNUNET_NO == handled) |
294 | { | ||
268 | LOG (GNUNET_ERROR_TYPE_INFO, | 295 | LOG (GNUNET_ERROR_TYPE_INFO, |
269 | "No handler for message of type %u and size %u\n", | 296 | "No handler for message of type %u and size %u\n", |
270 | mtype, msize); | 297 | mtype, msize); |
298 | return GNUNET_NO; | ||
299 | } | ||
300 | return GNUNET_OK; | ||
271 | } | 301 | } |
272 | 302 | ||
273 | 303 | ||