aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxrs <xrs@mail36.net>2018-11-16 18:22:09 +0100
committerxrs <xrs@mail36.net>2018-11-16 18:22:09 +0100
commitec3b834e1a8a8ce93f10221952b595d05e2c72a3 (patch)
tree63135c331bd7a49bb8b2a387e9027a7a41dd0336
parentd25f1b4026d5c2c195592daf092377eccfd2d71a (diff)
parent35e5be0b0b4c7aea5a56d6a62333ab3a964a2972 (diff)
downloadgnunet-ec3b834e1a8a8ce93f10221952b595d05e2c72a3.tar.gz
gnunet-ec3b834e1a8a8ce93f10221952b595d05e2c72a3.zip
Merge branch 'master' of ssh://gnunet.org/gnunet
-rw-r--r--configure.ac151
-rw-r--r--doc/handbook/chapters/installation.texi44
-rw-r--r--doc/handbook/chapters/user.texi27
-rw-r--r--doc/man/gnunet-namestore.18
-rw-r--r--po/POTFILES.in4
-rw-r--r--po/de.po2
-rw-r--r--po/sv.po2
-rw-r--r--po/vi.po2
-rw-r--r--po/zh_CN.po2
-rw-r--r--src/cadet/gnunet-service-cadet_paths.c6
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.c2
-rw-r--r--src/cadet/test_cadet.conf4
-rw-r--r--src/dht/gnunet-dht-get.c2
-rw-r--r--src/dht/gnunet-service-dht_clients.c2
-rw-r--r--src/fs/fs_getopt.c29
-rw-r--r--src/fs/gnunet-publish.c60
-rw-r--r--src/fs/gnunet-search.c49
-rw-r--r--src/fs/gnunet-service-fs.c2
-rw-r--r--src/gns/gnunet-gns-proxy.c48
-rwxr-xr-xsrc/gns/test_gns_cname_lookup.sh3
-rw-r--r--src/gns/test_gns_defaults.conf12
-rwxr-xr-xsrc/gns/test_gns_gns2dns_cname_lookup.sh9
-rwxr-xr-xsrc/gns/test_gns_gns2dns_lookup.sh10
-rwxr-xr-xsrc/gns/test_gns_mx_lookup.sh4
-rw-r--r--src/gnsrecord/gnsrecord.c3
-rw-r--r--src/include/gnunet_bandwidth_lib.h2
-rw-r--r--src/include/gnunet_configuration_lib.h31
-rw-r--r--src/include/gnunet_consensus_service.h2
-rw-r--r--src/include/gnunet_protocols.h44
-rw-r--r--src/include/gnunet_testbed_service.h4
-rw-r--r--src/include/gnunet_transport_communication_service.h10
-rw-r--r--src/include/gnunet_transport_core_service.h12
-rw-r--r--src/include/gnunet_transport_monitor_service.h18
-rw-r--r--src/my/my.c2
-rw-r--r--src/namestore/gnunet-namestore.c375
-rw-r--r--src/namestore/gnunet-zoneimport.c2
-rw-r--r--src/namestore/namestore_api.c2
-rw-r--r--src/namestore/test_namestore_put_multiple.sh123
-rw-r--r--src/testbed/testbed.h2
-rw-r--r--src/testbed/testbed_api_hosts.c2
-rw-r--r--src/topology/gnunet-daemon-topology.c3
-rw-r--r--src/transport/.gitignore1
-rw-r--r--src/transport/Makefile.am56
-rw-r--r--src/transport/communicator-unix.conf2
-rw-r--r--src/transport/gnunet-communicator-unix.c1147
-rw-r--r--src/transport/gnunet-service-tng.c1263
-rw-r--r--src/transport/gnunet-service-transport.c1
-rw-r--r--src/transport/gnunet-service-transport_neighbours.c3
-rw-r--r--src/transport/gnunet-transport.c2
-rw-r--r--src/transport/transport-testing.c4
-rw-r--r--src/transport/transport-testing.h8
-rw-r--r--src/transport/transport.h161
-rw-r--r--src/transport/transport_api2_communication.c194
-rw-r--r--src/transport/transport_api2_core.c938
-rw-r--r--src/transport/transport_api2_monitor.c313
-rw-r--r--src/transport/transport_api_core.c17
-rw-r--r--src/util/configuration.c62
-rw-r--r--src/util/disk.c51
-rw-r--r--src/util/getopt.c8
-rw-r--r--src/util/getopt_helpers.c25
-rw-r--r--src/util/gnunet-service-resolver.c18
-rw-r--r--src/util/service.c18
-rw-r--r--src/util/strings.c43
63 files changed, 4983 insertions, 473 deletions
diff --git a/configure.ac b/configure.ac
index e37df28dd..1d266225a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -300,30 +300,88 @@ then
300fi 300fi
301AC_DEFINE_UNQUOTED([NEED_LIBGCRYPT_VERSION], "$NEED_LIBGCRYPT_VERSION", [required libgcrypt version]) 301AC_DEFINE_UNQUOTED([NEED_LIBGCRYPT_VERSION], "$NEED_LIBGCRYPT_VERSION", [required libgcrypt version])
302 302
303# should the build process be building the documentation?
304AC_MSG_CHECKING(whether to build documentation)
305AC_ARG_ENABLE([documentation],
306 [AS_HELP_STRING([--disable-documentation], [do not build the documentation])],
307 [documentation=${enableval}],
308 [documentation=yes])
309AC_MSG_RESULT($documentation)
310if test "x$documentation" = "xyes"
311then
312 AM_CONDITIONAL([DOCUMENTATION],true)
313 AC_DEFINE([DOCUMENTATION],[1],[Building the documentation])
314else
315 AM_CONDITIONAL([DOCUMENTATION],false)
316 AC_DEFINE([DOCUMENTATION],[0],[Not building the documentation])
317fi
318
319# TODO: Include check for mandoc + texi2mdoc.
320# TODO: Rename the switch? Just 'section7' is too vague.
321# mdoc section 7 output.
322AC_MSG_CHECKING(wether to build section 7 mdoc output)
323AC_ARG_ENABLE([section7],
324[AS_HELP_STRING([--disable-section7], [do not build section 7 mdoc output])],
325[section7=${enableval}],
326[section7=yes])
327AC_MSG_RESULT($section7)
328if test "x$section7" = "xyes"
329then
330 if test "$texi2mdoc" = 0
331 then
332 AC_MSG_WARN([ERROR: mdoc output currently requires texi2mdoc.])
333 AC_MSG_WARN([ERROR: texi2mdoc can be obtained via your Operating System])
334 AC_MSG_WARN([ERROR: package manager or from https://mandoc.bsd.lv/texi2mdoc/])
335 else
336 AM_CONDITIONAL([SECTION7],true)
337 AC_DEFINE([SECTION7],[1],[Building section 7 mdoc output])
338 fi
339else
340 AM_CONDITIONAL([SECTION7],false)
341 AC_DEFINE([SECTION7],[0],[Not building section 7 mdoc output])
342fi
343
344# should the build process be building only the documentation?
345AC_MSG_CHECKING(whether to build only documentation)
346AC_ARG_ENABLE([documentation-only],
347 [AS_HELP_STRING([--enable-documentation-only], [build only the documentation])],
348 [documentation_only=${enableval}],
349 [documentation_only=no])
350AC_MSG_RESULT($documentation_only)
351if test "x$documentation_only" = "xyes"
352then
353 AM_CONDITIONAL([DOCUMENTATION_ONLY],true)
354 AC_DEFINE([DOCUMENTATION_ONLY],[1],[Building only the documentation])
355else
356 AM_CONDITIONAL([DOCUMENTATION_ONLY],false)
357 AC_DEFINE([DOCUMENTATION_ONLY],[0],[Not building only the documentation])
358fi
359
360
303# Check for makeinfo version >= 5, required for building documentation. 361# Check for makeinfo version >= 5, required for building documentation.
304# TODO: invalid version should imply --disable-documentation (and
305# maybe --with-section7).
306# TODO: add check for alternatives 362# TODO: add check for alternatives
307# TODO: add switch to skip documentation building
308have_makeinfo_5=false 363have_makeinfo_5=false
309AC_PROG_SED 364if test x"$documentation" = xyes || test x"$documentation_only" = xyes
310AC_CHECK_PROG([MAKEINFO_FOUND], [makeinfo], [yes])
311if test x"${MAKEINFO_FOUND}" = xyes
312then 365then
313 MAKEINFO_VERSION_REQ=5 366 AC_PROG_SED
314 AC_MSG_CHECKING([for makeinfo version >= $MAKEINFO_VERSION_REQ]) 367 AC_CHECK_PROG([MAKEINFO_FOUND], [makeinfo], [yes])
315 # XXX: is this sed invocation portable? 368 if test x"${MAKEINFO_FOUND}" = xyes
316 MAKEINFO_VERSION=`makeinfo --version | sed -ne 's/^\(makeinfo\|texi2any\) .* \([[0-9]][[0-9]]*\)\.[[0-9]][[0-9]]*.*$/\2/p'`
317 if test x$MAKEINFO_VERSION = x -o 0$MAKEINFO_VERSION -lt $MAKEINFO_VERSION_REQ
318 then 369 then
319 AC_MSG_RESULT([no]) 370 MAKEINFO_VERSION_REQ=5
320 AC_MSG_FAILURE([Program 'makeinfo' version >= $MAKEINFO_VERSION_REQ is required.]) 371 AC_MSG_CHECKING([for makeinfo version >= $MAKEINFO_VERSION_REQ])
372 # XXX: is this sed invocation portable?
373 MAKEINFO_VERSION=`makeinfo --version | sed -ne 's/^\(makeinfo\|texi2any\) .* \([[0-9]][[0-9]]*\)\.[[0-9]][[0-9]]*.*$/\2/p'`
374 if test x$MAKEINFO_VERSION = x -o 0$MAKEINFO_VERSION -lt $MAKEINFO_VERSION_REQ
375 then
376 AC_MSG_RESULT([no])
377 AC_MSG_FAILURE([Program 'makeinfo' version >= $MAKEINFO_VERSION_REQ is required.])
378 else
379 AC_MSG_RESULT([yes])
380 have_makeinfo_5=true
381 fi
321 else 382 else
322 AC_MSG_RESULT([yes]) 383 AC_MSG_FAILURE([Missing program 'makeinfo', Documentation will not be built. Please install it if you want 'info' documentation or refer to online resources at 'https://docs.gnunet.org'.])
323 have_makeinfo_5=true
324 fi 384 fi
325else
326 AC_MSG_FAILURE([Missing program 'makeinfo', Documentation will not be built. Please install it if you want 'info' documentation or refer to online resources at 'https://docs.gnunet.org'.])
327fi 385fi
328AM_CONDITIONAL([HAVE_MAKEINFO_5], [test x$have_makeinfo_5 = xtrue]) 386AM_CONDITIONAL([HAVE_MAKEINFO_5], [test x$have_makeinfo_5 = xtrue])
329 387
@@ -681,7 +739,7 @@ AC_CHECK_HEADERS([nss.h],[nss=true],[nss=false])
681if test x$nss = xfalse 739if test x$nss = xfalse
682then 740then
683 AM_CONDITIONAL(HAVE_GLIBCNSS, false) 741 AM_CONDITIONAL(HAVE_GLIBCNSS, false)
684 AC_MSG_WARN([ERROR: No GNU libc nss header, will not build NSS plugin]) 742 AC_MSG_WARN([No GNU libc nss header, will not build NSS plugin])
685else 743else
686 AM_CONDITIONAL(HAVE_GLIBCNSS, true) 744 AM_CONDITIONAL(HAVE_GLIBCNSS, true)
687fi 745fi
@@ -693,63 +751,6 @@ AC_CHECK_LIB([kvm],[kvm_open])
693AC_CHECK_LIB([kstat],[kstat_open]) 751AC_CHECK_LIB([kstat],[kstat_open])
694 752
695 753
696# should the build process be building the documentation?
697AC_MSG_CHECKING(whether to build documentation)
698AC_ARG_ENABLE([documentation],
699 [AS_HELP_STRING([--disable-documentation], [do not build the documentation])],
700 [documentation=${enableval}],
701 [documentation=yes])
702AC_MSG_RESULT($documentation)
703if test "x$documentation" = "xyes"
704then
705 AM_CONDITIONAL([DOCUMENTATION],true)
706 AC_DEFINE([DOCUMENTATION],[1],[Building the documentation])
707else
708 AM_CONDITIONAL([DOCUMENTATION],false)
709 AC_DEFINE([DOCUMENTATION],[0],[Not building the documentation])
710fi
711
712# TODO: Include check for mandoc + texi2mdoc.
713# TODO: Rename the switch? Just 'section7' is too vague.
714# mdoc section 7 output.
715AC_MSG_CHECKING(wether to build section 7 mdoc output)
716AC_ARG_ENABLE([section7],
717[AS_HELP_STRING([--disable-section7], [do not build section 7 mdoc output])],
718[section7=${enableval}],
719[section7=yes])
720AC_MSG_RESULT($section7)
721if test "x$section7" = "xyes"
722then
723 if test "$texi2mdoc" = 0
724 then
725 AC_MSG_WARN([ERROR: mdoc output currently requires texi2mdoc.])
726 AC_MSG_WARN([ERROR: texi2mdoc can be obtained via your Operating System])
727 AC_MSG_WARN([ERROR: package manager or from https://mandoc.bsd.lv/texi2mdoc/])
728 else
729 AM_CONDITIONAL([SECTION7],true)
730 AC_DEFINE([SECTION7],[1],[Building section 7 mdoc output])
731 fi
732else
733 AM_CONDITIONAL([SECTION7],false)
734 AC_DEFINE([SECTION7],[0],[Not building section 7 mdoc output])
735fi
736
737# should the build process be building only the documentation?
738AC_MSG_CHECKING(whether to build only documentation)
739AC_ARG_ENABLE([documentation-only],
740 [AS_HELP_STRING([--enable-documentation-only], [build only the documentation])],
741 [documentation_only=${enableval}],
742 [documentation_only=no])
743AC_MSG_RESULT($documentation_only)
744if test "x$documentation_only" = "xyes"
745then
746 AM_CONDITIONAL([DOCUMENTATION_ONLY],true)
747 AC_DEFINE([DOCUMENTATION_ONLY],[1],[Building only the documentation])
748else
749 AM_CONDITIONAL([DOCUMENTATION_ONLY],false)
750 AC_DEFINE([DOCUMENTATION_ONLY],[0],[Not building only the documentation])
751fi
752
753# should the build process be restricted to the code required 754# should the build process be restricted to the code required
754# for GNU Taler wallets? 755# for GNU Taler wallets?
755AC_MSG_CHECKING(whether to compile GNU Taler Wallet library ONLY) 756AC_MSG_CHECKING(whether to compile GNU Taler Wallet library ONLY)
diff --git a/doc/handbook/chapters/installation.texi b/doc/handbook/chapters/installation.texi
index 6b68ac498..c05f776f2 100644
--- a/doc/handbook/chapters/installation.texi
+++ b/doc/handbook/chapters/installation.texi
@@ -1464,29 +1464,31 @@ configuring the use of GNS with your operating system.
1464 1464
1465At this point in time you have different options depending on your OS: 1465At this point in time you have different options depending on your OS:
1466 1466
1467@table @asis 1467@itemize @bullet
1468 1468@item Use the gnunet-gns-proxy@*
1469@item Use the gnunet-gns-proxy This approach works for all operating 1469This approach works for all operating systems and is likely the
1470systems and is likely the easiest. However, it enables GNS only for 1470easiest. However, it enables GNS only for browsers, not for other
1471browsers, not for other applications that might be using DNS, such as SSH. 1471applications that might be using DNS, such as SSH. Still, using the
1472Still, using the proxy is required for using HTTP with GNS and is thus 1472proxy is required for using HTTP with GNS and is thus recommended for
1473recommended for all users. To do this, you simply have to run the 1473all users. To do this, you simply have to run the
1474@code{gnunet-gns-proxy-setup-ca} script as the user who will run the 1474@code{gnunet-gns-proxy-setup-ca} script as the user who will run the
1475browser (this will create a GNS certificate authority (CA) on your system 1475browser (this will create a GNS certificate authority (CA) on your
1476and import its key into your browser), then start @code{gnunet-gns-proxy} 1476system and import its key into your browser), then start
1477and inform your browser to use the Socks5 proxy which 1477@code{gnunet-gns-proxy} and inform your browser to use the Socks5
1478@code{gnunet-gns-proxy} makes available by default on port 7777. 1478proxy which @code{gnunet-gns-proxy} makes available by default on port
1479@item Use a nsswitch plugin (recommended on GNU systems) 14797777.
1480This approach has the advantage of offering fully personalized resolution 1480@item Use a nsswitch plugin (recommended on GNU systems)@*
1481even on multi-user systems. A potential disadvantage is that some 1481This approach has the advantage of offering fully personalized
1482applications might be able to bypass GNS. 1482resolution even on multi-user systems. A potential disadvantage is
1483@item Use a W32 resolver plugin (recommended on W32) 1483that some applications might be able to bypass GNS.
1484@item Use a W32 resolver plugin (recommended on W32)@*
1484This is currently the only option on W32 systems. 1485This is currently the only option on W32 systems.
1485@item Use system-wide DNS packet interception 1486@item Use system-wide DNS packet interception@*
1486This approach is recommended for the GNUnet VPN. It can be used to handle 1487This approach is recommended for the GNUnet VPN. It can be used to
1487GNS at the same time; however, if you only use this method, you will only 1488handle GNS at the same time; however, if you only use this method, you
1488get one root zone per machine (not so great for multi-user systems). 1489will only get one root zone per machine (not so great for multi-user
1489@end table 1490systems).
1491@end itemize
1490 1492
1491You can combine system-wide DNS packet interception with the nsswitch 1493You can combine system-wide DNS packet interception with the nsswitch
1492plugin. 1494plugin.
diff --git a/doc/handbook/chapters/user.texi b/doc/handbook/chapters/user.texi
index 5aa3a62bf..ea41bbb6c 100644
--- a/doc/handbook/chapters/user.texi
+++ b/doc/handbook/chapters/user.texi
@@ -1914,22 +1914,22 @@ Like other IdPs, re:claim features an (optional) OpenID-Connect 1.0-compliant pr
1914Before adding attributes to an identity, you must first create an ego: 1914Before adding attributes to an identity, you must first create an ego:
1915 1915
1916@example 1916@example
1917$ gnunet-identity -C "username" 1917$ gnunet-identity -C "user"
1918@end example 1918@end example
1919 1919
1920Henceforth, you can manage a new user profile of the user ``username''. 1920Henceforth, you can manage a new user profile of the user ``user''.
1921 1921
1922To add an email address to your user profile, simply use the @command{gnunet-reclaim} command line tool:: 1922To add an email address to your user profile, simply use the @command{gnunet-reclaim} command line tool::
1923 1923
1924@example 1924@example
1925$ gnunet-reclaim -e "username" -a "email" -V "username@@example.gnunet" 1925$ gnunet-reclaim -e "user" -a "email" -V "username@@example.gnunet"
1926@end example 1926@end example
1927 1927
1928All of your attributes can be listed using the @command{gnunet-reclaim} 1928All of your attributes can be listed using the @command{gnunet-reclaim}
1929command line tool as well: 1929command line tool as well:
1930 1930
1931@example 1931@example
1932$ gnunet-reclaim -e "username" -D 1932$ gnunet-reclaim -e "user" -D
1933@end example 1933@end example
1934 1934
1935Currently, and by default, attribute values are interpreted as plain text. 1935Currently, and by default, attribute values are interpreted as plain text.
@@ -1941,10 +1941,10 @@ In the future there might be more value types such as X.509 certificate credenti
1941If you want to allow a third party such as a website or friend to access to your attributes (or a subset thereof) execute: 1941If you want to allow a third party such as a website or friend to access to your attributes (or a subset thereof) execute:
1942 1942
1943@example 1943@example
1944$ gnunet-reclaim -e "username" -r "PKEY" -i "attribute1,attribute2,..." 1944$ gnunet-reclaim -e "user" -r "PKEY" -i "attribute1,attribute2,..."
1945@end example 1945@end example
1946 1946
1947Where "PKEY" is the public key of the third party and "attribute1,attribute2,..." is a comma-separated list of attribute names, such as "email", that you want to share. 1947Where "PKEY" is the public key of the third party and "attribute1,attribute2,..." is a comma-separated list of attribute names, such as "email,name,...", that you want to share.
1948 1948
1949The command will return a "ticket" string. 1949The command will return a "ticket" string.
1950You must give this "ticket" to the requesting third party. 1950You must give this "ticket" to the requesting third party.
@@ -1955,13 +1955,14 @@ The third party can then retrieve your shared identity attributes using:
1955$ gnunet-reclaim -e "friend" -C "ticket" 1955$ gnunet-reclaim -e "friend" -C "ticket"
1956@end example 1956@end example
1957 1957
1958Where "friend" is the name for "user" that the requesting party is using.
1958This will retrieve and list the shared identity attributes. 1959This will retrieve and list the shared identity attributes.
1959The above command will also work if the user "username" is currently offline since the attributes are retrieved from GNS. 1960The above command will also work if the user is currently offline since the attributes are retrieved from GNS.
1960Further, the "ticket" can be re-used later to retrieve up-to-date attributes in case "username" has changed the value(s). For instance, becasue his email address changed. 1961Further, the "ticket" can be re-used later to retrieve up-to-date attributes in case "friend" has changed the value(s). For instance, because his email address changed.
1961 1962
1962To list all given authorizations (tickets) you can execute: 1963To list all given authorizations (tickets) you can execute:
1963@example 1964@example
1964$ gnunet-reclaim -e "friend" -T (TODO there is only a REST API for this ATM) 1965$ gnunet-reclaim -e "friend" -T (TODO there is only a C and REST API for this at this time)
1965@end example 1966@end example
1966 1967
1967 1968
@@ -1971,7 +1972,7 @@ $ gnunet-reclaim -e "friend" -T (TODO there is only a REST API for this ATM)
1971If you want to revoke the access of a third party to your attributes you can execute: 1972If you want to revoke the access of a third party to your attributes you can execute:
1972 1973
1973@example 1974@example
1974$ gnunet-reclaim -e "username" -R "ticket" 1975$ gnunet-reclaim -e "user" -R "ticket"
1975@end example 1976@end example
1976 1977
1977This will prevent the third party from accessing the attribute in the future. 1978This will prevent the third party from accessing the attribute in the future.
@@ -1983,14 +1984,14 @@ This behaviour is _exactly the same_ as with other IdPs.
1983@subsection Using the OpenID-Connect IdP 1984@subsection Using the OpenID-Connect IdP
1984 1985
1985@menu 1986@menu
1986* Setting up reclaim.io:: 1987* Setting up reclaim.id::
1987* For Users:: 1988* For Users::
1988* For Service Providers:: 1989* For Service Providers::
1989@end menu 1990@end menu
1990 1991
1991 1992
1992@node Setting up reclaim.io 1993@node Setting up reclaim.id
1993@subsubsection Setting up reclaim.io 1994@subsubsection Setting up reclaim.id
1994 1995
1995@example 1996@example
1996$ gnunet-identity -C id 1997$ gnunet-identity -C id
diff --git a/doc/man/gnunet-namestore.1 b/doc/man/gnunet-namestore.1
index 10577a0d9..9f4b4d2d6 100644
--- a/doc/man/gnunet-namestore.1
+++ b/doc/man/gnunet-namestore.1
@@ -61,6 +61,14 @@ label)
61Determine our GNS name for the given public key (reverse lookup of the 61Determine our GNS name for the given public key (reverse lookup of the
62PKEY) in the given zone. 62PKEY) in the given zone.
63.B 63.B
64.IP "\-R RECORDLINE, \-\-replace=RECORDLINE"
65Sets record set to values given in RECORDLINE. This option can be specified multiple
66times to provide multiple records for the record set. Existing records under the
67same label will be deleted. The format for the RECORDLINE is
68"TTL TYPE FLAGS VALUE" where TTL is the time to live in seconds, TYPE is the
69DNS/GNS record type, FLAGS is "(N)ORMAL", "(S)HADOW" or "(P)UBLIC". The VALUE
70follows the usual human-readable value format(s) of DNS/GNS.
71.B
64.IP "\-s, \-\-shadow" 72.IP "\-s, \-\-shadow"
65Create a record that is a shadow record. Shadow records are only used 73Create a record that is a shadow record. Shadow records are only used
66once all other records of the same type under the same label have 74once all other records of the same type under the same label have
diff --git a/po/POTFILES.in b/po/POTFILES.in
index caf7353be..129c43cdd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -398,9 +398,11 @@ src/testing/list-keys.c
398src/testing/testing.c 398src/testing/testing.c
399src/topology/friends.c 399src/topology/friends.c
400src/topology/gnunet-daemon-topology.c 400src/topology/gnunet-daemon-topology.c
401src/transport/gnunet-communicator-unix.c
401src/transport/gnunet-helper-transport-bluetooth.c 402src/transport/gnunet-helper-transport-bluetooth.c
402src/transport/gnunet-helper-transport-wlan.c 403src/transport/gnunet-helper-transport-wlan.c
403src/transport/gnunet-helper-transport-wlan-dummy.c 404src/transport/gnunet-helper-transport-wlan-dummy.c
405src/transport/gnunet-service-tng.c
404src/transport/gnunet-service-transport_ats.c 406src/transport/gnunet-service-transport_ats.c
405src/transport/gnunet-service-transport.c 407src/transport/gnunet-service-transport.c
406src/transport/gnunet-service-transport_hello.c 408src/transport/gnunet-service-transport_hello.c
@@ -430,6 +432,8 @@ src/transport/tcp_server_legacy.c
430src/transport/tcp_server_mst_legacy.c 432src/transport/tcp_server_mst_legacy.c
431src/transport/tcp_service_legacy.c 433src/transport/tcp_service_legacy.c
432src/transport/transport_api2_communication.c 434src/transport/transport_api2_communication.c
435src/transport/transport_api2_core.c
436src/transport/transport_api2_monitor.c
433src/transport/transport_api_address_to_string.c 437src/transport/transport_api_address_to_string.c
434src/transport/transport_api_blacklist.c 438src/transport/transport_api_blacklist.c
435src/transport/transport_api_core.c 439src/transport/transport_api_core.c
diff --git a/po/de.po b/po/de.po
index eb6b2a4d3..d036280f7 100644
--- a/po/de.po
+++ b/po/de.po
@@ -7501,7 +7501,7 @@ msgstr "Adresse des Knotens `%s' konnte nicht ermittelt werden.\n"
7501 7501
7502#: src/transport/gnunet-transport.c:492 7502#: src/transport/gnunet-transport.c:492
7503#, fuzzy 7503#, fuzzy
7504msgid "Failed to list connections, timeout occured\n" 7504msgid "Failed to list connections, timeout occurred\n"
7505msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" 7505msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
7506 7506
7507#: src/transport/gnunet-transport.c:525 7507#: src/transport/gnunet-transport.c:525
diff --git a/po/sv.po b/po/sv.po
index 323f2de49..388ff2f82 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -7575,7 +7575,7 @@ msgstr "Misslyckades att binda till UDP-port %d.\n"
7575 7575
7576#: src/transport/gnunet-transport.c:492 7576#: src/transport/gnunet-transport.c:492
7577#, fuzzy 7577#, fuzzy
7578msgid "Failed to list connections, timeout occured\n" 7578msgid "Failed to list connections, timeout occurred\n"
7579msgstr "Misslyckades att ansluta till gnunetd.\n" 7579msgstr "Misslyckades att ansluta till gnunetd.\n"
7580 7580
7581#: src/transport/gnunet-transport.c:525 7581#: src/transport/gnunet-transport.c:525
diff --git a/po/vi.po b/po/vi.po
index 2f05f3daf..85131f055 100644
--- a/po/vi.po
+++ b/po/vi.po
@@ -7638,7 +7638,7 @@ msgstr "Lỗi đóng kết đến cổng %s %d.\n"
7638 7638
7639#: src/transport/gnunet-transport.c:492 7639#: src/transport/gnunet-transport.c:492
7640#, fuzzy 7640#, fuzzy
7641msgid "Failed to list connections, timeout occured\n" 7641msgid "Failed to list connections, timeout occurred\n"
7642msgstr "Không kết nối được đến trình nền gnunetd." 7642msgstr "Không kết nối được đến trình nền gnunetd."
7643 7643
7644#: src/transport/gnunet-transport.c:525 7644#: src/transport/gnunet-transport.c:525
diff --git a/po/zh_CN.po b/po/zh_CN.po
index cd3a10b4e..d881d0591 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -7353,7 +7353,7 @@ msgstr "找不到接口“%s”的一个 IP 地址。\n"
7353 7353
7354#: src/transport/gnunet-transport.c:492 7354#: src/transport/gnunet-transport.c:492
7355#, fuzzy 7355#, fuzzy
7356msgid "Failed to list connections, timeout occured\n" 7356msgid "Failed to list connections, timeout occurred\n"
7357msgstr "初始化“%s”服务失败。\n" 7357msgstr "初始化“%s”服务失败。\n"
7358 7358
7359#: src/transport/gnunet-transport.c:525 7359#: src/transport/gnunet-transport.c:525
diff --git a/src/cadet/gnunet-service-cadet_paths.c b/src/cadet/gnunet-service-cadet_paths.c
index 40f464e9b..7769a6043 100644
--- a/src/cadet/gnunet-service-cadet_paths.c
+++ b/src/cadet/gnunet-service-cadet_paths.c
@@ -354,7 +354,7 @@ check_match (void *cls,
354 (off + 1 != cm_ctx->cpath_length) ) 354 (off + 1 != cm_ctx->cpath_length) )
355 { 355 {
356 LOG (GNUNET_ERROR_TYPE_DEBUG, 356 LOG (GNUNET_ERROR_TYPE_DEBUG,
357 "check_match missmatch because path %s is too long (%u vs. %u vs. %u)\n", 357 "check_match mismatch because path %s is too long (%u vs. %u vs. %u)\n",
358 GCPP_2s (path), 358 GCPP_2s (path),
359 path->entries_length, 359 path->entries_length,
360 off + 1, 360 off + 1,
@@ -367,10 +367,10 @@ check_match (void *cls,
367 i)) 367 i))
368 { 368 {
369 LOG (GNUNET_ERROR_TYPE_DEBUG, 369 LOG (GNUNET_ERROR_TYPE_DEBUG,
370 "check_match path %s missmatches at offset %u\n", 370 "check_match path %s mismatches at offset %u\n",
371 GCPP_2s (path), 371 GCPP_2s (path),
372 i); 372 i);
373 return GNUNET_YES; /* missmatch, ignore */ 373 return GNUNET_YES; /* mismatch, ignore */
374 } 374 }
375 LOG (GNUNET_ERROR_TYPE_DEBUG, 375 LOG (GNUNET_ERROR_TYPE_DEBUG,
376 "check_match found match with path %s\n", 376 "check_match found match with path %s\n",
diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c
index 1e7a8e086..874c7e706 100644
--- a/src/cadet/gnunet-service-cadet_tunnels.c
+++ b/src/cadet/gnunet-service-cadet_tunnels.c
@@ -1983,7 +1983,7 @@ GCT_handle_kx_auth (struct CadetTConnection *ct,
1983 1, 1983 1,
1984 GNUNET_NO); 1984 GNUNET_NO);
1985 LOG (GNUNET_ERROR_TYPE_WARNING, 1985 LOG (GNUNET_ERROR_TYPE_WARNING,
1986 "KX AUTH missmatch!\n"); 1986 "KX AUTH mismatch!\n");
1987#if DEBUG_KX 1987#if DEBUG_KX
1988 { 1988 {
1989 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; 1989 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
diff --git a/src/cadet/test_cadet.conf b/src/cadet/test_cadet.conf
index 5ad67fec2..30e496aff 100644
--- a/src/cadet/test_cadet.conf
+++ b/src/cadet/test_cadet.conf
@@ -98,3 +98,7 @@ START_ON_DEMAND = NO
98[topology] 98[topology]
99IMMEDIATE_START = NO 99IMMEDIATE_START = NO
100START_ON_DEMAND = NO 100START_ON_DEMAND = NO
101
102[rps]
103IMMEDIATE_START = NO
104START_ON_DEMAND = NO
diff --git a/src/dht/gnunet-dht-get.c b/src/dht/gnunet-dht-get.c
index 3742ed739..2d9d76585 100644
--- a/src/dht/gnunet-dht-get.c
+++ b/src/dht/gnunet-dht-get.c
@@ -214,7 +214,7 @@ run (void *cls, char *const *args, const char *cfgfile,
214 GNUNET_CRYPTO_hash (query_key, strlen (query_key), &key); 214 GNUNET_CRYPTO_hash (query_key, strlen (query_key), &key);
215 if (verbose) 215 if (verbose)
216 FPRINTF (stderr, "%s `%s' \n", 216 FPRINTF (stderr, "%s `%s' \n",
217 _("Issueing DHT GET with key"), 217 _("Issuing DHT GET with key"),
218 GNUNET_h2s_full (&key)); 218 GNUNET_h2s_full (&key));
219 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); 219 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
220 tt = GNUNET_SCHEDULER_add_delayed (timeout_request, 220 tt = GNUNET_SCHEDULER_add_delayed (timeout_request,
diff --git a/src/dht/gnunet-service-dht_clients.c b/src/dht/gnunet-service-dht_clients.c
index 862654c83..332bc1eda 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -1018,7 +1018,7 @@ forward_reply (void *cls,
1018 (record->type != frc->type)) 1018 (record->type != frc->type))
1019 { 1019 {
1020 LOG (GNUNET_ERROR_TYPE_DEBUG, 1020 LOG (GNUNET_ERROR_TYPE_DEBUG,
1021 "Record type missmatch, not passing request for key %s to local client\n", 1021 "Record type mismatch, not passing request for key %s to local client\n",
1022 GNUNET_h2s (key)); 1022 GNUNET_h2s (key));
1023 GNUNET_STATISTICS_update (GDS_stats, 1023 GNUNET_STATISTICS_update (GDS_stats,
1024 gettext_noop 1024 gettext_noop
diff --git a/src/fs/fs_getopt.c b/src/fs/fs_getopt.c
index 7b5c2991d..cbd9339c9 100644
--- a/src/fs/fs_getopt.c
+++ b/src/fs/fs_getopt.c
@@ -38,19 +38,20 @@
38 * @param scls must be of type "struct GNUNET_FS_Uri **" 38 * @param scls must be of type "struct GNUNET_FS_Uri **"
39 * @param option name of the option (typically 'k') 39 * @param option name of the option (typically 'k')
40 * @param value command line argument given 40 * @param value command line argument given
41 * @return GNUNET_OK on success 41 * @return #GNUNET_OK on success
42 */ 42 */
43static int 43static int
44getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext 44getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
45 *ctx, void *scls, const char *option, 45 void *scls,
46 const char *value) 46 const char *option,
47 const char *value)
47{ 48{
48 struct GNUNET_FS_Uri **uri = scls; 49 struct GNUNET_FS_Uri **uri = scls;
49 struct GNUNET_FS_Uri *u = *uri; 50 struct GNUNET_FS_Uri *u = *uri;
50 char *val; 51 char *val;
51 size_t slen; 52 size_t slen;
52 53
53 if (u == NULL) 54 if (NULL == u)
54 { 55 {
55 u = GNUNET_new (struct GNUNET_FS_Uri); 56 u = GNUNET_new (struct GNUNET_FS_Uri);
56 *uri = u; 57 *uri = u;
@@ -60,10 +61,10 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext
60 } 61 }
61 else 62 else
62 { 63 {
63 GNUNET_assert (u->type == GNUNET_FS_URI_KSK); 64 GNUNET_assert (GNUNET_FS_URI_KSK == u->type);
64 } 65 }
65 slen = strlen (value); 66 slen = strlen (value);
66 if (slen == 0) 67 if (0 == slen)
67 return GNUNET_SYSERR; /* cannot be empty */ 68 return GNUNET_SYSERR; /* cannot be empty */
68 if (value[0] == '+') 69 if (value[0] == '+')
69 { 70 {
@@ -75,7 +76,9 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext
75 /* remove the quotes, keep the '+' */ 76 /* remove the quotes, keep the '+' */
76 val = GNUNET_malloc (slen - 1); 77 val = GNUNET_malloc (slen - 1);
77 val[0] = '+'; 78 val[0] = '+';
78 GNUNET_memcpy (&val[1], &value[2], slen - 3); 79 GNUNET_memcpy (&val[1],
80 &value[2],
81 slen - 3);
79 val[slen - 2] = '\0'; 82 val[slen - 2] = '\0';
80 } 83 }
81 else 84 else
@@ -91,7 +94,9 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext
91 /* remove the quotes, add a space */ 94 /* remove the quotes, add a space */
92 val = GNUNET_malloc (slen); 95 val = GNUNET_malloc (slen);
93 val[0] = ' '; 96 val[0] = ' ';
94 GNUNET_memcpy (&val[1], &value[1], slen - 2); 97 GNUNET_memcpy (&val[1],
98 &value[1],
99 slen - 2);
95 val[slen - 1] = '\0'; 100 val[slen - 1] = '\0';
96 } 101 }
97 else 102 else
@@ -102,10 +107,13 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext
102 strcat (val, value); 107 strcat (val, value);
103 } 108 }
104 } 109 }
105 GNUNET_array_append (u->data.ksk.keywords, u->data.ksk.keywordCount, val); 110 GNUNET_array_append (u->data.ksk.keywords,
111 u->data.ksk.keywordCount,
112 val);
106 return GNUNET_OK; 113 return GNUNET_OK;
107} 114}
108 115
116
109/** 117/**
110 * Allow user to specify keywords. 118 * Allow user to specify keywords.
111 * 119 *
@@ -135,6 +143,7 @@ GNUNET_FS_GETOPT_KEYWORDS (char shortName,
135 return clo; 143 return clo;
136} 144}
137 145
146
138/** 147/**
139 * Command-line option parser function that allows the user to specify 148 * Command-line option parser function that allows the user to specify
140 * one or more '-m' options with metadata. Each specified entry of 149 * one or more '-m' options with metadata. Each specified entry of
diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c
index 999301c2f..ffcf9b5d0 100644
--- a/src/fs/gnunet-publish.c
+++ b/src/fs/gnunet-publish.c
@@ -496,21 +496,22 @@ uri_ksk_continuation (void *cls,
496 emsg); 496 emsg);
497 ret = 1; 497 ret = 1;
498 } 498 }
499 if (NULL != namespace) 499 if (NULL == namespace)
500 { 500 {
501 priv = GNUNET_IDENTITY_ego_get_private_key (namespace); 501 GNUNET_SCHEDULER_shutdown ();
502 GNUNET_FS_publish_sks (ctx,
503 priv,
504 this_id,
505 next_id,
506 meta,
507 uri,
508 &bo,
509 GNUNET_FS_PUBLISH_OPTION_NONE,
510 &uri_sks_continuation, NULL);
511 return; 502 return;
512 } 503 }
513 GNUNET_SCHEDULER_shutdown (); 504 priv = GNUNET_IDENTITY_ego_get_private_key (namespace);
505 GNUNET_FS_publish_sks (ctx,
506 priv,
507 this_id,
508 next_id,
509 meta,
510 uri,
511 &bo,
512 GNUNET_FS_PUBLISH_OPTION_NONE,
513 &uri_sks_continuation,
514 NULL);
514} 515}
515 516
516 517
@@ -728,7 +729,8 @@ identity_continuation (const char *args0)
728 GNUNET_SCHEDULER_shutdown (); 729 GNUNET_SCHEDULER_shutdown ();
729 return; 730 return;
730 } 731 }
731 GNUNET_FS_publish_ksk (ctx, topKeywords, 732 GNUNET_FS_publish_ksk (ctx,
733 topKeywords,
732 meta, uri, 734 meta, uri,
733 &bo, 735 &bo,
734 GNUNET_FS_PUBLISH_OPTION_NONE, 736 GNUNET_FS_PUBLISH_OPTION_NONE,
@@ -889,7 +891,8 @@ run (void *cls,
889 * @return 0 ok, 1 on error 891 * @return 0 ok, 1 on error
890 */ 892 */
891int 893int
892main (int argc, char *const *argv) 894main (int argc,
895 char *const *argv)
893{ 896{
894 struct GNUNET_GETOPT_CommandLineOption options[] = { 897 struct GNUNET_GETOPT_CommandLineOption options[] = {
895 GNUNET_GETOPT_option_uint ('a', 898 GNUNET_GETOPT_option_uint ('a',
@@ -922,26 +925,22 @@ main (int argc, char *const *argv)
922 "TYPE:VALUE", 925 "TYPE:VALUE",
923 gettext_noop ("set the meta-data for the given TYPE to the given VALUE"), 926 gettext_noop ("set the meta-data for the given TYPE to the given VALUE"),
924 &meta), 927 &meta),
925
926 GNUNET_GETOPT_option_flag ('n', 928 GNUNET_GETOPT_option_flag ('n',
927 "noindex", 929 "noindex",
928 gettext_noop ("do not index, perform full insertion (stores " 930 gettext_noop ("do not index, perform full insertion (stores "
929 "entire file in encrypted form in GNUnet database)"), 931 "entire file in encrypted form in GNUnet database)"),
930 &do_insert), 932 &do_insert),
931
932 GNUNET_GETOPT_option_string ('N', 933 GNUNET_GETOPT_option_string ('N',
933 "next", 934 "next",
934 "ID", 935 "ID",
935 gettext_noop ("specify ID of an updated version to be " 936 gettext_noop ("specify ID of an updated version to be "
936 "published in the future (for namespace insertions only)"), 937 "published in the future (for namespace insertions only)"),
937 &next_id), 938 &next_id),
938
939 GNUNET_GETOPT_option_uint ('p', 939 GNUNET_GETOPT_option_uint ('p',
940 "priority", 940 "priority",
941 "PRIORITY", 941 "PRIORITY",
942 gettext_noop ("specify the priority of the content"), 942 gettext_noop ("specify the priority of the content"),
943 &bo.content_priority), 943 &bo.content_priority),
944
945 GNUNET_GETOPT_option_string ('P', 944 GNUNET_GETOPT_option_string ('P',
946 "pseudonym", 945 "pseudonym",
947 "NAME", 946 "NAME",
@@ -964,7 +963,6 @@ main (int argc, char *const *argv)
964 gettext_noop ("set the ID of this version of the publication " 963 gettext_noop ("set the ID of this version of the publication "
965 "(for namespace insertions only)"), 964 "(for namespace insertions only)"),
966 &this_id), 965 &this_id),
967
968 GNUNET_GETOPT_option_string ('u', 966 GNUNET_GETOPT_option_string ('u',
969 "uri", 967 "uri",
970 "URI", 968 "URI",
@@ -982,10 +980,14 @@ main (int argc, char *const *argv)
982 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 980 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
983 return 2; 981 return 2;
984 ret = (GNUNET_OK == 982 ret = (GNUNET_OK ==
985 GNUNET_PROGRAM_run (argc, argv, "gnunet-publish [OPTIONS] FILENAME", 983 GNUNET_PROGRAM_run (argc,
984 argv,
985 "gnunet-publish [OPTIONS] FILENAME",
986 gettext_noop 986 gettext_noop
987 ("Publish a file or directory on GNUnet"), 987 ("Publish a file or directory on GNUnet"),
988 options, &run, NULL)) ? ret : 1; 988 options,
989 &run,
990 NULL)) ? ret : 1;
989 GNUNET_free ((void*) argv); 991 GNUNET_free ((void*) argv);
990 return ret; 992 return ret;
991} 993}
diff --git a/src/fs/gnunet-search.c b/src/fs/gnunet-search.c
index 780b3c93d..2a0a153e7 100644
--- a/src/fs/gnunet-search.c
+++ b/src/fs/gnunet-search.c
@@ -304,49 +304,44 @@ int
304main (int argc, char *const *argv) 304main (int argc, char *const *argv)
305{ 305{
306 struct GNUNET_GETOPT_CommandLineOption options[] = { 306 struct GNUNET_GETOPT_CommandLineOption options[] = {
307
308 GNUNET_GETOPT_option_uint ('a', 307 GNUNET_GETOPT_option_uint ('a',
309 "anonymity", 308 "anonymity",
310 "LEVEL", 309 "LEVEL",
311 gettext_noop ("set the desired LEVEL of receiver-anonymity"), 310 gettext_noop ("set the desired LEVEL of receiver-anonymity"),
312 &anonymity), 311 &anonymity),
313
314
315 GNUNET_GETOPT_option_flag ('n', 312 GNUNET_GETOPT_option_flag ('n',
316 "no-network", 313 "no-network",
317 gettext_noop ("only search the local peer (no P2P network search)"), 314 gettext_noop ("only search the local peer (no P2P network search)"),
318 &local_only), 315 &local_only),
319
320 GNUNET_GETOPT_option_string ('o', 316 GNUNET_GETOPT_option_string ('o',
321 "output", 317 "output",
322 "PREFIX", 318 "PREFIX",
323 gettext_noop ("write search results to file starting with PREFIX"), 319 gettext_noop ("write search results to file starting with PREFIX"),
324 &output_filename), 320 &output_filename),
325
326 GNUNET_GETOPT_option_relative_time ('t', 321 GNUNET_GETOPT_option_relative_time ('t',
327 "timeout", 322 "timeout",
328 "DELAY", 323 "DELAY",
329 gettext_noop ("automatically terminate search after DELAY"), 324 gettext_noop ("automatically terminate search after DELAY"),
330 &timeout), 325 &timeout),
331
332
333 GNUNET_GETOPT_option_verbose (&verbose), 326 GNUNET_GETOPT_option_verbose (&verbose),
334
335 GNUNET_GETOPT_option_uint ('N', 327 GNUNET_GETOPT_option_uint ('N',
336 "results", 328 "results",
337 "VALUE", 329 "VALUE",
338 gettext_noop ("automatically terminate search " 330 gettext_noop ("automatically terminate search "
339 "after VALUE results are found"), 331 "after VALUE results are found"),
340 &results_limit), 332 &results_limit),
341
342 GNUNET_GETOPT_OPTION_END 333 GNUNET_GETOPT_OPTION_END
343 }; 334 };
344 335
345 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 336 if (GNUNET_OK !=
337 GNUNET_STRINGS_get_utf8_args (argc, argv,
338 &argc, &argv))
346 return 2; 339 return 2;
347 340
348 ret = (GNUNET_OK == 341 ret = (GNUNET_OK ==
349 GNUNET_PROGRAM_run (argc, argv, "gnunet-search [OPTIONS] KEYWORD", 342 GNUNET_PROGRAM_run (argc,
343 argv,
344 "gnunet-search [OPTIONS] KEYWORD",
350 gettext_noop 345 gettext_noop
351 ("Search GNUnet for files that were published on GNUnet"), 346 ("Search GNUnet for files that were published on GNUnet"),
352 options, &run, NULL)) ? ret : 1; 347 options, &run, NULL)) ? ret : 1;
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index 594896c93..fea22f279 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -1232,7 +1232,7 @@ peer_init_handler (void *cls,
1232 my_identity)) 1232 my_identity))
1233 { 1233 {
1234 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1234 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1235 "Peer identity missmatch, refusing to start!\n"); 1235 "Peer identity mismatch, refusing to start!\n");
1236 GNUNET_SCHEDULER_shutdown (); 1236 GNUNET_SCHEDULER_shutdown ();
1237 } 1237 }
1238} 1238}
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c
index a9013390e..e1997e215 100644
--- a/src/gns/gnunet-gns-proxy.c
+++ b/src/gns/gnunet-gns-proxy.c
@@ -59,6 +59,12 @@
59#define MAX_HTTP_URI_LENGTH 2048 59#define MAX_HTTP_URI_LENGTH 2048
60 60
61/** 61/**
62 * Maximum number of DANE records we support
63 * per domain name (and port and protocol).
64 */
65#define MAX_DANES 32
66
67/**
62 * Size of the buffer for the data upload / download. Must be 68 * Size of the buffer for the data upload / download. Must be
63 * enough for curl, thus CURL_MAX_WRITE_SIZE is needed here (16k). 69 * enough for curl, thus CURL_MAX_WRITE_SIZE is needed here (16k).
64 */ 70 */
@@ -543,9 +549,9 @@ struct Socks5Request
543 char *leho; 549 char *leho;
544 550
545 /** 551 /**
546 * Payload of the (last) DANE record encountered. 552 * Payload of the DANE records encountered.
547 */ 553 */
548 char *dane_data; 554 char *dane_data[MAX_DANES + 1];
549 555
550 /** 556 /**
551 * The URL to fetch 557 * The URL to fetch
@@ -575,7 +581,13 @@ struct Socks5Request
575 /** 581 /**
576 * Number of bytes in @e dane_data. 582 * Number of bytes in @e dane_data.
577 */ 583 */
578 size_t dane_data_len; 584 int dane_data_len[MAX_DANES + 1];
585
586 /**
587 * Number of entries used in @e dane_data_len
588 * and @e dane_data.
589 */
590 unsigned int num_danes;
579 591
580 /** 592 /**
581 * Number of bytes already in read buffer 593 * Number of bytes already in read buffer
@@ -816,7 +828,8 @@ cleanup_s5r (struct Socks5Request *s5r)
816 GNUNET_free_non_null (s5r->domain); 828 GNUNET_free_non_null (s5r->domain);
817 GNUNET_free_non_null (s5r->leho); 829 GNUNET_free_non_null (s5r->leho);
818 GNUNET_free_non_null (s5r->url); 830 GNUNET_free_non_null (s5r->url);
819 GNUNET_free_non_null (s5r->dane_data); 831 for (unsigned int i=0;i<s5r->num_danes;i++)
832 GNUNET_free (s5r->dane_data[i]);
820 GNUNET_free (s5r); 833 GNUNET_free (s5r);
821} 834}
822 835
@@ -989,10 +1002,8 @@ check_ssl_certificate (struct Socks5Request *s5r)
989 } 1002 }
990 /* check for TLSA/DANE records */ 1003 /* check for TLSA/DANE records */
991#if HAVE_GNUTLS_DANE 1004#if HAVE_GNUTLS_DANE
992 if (NULL != s5r->dane_data) 1005 if (0 != s5r->num_danes)
993 { 1006 {
994 char *dd[] = { s5r->dane_data, NULL };
995 int dlen[] = { s5r->dane_data_len, 0};
996 dane_state_t dane_state; 1007 dane_state_t dane_state;
997 dane_query_t dane_query; 1008 dane_query_t dane_query;
998 unsigned int verify; 1009 unsigned int verify;
@@ -1010,10 +1021,12 @@ check_ssl_certificate (struct Socks5Request *s5r)
1010 gnutls_x509_crt_deinit (x509_cert); 1021 gnutls_x509_crt_deinit (x509_cert);
1011 return GNUNET_SYSERR; 1022 return GNUNET_SYSERR;
1012 } 1023 }
1024 s5r->dane_data[s5r->num_danes] = NULL;
1025 s5r->dane_data_len[s5r->num_danes] = 0;
1013 if (0 != (rc = dane_raw_tlsa (dane_state, 1026 if (0 != (rc = dane_raw_tlsa (dane_state,
1014 &dane_query, 1027 &dane_query,
1015 dd, 1028 s5r->dane_data,
1016 dlen, 1029 s5r->dane_data_len,
1017 GNUNET_YES, 1030 GNUNET_YES,
1018 GNUNET_NO))) 1031 GNUNET_NO)))
1019 { 1032 {
@@ -3070,12 +3083,17 @@ handle_gns_result (void *cls,
3070 (ntohs (box->protocol) != IPPROTO_TCP) || 3083 (ntohs (box->protocol) != IPPROTO_TCP) ||
3071 (ntohs (box->service) != s5r->port) ) 3084 (ntohs (box->service) != s5r->port) )
3072 break; /* BOX record does not apply */ 3085 break; /* BOX record does not apply */
3073 GNUNET_free_non_null (s5r->dane_data); 3086 if (s5r->num_danes >= MAX_DANES)
3074 s5r->dane_data_len = r->data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord); 3087 {
3075 s5r->dane_data = GNUNET_malloc (s5r->dane_data_len); 3088 GNUNET_break (0); /* MAX_DANES too small */
3076 GNUNET_memcpy (s5r->dane_data, 3089 break;
3077 &box[1], 3090 }
3078 s5r->dane_data_len); 3091 s5r->dane_data_len[s5r->num_danes]
3092 = r->data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord);
3093 s5r->dane_data[s5r->num_danes]
3094 = GNUNET_memdup (&box[1],
3095 s5r->dane_data_len);
3096 s5r->num_danes++;
3079 break; 3097 break;
3080 } 3098 }
3081 default: 3099 default:
diff --git a/src/gns/test_gns_cname_lookup.sh b/src/gns/test_gns_cname_lookup.sh
index f6b7a842d..de575c561 100755
--- a/src/gns/test_gns_cname_lookup.sh
+++ b/src/gns/test_gns_cname_lookup.sh
@@ -54,6 +54,9 @@ gnunet-identity -D $MY_EGO -c test_gns_lookup.conf
54gnunet-arm -e -c test_gns_lookup.conf 54gnunet-arm -e -c test_gns_lookup.conf
55rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` 55rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
56 56
57# make cmp case-insensitive by converting to lower case first
58RES_CNAME_RAW=`echo $RES_CNAME_RAW | tr [A-Z] [a-z]`
59TESTEGOZONE=`echo $TESTEGOZONE | tr [A-Z] [a-z]`
57if [ "$RES_CNAME_RAW" == "server.$TESTEGOZONE" ] 60if [ "$RES_CNAME_RAW" == "server.$TESTEGOZONE" ]
58then 61then
59 echo "PASS: CNAME resolution from GNS" 62 echo "PASS: CNAME resolution from GNS"
diff --git a/src/gns/test_gns_defaults.conf b/src/gns/test_gns_defaults.conf
index 19ba01ebb..80a2f3c44 100644
--- a/src/gns/test_gns_defaults.conf
+++ b/src/gns/test_gns_defaults.conf
@@ -20,3 +20,15 @@ PLUGINS = tcp
20[transport-tcp] 20[transport-tcp]
21BINDTO = 127.0.0.1 21BINDTO = 127.0.0.1
22 22
23
24[fs]
25IMMEDIATE_START = NO
26START_ON_DEMAND = NO
27
28[rps]
29IMMEDIATE_START = NO
30START_ON_DEMAND = NO
31
32[topology]
33IMMEDIATE_START = NO
34START_ON_DEMAND = NO
diff --git a/src/gns/test_gns_gns2dns_cname_lookup.sh b/src/gns/test_gns_gns2dns_cname_lookup.sh
index 84ad8549f..17196f820 100755
--- a/src/gns/test_gns_gns2dns_cname_lookup.sh
+++ b/src/gns/test_gns_gns2dns_cname_lookup.sh
@@ -43,7 +43,15 @@ MY_EGO="myego"
43# various names we will use for resolution 43# various names we will use for resolution
44TEST_DOMAIN="www.${TEST_RECORD_NAME}.$MY_EGO" 44TEST_DOMAIN="www.${TEST_RECORD_NAME}.$MY_EGO"
45 45
46which timeout &> /dev/null && DO_TIMEOUT="timeout 15"
47
48
46gnunet-arm -s -c test_gns_lookup.conf 49gnunet-arm -s -c test_gns_lookup.conf
50
51echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found, skipping test"; exit 77; }
52echo $OUT | grep $TEST6_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found, skipping test"; exit 77; }
53
54
47gnunet-identity -C $MY_EGO -c test_gns_lookup.conf 55gnunet-identity -C $MY_EGO -c test_gns_lookup.conf
48 56
49# set IP address for DNS resolver for resolving in gnunet.org domain 57# set IP address for DNS resolver for resolving in gnunet.org domain
@@ -52,7 +60,6 @@ gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECOR
52gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS2 -e never -c test_gns_lookup.conf 60gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS2 -e never -c test_gns_lookup.conf
53gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS3 -e never -c test_gns_lookup.conf 61gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS3 -e never -c test_gns_lookup.conf
54 62
55which timeout &> /dev/null && DO_TIMEOUT="timeout 15"
56 63
57echo "EGOs:" 64echo "EGOs:"
58gnunet-identity -d 65gnunet-identity -d
diff --git a/src/gns/test_gns_gns2dns_lookup.sh b/src/gns/test_gns_gns2dns_lookup.sh
index 122e45525..431f01086 100755
--- a/src/gns/test_gns_gns2dns_lookup.sh
+++ b/src/gns/test_gns_gns2dns_lookup.sh
@@ -44,8 +44,17 @@ TEST_DOMAIN="www.${TEST_RECORD_NAME}.$MY_EGO"
44TEST_DOMAIN_ALT="${TEST_RECORD_NAME}.$MY_EGO" 44TEST_DOMAIN_ALT="${TEST_RECORD_NAME}.$MY_EGO"
45TEST_DOMAIN_ALT2="docs.${TEST_RECORD_NAME}.$MY_EGO" 45TEST_DOMAIN_ALT2="docs.${TEST_RECORD_NAME}.$MY_EGO"
46 46
47which timeout &> /dev/null && DO_TIMEOUT="timeout 15"
48
47 49
48gnunet-arm -s -c test_gns_lookup.conf 50gnunet-arm -s -c test_gns_lookup.conf
51
52OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf gnunet.org`
53echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found, skipping test"; exit 77; }
54echo $OUT | grep $TEST6_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found, skipping test"; exit 77; }
55
56
57
49gnunet-identity -C $MY_EGO -c test_gns_lookup.conf 58gnunet-identity -C $MY_EGO -c test_gns_lookup.conf
50 59
51# set IP address for DNS resolver for resolving in gnunet.org domain 60# set IP address for DNS resolver for resolving in gnunet.org domain
@@ -53,7 +62,6 @@ gnunet-namestore -p -z $MY_EGO -a -n $TEST_RESOLVER_LABEL -t A -V $TEST_IP_GNS2D
53# map '$TEST_RECORD_NAME.$MY_EGO' to 'gnunet.org' in DNS 62# map '$TEST_RECORD_NAME.$MY_EGO' to 'gnunet.org' in DNS
54gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS -e never -c test_gns_lookup.conf 63gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS -e never -c test_gns_lookup.conf
55 64
56which timeout &> /dev/null && DO_TIMEOUT="timeout 15"
57 65
58echo "EGOs:" 66echo "EGOs:"
59gnunet-identity -d 67gnunet-identity -d
diff --git a/src/gns/test_gns_mx_lookup.sh b/src/gns/test_gns_mx_lookup.sh
index 3a360494b..79ac37b0a 100755
--- a/src/gns/test_gns_mx_lookup.sh
+++ b/src/gns/test_gns_mx_lookup.sh
@@ -31,6 +31,10 @@ gnunet-identity -D $MY_EGO -c test_gns_lookup.conf
31gnunet-arm -e -c test_gns_lookup.conf 31gnunet-arm -e -c test_gns_lookup.conf
32rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` 32rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
33 33
34# make cmp case-insensitive by converting to lower case first
35RES_MX=`echo $RES_MX | tr [A-Z] [a-z]`
36WANT_MX=`echo $WANT_MX | tr [A-Z] [a-z]`
37
34if [ "$RES_MX" == "$WANT_MX" ] 38if [ "$RES_MX" == "$WANT_MX" ]
35then 39then
36 exit 0 40 exit 0
diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c
index b80d86073..f0d7a839e 100644
--- a/src/gnsrecord/gnsrecord.c
+++ b/src/gnsrecord/gnsrecord.c
@@ -28,10 +28,7 @@
28#include "gnunet_constants.h" 28#include "gnunet_constants.h"
29#include "gnunet_gnsrecord_lib.h" 29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_gnsrecord_plugin.h" 30#include "gnunet_gnsrecord_plugin.h"
31#include "gnunet_json_lib.h"
32#include "gnunet_tun_lib.h" 31#include "gnunet_tun_lib.h"
33#include <jansson.h>
34
35 32
36#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) 33#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
37 34
diff --git a/src/include/gnunet_bandwidth_lib.h b/src/include/gnunet_bandwidth_lib.h
index 78610c48b..4395b878b 100644
--- a/src/include/gnunet_bandwidth_lib.h
+++ b/src/include/gnunet_bandwidth_lib.h
@@ -11,7 +11,7 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/ 17*/
diff --git a/src/include/gnunet_configuration_lib.h b/src/include/gnunet_configuration_lib.h
index e3eefa18d..ec3d12738 100644
--- a/src/include/gnunet_configuration_lib.h
+++ b/src/include/gnunet_configuration_lib.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2006, 2008, 2009 GNUnet e.V. 3 Copyright (C) 2006, 2008, 2009, 2018 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -191,6 +191,35 @@ GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg);
191 191
192 192
193/** 193/**
194 * Signature of a function to be run with a configuration.
195 *
196 * @param cls closure
197 * @param cfg the configuration
198 * @return status code
199 */
200typedef int
201(*GNUNET_CONFIGURATION_Callback)(void *cls,
202 const struct GNUNET_CONFIGURATION_Handle *cfg);
203
204
205/**
206 * Parse a configuration file @a filename and run the function
207 * @a cb with the resulting configuration object. Then free the
208 * configuration object and return the status value from @a cb.
209 *
210 * @param filename configuration to parse, NULL for "default"
211 * @param cb function to run
212 * @param cb_cls closure for @a cb
213 * @return #GNUNET_SYSERR if parsing the configuration failed,
214 * otherwise return value from @a cb.
215 */
216int
217GNUNET_CONFIGURATION_parse_and_run (const char *filename,
218 GNUNET_CONFIGURATION_Callback cb,
219 void *cb_cls);
220
221
222/**
194 * Function to iterate over options. 223 * Function to iterate over options.
195 * 224 *
196 * @param cls closure 225 * @param cls closure
diff --git a/src/include/gnunet_consensus_service.h b/src/include/gnunet_consensus_service.h
index eee9fc23b..c6aed298c 100644
--- a/src/include/gnunet_consensus_service.h
+++ b/src/include/gnunet_consensus_service.h
@@ -53,7 +53,7 @@ extern "C"
53 53
54 54
55/** 55/**
56 * Called when a new element was received from another peer, or an error occured. 56 * Called when a new element was received from another peer, or an error occurred.
57 * May deliver duplicate values. 57 * May deliver duplicate values.
58 * Elements given to a consensus operation by the local peer are NOT given 58 * Elements given to a consensus operation by the local peer are NOT given
59 * to this callback. 59 * to this callback.
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 898ad6258..6f3b886d8 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -11,7 +11,7 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/ 17*/
@@ -3041,7 +3041,7 @@ extern "C"
3041#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP 1204 3041#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP 1204
3042 3042
3043/** 3043/**
3044 * @brief inform transport that a queue was torn down 3044 * @brief inform transport that a queue was torn down
3045 */ 3045 */
3046#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN 1205 3046#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN 1205
3047 3047
@@ -3051,18 +3051,52 @@ extern "C"
3051#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE 1206 3051#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE 1206
3052 3052
3053/** 3053/**
3054 * Response from communicator: will try to create queue.
3055 */
3056#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK 1207
3057
3058/**
3059 * Response from communicator: address bogus, will not try to create queue.
3060 */
3061#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL 1208
3062
3063/**
3054 * @brief transport tells communicator it wants to transmit 3064 * @brief transport tells communicator it wants to transmit
3055 */ 3065 */
3056#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG 1207 3066#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG 1209
3057 3067
3058/** 3068/**
3059 * @brief communicator tells transports that message was sent 3069 * @brief communicator tells transports that message was sent
3060 */ 3070 */
3061#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK 1208 3071#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK 1210
3072
3073/**
3074 * Message sent to indicate to the transport which address
3075 * prefix is supported by a communicator.
3076 */
3077#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR 1211
3078
3079
3080/**
3081 * Message sent to indicate to the transport that a monitor
3082 * wants to observe certain events.
3083 */
3084#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START 1250
3085
3086/**
3087 * Message sent to indicate to a monitor about events.
3088 */
3089#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA 1251
3090
3091/**
3092 * Message sent to indicate to a monitor that a one-shot
3093 * iteration over events is done.
3094 */
3095#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END 1252
3062 3096
3063 3097
3064/** 3098/**
3065 * Next available: 1300 3099 * Next available: 1400
3066 */ 3100 */
3067 3101
3068 3102
diff --git a/src/include/gnunet_testbed_service.h b/src/include/gnunet_testbed_service.h
index 4b8d63ad2..302b32019 100644
--- a/src/include/gnunet_testbed_service.h
+++ b/src/include/gnunet_testbed_service.h
@@ -443,7 +443,7 @@ typedef void
443 443
444 444
445/** 445/**
446 * Starts a controller process at the given host. The given host's configration 446 * Starts a controller process at the given host. The given host's configuration
447 * is used as a Template configuration to use for the remote controller; the 447 * is used as a Template configuration to use for the remote controller; the
448 * remote controller will be started with a slightly modified configuration 448 * remote controller will be started with a slightly modified configuration
449 * (port numbers, unix domain sockets and service home values are changed as per 449 * (port numbers, unix domain sockets and service home values are changed as per
@@ -486,7 +486,7 @@ GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc);
486 486
487/** 487/**
488 * Connect to a controller process. The configuration to use for the connection 488 * Connect to a controller process. The configuration to use for the connection
489 * is retreived from the given host where a controller is started using 489 * is retrieved from the given host where a controller is started using
490 * GNUNET_TESTBED_controller_start(). 490 * GNUNET_TESTBED_controller_start().
491 * 491 *
492 * @param host host to run the controller on; This should be the same host if 492 * @param host host to run the controller on; This should be the same host if
diff --git a/src/include/gnunet_transport_communication_service.h b/src/include/gnunet_transport_communication_service.h
index d93d5134e..50f94bddf 100644
--- a/src/include/gnunet_transport_communication_service.h
+++ b/src/include/gnunet_transport_communication_service.h
@@ -42,6 +42,7 @@ extern "C"
42#endif 42#endif
43 43
44#include "gnunet_util_lib.h" 44#include "gnunet_util_lib.h"
45#include "gnunet_ats_service.h"
45 46
46/** 47/**
47 * Version number of the transport communication API. 48 * Version number of the transport communication API.
@@ -69,7 +70,7 @@ extern "C"
69typedef int 70typedef int
70(*GNUNET_TRANSPORT_CommunicatorMqInit) (void *cls, 71(*GNUNET_TRANSPORT_CommunicatorMqInit) (void *cls,
71 const struct GNUNET_PeerIdentity *peer, 72 const struct GNUNET_PeerIdentity *peer,
72 const void *address); 73 const char *address);
73 74
74 75
75/** 76/**
@@ -82,7 +83,9 @@ struct GNUNET_TRANSPORT_CommunicatorHandle;
82 * Connect to the transport service. 83 * Connect to the transport service.
83 * 84 *
84 * @param cfg configuration to use 85 * @param cfg configuration to use
85 * @param name name of the communicator that is connecting 86 * @param config_section section of the configuration to use for options
87 * @param addr_prefix address prefix for addresses supported by this
88 * communicator, could be NULL for incoming-only communicators
86 * @param mtu maximum message size supported by communicator, 0 if 89 * @param mtu maximum message size supported by communicator, 0 if
87 * sending is not supported, SIZE_MAX for no MTU 90 * sending is not supported, SIZE_MAX for no MTU
88 * @param mq_init function to call to initialize a message queue given 91 * @param mq_init function to call to initialize a message queue given
@@ -93,7 +96,8 @@ struct GNUNET_TRANSPORT_CommunicatorHandle;
93 */ 96 */
94struct GNUNET_TRANSPORT_CommunicatorHandle * 97struct GNUNET_TRANSPORT_CommunicatorHandle *
95GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, 98GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
96 const char *name, 99 const char *config_section_name,
100 const char *addr_prefix,
97 size_t mtu, 101 size_t mtu,
98 GNUNET_TRANSPORT_CommunicatorMqInit mq_init, 102 GNUNET_TRANSPORT_CommunicatorMqInit mq_init,
99 void *mq_init_cls); 103 void *mq_init_cls);
diff --git a/src/include/gnunet_transport_core_service.h b/src/include/gnunet_transport_core_service.h
index 5fbfcee21..b52dbe5f8 100644
--- a/src/include/gnunet_transport_core_service.h
+++ b/src/include/gnunet_transport_core_service.h
@@ -66,7 +66,7 @@ struct GNUNET_TRANSPORT_CoreHandle;
66 * @return closure to use in MQ handlers 66 * @return closure to use in MQ handlers
67 */ 67 */
68typedef void * 68typedef void *
69(*GNUNET_TRANSPORT_NotifyConnecT) (void *cls, 69(*GNUNET_TRANSPORT_NotifyConnect) (void *cls,
70 const struct GNUNET_PeerIdentity *peer, 70 const struct GNUNET_PeerIdentity *peer,
71 struct GNUNET_MQ_Handle *mq); 71 struct GNUNET_MQ_Handle *mq);
72 72
@@ -83,7 +83,7 @@ typedef void *
83 * connect notification callback 83 * connect notification callback
84 */ 84 */
85typedef void 85typedef void
86(*GNUNET_TRANSPORT_NotifyDisconnecT) (void *cls, 86(*GNUNET_TRANSPORT_NotifyDisconnect) (void *cls,
87 const struct GNUNET_PeerIdentity *peer, 87 const struct GNUNET_PeerIdentity *peer,
88 void *handler_cls); 88 void *handler_cls);
89 89
@@ -105,7 +105,7 @@ typedef void
105 * connect notification callback 105 * connect notification callback
106 */ 106 */
107typedef void 107typedef void
108(*GNUNET_TRANSPORT_NotifyExcessBandwidtH)(void *cls, 108(*GNUNET_TRANSPORT_NotifyExcessBandwidth)(void *cls,
109 const struct GNUNET_PeerIdentity *neighbour, 109 const struct GNUNET_PeerIdentity *neighbour,
110 void *handlers_cls); 110 void *handlers_cls);
111 111
@@ -133,9 +133,9 @@ GNUNET_TRANSPORT_core_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
133 const struct GNUNET_PeerIdentity *self, 133 const struct GNUNET_PeerIdentity *self,
134 const struct GNUNET_MQ_MessageHandler *handlers, 134 const struct GNUNET_MQ_MessageHandler *handlers,
135 void *cls, 135 void *cls,
136 GNUNET_TRANSPORT_NotifyConnecT nc, 136 GNUNET_TRANSPORT_NotifyConnect nc,
137 GNUNET_TRANSPORT_NotifyDisconnecT nd, 137 GNUNET_TRANSPORT_NotifyDisconnect nd,
138 GNUNET_TRANSPORT_NotifyExcessBandwidtH neb); 138 GNUNET_TRANSPORT_NotifyExcessBandwidth neb);
139 139
140 140
141/** 141/**
diff --git a/src/include/gnunet_transport_monitor_service.h b/src/include/gnunet_transport_monitor_service.h
index b9d024d59..76fec0af4 100644
--- a/src/include/gnunet_transport_monitor_service.h
+++ b/src/include/gnunet_transport_monitor_service.h
@@ -11,7 +11,7 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/ 17*/
@@ -29,7 +29,6 @@
29 * 29 *
30 * @{ 30 * @{
31 */ 31 */
32
33#ifndef GNUNET_TRANSPORT_MONITOR_SERVICE_H 32#ifndef GNUNET_TRANSPORT_MONITOR_SERVICE_H
34#define GNUNET_TRANSPORT_MONITOR_SERVICE_H 33#define GNUNET_TRANSPORT_MONITOR_SERVICE_H
35 34
@@ -42,6 +41,7 @@ extern "C"
42#endif 41#endif
43 42
44#include "gnunet_util_lib.h" 43#include "gnunet_util_lib.h"
44#include "gnunet_ats_service.h"
45 45
46/** 46/**
47 * Version number of the transport API. 47 * Version number of the transport API.
@@ -121,7 +121,7 @@ struct GNUNET_TRANSPORT_MonitorInformation
121 * @param mi monitoring data on the peer 121 * @param mi monitoring data on the peer
122 */ 122 */
123typedef void 123typedef void
124(*GNUNET_TRANSPORT_MontiorCallback) (void *cls, 124(*GNUNET_TRANSPORT_MonitorCallback) (void *cls,
125 const struct GNUNET_PeerIdentity *peer, 125 const struct GNUNET_PeerIdentity *peer,
126 const struct GNUNET_TRANSPORT_MonitorInformation *mi); 126 const struct GNUNET_TRANSPORT_MonitorInformation *mi);
127 127
@@ -155,24 +155,24 @@ struct GNUNET_TRANSPORT_MonitorContext;
155 * NULL for all peers 155 * NULL for all peers
156 * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL), 156 * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL),
157 * #GNUNET_NO to monitor peers continuously 157 * #GNUNET_NO to monitor peers continuously
158 * @param mc function to call with the results 158 * @param cb function to call with the results
159 * @param mc_cls closure for @a mc 159 * @param cb_cls closure for @a mc
160 */ 160 */
161struct GNUNET_TRANSPORT_MonitorContext * 161struct GNUNET_TRANSPORT_MonitorContext *
162GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg, 162GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
163 const struct GNUNET_PeerIdentity *peer, 163 const struct GNUNET_PeerIdentity *peer,
164 int one_shot, 164 int one_shot,
165 GNUNET_TRANSPORT_MonitorCallback mc, 165 GNUNET_TRANSPORT_MonitorCallback cb,
166 void *mc_cls); 166 void *cb_cls);
167 167
168 168
169/** 169/**
170 * Cancel request to monitor peers 170 * Cancel request to monitor peers
171 * 171 *
172 * @param pmc handle for the request to cancel 172 * @param mc handle for the request to cancel
173 */ 173 */
174void 174void
175GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *pmc); 175GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *mc);
176 176
177 177
178#if 0 /* keep Emacsens' auto-indent happy */ 178#if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/my/my.c b/src/my/my.c
index 2f4cd3ba3..16df437b2 100644
--- a/src/my/my.c
+++ b/src/my/my.c
@@ -157,7 +157,7 @@ GNUNET_MY_extract_result (struct GNUNET_MYSQL_StatementHandle *sh,
157 if (mysql_stmt_field_count (stmt) != num_fields) 157 if (mysql_stmt_field_count (stmt) != num_fields)
158 { 158 {
159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
160 "Number of fields missmatch between SQL result and result specification\n"); 160 "Number of fields mismatch between SQL result and result specification\n");
161 return GNUNET_SYSERR; 161 return GNUNET_SYSERR;
162 } 162 }
163 163
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c
index c5f48848e..8386a696d 100644
--- a/src/namestore/gnunet-namestore.c
+++ b/src/namestore/gnunet-namestore.c
@@ -33,6 +33,24 @@
33 33
34 34
35/** 35/**
36 * Entry in record set for bulk processing.
37 */
38struct RecordSetEntry
39{
40 /**
41 * Kept in a linked list.
42 */
43 struct RecordSetEntry *next;
44
45 /**
46 * The record to add/remove.
47 */
48 struct GNUNET_GNSRECORD_Data record;
49
50};
51
52
53/**
36 * Handle to the namestore. 54 * Handle to the namestore.
37 */ 55 */
38static struct GNUNET_NAMESTORE_Handle *ns; 56static struct GNUNET_NAMESTORE_Handle *ns;
@@ -118,6 +136,11 @@ static int is_shadow;
118static struct GNUNET_NAMESTORE_QueueEntry *del_qe; 136static struct GNUNET_NAMESTORE_QueueEntry *del_qe;
119 137
120/** 138/**
139 * Queue entry for the 'set/replace' operation.
140 */
141static struct GNUNET_NAMESTORE_QueueEntry *set_qe;
142
143/**
121 * Name of the records to add/list/remove. 144 * Name of the records to add/list/remove.
122 */ 145 */
123static char *name; 146static char *name;
@@ -173,14 +196,9 @@ static void *data;
173static size_t data_size; 196static size_t data_size;
174 197
175/** 198/**
176 * Expirationstring converted to relative time. 199 * Expiration string converted to numeric value.
177 */
178static struct GNUNET_TIME_Relative etime_rel;
179
180/**
181 * Expirationstring converted to absolute time.
182 */ 200 */
183static struct GNUNET_TIME_Absolute etime_abs; 201static uint64_t etime;
184 202
185/** 203/**
186 * Is expiration time relative or absolute time? 204 * Is expiration time relative or absolute time?
@@ -197,6 +215,11 @@ static struct GNUNET_NAMESTORE_ZoneMonitor *zm;
197 */ 215 */
198static int monitor; 216static int monitor;
199 217
218/**
219 * Entry in record set for processing records in bulk.
220 */
221static struct RecordSetEntry *recordset;
222
200 223
201/** 224/**
202 * Task run on shutdown. Cleans up everything. 225 * Task run on shutdown. Cleans up everything.
@@ -232,6 +255,11 @@ do_shutdown (void *cls)
232 GNUNET_NAMESTORE_cancel (add_qe); 255 GNUNET_NAMESTORE_cancel (add_qe);
233 add_qe = NULL; 256 add_qe = NULL;
234 } 257 }
258 if (NULL != set_qe)
259 {
260 GNUNET_NAMESTORE_cancel (set_qe);
261 set_qe = NULL;
262 }
235 if (NULL != add_qe_uri) 263 if (NULL != add_qe_uri)
236 { 264 {
237 GNUNET_NAMESTORE_cancel (add_qe_uri); 265 GNUNET_NAMESTORE_cancel (add_qe_uri);
@@ -516,6 +544,8 @@ display_record_lookup (void *cls,
516 unsigned int rd_len, 544 unsigned int rd_len,
517 const struct GNUNET_GNSRECORD_Data *rd) 545 const struct GNUNET_GNSRECORD_Data *rd)
518{ 546{
547 (void) cls;
548 (void) zone_key;
519 get_qe = NULL; 549 get_qe = NULL;
520 display_record (rname, 550 display_record (rname,
521 rd_len, 551 rd_len,
@@ -694,14 +724,10 @@ get_existing_record (void *cls,
694 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; 724 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
695 if (1 != is_public) 725 if (1 != is_public)
696 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; 726 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
727 rde->expiration_time = etime;
697 if (GNUNET_YES == etime_is_rel) 728 if (GNUNET_YES == etime_is_rel)
698 {
699 rde->expiration_time = etime_rel.rel_value_us;
700 rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; 729 rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
701 } 730 else if (GNUNET_NO != etime_is_rel)
702 else if (GNUNET_NO == etime_is_rel)
703 rde->expiration_time = etime_abs.abs_value_us;
704 else
705 rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; 731 rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
706 GNUNET_assert (NULL != name); 732 GNUNET_assert (NULL != name);
707 add_qe = GNUNET_NAMESTORE_records_store (ns, 733 add_qe = GNUNET_NAMESTORE_records_store (ns,
@@ -864,6 +890,85 @@ del_monitor (void *cls,
864 890
865 891
866/** 892/**
893 * Parse expiration time.
894 *
895 * @param expirationstring text to parse
896 * @param etime_is_rel[out] set to #GNUNET_YES if time is relative
897 * @param etime[out] set to expiration time (abs or rel)
898 * @return #GNUNET_OK on success
899 */
900static int
901parse_expiration (const char *expirationstring,
902 int *etime_is_rel,
903 uint64_t *etime)
904{
905 struct GNUNET_TIME_Relative etime_rel;
906 struct GNUNET_TIME_Absolute etime_abs;
907
908 if (0 == strcmp (expirationstring,
909 "never"))
910 {
911 *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
912 *etime_is_rel = GNUNET_NO;
913 return GNUNET_OK;
914 }
915 if (GNUNET_OK ==
916 GNUNET_STRINGS_fancy_time_to_relative (expirationstring,
917 &etime_rel))
918 {
919 *etime_is_rel = GNUNET_YES;
920 *etime = etime_rel.rel_value_us;
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922 "Storing record with relative expiration time of %s\n",
923 GNUNET_STRINGS_relative_time_to_string (etime_rel,
924 GNUNET_NO));
925 return GNUNET_OK;
926 }
927 if (GNUNET_OK ==
928 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring,
929 &etime_abs))
930 {
931 *etime_is_rel = GNUNET_NO;
932 *etime = etime_abs.abs_value_us;
933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
934 "Storing record with absolute expiration time of %s\n",
935 GNUNET_STRINGS_absolute_time_to_string (etime_abs));
936 return GNUNET_OK;
937 }
938 return GNUNET_SYSERR;
939}
940
941
942/**
943 * Function called when namestore is done with the replace
944 * operation.
945 *
946 * @param cls NULL
947 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
948 * #GNUNET_NO if content was already there or not found
949 * #GNUNET_YES (or other positive value) on success
950 * @param emsg NULL on success, otherwise an error message
951 */
952static void
953replace_cont (void *cls,
954 int success,
955 const char *emsg)
956{
957 (void) cls;
958
959 set_qe = NULL;
960 if (GNUNET_OK != success)
961 {
962 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
963 _("Failed to replace records: %s\n"),
964 emsg);
965 ret = 1; /* fail from 'main' */
966 }
967 GNUNET_SCHEDULER_shutdown ();
968}
969
970
971/**
867 * Callback invoked from identity service with ego information. 972 * Callback invoked from identity service with ego information.
868 * An @a ego of NULL means the ego was not found. 973 * An @a ego of NULL means the ego was not found.
869 * 974 *
@@ -895,7 +1000,7 @@ identity_cb (void *cls,
895 GNUNET_free_non_null (ego_name); 1000 GNUNET_free_non_null (ego_name);
896 ego_name = NULL; 1001 ego_name = NULL;
897 1002
898 if (! (add|del|list|(NULL != nickstring)|(NULL != uri)|(NULL != reverse_pkey)) ) 1003 if (! (add|del|list|(NULL != nickstring)|(NULL != uri)|(NULL != reverse_pkey))|(NULL != recordset) )
899 { 1004 {
900 /* nothing more to be done */ 1005 /* nothing more to be done */
901 fprintf (stderr, 1006 fprintf (stderr,
@@ -904,8 +1009,7 @@ identity_cb (void *cls,
904 return; 1009 return;
905 } 1010 }
906 GNUNET_CRYPTO_ecdsa_key_get_public (&zone_pkey, 1011 GNUNET_CRYPTO_ecdsa_key_get_public (&zone_pkey,
907 &pub); 1012 &pub);
908
909 ns = GNUNET_NAMESTORE_connect (cfg); 1013 ns = GNUNET_NAMESTORE_connect (cfg);
910 if (NULL == ns) 1014 if (NULL == ns)
911 { 1015 {
@@ -913,6 +1017,44 @@ identity_cb (void *cls,
913 _("Failed to connect to namestore\n")); 1017 _("Failed to connect to namestore\n"));
914 return; 1018 return;
915 } 1019 }
1020
1021 if (NULL != recordset)
1022 {
1023 /* replace entire record set */
1024 unsigned int rd_count;
1025 struct GNUNET_GNSRECORD_Data *rd;
1026
1027 if (NULL == name)
1028 {
1029 fprintf (stderr,
1030 _("Missing option `%s' for operation `%s'\n"),
1031 "-n", _("replace"));
1032 GNUNET_SCHEDULER_shutdown ();
1033 ret = 1;
1034 return;
1035 }
1036 rd_count = 0;
1037 for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next)
1038 rd_count++;
1039 rd = GNUNET_new_array (rd_count,
1040 struct GNUNET_GNSRECORD_Data);
1041 rd_count = 0;
1042 for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next)
1043 {
1044 rd[rd_count] = e->record;
1045 rd_count++;
1046 }
1047 set_qe = GNUNET_NAMESTORE_records_store (ns,
1048 &zone_pkey,
1049 name,
1050 rd_count,
1051 rd,
1052 &replace_cont,
1053 NULL);
1054 GNUNET_free (rd);
1055 return;
1056 }
1057
916 if (add) 1058 if (add)
917 { 1059 {
918 if (NULL == name) 1060 if (NULL == name)
@@ -976,32 +1118,10 @@ identity_cb (void *cls,
976 ret = 1; 1118 ret = 1;
977 return; 1119 return;
978 } 1120 }
979 if (0 == strcmp (expirationstring, 1121 if (GNUNET_OK !=
980 "never")) 1122 parse_expiration (expirationstring,
981 { 1123 &etime_is_rel,
982 etime_abs = GNUNET_TIME_UNIT_FOREVER_ABS; 1124 &etime))
983 etime_is_rel = GNUNET_NO;
984 }
985 else if (GNUNET_OK ==
986 GNUNET_STRINGS_fancy_time_to_relative (expirationstring,
987 &etime_rel))
988 {
989 etime_is_rel = GNUNET_YES;
990 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
991 "Storing record with relative expiration time of %s\n",
992 GNUNET_STRINGS_relative_time_to_string (etime_rel,
993 GNUNET_NO));
994 }
995 else if (GNUNET_OK ==
996 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring,
997 &etime_abs))
998 {
999 etime_is_rel = GNUNET_NO;
1000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1001 "Storing record with absolute expiration time of %s\n",
1002 GNUNET_STRINGS_absolute_time_to_string (etime_abs));
1003 }
1004 else
1005 { 1125 {
1006 fprintf (stderr, 1126 fprintf (stderr,
1007 _("Invalid time format `%s'\n"), 1127 _("Invalid time format `%s'\n"),
@@ -1106,16 +1226,9 @@ identity_cb (void *cls,
1106 rd.data = &pkey; 1226 rd.data = &pkey;
1107 rd.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); 1227 rd.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
1108 rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; 1228 rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
1109 if (GNUNET_YES == etime_is_rel) 1229 rd.expiration_time = etime;
1110 { 1230 if (GNUNET_YES == etime_is_rel)
1111 rd.expiration_time = etime_rel.rel_value_us;
1112 rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; 1231 rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1113 }
1114 else if (GNUNET_NO == etime_is_rel)
1115 rd.expiration_time = etime_abs.abs_value_us;
1116 else
1117 rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
1118
1119 if (1 == is_shadow) 1232 if (1 == is_shadow)
1120 rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; 1233 rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
1121 add_qe_uri = GNUNET_NAMESTORE_records_store (ns, 1234 add_qe_uri = GNUNET_NAMESTORE_records_store (ns,
@@ -1247,6 +1360,161 @@ run (void *cls,
1247 1360
1248 1361
1249/** 1362/**
1363 * Command-line option parser function that allows the user to specify
1364 * a complete record as one argument for adding/removing. A pointer
1365 * to the head of the list of record sets must be passed as the "scls"
1366 * argument.
1367 *
1368 * @param ctx command line processor context
1369 * @param scls must be of type "struct GNUNET_FS_Uri **"
1370 * @param option name of the option (typically 'R')
1371 * @param value command line argument given; format is
1372 * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs),
1373 * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or
1374 * a combination of 's' (shadow) and 'p' (public) and VALUE is the
1375 * value (in human-readable format)
1376 * @return #GNUNET_OK on success
1377 */
1378static int
1379multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
1380 void *scls,
1381 const char *option,
1382 const char *value)
1383{
1384 struct RecordSetEntry **head = scls;
1385 struct RecordSetEntry *r;
1386 struct GNUNET_GNSRECORD_Data record;
1387 char *cp;
1388 char *tok;
1389 int etime_is_rel;
1390 void *raw_data;
1391
1392 (void) ctx;
1393 (void) option;
1394 cp = GNUNET_strdup (value);
1395 tok = strtok (cp, " ");
1396 if (NULL == tok)
1397 {
1398 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1399 _("Empty record line argument is not allowed.\n"));
1400 GNUNET_free (cp);
1401 return GNUNET_SYSERR;
1402 }
1403 if (GNUNET_OK !=
1404 parse_expiration (tok,
1405 &etime_is_rel,
1406 &record.expiration_time))
1407 {
1408 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1409 _("Invalid expiration time `%s'\n"),
1410 tok);
1411 GNUNET_free (cp);
1412 return GNUNET_SYSERR;
1413 }
1414 tok = strtok (NULL, " ");
1415 if (NULL == tok)
1416 {
1417 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1418 _("Missing entries in record line `%s'.\n"),
1419 value);
1420 GNUNET_free (cp);
1421 return GNUNET_SYSERR;
1422 }
1423 record.record_type = GNUNET_GNSRECORD_typename_to_number (tok);
1424 if (UINT32_MAX == record.record_type)
1425 {
1426 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1427 _("Unknown record type `%s'\n"),
1428 tok);
1429 GNUNET_free (cp);
1430 return GNUNET_SYSERR;
1431 }
1432 tok = strtok (NULL, " ");
1433 if (NULL == tok)
1434 {
1435 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1436 _("Missing entries in record line `%s'.\n"),
1437 value);
1438 GNUNET_free (cp);
1439 return GNUNET_SYSERR;
1440 }
1441 record.flags = GNUNET_GNSRECORD_RF_NONE;
1442 if (etime_is_rel)
1443 record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1444 if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */
1445 record.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1446 if (NULL != strchr (tok, (unsigned char) 's'))
1447 record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
1448 /* find beginning of record value */
1449 tok = strchr (&value[tok - cp], (unsigned char) ' ');
1450 if (NULL == tok)
1451 {
1452 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1453 _("Missing entries in record line `%s'.\n"),
1454 value);
1455 GNUNET_free (cp);
1456 return GNUNET_SYSERR;
1457 }
1458 GNUNET_free (cp);
1459 tok++; /* skip space */
1460 if (GNUNET_OK !=
1461 GNUNET_GNSRECORD_string_to_value (record.record_type,
1462 tok,
1463 &raw_data,
1464 &record.data_size))
1465 {
1466 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1467 _("Invalid record data for type %s: `%s'.\n"),
1468 GNUNET_GNSRECORD_number_to_typename (record.record_type),
1469 tok);
1470 return GNUNET_SYSERR;
1471 }
1472
1473 r = GNUNET_malloc (sizeof (struct RecordSetEntry) + record.data_size);
1474 r->next = *head;
1475 record.data = &r[1];
1476 memcpy (&r[1],
1477 raw_data,
1478 record.data_size);
1479 GNUNET_free (raw_data);
1480 r->record = record;
1481 *head = r;
1482 return GNUNET_OK;
1483}
1484
1485
1486/**
1487 * Allow user to specify keywords.
1488 *
1489 * @param shortName short name of the option
1490 * @param name long name of the option
1491 * @param argumentHelp help text for the option argument
1492 * @param description long help text for the option
1493 * @param[out] topKeywords set to the desired value
1494 */
1495struct GNUNET_GETOPT_CommandLineOption
1496multirecord_option (char shortName,
1497 const char *name,
1498 const char *argumentHelp,
1499 const char *description,
1500 struct RecordSetEntry **rs)
1501{
1502 struct GNUNET_GETOPT_CommandLineOption clo = {
1503 .shortName = shortName,
1504 .name = name,
1505 .argumentHelp = argumentHelp,
1506 .description = description,
1507 .require_argument = 1,
1508 .processor = &multirecord_process,
1509 .scls = (void *) rs
1510 };
1511
1512 return clo;
1513}
1514
1515
1516
1517/**
1250 * The main function for gnunet-namestore. 1518 * The main function for gnunet-namestore.
1251 * 1519 *
1252 * @param argc number of arguments from the command line 1520 * @param argc number of arguments from the command line
@@ -1294,6 +1562,11 @@ main (int argc,
1294 "PKEY", 1562 "PKEY",
1295 gettext_noop ("determine our name for the given PKEY"), 1563 gettext_noop ("determine our name for the given PKEY"),
1296 &reverse_pkey), 1564 &reverse_pkey),
1565 multirecord_option ('R',
1566 "replace",
1567 "RECORDLINE",
1568 gettext_noop ("set record set to values given by (possibly multiple) RECORDLINES; can be specified multiple times"),
1569 &recordset),
1297 GNUNET_GETOPT_option_string ('t', 1570 GNUNET_GETOPT_option_string ('t',
1298 "type", 1571 "type",
1299 "TYPE", 1572 "TYPE",
diff --git a/src/namestore/gnunet-zoneimport.c b/src/namestore/gnunet-zoneimport.c
index ddc8b483a..01706b777 100644
--- a/src/namestore/gnunet-zoneimport.c
+++ b/src/namestore/gnunet-zoneimport.c
@@ -1159,7 +1159,7 @@ process_result (void *cls,
1159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1160 "DNS ID did not match request, ignoring reply\n"); 1160 "DNS ID did not match request, ignoring reply\n");
1161 GNUNET_STATISTICS_update (stats, 1161 GNUNET_STATISTICS_update (stats,
1162 "# DNS ID missmatches", 1162 "# DNS ID mismatches",
1163 1, 1163 1,
1164 GNUNET_NO); 1164 GNUNET_NO);
1165 return; 1165 return;
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index 527576718..2cc293b37 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -754,7 +754,7 @@ handle_zone_to_name_response (void *cls,
754 { 754 {
755 case GNUNET_SYSERR: 755 case GNUNET_SYSERR:
756 LOG (GNUNET_ERROR_TYPE_DEBUG, 756 LOG (GNUNET_ERROR_TYPE_DEBUG,
757 "An error occured during zone to name operation\n"); 757 "An error occurred during zone to name operation\n");
758 break; 758 break;
759 case GNUNET_NO: 759 case GNUNET_NO:
760 LOG (GNUNET_ERROR_TYPE_DEBUG, 760 LOG (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/namestore/test_namestore_put_multiple.sh b/src/namestore/test_namestore_put_multiple.sh
new file mode 100644
index 000000000..81e1ad2b5
--- /dev/null
+++ b/src/namestore/test_namestore_put_multiple.sh
@@ -0,0 +1,123 @@
1#!/bin/bash
2
3# Check for required packages
4if ! [ -x "$(command -v gnunet-namestore)" ]; then
5 echo 'bind/named is not installed' >&2
6 exit 1
7fi
8
9# Check if gnunet is running
10gnunet-arm -I 2&>1 /dev/null
11ret=$?
12if [ 0 -ne $ret ]; then
13 echo 'gnunet services are not running'
14 exit 1
15fi
16
17## GNUNET part
18# Check if identity exists and delets and readds it to get rid of entries in zone
19gnunet-identity -d | grep randomtestingid 2>&1 /dev/null
20ret=$?
21
22if [ 0 -ne $ret ]; then
23 gnunet-identity -D randomtestingid
24 gnunet-identity -C randomtestingid
25fi
26
27function minimize_ttl {
28 ttl=10000000
29 arr=$1
30 # parse each element and update ttl to smallest one
31 for i in "${arr[@]}"
32 do
33 currttl=$(echo -n "$i" | cut -d' ' -f1)
34 if [ "$currttl" -lt "$ttl" ]
35 then
36 ttl=$currttl
37 fi
38
39 done
40 echo "$ttl"
41}
42
43function get_record_type {
44 arr=$1
45 typ=$(echo -n "${arr[0]}" | cut -d' ' -f2)
46 echo "$typ"
47}
48
49function get_value {
50 arr=$1
51 val=$(echo -n "${arr[0]}" | cut -d' ' -f4-)
52 echo "$val"
53}
54
55function testing {
56 label=$1
57 records=$2
58 recordstring=""
59 typ=$(get_record_type "${records[@]}")
60 for i in "${records[@]}"
61 do
62 recordstring+="-R $i"
63 done
64 #echo "$recordstring"
65 gnunet-namestore -z randomtestingid -n "$label" "$recordstring" 2>&1 /dev/null
66 if [ 0 -ne $ret ]; then
67 echo "failed to add record $label: $recordstring"
68 fi
69 gnunet-gns -t "$typ" -u foo2.randomtestingid 2>&1 /dev/null
70 if [ 0 -ne $ret ]; then
71 echo "record $label could not be found"
72 fi
73}
74
75# TEST CASES
76# 1
77echo "Testing adding of single A record with -R"
78testing test1 "${arr[@]}"
79# 2
80echo "Testing adding of multiple A records with -R"
81declare -a arr=('1200 A n 127.0.0.1' '2400 A n 127.0.0.2')
82testing test2 "${arr[@]}"
83# 3
84echo "Testing adding of multiple different records with -R"
85declare -a arr=('1200 A n 127.0.0.1' '2400 AAAA n 2002::')
86testing test3 "${arr[@]}"
87# 4
88echo "Testing adding of single GNS2DNS record with -R"
89declare -a arr=('86400 GNS2DNS n gnu.org@127.0.0.1')
90testing test4 "${arr[@]}"
91# 5
92echo "Testing adding of single GNS2DNS shadow record with -R"
93declare -a arr=('86409 GNS2DNS s gnu.org@127.0.0.250')
94testing test5 "${arr[@]}"
95# 6
96echo "Testing adding of multiple GNS2DNS record with -R"
97declare -a arr=('1 GNS2DNS n gnunet.org@127.0.0.1' '3600 GNS2DNS s gnunet.org@127.0.0.2')
98testing test6 "${arr[@]}"
99val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid)
100if [[ $val == *"127.0.0.1"* ]]; then
101 echo "shadow!"
102fi
103echo "Sleeping to let record expire"
104sleep 5
105val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid)
106if [[ $val == *"127.0.0.2"* ]]; then
107 echo "no shadow!"
108fi
109# 7
110echo "Testing adding MX record with -R"
111declare -a arr=('3600 MX n 10,mail')
112testing test7 "${arr[@]}"
113# 8
114echo "Testing adding TXT record with -R"
115declare -a arr=('3600 TXT n Pretty_Unicorns')
116testing test8 "${arr[@]}"
117# 8
118echo "Testing adding TXT record with -R"
119declare -a arr=('3600 SRV n _autodiscover_old._tcp.bfh.ch.')
120testing test8 "${arr[@]}"
121
122# CLEANUP
123gnunet-identity -D randomtestingid
diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h
index b6ce7fb09..5b01a8e7f 100644
--- a/src/testbed/testbed.h
+++ b/src/testbed/testbed.h
@@ -101,7 +101,7 @@ struct GNUNET_TESTBED_AddHostMessage
101 /* followed by non 0-terminated host name */ 101 /* followed by non 0-terminated host name */
102 102
103 /* followed by gzip compressed configuration to start or connect to a 103 /* followed by gzip compressed configuration to start or connect to a
104 controller on this host. While starting the controller this configration 104 controller on this host. While starting the controller this configuration
105 is used as a template */ 105 is used as a template */
106 106
107}; 107};
diff --git a/src/testbed/testbed_api_hosts.c b/src/testbed/testbed_api_hosts.c
index 2c25eabcf..84296b26a 100644
--- a/src/testbed/testbed_api_hosts.c
+++ b/src/testbed/testbed_api_hosts.c
@@ -1041,7 +1041,7 @@ helper_exp_cb (void *cls)
1041 1041
1042 1042
1043/** 1043/**
1044 * Starts a controller process at the given host. The given host's configration 1044 * Starts a controller process at the given host. The given host's configuration
1045 * is used as a Template configuration to use for the remote controller; the 1045 * is used as a Template configuration to use for the remote controller; the
1046 * remote controller will be started with a slightly modified configuration 1046 * remote controller will be started with a slightly modified configuration
1047 * (port numbers, unix domain sockets and service home values are changed as per 1047 * (port numbers, unix domain sockets and service home values are changed as per
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index f7a4e4525..dd384d9a1 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -1213,7 +1213,8 @@ run (void *cls,
1213 * @return 0 ok, 1 on error 1213 * @return 0 ok, 1 on error
1214 */ 1214 */
1215int 1215int
1216main (int argc, char *const *argv) 1216main (int argc,
1217 char *const *argv)
1217{ 1218{
1218 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 1219 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1219 GNUNET_GETOPT_OPTION_END 1220 GNUNET_GETOPT_OPTION_END
diff --git a/src/transport/.gitignore b/src/transport/.gitignore
index d035b4011..90f908a47 100644
--- a/src/transport/.gitignore
+++ b/src/transport/.gitignore
@@ -83,3 +83,4 @@ test_transport_blacklisting_outbound_bl_full
83test_transport_blacklisting_outbound_bl_plugin 83test_transport_blacklisting_outbound_bl_plugin
84test_transport_testing_restart 84test_transport_testing_restart
85test_transport_testing_startstop 85test_transport_testing_startstop
86gnunet-communicator-unix
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index d0db6b141..deeb39b48 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -8,7 +8,8 @@ pkgcfgdir= $(pkgdatadir)/config.d/
8libexecdir= $(pkglibdir)/libexec/ 8libexecdir= $(pkglibdir)/libexec/
9 9
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 transport.conf 11 transport.conf \
12 communicator-unix.conf
12 13
13if HAVE_MHD 14if HAVE_MHD
14 GN_LIBMHD = -lmicrohttpd 15 GN_LIBMHD = -lmicrohttpd
@@ -140,6 +141,8 @@ endif
140 141
141noinst_PROGRAMS = \ 142noinst_PROGRAMS = \
142 gnunet-transport-profiler \ 143 gnunet-transport-profiler \
144 gnunet-communicator-unix \
145 gnunet-service-tng \
143 $(WLAN_BIN_SENDER) \ 146 $(WLAN_BIN_SENDER) \
144 $(WLAN_BIN_RECEIVER) 147 $(WLAN_BIN_RECEIVER)
145 148
@@ -149,6 +152,9 @@ endif
149 152
150lib_LTLIBRARIES = \ 153lib_LTLIBRARIES = \
151 libgnunettransport.la \ 154 libgnunettransport.la \
155 libgnunettransportcore.la \
156 libgnunettransportcommunicator.la \
157 libgnunettransportmonitor.la \
152 $(TESTING_LIBS) 158 $(TESTING_LIBS)
153 159
154libgnunettransporttesting_la_SOURCES = \ 160libgnunettransporttesting_la_SOURCES = \
@@ -187,6 +193,37 @@ libgnunettransport_la_LDFLAGS = \
187 $(GN_LIB_LDFLAGS) $(WINFLAGS) \ 193 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
188 -version-info 4:0:2 194 -version-info 4:0:2
189 195
196
197
198libgnunettransportcore_la_SOURCES = \
199 transport_api2_core.c
200libgnunettransportcore_la_LIBADD = \
201 $(top_builddir)/src/util/libgnunetutil.la \
202 $(GN_LIBINTL)
203libgnunettransportcore_la_LDFLAGS = \
204 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
205 -version-info 0:0:0
206
207libgnunettransportcommunicator_la_SOURCES = \
208 transport_api2_communication.c
209libgnunettransportcommunicator_la_LIBADD = \
210 $(top_builddir)/src/util/libgnunetutil.la \
211 $(GN_LIBINTL)
212libgnunettransportcommunicator_la_LDFLAGS = \
213 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
214 -version-info 0:0:0
215
216
217libgnunettransportmonitor_la_SOURCES = \
218 transport_api2_monitor.c
219libgnunettransportmonitor_la_LIBADD = \
220 $(top_builddir)/src/util/libgnunetutil.la \
221 $(GN_LIBINTL)
222libgnunettransportmonitor_la_LDFLAGS = \
223 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
224 -version-info 0:0:0
225
226
190libexec_PROGRAMS = \ 227libexec_PROGRAMS = \
191 $(WLAN_BIN) \ 228 $(WLAN_BIN) \
192 $(WLAN_BIN_DUMMY) \ 229 $(WLAN_BIN_DUMMY) \
@@ -207,6 +244,14 @@ gnunet_transport_certificate_creation_SOURCES = \
207gnunet_transport_certificate_creation_LDADD = \ 244gnunet_transport_certificate_creation_LDADD = \
208 $(top_builddir)/src/util/libgnunetutil.la 245 $(top_builddir)/src/util/libgnunetutil.la
209 246
247gnunet_communicator_unix_SOURCES = \
248 gnunet-communicator-unix.c
249gnunet_communicator_unix_LDADD = \
250 libgnunettransportcommunicator.la \
251 $(top_builddir)/src/statistics/libgnunetstatistics.la \
252 $(top_builddir)/src/util/libgnunetutil.la
253
254
210gnunet_helper_transport_wlan_SOURCES = \ 255gnunet_helper_transport_wlan_SOURCES = \
211 gnunet-helper-transport-wlan.c 256 gnunet-helper-transport-wlan.c
212 257
@@ -278,6 +323,15 @@ gnunet_service_transport_CFLAGS = \
278 $(CFLAGS) 323 $(CFLAGS)
279# -DANALYZE 324# -DANALYZE
280 325
326
327gnunet_service_tng_SOURCES = \
328 gnunet-service-tng.c
329gnunet_service_tng_LDADD = \
330 $(top_builddir)/src/ats/libgnunetats.la \
331 $(top_builddir)/src/statistics/libgnunetstatistics.la \
332 $(top_builddir)/src/util/libgnunetutil.la \
333 $(GN_LIBINTL)
334
281plugin_LTLIBRARIES = \ 335plugin_LTLIBRARIES = \
282 libgnunet_plugin_transport_tcp.la \ 336 libgnunet_plugin_transport_tcp.la \
283 libgnunet_plugin_transport_udp.la \ 337 libgnunet_plugin_transport_udp.la \
diff --git a/src/transport/communicator-unix.conf b/src/transport/communicator-unix.conf
new file mode 100644
index 000000000..ad92616c6
--- /dev/null
+++ b/src/transport/communicator-unix.conf
@@ -0,0 +1,2 @@
1[communicator-unix]
2UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-communicator-unix.sock
diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c
new file mode 100644
index 000000000..b2eebbe20
--- /dev/null
+++ b/src/transport/gnunet-communicator-unix.c
@@ -0,0 +1,1147 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file transport/gnunet-communicator-unix.c
21 * @brief Transport plugin using unix domain sockets (!)
22 * Clearly, can only be used locally on Unix/Linux hosts...
23 * ONLY INTENDED FOR TESTING!!!
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_protocols.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet_transport_communication_service.h"
32
33/**
34 * How many messages do we keep at most in the queue to the
35 * transport service before we start to drop (default,
36 * can be changed via the configuration file).
37 * Should be _below_ the level of the communicator API, as
38 * otherwise we may read messages just to have them dropped
39 * by the communicator API.
40 */
41#define DEFAULT_MAX_QUEUE_LENGTH 8
42
43/**
44 * Address prefix used by the communicator.
45 */
46#define COMMUNICATOR_ADDRESS_PREFIX "unix"
47
48/**
49 * Configuration section used by the communicator.
50 */
51#define COMMUNICATOR_CONFIG_SECTION "communicator-unix"
52
53
54GNUNET_NETWORK_STRUCT_BEGIN
55
56/**
57 * UNIX Message-Packet header.
58 */
59struct UNIXMessage
60{
61 /**
62 * Message header.
63 */
64 struct GNUNET_MessageHeader header;
65
66 /**
67 * What is the identity of the sender (GNUNET_hash of public key)
68 */
69 struct GNUNET_PeerIdentity sender;
70
71};
72
73GNUNET_NETWORK_STRUCT_END
74
75
76/**
77 * Handle for a queue.
78 */
79struct Queue
80{
81
82 /**
83 * Queues with pending messages (!) are kept in a DLL.
84 */
85 struct Queue *next;
86
87 /**
88 * Queues with pending messages (!) are kept in a DLL.
89 */
90 struct Queue *prev;
91
92 /**
93 * To whom are we talking to.
94 */
95 struct GNUNET_PeerIdentity target;
96
97 /**
98 * Address of the other peer.
99 */
100 struct sockaddr_un *address;
101
102 /**
103 * Length of the address.
104 */
105 socklen_t address_len;
106
107 /**
108 * Message currently scheduled for transmission, non-NULL if and only
109 * if this queue is in the #queue_head DLL.
110 */
111 const struct GNUNET_MessageHeader *msg;
112
113 /**
114 * Message queue we are providing for the #ch.
115 */
116 struct GNUNET_MQ_Handle *mq;
117
118 /**
119 * handle for this queue with the #ch.
120 */
121 struct GNUNET_TRANSPORT_QueueHandle *qh;
122
123 /**
124 * Number of bytes we currently have in our write queue.
125 */
126 unsigned long long bytes_in_queue;
127
128 /**
129 * Timeout for this queue.
130 */
131 struct GNUNET_TIME_Absolute timeout;
132
133 /**
134 * Queue timeout task.
135 */
136 struct GNUNET_SCHEDULER_Task *timeout_task;
137
138};
139
140
141/**
142 * ID of read task
143 */
144static struct GNUNET_SCHEDULER_Task *read_task;
145
146/**
147 * ID of write task
148 */
149static struct GNUNET_SCHEDULER_Task *write_task;
150
151/**
152 * Number of messages we currently have in our queues towards the transport service.
153 */
154static unsigned long long delivering_messages;
155
156/**
157 * Maximum queue length before we stop reading towards the transport service.
158 */
159static unsigned long long max_queue_length;
160
161/**
162 * For logging statistics.
163 */
164static struct GNUNET_STATISTICS_Handle *stats;
165
166/**
167 * Our environment.
168 */
169static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
170
171/**
172 * Queues (map from peer identity to `struct Queue`)
173 */
174static struct GNUNET_CONTAINER_MultiPeerMap *queue_map;
175
176/**
177 * Head of queue of messages to transmit.
178 */
179static struct Queue *queue_head;
180
181/**
182 * Tail of queue of messages to transmit.
183 */
184static struct Queue *queue_tail;
185
186/**
187 * socket that we transmit all data with
188 */
189static struct GNUNET_NETWORK_Handle *unix_sock;
190
191/**
192 * Handle to the operation that publishes our address.
193 */
194static struct GNUNET_TRANSPORT_AddressIdentifier *ai;
195
196
197/**
198 * Functions with this signature are called whenever we need
199 * to close a queue due to a disconnect or failure to
200 * establish a connection.
201 *
202 * @param queue queue to close down
203 */
204static void
205queue_destroy (struct Queue *queue)
206{
207 struct GNUNET_MQ_Handle *mq;
208
209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
210 "Disconnecting queue for peer `%s'\n",
211 GNUNET_i2s (&queue->target));
212 if (0 != queue->bytes_in_queue)
213 {
214 GNUNET_CONTAINER_DLL_remove (queue_head,
215 queue_tail,
216 queue);
217 queue->bytes_in_queue = 0;
218 }
219 if (NULL != (mq = queue->mq))
220 {
221 queue->mq = NULL;
222 GNUNET_MQ_destroy (mq);
223 }
224 GNUNET_assert (GNUNET_YES ==
225 GNUNET_CONTAINER_multipeermap_remove (queue_map,
226 &queue->target,
227 queue));
228 GNUNET_STATISTICS_set (stats,
229 "# UNIX queues active",
230 GNUNET_CONTAINER_multipeermap_size (queue_map),
231 GNUNET_NO);
232 if (NULL != queue->timeout_task)
233 {
234 GNUNET_SCHEDULER_cancel (queue->timeout_task);
235 queue->timeout_task = NULL;
236 }
237 GNUNET_free (queue->address);
238 GNUNET_free (queue);
239}
240
241
242/**
243 * Queue was idle for too long, so disconnect it
244 *
245 * @param cls the `struct Queue *` to disconnect
246 */
247static void
248queue_timeout (void *cls)
249{
250 struct Queue *queue = cls;
251 struct GNUNET_TIME_Relative left;
252
253 queue->timeout_task = NULL;
254 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
255 if (0 != left.rel_value_us)
256 {
257 /* not actually our turn yet, but let's at least update
258 the monitor, it may think we're about to die ... */
259 queue->timeout_task
260 = GNUNET_SCHEDULER_add_delayed (left,
261 &queue_timeout,
262 queue);
263 return;
264 }
265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
266 "Queue %p was idle for %s, disconnecting\n",
267 queue,
268 GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
269 GNUNET_YES));
270 queue_destroy (queue);
271}
272
273
274/**
275 * Increment queue timeout due to activity. We do not immediately
276 * notify the monitor here as that might generate excessive
277 * signalling.
278 *
279 * @param queue queue for which the timeout should be rescheduled
280 */
281static void
282reschedule_queue_timeout (struct Queue *queue)
283{
284 GNUNET_assert (NULL != queue->timeout_task);
285 queue->timeout
286 = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
287}
288
289
290/**
291 * Convert unix path to a `struct sockaddr_un *`
292 *
293 * @param unixpath path to convert
294 * @param[out] sock_len set to the length of the address
295 * @param is_abstract is this an abstract @a unixpath
296 * @return converted unix path
297 */
298static struct sockaddr_un *
299unix_address_to_sockaddr (const char *unixpath,
300 socklen_t *sock_len)
301{
302 struct sockaddr_un *un;
303 size_t slen;
304
305 GNUNET_assert (0 < strlen (unixpath)); /* sanity check */
306 un = GNUNET_new (struct sockaddr_un);
307 un->sun_family = AF_UNIX;
308 slen = strlen (unixpath);
309 if (slen >= sizeof (un->sun_path))
310 slen = sizeof (un->sun_path) - 1;
311 GNUNET_memcpy (un->sun_path,
312 unixpath,
313 slen);
314 un->sun_path[slen] = '\0';
315 slen = sizeof (struct sockaddr_un);
316#if HAVE_SOCKADDR_UN_SUN_LEN
317 un->sun_len = (u_char) slen;
318#endif
319 (*sock_len) = slen;
320 if ('@' == un->sun_path[0])
321 un->sun_path[0] = '\0';
322 return un;
323}
324
325
326/**
327 * Closure to #lookup_queue_it().
328 */
329struct LookupCtx
330{
331 /**
332 * Location to store the queue, if found.
333 */
334 struct Queue *res;
335
336 /**
337 * Address we are looking for.
338 */
339 const struct sockaddr_un *un;
340
341 /**
342 * Number of bytes in @a un
343 */
344 socklen_t un_len;
345};
346
347
348/**
349 * Function called to find a queue by address.
350 *
351 * @param cls the `struct LookupCtx *`
352 * @param key peer we are looking for (unused)
353 * @param value a queue
354 * @return #GNUNET_YES if not found (continue looking), #GNUNET_NO on success
355 */
356static int
357lookup_queue_it (void *cls,
358 const struct GNUNET_PeerIdentity *key,
359 void *value)
360{
361 struct LookupCtx *lctx = cls;
362 struct Queue *queue = value;
363
364 if ( (queue->address_len = lctx->un_len) &&
365 (0 == memcmp (lctx->un,
366 queue->address,
367 queue->address_len)) )
368 {
369 lctx->res = queue;
370 return GNUNET_NO;
371 }
372 return GNUNET_YES;
373}
374
375
376/**
377 * Find an existing queue by address.
378 *
379 * @param plugin the plugin
380 * @param address the address to find
381 * @return NULL if queue was not found
382 */
383static struct Queue *
384lookup_queue (const struct GNUNET_PeerIdentity *peer,
385 const struct sockaddr_un *un,
386 socklen_t un_len)
387{
388 struct LookupCtx lctx;
389
390 lctx.un = un;
391 lctx.un_len = un_len;
392 GNUNET_CONTAINER_multipeermap_get_multiple (queue_map,
393 peer,
394 &lookup_queue_it,
395 &lctx);
396 return lctx.res;
397}
398
399
400/**
401 * We have been notified that our socket is ready to write.
402 * Then reschedule this function to be called again once more is available.
403 *
404 * @param cls NULL
405 */
406static void
407select_write_cb (void *cls)
408{
409 struct Queue *queue = queue_tail;
410 const struct GNUNET_MessageHeader *msg = queue->msg;
411 size_t msg_size = ntohs (msg->size);
412 ssize_t sent;
413
414 /* take queue of the ready list */
415 write_task = NULL;
416 GNUNET_CONTAINER_DLL_remove (queue_head,
417 queue_tail,
418 queue);
419 if (NULL != queue_head)
420 write_task =
421 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
422 unix_sock,
423 &select_write_cb,
424 NULL);
425
426 /* send 'msg' */
427 queue->msg = NULL;
428 GNUNET_MQ_impl_send_continue (queue->mq);
429 resend:
430 /* Send the data */
431 sent = GNUNET_NETWORK_socket_sendto (unix_sock,
432 queue->msg,
433 msg_size,
434 (const struct sockaddr *) queue->address,
435 queue->address_len);
436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
437 "UNIX transmitted message to %s (%d/%u: %s)\n",
438 GNUNET_i2s (&queue->target),
439 (int) sent,
440 (unsigned int) msg_size,
441 (sent < 0) ? STRERROR (errno) : "ok");
442 if (-1 != sent)
443 {
444 GNUNET_STATISTICS_update (stats,
445 "# bytes sent",
446 (long long) sent,
447 GNUNET_NO);
448 reschedule_queue_timeout (queue);
449 return; /* all good */
450 }
451 GNUNET_STATISTICS_update (stats,
452 "# network transmission failures",
453 1,
454 GNUNET_NO);
455 switch (errno)
456 {
457 case EAGAIN:
458 case ENOBUFS:
459 /* We should retry later... */
460 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG,
461 "send");
462 return;
463 case EMSGSIZE:
464 {
465 socklen_t size = 0;
466 socklen_t len = sizeof (size);
467
468 GNUNET_NETWORK_socket_getsockopt (unix_sock,
469 SOL_SOCKET,
470 SO_SNDBUF,
471 &size,
472 &len);
473 if (size > ntohs (msg->size))
474 {
475 /* Buffer is bigger than message: error, no retry
476 * This should never happen!*/
477 GNUNET_break (0);
478 return;
479 }
480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
481 "Trying to increase socket buffer size from %u to %u for message size %u\n",
482 (unsigned int) size,
483 (unsigned int) ((msg_size / 1000) + 2) * 1000,
484 (unsigned int) msg_size);
485 size = ((msg_size / 1000) + 2) * 1000;
486 if (GNUNET_OK ==
487 GNUNET_NETWORK_socket_setsockopt (unix_sock,
488 SOL_SOCKET,
489 SO_SNDBUF,
490 &size,
491 sizeof (size)))
492 goto resend; /* Increased buffer size, retry sending */
493 /* Ok, then just try very modest increase */
494 size = msg_size;
495 if (GNUNET_OK ==
496 GNUNET_NETWORK_socket_setsockopt (unix_sock,
497 SOL_SOCKET,
498 SO_SNDBUF,
499 &size,
500 sizeof (size)))
501 goto resend; /* Increased buffer size, retry sending */
502 /* Could not increase buffer size: error, no retry */
503 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
504 "setsockopt");
505 return;
506 }
507 default:
508 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
509 "send");
510 return;
511 }
512}
513
514
515/**
516 * Signature of functions implementing the sending functionality of a
517 * message queue.
518 *
519 * @param mq the message queue
520 * @param msg the message to send
521 * @param impl_state our `struct Queue`
522 */
523static void
524mq_send (struct GNUNET_MQ_Handle *mq,
525 const struct GNUNET_MessageHeader *msg,
526 void *impl_state)
527{
528 struct Queue *queue = impl_state;
529
530 GNUNET_assert (mq == queue->mq);
531 GNUNET_assert (NULL == queue->msg);
532 queue->msg = msg;
533 GNUNET_CONTAINER_DLL_insert (queue_head,
534 queue_tail,
535 queue);
536 GNUNET_assert (NULL != unix_sock);
537 if (NULL == write_task)
538 write_task =
539 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
540 unix_sock,
541 &select_write_cb,
542 NULL);
543}
544
545
546/**
547 * Signature of functions implementing the destruction of a message
548 * queue. Implementations must not free @a mq, but should take care
549 * of @a impl_state.
550 *
551 * @param mq the message queue to destroy
552 * @param impl_state our `struct Queue`
553 */
554static void
555mq_destroy (struct GNUNET_MQ_Handle *mq,
556 void *impl_state)
557{
558 struct Queue *queue = impl_state;
559
560 if (mq == queue->mq)
561 {
562 queue->mq = NULL;
563 queue_destroy (queue);
564 }
565}
566
567
568/**
569 * Implementation function that cancels the currently sent message.
570 *
571 * @param mq message queue
572 * @param impl_state our `struct Queue`
573 */
574static void
575mq_cancel (struct GNUNET_MQ_Handle *mq,
576 void *impl_state)
577{
578 struct Queue *queue = impl_state;
579
580 GNUNET_assert (NULL != queue->msg);
581 queue->msg = NULL;
582 GNUNET_CONTAINER_DLL_remove (queue_head,
583 queue_tail,
584 queue);
585 GNUNET_assert (NULL != write_task);
586 if (NULL == queue_head)
587 {
588 GNUNET_SCHEDULER_cancel (write_task);
589 write_task = NULL;
590 }
591}
592
593
594/**
595 * Generic error handler, called with the appropriate
596 * error code and the same closure specified at the creation of
597 * the message queue.
598 * Not every message queue implementation supports an error handler.
599 *
600 * @param cls our `struct Queue`
601 * @param error error code
602 */
603static void
604mq_error (void *cls,
605 enum GNUNET_MQ_Error error)
606{
607 struct Queue *queue = cls;
608
609 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
610 "UNIX MQ error in queue to %s: %d\n",
611 GNUNET_i2s (&queue->target),
612 (int) error);
613 queue_destroy (queue);
614}
615
616
617/**
618 * Creates a new outbound queue the transport service will use to send
619 * data to another peer.
620 *
621 * @param peer the target peer
622 * @param un the address
623 * @param un_len number of bytes in @a un
624 * @return the queue or NULL of max connections exceeded
625 */
626static struct Queue *
627setup_queue (const struct GNUNET_PeerIdentity *target,
628 const struct sockaddr_un *un,
629 socklen_t un_len)
630{
631 struct Queue *queue;
632
633 queue = GNUNET_new (struct Queue);
634 queue->target = *target;
635 queue->address = GNUNET_memdup (un,
636 un_len);
637 queue->address_len = un_len;
638 (void) GNUNET_CONTAINER_multipeermap_put (queue_map,
639 &queue->target,
640 queue,
641 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
642 GNUNET_STATISTICS_set (stats,
643 "# queues active",
644 GNUNET_CONTAINER_multipeermap_size (queue_map),
645 GNUNET_NO);
646 queue->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
647 queue->timeout_task
648 = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
649 &queue_timeout,
650 queue);
651 queue->mq
652 = GNUNET_MQ_queue_for_callbacks (&mq_send,
653 &mq_destroy,
654 &mq_cancel,
655 queue,
656 NULL,
657 &mq_error,
658 queue);
659 {
660 char *foreign_addr;
661
662 if ('\0' == un->sun_path[0])
663 GNUNET_asprintf (&foreign_addr,
664 "%s-@%s",
665 COMMUNICATOR_ADDRESS_PREFIX,
666 &un->sun_path[1]);
667 else
668 GNUNET_asprintf (&foreign_addr,
669 "%s-%s",
670 COMMUNICATOR_ADDRESS_PREFIX,
671 un->sun_path);
672 queue->qh
673 = GNUNET_TRANSPORT_communicator_mq_add (ch,
674 &queue->target,
675 foreign_addr,
676 GNUNET_ATS_NET_LOOPBACK,
677 queue->mq);
678 GNUNET_free (foreign_addr);
679 }
680 return queue;
681}
682
683
684/**
685 * We have been notified that our socket has something to read. Do the
686 * read and reschedule this function to be called again once more is
687 * available.
688 *
689 * @param cls NULL
690 */
691static void
692select_read_cb (void *cls);
693
694
695/**
696 * Function called when message was successfully passed to
697 * transport service. Continue read activity.
698 *
699 * @param cls NULL
700 * @param success #GNUNET_OK on success
701 */
702static void
703receive_complete_cb (void *cls,
704 int success)
705{
706 delivering_messages--;
707 if (GNUNET_OK != success)
708 GNUNET_STATISTICS_update (stats,
709 "# transport transmission failures",
710 1,
711 GNUNET_NO);
712 GNUNET_assert (NULL != unix_sock);
713 if ( (NULL == read_task) &&
714 (delivering_messages < max_queue_length) )
715 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
716 unix_sock,
717 &select_read_cb,
718 NULL);
719}
720
721
722/**
723 * We have been notified that our socket has something to read. Do the
724 * read and reschedule this function to be called again once more is
725 * available.
726 *
727 * @param cls NULL
728 */
729static void
730select_read_cb (void *cls)
731{
732 char buf[65536] GNUNET_ALIGN;
733 struct Queue *queue;
734 const struct UNIXMessage *msg;
735 struct sockaddr_un un;
736 socklen_t addrlen;
737 ssize_t ret;
738 uint16_t msize;
739
740 GNUNET_assert (NULL != unix_sock);
741 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
742 unix_sock,
743 &select_read_cb,
744 NULL);
745 addrlen = sizeof (un);
746 memset (&un,
747 0,
748 sizeof (un));
749 ret = GNUNET_NETWORK_socket_recvfrom (unix_sock,
750 buf,
751 sizeof (buf),
752 (struct sockaddr *) &un,
753 &addrlen);
754 if ( (-1 == ret) &&
755 ( (EAGAIN == errno) ||
756 (ENOBUFS == errno) ) )
757 return;
758 if (-1 == ret)
759 {
760 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
761 "recvfrom");
762 return;
763 }
764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
765 "Read %d bytes from socket %s\n",
766 (int) ret,
767 un.sun_path);
768 GNUNET_assert (AF_UNIX == (un.sun_family));
769 msg = (struct UNIXMessage *) buf;
770 msize = ntohs (msg->header.size);
771 if ( (msize < sizeof (struct UNIXMessage)) ||
772 (msize > ret) )
773 {
774 GNUNET_break_op (0);
775 return;
776 }
777 queue = lookup_queue (&msg->sender,
778 &un,
779 addrlen);
780 if (NULL == queue)
781 queue = setup_queue (&msg->sender,
782 &un,
783 addrlen);
784 else
785 reschedule_queue_timeout (queue);
786 if (NULL == queue)
787 {
788 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
789 _("Maximum number of UNIX connections exceeded, dropping incoming message\n"));
790 return;
791 }
792
793 {
794 uint16_t offset = 0;
795 uint16_t tsize = msize - sizeof (struct UNIXMessage);
796 const char *msgbuf = (const char *) &msg[1];
797
798 while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize)
799 {
800 const struct GNUNET_MessageHeader *currhdr;
801 struct GNUNET_MessageHeader al_hdr;
802 uint16_t csize;
803
804 currhdr = (const struct GNUNET_MessageHeader *) &msgbuf[offset];
805 /* ensure aligned access */
806 memcpy (&al_hdr,
807 currhdr,
808 sizeof (al_hdr));
809 csize = ntohs (al_hdr.size);
810 if ( (csize < sizeof (struct GNUNET_MessageHeader)) ||
811 (csize > tsize - offset))
812 {
813 GNUNET_break_op (0);
814 break;
815 }
816 ret = GNUNET_TRANSPORT_communicator_receive (ch,
817 &msg->sender,
818 currhdr,
819 &receive_complete_cb,
820 NULL);
821 if (GNUNET_SYSERR == ret)
822 return; /* transport not up */
823 if (GNUNET_NO == ret)
824 break;
825 delivering_messages++;
826 offset += csize;
827 }
828 }
829 if (delivering_messages >= max_queue_length)
830 {
831 /* we should try to apply 'back pressure' */
832 GNUNET_SCHEDULER_cancel (read_task);
833 read_task = NULL;
834 }
835}
836
837
838/**
839 * Function called by the transport service to initialize a
840 * message queue given address information about another peer.
841 * If and when the communication channel is established, the
842 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
843 * to notify the service that the channel is now up. It is
844 * the responsibility of the communicator to manage sane
845 * retries and timeouts for any @a peer/@a address combination
846 * provided by the transport service. Timeouts and retries
847 * do not need to be signalled to the transport service.
848 *
849 * @param cls closure
850 * @param peer identity of the other peer
851 * @param address where to send the message, human-readable
852 * communicator-specific format, 0-terminated, UTF-8
853 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid
854 */
855static int
856mq_init (void *cls,
857 const struct GNUNET_PeerIdentity *peer,
858 const char *address)
859{
860 struct Queue *queue;
861 const char *path;
862 struct sockaddr_un *un;
863 socklen_t un_len;
864
865 if (0 != strncmp (address,
866 COMMUNICATOR_ADDRESS_PREFIX "-",
867 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
868 {
869 GNUNET_break_op (0);
870 return GNUNET_SYSERR;
871 }
872 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
873 un = unix_address_to_sockaddr (path,
874 &un_len);
875 queue = lookup_queue (peer,
876 un,
877 un_len);
878 if (NULL != queue)
879 {
880 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
881 "Address `%s' for %s ignored, queue exists\n",
882 path,
883 GNUNET_i2s (peer));
884 GNUNET_free (un);
885 return GNUNET_OK;
886 }
887 queue = setup_queue (peer,
888 un,
889 un_len);
890 GNUNET_free (un);
891 if (NULL == queue)
892 {
893 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
894 "Failed to setup queue to %s at `%s'\n",
895 GNUNET_i2s (peer),
896 path);
897 return GNUNET_NO;
898 }
899 return GNUNET_OK;
900}
901
902
903/**
904 * Iterator over all message queues to clean up.
905 *
906 * @param cls NULL
907 * @param target unused
908 * @param value the queue to destroy
909 * @return #GNUNET_OK to continue to iterate
910 */
911static int
912get_queue_delete_it (void *cls,
913 const struct GNUNET_PeerIdentity *target,
914 void *value)
915{
916 struct Queue *queue = value;
917
918 (void) cls;
919 (void) target;
920 queue_destroy (queue);
921 return GNUNET_OK;
922}
923
924
925/**
926 * Shutdown the UNIX communicator.
927 *
928 * @param cls NULL (always)
929 */
930static void
931do_shutdown (void *cls)
932{
933 if (NULL != read_task)
934 {
935 GNUNET_SCHEDULER_cancel (read_task);
936 read_task = NULL;
937 }
938 if (NULL != write_task)
939 {
940 GNUNET_SCHEDULER_cancel (write_task);
941 write_task = NULL;
942 }
943 if (NULL != unix_sock)
944 {
945 GNUNET_break (GNUNET_OK ==
946 GNUNET_NETWORK_socket_close (unix_sock));
947 unix_sock = NULL;
948 }
949 GNUNET_CONTAINER_multipeermap_iterate (queue_map,
950 &get_queue_delete_it,
951 NULL);
952 GNUNET_CONTAINER_multipeermap_destroy (queue_map);
953 if (NULL != ai)
954 {
955 GNUNET_TRANSPORT_communicator_address_remove (ai);
956 ai = NULL;
957 }
958 if (NULL != ch)
959 {
960 GNUNET_TRANSPORT_communicator_disconnect (ch);
961 ch = NULL;
962 }
963 if (NULL != stats)
964 {
965 GNUNET_STATISTICS_destroy (stats,
966 GNUNET_NO);
967 stats = NULL;
968 }
969}
970
971
972/**
973 * Setup communicator and launch network interactions.
974 *
975 * @param cls NULL (always)
976 * @param args remaining command-line arguments
977 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
978 * @param cfg configuration
979 */
980static void
981run (void *cls,
982 char *const *args,
983 const char *cfgfile,
984 const struct GNUNET_CONFIGURATION_Handle *cfg)
985{
986 char *unix_socket_path;
987 struct sockaddr_un *un;
988 socklen_t un_len;
989 char *my_addr;
990 (void) cls;
991
992 if (GNUNET_OK !=
993 GNUNET_CONFIGURATION_get_value_filename (cfg,
994 COMMUNICATOR_CONFIG_SECTION,
995 "UNIXPATH",
996 &unix_socket_path))
997 {
998 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
999 COMMUNICATOR_CONFIG_SECTION,
1000 "UNIXPATH");
1001 return;
1002 }
1003 if (GNUNET_OK !=
1004 GNUNET_CONFIGURATION_get_value_number (cfg,
1005 COMMUNICATOR_CONFIG_SECTION,
1006 "MAX_QUEUE_LENGTH",
1007 &max_queue_length))
1008 max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
1009
1010 un = unix_address_to_sockaddr (unix_socket_path,
1011 &un_len);
1012 if (NULL == un)
1013 {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1015 "Failed to setup UNIX domain socket address with path `%s'\n",
1016 unix_socket_path);
1017 GNUNET_free (unix_socket_path);
1018 return;
1019 }
1020 unix_sock = GNUNET_NETWORK_socket_create (AF_UNIX,
1021 SOCK_DGRAM,
1022 0);
1023 if (NULL == unix_sock)
1024 {
1025 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1026 "socket");
1027 GNUNET_free (un);
1028 GNUNET_free (unix_socket_path);
1029 return;
1030 }
1031 if ( ('\0' != un->sun_path[0]) &&
1032 (GNUNET_OK !=
1033 GNUNET_DISK_directory_create_for_file (un->sun_path)) )
1034 {
1035 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1036 _("Cannot create path to `%s'\n"),
1037 un->sun_path);
1038 GNUNET_NETWORK_socket_close (unix_sock);
1039 unix_sock = NULL;
1040 GNUNET_free (un);
1041 GNUNET_free (unix_socket_path);
1042 return;
1043 }
1044 if (GNUNET_OK !=
1045 GNUNET_NETWORK_socket_bind (unix_sock,
1046 (const struct sockaddr *) un,
1047 un_len))
1048 {
1049 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
1050 "bind",
1051 un->sun_path);
1052 GNUNET_NETWORK_socket_close (unix_sock);
1053 unix_sock = NULL;
1054 GNUNET_free (un);
1055 GNUNET_free (unix_socket_path);
1056 return;
1057 }
1058 GNUNET_free (un);
1059 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1060 "Bound to `%s'\n",
1061 unix_socket_path);
1062 stats = GNUNET_STATISTICS_create ("C-UNIX",
1063 cfg);
1064 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1065 NULL);
1066 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1067 unix_sock,
1068 &select_read_cb,
1069 NULL);
1070 queue_map = GNUNET_CONTAINER_multipeermap_create (10,
1071 GNUNET_NO);
1072 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
1073 COMMUNICATOR_CONFIG_SECTION,
1074 COMMUNICATOR_ADDRESS_PREFIX,
1075 65535,
1076 &mq_init,
1077 NULL);
1078 if (NULL == ch)
1079 {
1080 GNUNET_break (0);
1081 GNUNET_SCHEDULER_shutdown ();
1082 GNUNET_free (unix_socket_path);
1083 return;
1084 }
1085 GNUNET_asprintf (&my_addr,
1086 "%s-%s",
1087 COMMUNICATOR_ADDRESS_PREFIX,
1088 unix_socket_path);
1089 GNUNET_free (unix_socket_path);
1090 ai = GNUNET_TRANSPORT_communicator_address_add (ch,
1091 my_addr,
1092 GNUNET_ATS_NET_LOOPBACK,
1093 GNUNET_TIME_UNIT_FOREVER_REL);
1094 GNUNET_free (my_addr);
1095}
1096
1097
1098/**
1099 * The main function for the UNIX communicator.
1100 *
1101 * @param argc number of arguments from the command line
1102 * @param argv command line arguments
1103 * @return 0 ok, 1 on error
1104 */
1105int
1106main (int argc,
1107 char *const *argv)
1108{
1109 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1110 GNUNET_GETOPT_OPTION_END
1111 };
1112 int ret;
1113
1114 if (GNUNET_OK !=
1115 GNUNET_STRINGS_get_utf8_args (argc, argv,
1116 &argc, &argv))
1117 return 2;
1118
1119 ret =
1120 (GNUNET_OK ==
1121 GNUNET_PROGRAM_run (argc, argv,
1122 "gnunet-communicator-unix",
1123 _("GNUnet UNIX domain socket communicator"),
1124 options,
1125 &run,
1126 NULL)) ? 0 : 1;
1127 GNUNET_free ((void*) argv);
1128 return ret;
1129}
1130
1131
1132#if defined(LINUX) && defined(__GLIBC__)
1133#include <malloc.h>
1134
1135/**
1136 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1137 */
1138void __attribute__ ((constructor))
1139GNUNET_ARM_memory_init ()
1140{
1141 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1142 mallopt (M_TOP_PAD, 1 * 1024);
1143 malloc_trim (0);
1144}
1145#endif
1146
1147/* end of gnunet-communicator-unix.c */
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
new file mode 100644
index 000000000..c7bdfd77c
--- /dev/null
+++ b/src/transport/gnunet-service-tng.c
@@ -0,0 +1,1263 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2016, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18/**
19 * @file transport/gnunet-service-transport.c
20 * @brief main for gnunet-service-transport
21 * @author Christian Grothoff
22 *
23 * TODO:
24 * - make *our* collected addresses available somehow somewhere
25 * => Choices: in peerstore or revive/keep peerinfo?
26 * - MTU information is missing for queues!
27 * - start supporting monitor logic (add functions to signal monitors!)
28 * - manage fragmentation/defragmentation, retransmission, track RTT, loss, etc.
29 * - ask ATS about bandwidth allocation
30 * -
31 */
32#include "platform.h"
33#include "gnunet_util_lib.h"
34#include "gnunet_statistics_service.h"
35#include "gnunet_transport_service.h"
36#include "gnunet_peerinfo_service.h"
37#include "gnunet_ats_service.h"
38#include "gnunet-service-transport.h"
39#include "transport.h"
40
41
42/**
43 * How many messages can we have pending for a given client process
44 * before we start to drop incoming messages? We typically should
45 * have only one client and so this would be the primary buffer for
46 * messages, so the number should be chosen rather generously.
47 *
48 * The expectation here is that most of the time the queue is large
49 * enough so that a drop is virtually never required. Note that
50 * this value must be about as large as 'TOTAL_MSGS' in the
51 * 'test_transport_api_reliability.c', otherwise that testcase may
52 * fail.
53 */
54#define MAX_PENDING (128 * 1024)
55
56
57/**
58 * What type of client is the `struct TransportClient` about?
59 */
60enum ClientType
61{
62 /**
63 * We do not know yet (client is fresh).
64 */
65 CT_NONE = 0,
66
67 /**
68 * Is the CORE service, we need to forward traffic to it.
69 */
70 CT_CORE = 1,
71
72 /**
73 * It is a monitor, forward monitor data.
74 */
75 CT_MONITOR = 2,
76
77 /**
78 * It is a communicator, use for communication.
79 */
80 CT_COMMUNICATOR = 3
81};
82
83
84/**
85 * Client connected to the transport service.
86 */
87struct TransportClient;
88
89
90/**
91 * A neighbour that at least one communicator is connected to.
92 */
93struct Neighbour;
94
95
96/**
97 * List of available queues for a particular neighbour.
98 */
99struct Queue
100{
101 /**
102 * Kept in a MDLL.
103 */
104 struct Queue *next_neighbour;
105
106 /**
107 * Kept in a MDLL.
108 */
109 struct Queue *prev_neighbour;
110
111 /**
112 * Kept in a MDLL.
113 */
114 struct Queue *prev_client;
115
116 /**
117 * Kept in a MDLL.
118 */
119 struct Queue *next_client;
120
121 /**
122 * Which neighbour is this queue for?
123 */
124 struct Neighbour *neighbour;
125
126 /**
127 * Which communicator offers this queue?
128 */
129 struct TransportClient *tc;
130
131 /**
132 * Address served by the queue.
133 */
134 const char *address;
135
136 /**
137 * Unique identifier of this queue with the communicator.
138 */
139 uint32_t qid;
140
141 /**
142 * Network type offered by this queue.
143 */
144 enum GNUNET_ATS_Network_Type nt;
145
146 // FIXME: add ATS-specific fields here!
147};
148
149
150/**
151 * A neighbour that at least one communicator is connected to.
152 */
153struct Neighbour
154{
155
156 /**
157 * Which peer is this about?
158 */
159 struct GNUNET_PeerIdentity pid;
160
161 /**
162 * Head of list of messages pending for this neighbour.
163 */
164 struct PendingMessage *pending_msg_head;
165
166 /**
167 * Tail of list of messages pending for this neighbour.
168 */
169 struct PendingMessage *pending_msg_tail;
170
171 /**
172 * Head of DLL of queues to this peer.
173 */
174 struct Queue *queue_head;
175
176 /**
177 * Tail of DLL of queues to this peer.
178 */
179 struct Queue *queue_tail;
180
181 /**
182 * Quota at which CORE is allowed to transmit to this peer
183 * according to ATS.
184 *
185 * FIXME: not yet used, tricky to get right given multiple queues!
186 * (=> Idea: let ATS set a quota per queue and we add them up here?)
187 * FIXME: how do we set this value initially when we tell CORE?
188 * Options: start at a minimum value or at literally zero (before ATS?)
189 * (=> Current thought: clean would be zero!)
190 */
191 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
192
193};
194
195
196/**
197 * Transmission request from CORE that is awaiting delivery.
198 */
199struct PendingMessage
200{
201 /**
202 * Kept in a MDLL of messages for this @a target.
203 */
204 struct PendingMessage *next_neighbour;
205
206 /**
207 * Kept in a MDLL of messages for this @a target.
208 */
209 struct PendingMessage *prev_neighbour;
210
211 /**
212 * Kept in a MDLL of messages from this @a client.
213 */
214 struct PendingMessage *next_client;
215
216 /**
217 * Kept in a MDLL of messages from this @a client.
218 */
219 struct PendingMessage *prev_client;
220
221 /**
222 * Target of the request.
223 */
224 struct Neighbour *target;
225
226 /**
227 * Client that issued the transmission request.
228 */
229 struct TransportClient *client;
230
231 /**
232 * Size of the original message.
233 */
234 uint32_t bytes_msg;
235
236};
237
238
239/**
240 * One of the addresses of this peer.
241 */
242struct AddressListEntry
243{
244
245 /**
246 * Kept in a DLL.
247 */
248 struct AddressListEntry *next;
249
250 /**
251 * Kept in a DLL.
252 */
253 struct AddressListEntry *prev;
254
255 /**
256 * Which communicator provides this address?
257 */
258 struct TransportClient *tc;
259
260 /**
261 * The actual address.
262 */
263 const char *address;
264
265 /**
266 * What is a typical lifetime the communicator expects this
267 * address to have? (Always from now.)
268 */
269 struct GNUNET_TIME_Relative expiration;
270
271 /**
272 * Address identifier used by the communicator.
273 */
274 uint32_t aid;
275
276 /**
277 * Network type offered by this address.
278 */
279 enum GNUNET_ATS_Network_Type nt;
280
281};
282
283
284/**
285 * Client connected to the transport service.
286 */
287struct TransportClient
288{
289
290 /**
291 * Kept in a DLL.
292 */
293 struct TransportClient *next;
294
295 /**
296 * Kept in a DLL.
297 */
298 struct TransportClient *prev;
299
300 /**
301 * Handle to the client.
302 */
303 struct GNUNET_SERVICE_Client *client;
304
305 /**
306 * Message queue to the client.
307 */
308 struct GNUNET_MQ_Handle *mq;
309
310 /**
311 * What type of client is this?
312 */
313 enum ClientType type;
314
315 union
316 {
317
318 /**
319 * Information for @e type #CT_CORE.
320 */
321 struct {
322
323 /**
324 * Head of list of messages pending for this client.
325 */
326 struct PendingMessage *pending_msg_head;
327
328 /**
329 * Tail of list of messages pending for this client.
330 */
331 struct PendingMessage *pending_msg_tail;
332
333 } core;
334
335 /**
336 * Information for @e type #CT_MONITOR.
337 */
338 struct {
339
340 /**
341 * Peer identity to monitor the addresses of.
342 * Zero to monitor all neighbours. Valid if
343 * @e type is #CT_MONITOR.
344 */
345 struct GNUNET_PeerIdentity peer;
346
347 /**
348 * Is this a one-shot monitor?
349 */
350 int one_shot;
351
352 } monitor;
353
354
355 /**
356 * Information for @e type #CT_COMMUNICATOR.
357 */
358 struct {
359 /**
360 * If @e type is #CT_COMMUNICATOR, this communicator
361 * supports communicating using these addresses.
362 */
363 char *address_prefix;
364
365 /**
366 * Head of DLL of queues offered by this communicator.
367 */
368 struct Queue *queue_head;
369
370 /**
371 * Tail of DLL of queues offered by this communicator.
372 */
373 struct Queue *queue_tail;
374
375 /**
376 * Head of list of the addresses of this peer offered by this communicator.
377 */
378 struct AddressListEntry *addr_head;
379
380 /**
381 * Tail of list of the addresses of this peer offered by this communicator.
382 */
383 struct AddressListEntry *addr_tail;
384
385 } communicator;
386
387 } details;
388
389};
390
391
392/**
393 * Head of linked list of all clients to this service.
394 */
395static struct TransportClient *clients_head;
396
397/**
398 * Tail of linked list of all clients to this service.
399 */
400static struct TransportClient *clients_tail;
401
402/**
403 * Statistics handle.
404 */
405struct GNUNET_STATISTICS_Handle *GST_stats;
406
407/**
408 * Configuration handle.
409 */
410const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
411
412/**
413 * Our public key.
414 */
415struct GNUNET_PeerIdentity GST_my_identity;
416
417/**
418 * Our private key.
419 */
420struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
421
422/**
423 * Map from PIDs to `struct Neighbour` entries. A peer is
424 * a neighbour if we have an MQ to it from some communicator.
425 */
426static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
427
428
429/**
430 * Lookup neighbour record for peer @a pid.
431 *
432 * @param pid neighbour to look for
433 * @return NULL if we do not have this peer as a neighbour
434 */
435static struct Neighbour *
436lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
437{
438 return GNUNET_CONTAINER_multipeermap_get (neighbours,
439 pid);
440}
441
442
443/**
444 * Called whenever a client connects. Allocates our
445 * data structures associated with that client.
446 *
447 * @param cls closure, NULL
448 * @param client identification of the client
449 * @param mq message queue for the client
450 * @return our `struct TransportClient`
451 */
452static void *
453client_connect_cb (void *cls,
454 struct GNUNET_SERVICE_Client *client,
455 struct GNUNET_MQ_Handle *mq)
456{
457 struct TransportClient *tc;
458
459 tc = GNUNET_new (struct TransportClient);
460 tc->client = client;
461 tc->mq = mq;
462 GNUNET_CONTAINER_DLL_insert (clients_head,
463 clients_tail,
464 tc);
465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
466 "Client %p connected\n",
467 tc);
468 return tc;
469}
470
471
472/**
473 * Called whenever a client is disconnected. Frees our
474 * resources associated with that client.
475 *
476 * @param cls closure, NULL
477 * @param client identification of the client
478 * @param app_ctx our `struct TransportClient`
479 */
480static void
481client_disconnect_cb (void *cls,
482 struct GNUNET_SERVICE_Client *client,
483 void *app_ctx)
484{
485 struct TransportClient *tc = app_ctx;
486
487 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
488 "Client %p disconnected, cleaning up.\n",
489 tc);
490 GNUNET_CONTAINER_DLL_remove (clients_head,
491 clients_tail,
492 tc);
493 switch (tc->type)
494 {
495 case CT_NONE:
496 break;
497 case CT_CORE:
498 {
499 struct PendingMessage *pm;
500
501 while (NULL != (pm = tc->details.core.pending_msg_head))
502 {
503 GNUNET_CONTAINER_MDLL_remove (client,
504 tc->details.core.pending_msg_head,
505 tc->details.core.pending_msg_tail,
506 pm);
507 pm->client = NULL;
508 }
509 }
510 break;
511 case CT_MONITOR:
512 break;
513 case CT_COMMUNICATOR:
514 GNUNET_free (tc->details.communicator.address_prefix);
515 break;
516 }
517 GNUNET_free (tc);
518}
519
520
521/**
522 * Initialize a "CORE" client. We got a start message from this
523 * client, so add it to the list of clients for broadcasting of
524 * inbound messages.
525 *
526 * @param cls the client
527 * @param start the start message that was sent
528 */
529static void
530handle_client_start (void *cls,
531 const struct StartMessage *start)
532{
533 struct TransportClient *tc = cls;
534 uint32_t options;
535
536 options = ntohl (start->options);
537 if ( (0 != (1 & options)) &&
538 (0 !=
539 memcmp (&start->self,
540 &GST_my_identity,
541 sizeof (struct GNUNET_PeerIdentity)) ) )
542 {
543 /* client thinks this is a different peer, reject */
544 GNUNET_break (0);
545 GNUNET_SERVICE_client_drop (tc->client);
546 return;
547 }
548 if (CT_NONE != tc->type)
549 {
550 GNUNET_break (0);
551 GNUNET_SERVICE_client_drop (tc->client);
552 return;
553 }
554 tc->type = CT_CORE;
555 GNUNET_SERVICE_client_continue (tc->client);
556}
557
558
559/**
560 * Client asked for transmission to a peer. Process the request.
561 *
562 * @param cls the client
563 * @param obm the send message that was sent
564 */
565static int
566check_client_send (void *cls,
567 const struct OutboundMessage *obm)
568{
569 struct TransportClient *tc = cls;
570 uint16_t size;
571 const struct GNUNET_MessageHeader *obmm;
572
573 if (CT_CORE != tc->type)
574 {
575 GNUNET_break (0);
576 return GNUNET_SYSERR;
577 }
578 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
579 if (size < sizeof (struct GNUNET_MessageHeader))
580 {
581 GNUNET_break (0);
582 return GNUNET_SYSERR;
583 }
584 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
585 if (size != ntohs (obmm->size))
586 {
587 GNUNET_break (0);
588 return GNUNET_SYSERR;
589 }
590 return GNUNET_OK;
591}
592
593
594/**
595 * Send a response to the @a pm that we have processed a
596 * "send" request with status @a success. We
597 * transmitted @a bytes_physical on the actual wire.
598 * Sends a confirmation to the "core" client responsible
599 * for the original request and free's @a pm.
600 *
601 * @param pm handle to the original pending message
602 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
603 * for transmission failure
604 * @param bytes_physical amount of bandwidth consumed
605 */
606static void
607client_send_response (struct PendingMessage *pm,
608 int success,
609 uint32_t bytes_physical)
610{
611 struct TransportClient *tc = pm->client;
612 struct Neighbour *target = pm->target;
613 struct GNUNET_MQ_Envelope *env;
614 struct SendOkMessage *som;
615
616 if (NULL != tc)
617 {
618 env = GNUNET_MQ_msg (som,
619 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
620 som->success = htonl ((uint32_t) success);
621 som->bytes_msg = htonl (pm->bytes_msg);
622 som->bytes_physical = htonl (bytes_physical);
623 som->peer = target->pid;
624 GNUNET_MQ_send (tc->mq,
625 env);
626 GNUNET_CONTAINER_MDLL_remove (client,
627 tc->details.core.pending_msg_head,
628 tc->details.core.pending_msg_tail,
629 pm);
630 }
631 GNUNET_CONTAINER_MDLL_remove (neighbour,
632 target->pending_msg_head,
633 target->pending_msg_tail,
634 pm);
635 GNUNET_free (pm);
636}
637
638
639/**
640 * Client asked for transmission to a peer. Process the request.
641 *
642 * @param cls the client
643 * @param obm the send message that was sent
644 */
645static void
646handle_client_send (void *cls,
647 const struct OutboundMessage *obm)
648{
649 struct TransportClient *tc = cls;
650 struct PendingMessage *pm;
651 const struct GNUNET_MessageHeader *obmm;
652 struct Neighbour *target;
653 uint32_t bytes_msg;
654
655 GNUNET_assert (CT_CORE == tc->type);
656 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
657 bytes_msg = ntohs (obmm->size);
658 target = lookup_neighbour (&obm->peer);
659 if (NULL == target)
660 {
661 /* Failure: don't have this peer as a neighbour (anymore).
662 Might have gone down asynchronously, so this is NOT
663 a protocol violation by CORE. Still count the event,
664 as this should be rare. */
665 struct GNUNET_MQ_Envelope *env;
666 struct SendOkMessage *som;
667
668 env = GNUNET_MQ_msg (som,
669 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
670 som->success = htonl (GNUNET_SYSERR);
671 som->bytes_msg = htonl (bytes_msg);
672 som->bytes_physical = htonl (0);
673 som->peer = obm->peer;
674 GNUNET_MQ_send (tc->mq,
675 env);
676 GNUNET_SERVICE_client_continue (tc->client);
677 GNUNET_STATISTICS_update (GST_stats,
678 "# messages dropped (neighbour unknown)",
679 1,
680 GNUNET_NO);
681 return;
682 }
683 pm = GNUNET_new (struct PendingMessage);
684 pm->client = tc;
685 pm->target = target;
686 pm->bytes_msg = bytes_msg;
687 GNUNET_CONTAINER_MDLL_insert (neighbour,
688 target->pending_msg_head,
689 target->pending_msg_tail,
690 pm);
691 GNUNET_CONTAINER_MDLL_insert (client,
692 tc->details.core.pending_msg_head,
693 tc->details.core.pending_msg_tail,
694 pm);
695 // FIXME: do the work, continuation with:
696 client_send_response (pm,
697 GNUNET_NO,
698 0);
699}
700
701
702/**
703 * Communicator started. Test message is well-formed.
704 *
705 * @param cls the client
706 * @param cam the send message that was sent
707 */
708static int
709check_communicator_available (void *cls,
710 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
711{
712 struct TransportClient *tc = cls;
713 const char *addr;
714 uint16_t size;
715
716 if (CT_NONE != tc->type)
717 {
718 GNUNET_break (0);
719 return GNUNET_SYSERR;
720 }
721 tc->type = CT_COMMUNICATOR;
722 size = ntohs (cam->header.size) - sizeof (*cam);
723 if (0 == size)
724 return GNUNET_OK; /* receive-only communicator */
725 addr = (const char *) &cam[1];
726 if ('\0' != addr[size-1])
727 {
728 GNUNET_break (0);
729 return GNUNET_SYSERR;
730 }
731 return GNUNET_OK;
732}
733
734
735/**
736 * Communicator started. Process the request.
737 *
738 * @param cls the client
739 * @param cam the send message that was sent
740 */
741static void
742handle_communicator_available (void *cls,
743 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
744{
745 struct TransportClient *tc = cls;
746 uint16_t size;
747
748 size = ntohs (cam->header.size) - sizeof (*cam);
749 if (0 == size)
750 return; /* receive-only communicator */
751 tc->details.communicator.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
752 GNUNET_SERVICE_client_continue (tc->client);
753}
754
755
756/**
757 * Address of our peer added. Test message is well-formed.
758 *
759 * @param cls the client
760 * @param aam the send message that was sent
761 */
762static int
763check_add_address (void *cls,
764 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
765{
766 struct TransportClient *tc = cls;
767 const char *addr;
768 uint16_t size;
769
770 if (CT_COMMUNICATOR != tc->type)
771 {
772 GNUNET_break (0);
773 return GNUNET_SYSERR;
774 }
775 size = ntohs (aam->header.size) - sizeof (*aam);
776 if (0 == size)
777 {
778 GNUNET_break (0);
779 return GNUNET_SYSERR;
780 }
781 addr = (const char *) &aam[1];
782 if ('\0' != addr[size-1])
783 {
784 GNUNET_break (0);
785 return GNUNET_SYSERR;
786 }
787 return GNUNET_OK;
788}
789
790
791/**
792 * Address of our peer added. Process the request.
793 *
794 * @param cls the client
795 * @param aam the send message that was sent
796 */
797static void
798handle_add_address (void *cls,
799 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
800{
801 struct TransportClient *tc = cls;
802 struct AddressListEntry *ale;
803 size_t slen;
804
805 slen = ntohs (aam->header.size) - sizeof (*aam);
806 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
807 ale->tc = tc;
808 ale->address = (const char *) &ale[1];
809 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
810 ale->aid = aam->aid;
811 ale->nt = (enum GNUNET_ATS_Network_Type) ntohl (aam->nt);
812 memcpy (&ale[1],
813 &aam[1],
814 slen);
815 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
816 tc->details.communicator.addr_tail,
817 ale);
818 // FIXME: notify somebody?!
819 GNUNET_SERVICE_client_continue (tc->client);
820}
821
822
823/**
824 * Address of our peer deleted. Process the request.
825 *
826 * @param cls the client
827 * @param dam the send message that was sent
828 */
829static void
830handle_del_address (void *cls,
831 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
832{
833 struct TransportClient *tc = cls;
834
835 if (CT_COMMUNICATOR != tc->type)
836 {
837 GNUNET_break (0);
838 GNUNET_SERVICE_client_drop (tc->client);
839 return;
840 }
841 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
842 NULL != ale;
843 ale = ale->next)
844 {
845 if (dam->aid != ale->aid)
846 continue;
847 GNUNET_assert (ale->tc == tc);
848 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
849 tc->details.communicator.addr_tail,
850 ale);
851 // FIXME: notify somebody?
852 GNUNET_free (ale);
853 GNUNET_SERVICE_client_continue (tc->client);
854 }
855 GNUNET_break (0);
856 GNUNET_SERVICE_client_drop (tc->client);
857}
858
859
860/**
861 * Client notified us about transmission from a peer. Process the request.
862 *
863 * @param cls the client
864 * @param obm the send message that was sent
865 */
866static int
867check_incoming_msg (void *cls,
868 const struct GNUNET_TRANSPORT_IncomingMessage *im)
869{
870 struct TransportClient *tc = cls;
871 uint16_t size;
872 const struct GNUNET_MessageHeader *obmm;
873
874 if (CT_COMMUNICATOR != tc->type)
875 {
876 GNUNET_break (0);
877 return GNUNET_SYSERR;
878 }
879 size = ntohs (im->header.size) - sizeof (*im);
880 if (size < sizeof (struct GNUNET_MessageHeader))
881 {
882 GNUNET_break (0);
883 return GNUNET_SYSERR;
884 }
885 obmm = (const struct GNUNET_MessageHeader *) &im[1];
886 if (size != ntohs (obmm->size))
887 {
888 GNUNET_break (0);
889 return GNUNET_SYSERR;
890 }
891 return GNUNET_OK;
892}
893
894
895/**
896 * Incoming meessage. Process the request.
897 *
898 * @param cls the client
899 * @param im the send message that was received
900 */
901static void
902handle_incoming_msg (void *cls,
903 const struct GNUNET_TRANSPORT_IncomingMessage *im)
904{
905 struct TransportClient *tc = cls;
906
907 GNUNET_SERVICE_client_continue (tc->client);
908}
909
910
911/**
912 * New queue became available. Check message.
913 *
914 * @param cls the client
915 * @param aqm the send message that was sent
916 */
917static int
918check_add_queue_message (void *cls,
919 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
920{
921 struct TransportClient *tc = cls;
922 const char *addr;
923 uint16_t size;
924
925 if (CT_COMMUNICATOR != tc->type)
926 {
927 GNUNET_break (0);
928 return GNUNET_SYSERR;
929 }
930 size = ntohs (aqm->header.size) - sizeof (*aqm);
931 if (0 == size)
932 {
933 GNUNET_break (0);
934 return GNUNET_SYSERR;
935 }
936 addr = (const char *) &aqm[1];
937 if ('\0' != addr[size-1])
938 {
939 GNUNET_break (0);
940 return GNUNET_SYSERR;
941 }
942 return GNUNET_OK;
943}
944
945
946/**
947 * New queue became available. Process the request.
948 *
949 * @param cls the client
950 * @param aqm the send message that was sent
951 */
952static void
953handle_add_queue_message (void *cls,
954 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
955{
956 struct TransportClient *tc = cls;
957 struct Queue *queue;
958 struct Neighbour *neighbour;
959 const char *addr;
960 uint16_t addr_len;
961
962 neighbour = lookup_neighbour (&aqm->receiver);
963 if (NULL == neighbour)
964 {
965 neighbour = GNUNET_new (struct Neighbour);
966 neighbour->pid = aqm->receiver;
967 GNUNET_assert (GNUNET_OK ==
968 GNUNET_CONTAINER_multipeermap_put (neighbours,
969 &neighbour->pid,
970 neighbour,
971 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
972 // FIXME: notify ATS/COREs/monitors!
973 }
974 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
975 addr = (const char *) &aqm[1];
976
977 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
978 queue->qid = aqm->qid;
979 queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt);
980 queue->tc = tc;
981 queue->neighbour = neighbour;
982 queue->address = (const char *) &queue[1];
983 memcpy (&queue[1],
984 addr,
985 addr_len);
986 GNUNET_CONTAINER_MDLL_insert (neighbour,
987 neighbour->queue_head,
988 neighbour->queue_tail,
989 queue);
990 GNUNET_CONTAINER_MDLL_insert (client,
991 tc->details.communicator.queue_head,
992 tc->details.communicator.queue_tail,
993 queue);
994 // FIXME: possibly transmit queued messages?
995 GNUNET_SERVICE_client_continue (tc->client);
996}
997
998
999/**
1000 * Release memory used by @a neighbour.
1001 *
1002 * @param neighbour neighbour entry to free
1003 */
1004static void
1005free_neighbour (struct Neighbour *neighbour)
1006{
1007 GNUNET_assert (NULL == neighbour->queue_head);
1008 GNUNET_assert (GNUNET_YES ==
1009 GNUNET_CONTAINER_multipeermap_remove (neighbours,
1010 &neighbour->pid,
1011 neighbour));
1012 GNUNET_free (neighbour);
1013}
1014
1015
1016/**
1017 * Queue to a peer went down. Process the request.
1018 *
1019 * @param cls the client
1020 * @param dqm the send message that was sent
1021 */
1022static void
1023handle_del_queue_message (void *cls,
1024 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1025{
1026 struct TransportClient *tc = cls;
1027
1028 if (CT_COMMUNICATOR != tc->type)
1029 {
1030 GNUNET_break (0);
1031 GNUNET_SERVICE_client_drop (tc->client);
1032 return;
1033 }
1034 for (struct Queue *queue = tc->details.communicator.queue_head;
1035 NULL != queue;
1036 queue = queue->next_client)
1037 {
1038 struct Neighbour *neighbour = queue->neighbour;
1039
1040 if ( (dqm->qid != queue->qid) ||
1041 (0 != memcmp (&dqm->receiver,
1042 &neighbour->pid,
1043 sizeof (struct GNUNET_PeerIdentity))) )
1044 continue;
1045 GNUNET_CONTAINER_MDLL_remove (neighbour,
1046 neighbour->queue_head,
1047 neighbour->queue_tail,
1048 queue);
1049 GNUNET_CONTAINER_MDLL_remove (client,
1050 tc->details.communicator.queue_head,
1051 tc->details.communicator.queue_tail,
1052 queue);
1053 GNUNET_free (queue);
1054 if (NULL == neighbour->queue_head)
1055 {
1056 // FIXME: notify cores/monitors!
1057 free_neighbour (neighbour);
1058 }
1059 GNUNET_SERVICE_client_continue (tc->client);
1060 return;
1061 }
1062 GNUNET_break (0);
1063 GNUNET_SERVICE_client_drop (tc->client);
1064}
1065
1066
1067/**
1068 * Message was transmitted. Process the request.
1069 *
1070 * @param cls the client
1071 * @param sma the send message that was sent
1072 */
1073static void
1074handle_send_message_ack (void *cls,
1075 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1076{
1077 struct TransportClient *tc = cls;
1078
1079 if (CT_COMMUNICATOR != tc->type)
1080 {
1081 GNUNET_break (0);
1082 GNUNET_SERVICE_client_drop (tc->client);
1083 return;
1084 }
1085 GNUNET_SERVICE_client_continue (tc->client);
1086}
1087
1088
1089/**
1090 * Initialize a monitor client.
1091 *
1092 * @param cls the client
1093 * @param start the start message that was sent
1094 */
1095static void
1096handle_monitor_start (void *cls,
1097 const struct GNUNET_TRANSPORT_MonitorStart *start)
1098{
1099 struct TransportClient *tc = cls;
1100
1101 if (CT_NONE != tc->type)
1102 {
1103 GNUNET_break (0);
1104 GNUNET_SERVICE_client_drop (tc->client);
1105 return;
1106 }
1107 tc->type = CT_MONITOR;
1108 tc->details.monitor.peer = start->peer;
1109 tc->details.monitor.one_shot = ntohl (start->one_shot);
1110 // FIXME: do work!
1111 GNUNET_SERVICE_client_continue (tc->client);
1112}
1113
1114
1115/**
1116 * Free neighbour entry.
1117 *
1118 * @param cls NULL
1119 * @param pid unused
1120 * @param value a `struct Neighbour`
1121 * @return #GNUNET_OK (always)
1122 */
1123static int
1124free_neighbour_cb (void *cls,
1125 const struct GNUNET_PeerIdentity *pid,
1126 void *value)
1127{
1128 struct Neighbour *neighbour = value;
1129
1130 (void) cls;
1131 (void) pid;
1132 GNUNET_break (0); // should this ever happen?
1133 free_neighbour (neighbour);
1134
1135 return GNUNET_OK;
1136}
1137
1138
1139/**
1140 * Function called when the service shuts down. Unloads our plugins
1141 * and cancels pending validations.
1142 *
1143 * @param cls closure, unused
1144 */
1145static void
1146do_shutdown (void *cls)
1147{
1148 (void) cls;
1149
1150 if (NULL != GST_stats)
1151 {
1152 GNUNET_STATISTICS_destroy (GST_stats,
1153 GNUNET_NO);
1154 GST_stats = NULL;
1155 }
1156 if (NULL != GST_my_private_key)
1157 {
1158 GNUNET_free (GST_my_private_key);
1159 GST_my_private_key = NULL;
1160 }
1161 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1162 &free_neighbour_cb,
1163 NULL);
1164 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1165}
1166
1167
1168/**
1169 * Initiate transport service.
1170 *
1171 * @param cls closure
1172 * @param c configuration to use
1173 * @param service the initialized service
1174 */
1175static void
1176run (void *cls,
1177 const struct GNUNET_CONFIGURATION_Handle *c,
1178 struct GNUNET_SERVICE_Handle *service)
1179{
1180 (void) cls;
1181 /* setup globals */
1182 GST_cfg = c;
1183 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1184 GNUNET_YES);
1185 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1186 if (NULL == GST_my_private_key)
1187 {
1188 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1189 _("Transport service is lacking key configuration settings. Exiting.\n"));
1190 GNUNET_SCHEDULER_shutdown ();
1191 return;
1192 }
1193 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1194 &GST_my_identity.public_key);
1195 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1196 "My identity is `%s'\n",
1197 GNUNET_i2s_full (&GST_my_identity));
1198
1199 GST_stats = GNUNET_STATISTICS_create ("transport",
1200 GST_cfg);
1201 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1202 NULL);
1203 /* start subsystems */
1204}
1205
1206
1207/**
1208 * Define "main" method using service macro.
1209 */
1210GNUNET_SERVICE_MAIN
1211("transport",
1212 GNUNET_SERVICE_OPTION_NONE,
1213 &run,
1214 &client_connect_cb,
1215 &client_disconnect_cb,
1216 NULL,
1217 /* communication with core */
1218 GNUNET_MQ_hd_fixed_size (client_start,
1219 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1220 struct StartMessage,
1221 NULL),
1222 GNUNET_MQ_hd_var_size (client_send,
1223 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1224 struct OutboundMessage,
1225 NULL),
1226 /* communication with communicators */
1227 GNUNET_MQ_hd_var_size (communicator_available,
1228 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1229 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1230 NULL),
1231 GNUNET_MQ_hd_var_size (add_address,
1232 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1233 struct GNUNET_TRANSPORT_AddAddressMessage,
1234 NULL),
1235 GNUNET_MQ_hd_fixed_size (del_address,
1236 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1237 struct GNUNET_TRANSPORT_DelAddressMessage,
1238 NULL),
1239 GNUNET_MQ_hd_var_size (incoming_msg,
1240 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1241 struct GNUNET_TRANSPORT_IncomingMessage,
1242 NULL),
1243 GNUNET_MQ_hd_var_size (add_queue_message,
1244 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1245 struct GNUNET_TRANSPORT_AddQueueMessage,
1246 NULL),
1247 GNUNET_MQ_hd_fixed_size (del_queue_message,
1248 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1249 struct GNUNET_TRANSPORT_DelQueueMessage,
1250 NULL),
1251 GNUNET_MQ_hd_fixed_size (send_message_ack,
1252 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1253 struct GNUNET_TRANSPORT_SendMessageToAck,
1254 NULL),
1255 /* communication with monitors */
1256 GNUNET_MQ_hd_fixed_size (monitor_start,
1257 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1258 struct GNUNET_TRANSPORT_MonitorStart,
1259 NULL),
1260 GNUNET_MQ_handler_end ());
1261
1262
1263/* end of file gnunet-service-transport.c */
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 8c4f33fd0..2d9803651 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -602,7 +602,6 @@ notify_client_about_neighbour (void *cls,
602 cim.header.size = htons (sizeof (struct ConnectInfoMessage)); 602 cim.header.size = htons (sizeof (struct ConnectInfoMessage));
603 cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); 603 cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
604 cim.id = *peer; 604 cim.id = *peer;
605 cim.quota_in = bandwidth_in;
606 cim.quota_out = bandwidth_out; 605 cim.quota_out = bandwidth_out;
607 unicast (tc, 606 unicast (tc,
608 &cim.header, 607 &cim.header,
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c
index 3965bc13e..68344bcf4 100644
--- a/src/transport/gnunet-service-transport_neighbours.c
+++ b/src/transport/gnunet-service-transport_neighbours.c
@@ -11,7 +11,7 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/ 17*/
@@ -571,7 +571,6 @@ neighbours_connect_notification (struct NeighbourMapEntry *n)
571 connect_msg->header.size = htons (sizeof(buf)); 571 connect_msg->header.size = htons (sizeof(buf));
572 connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); 572 connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
573 connect_msg->id = n->id; 573 connect_msg->id = n->id;
574 connect_msg->quota_in = n->primary_address.bandwidth_in;
575 connect_msg->quota_out = bandwidth_min; 574 connect_msg->quota_out = bandwidth_min;
576 GST_clients_broadcast (&connect_msg->header, 575 GST_clients_broadcast (&connect_msg->header,
577 GNUNET_NO); 576 GNUNET_NO);
diff --git a/src/transport/gnunet-transport.c b/src/transport/gnunet-transport.c
index fed509fe1..6c589307b 100644
--- a/src/transport/gnunet-transport.c
+++ b/src/transport/gnunet-transport.c
@@ -489,7 +489,7 @@ operation_timeout (void *cls)
489 } 489 }
490 FPRINTF (stdout, 490 FPRINTF (stdout,
491 "%s", 491 "%s",
492 _("Failed to list connections, timeout occured\n")); 492 _("Failed to list connections, timeout occurred\n"));
493 GNUNET_SCHEDULER_shutdown (); 493 GNUNET_SCHEDULER_shutdown ();
494 ret = 1; 494 ret = 1;
495 return; 495 return;
diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c
index e3d4b7a9b..4295446d2 100644
--- a/src/transport/transport-testing.c
+++ b/src/transport/transport-testing.c
@@ -374,8 +374,8 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth
374 const char *cfgname, 374 const char *cfgname,
375 int peer_id, 375 int peer_id,
376 const struct GNUNET_MQ_MessageHandler *handlers, 376 const struct GNUNET_MQ_MessageHandler *handlers,
377 GNUNET_TRANSPORT_NotifyConnecT nc, 377 GNUNET_TRANSPORT_NotifyConnect nc,
378 GNUNET_TRANSPORT_NotifyDisconnecT nd, 378 GNUNET_TRANSPORT_NotifyDisconnect nd,
379 void *cb_cls, 379 void *cb_cls,
380 GNUNET_SCHEDULER_TaskCallback start_cb, 380 GNUNET_SCHEDULER_TaskCallback start_cb,
381 void *start_cb_cls) 381 void *start_cb_cls)
diff --git a/src/transport/transport-testing.h b/src/transport/transport-testing.h
index a4cfd89f6..3a638580d 100644
--- a/src/transport/transport-testing.h
+++ b/src/transport/transport-testing.h
@@ -115,12 +115,12 @@ struct GNUNET_TRANSPORT_TESTING_PeerContext
115 /** 115 /**
116 * Notify connect callback 116 * Notify connect callback
117 */ 117 */
118 GNUNET_TRANSPORT_NotifyConnecT nc; 118 GNUNET_TRANSPORT_NotifyConnect nc;
119 119
120 /** 120 /**
121 * Notify disconnect callback 121 * Notify disconnect callback
122 */ 122 */
123 GNUNET_TRANSPORT_NotifyDisconnecT nd; 123 GNUNET_TRANSPORT_NotifyDisconnect nd;
124 124
125 /** 125 /**
126 * Startup completed callback 126 * Startup completed callback
@@ -291,8 +291,8 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth
291 const char *cfgname, 291 const char *cfgname,
292 int peer_id, 292 int peer_id,
293 const struct GNUNET_MQ_MessageHandler *handlers, 293 const struct GNUNET_MQ_MessageHandler *handlers,
294 GNUNET_TRANSPORT_NotifyConnecT nc, 294 GNUNET_TRANSPORT_NotifyConnect nc,
295 GNUNET_TRANSPORT_NotifyDisconnecT nd, 295 GNUNET_TRANSPORT_NotifyDisconnect nd,
296 void *cb_cls, 296 void *cb_cls,
297 GNUNET_SCHEDULER_TaskCallback start_cb, 297 GNUNET_SCHEDULER_TaskCallback start_cb,
298 void *start_cb_cls); 298 void *start_cb_cls);
diff --git a/src/transport/transport.h b/src/transport/transport.h
index e68536bcc..423d3cefa 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -11,7 +11,7 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/ 17*/
@@ -94,7 +94,7 @@ struct StartMessage
94 94
95 /** 95 /**
96 * 0: no options 96 * 0: no options
97 * 1: The 'self' field should be checked 97 * 1: The @e self field should be checked
98 * 2: this client is interested in payload traffic 98 * 2: this client is interested in payload traffic
99 */ 99 */
100 uint32_t options; 100 uint32_t options;
@@ -121,19 +121,14 @@ struct ConnectInfoMessage
121 struct GNUNET_MessageHeader header; 121 struct GNUNET_MessageHeader header;
122 122
123 /** 123 /**
124 * Identity of the new neighbour. 124 * Current outbound quota for this peer
125 */
126 struct GNUNET_PeerIdentity id;
127
128 /**
129 * Current inbound quota for this peer
130 */ 125 */
131 struct GNUNET_BANDWIDTH_Value32NBO quota_in; 126 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
132 127
133 /** 128 /**
134 * Current outbound quota for this peer 129 * Identity of the new neighbour.
135 */ 130 */
136 struct GNUNET_BANDWIDTH_Value32NBO quota_out; 131 struct GNUNET_PeerIdentity id;
137}; 132};
138 133
139 134
@@ -404,6 +399,7 @@ struct ValidationIterateResponseMessage
404 struct GNUNET_TIME_AbsoluteNBO next_validation; 399 struct GNUNET_TIME_AbsoluteNBO next_validation;
405}; 400};
406 401
402
407/** 403/**
408 * Message from the library to the transport service 404 * Message from the library to the transport service
409 * asking for binary addresses known for a peer. 405 * asking for binary addresses known for a peer.
@@ -654,6 +650,22 @@ struct TransportPluginMonitorMessage
654/* *********************** TNG messages ***************** */ 650/* *********************** TNG messages ***************** */
655 651
656/** 652/**
653 * Communicator goes online. Note which addresses it can
654 * work with.
655 */
656struct GNUNET_TRANSPORT_CommunicatorAvailableMessage
657{
658
659 /**
660 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR.
661 */
662 struct GNUNET_MessageHeader header;
663
664 /* Followed by the address prefix of the communicator */
665};
666
667
668/**
657 * Add address to the list. 669 * Add address to the list.
658 */ 670 */
659struct GNUNET_TRANSPORT_AddAddressMessage 671struct GNUNET_TRANSPORT_AddAddressMessage
@@ -678,7 +690,7 @@ struct GNUNET_TRANSPORT_AddAddressMessage
678 * An `enum GNUNET_ATS_Network_Type` in NBO. 690 * An `enum GNUNET_ATS_Network_Type` in NBO.
679 */ 691 */
680 uint32_t nt; 692 uint32_t nt;
681 693
682 /* followed by UTF-8 encoded, 0-terminated human-readable address */ 694 /* followed by UTF-8 encoded, 0-terminated human-readable address */
683}; 695};
684 696
@@ -717,12 +729,12 @@ struct GNUNET_TRANSPORT_IncomingMessage
717 * Do we use flow control or not? 729 * Do we use flow control or not?
718 */ 730 */
719 uint32_t fc_on GNUNET_PACKED; 731 uint32_t fc_on GNUNET_PACKED;
720 732
721 /** 733 /**
722 * 64-bit number to identify the matching ACK. 734 * 64-bit number to identify the matching ACK.
723 */ 735 */
724 uint64_t fc_id GNUNET_PACKED; 736 uint64_t fc_id GNUNET_PACKED;
725 737
726 /** 738 /**
727 * Sender identifier. 739 * Sender identifier.
728 */ 740 */
@@ -748,12 +760,12 @@ struct GNUNET_TRANSPORT_IncomingMessageAck
748 * Reserved (0) 760 * Reserved (0)
749 */ 761 */
750 uint32_t reserved GNUNET_PACKED; 762 uint32_t reserved GNUNET_PACKED;
751 763
752 /** 764 /**
753 * Which message is being ACKed? 765 * Which message is being ACKed?
754 */ 766 */
755 uint64_t fc_id GNUNET_PACKED; 767 uint64_t fc_id GNUNET_PACKED;
756 768
757 /** 769 /**
758 * Sender identifier of the original message. 770 * Sender identifier of the original message.
759 */ 771 */
@@ -769,7 +781,7 @@ struct GNUNET_TRANSPORT_AddQueueMessage
769{ 781{
770 782
771 /** 783 /**
772 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_QUEUE. 784 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
773 */ 785 */
774 struct GNUNET_MessageHeader header; 786 struct GNUNET_MessageHeader header;
775 787
@@ -787,7 +799,9 @@ struct GNUNET_TRANSPORT_AddQueueMessage
787 * An `enum GNUNET_ATS_Network_Type` in NBO. 799 * An `enum GNUNET_ATS_Network_Type` in NBO.
788 */ 800 */
789 uint32_t nt; 801 uint32_t nt;
790 802
803 // FIXME: add MTU?
804
791 /* followed by UTF-8 encoded, 0-terminated human-readable address */ 805 /* followed by UTF-8 encoded, 0-terminated human-readable address */
792}; 806};
793 807
@@ -799,7 +813,7 @@ struct GNUNET_TRANSPORT_DelQueueMessage
799{ 813{
800 814
801 /** 815 /**
802 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_QUEUE. 816 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN.
803 */ 817 */
804 struct GNUNET_MessageHeader header; 818 struct GNUNET_MessageHeader header;
805 819
@@ -828,9 +842,9 @@ struct GNUNET_TRANSPORT_CreateQueue
828 struct GNUNET_MessageHeader header; 842 struct GNUNET_MessageHeader header;
829 843
830 /** 844 /**
831 * Always zero. 845 * Unique ID for the request.
832 */ 846 */
833 uint32_t reserved GNUNET_PACKED; 847 uint32_t request_id GNUNET_PACKED;
834 848
835 /** 849 /**
836 * Receiver that can be addressed via the queue. 850 * Receiver that can be addressed via the queue.
@@ -842,6 +856,24 @@ struct GNUNET_TRANSPORT_CreateQueue
842 856
843 857
844/** 858/**
859 * Transport tells communicator that it wants a new queue.
860 */
861struct GNUNET_TRANSPORT_CreateQueueResponse
862{
863
864 /**
865 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK or #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL.
866 */
867 struct GNUNET_MessageHeader header;
868
869 /**
870 * Unique ID for the request.
871 */
872 uint32_t request_id GNUNET_PACKED;
873};
874
875
876/**
845 * Inform communicator about transport's desire to send a message. 877 * Inform communicator about transport's desire to send a message.
846 */ 878 */
847struct GNUNET_TRANSPORT_SendMessageTo 879struct GNUNET_TRANSPORT_SendMessageTo
@@ -861,7 +893,7 @@ struct GNUNET_TRANSPORT_SendMessageTo
861 * Message ID, used for flow control. 893 * Message ID, used for flow control.
862 */ 894 */
863 uint64_t mid GNUNET_PACKED; 895 uint64_t mid GNUNET_PACKED;
864 896
865 /** 897 /**
866 * Receiver identifier. 898 * Receiver identifier.
867 */ 899 */
@@ -891,7 +923,7 @@ struct GNUNET_TRANSPORT_SendMessageToAck
891 * Message ID of the original message. 923 * Message ID of the original message.
892 */ 924 */
893 uint64_t mid GNUNET_PACKED; 925 uint64_t mid GNUNET_PACKED;
894 926
895 /** 927 /**
896 * Receiver identifier. 928 * Receiver identifier.
897 */ 929 */
@@ -901,6 +933,89 @@ struct GNUNET_TRANSPORT_SendMessageToAck
901 933
902 934
903 935
936
937/**
938 * Request to start monitoring.
939 */
940struct GNUNET_TRANSPORT_MonitorStart
941{
942
943 /**
944 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START.
945 */
946 struct GNUNET_MessageHeader header;
947
948 /**
949 * #GNUNET_YES for one-shot montoring, #GNUNET_NO for continuous monitoring.
950 */
951 uint32_t one_shot;
952
953 /**
954 * Target identifier to monitor, all zeros for "all peers".
955 */
956 struct GNUNET_PeerIdentity peer;
957
958};
959
960
961/**
962 * Monitoring data.
963 */
964struct GNUNET_TRANSPORT_MonitorData
965{
966
967 /**
968 * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA.
969 */
970 struct GNUNET_MessageHeader header;
971
972 /**
973 * Network type (an `enum GNUNET_ATS_Network_Type` in NBO).
974 */
975 uint32_t nt GNUNET_PACKED;
976
977 /**
978 * Target identifier.
979 */
980 struct GNUNET_PeerIdentity peer;
981
982 /**
983 * @deprecated To be discussed if we keep these...
984 */
985 struct GNUNET_TIME_AbsoluteNBO last_validation;
986 struct GNUNET_TIME_AbsoluteNBO valid_until;
987 struct GNUNET_TIME_AbsoluteNBO next_validation;
988
989 /**
990 * Current round-trip time estimate.
991 */
992 struct GNUNET_TIME_RelativeNBO rtt;
993
994 /**
995 * Is inbound (in NBO).
996 */
997 uint32_t is_inbound GNUNET_PACKED;
998
999 /**
1000 * Messages pending (in NBO).
1001 */
1002 uint32_t num_msg_pending GNUNET_PACKED;
1003
1004 /**
1005 * Bytes pending (in NBO).
1006 */
1007 uint32_t num_bytes_pending GNUNET_PACKED;
1008
1009 /* Followed by 0-terminated address of the peer
1010 (TODO: do we allow no address? If so,
1011 adjust transport_api2_monitor!) */
1012
1013};
1014
1015
1016
1017
1018
904GNUNET_NETWORK_STRUCT_END 1019GNUNET_NETWORK_STRUCT_END
905 1020
906/* end of transport.h */ 1021/* end of transport.h */
diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c
index d446516bd..3a68c6eba 100644
--- a/src/transport/transport_api2_communication.c
+++ b/src/transport/transport_api2_communication.c
@@ -90,6 +90,11 @@ struct AckPending
90 struct AckPending *prev; 90 struct AckPending *prev;
91 91
92 /** 92 /**
93 * Communicator this entry belongs to.
94 */
95 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
96
97 /**
93 * Which peer is this about? 98 * Which peer is this about?
94 */ 99 */
95 struct GNUNET_PeerIdentity receiver; 100 struct GNUNET_PeerIdentity receiver;
@@ -134,17 +139,17 @@ struct GNUNET_TRANSPORT_CommunicatorHandle
134 /** 139 /**
135 * DLL of messages awaiting transmission confirmation (ack). 140 * DLL of messages awaiting transmission confirmation (ack).
136 */ 141 */
137 struct AckPending *ac_tail; 142 struct AckPending *ap_tail;
138 143
139 /** 144 /**
140 * DLL of queues we offer. 145 * DLL of queues we offer.
141 */ 146 */
142 struct QueueHandle *queue_head; 147 struct GNUNET_TRANSPORT_QueueHandle *queue_head;
143 148
144 /** 149 /**
145 * DLL of queues we offer. 150 * DLL of queues we offer.
146 */ 151 */
147 struct QueueHandle *queue_tail; 152 struct GNUNET_TRANSPORT_QueueHandle *queue_tail;
148 153
149 /** 154 /**
150 * Our configuration. 155 * Our configuration.
@@ -152,9 +157,14 @@ struct GNUNET_TRANSPORT_CommunicatorHandle
152 const struct GNUNET_CONFIGURATION_Handle *cfg; 157 const struct GNUNET_CONFIGURATION_Handle *cfg;
153 158
154 /** 159 /**
155 * Name of the communicator. 160 * Config section to use.
161 */
162 const char *config_section;
163
164 /**
165 * Address prefix to use.
156 */ 166 */
157 const char *name; 167 const char *addr_prefix;
158 168
159 /** 169 /**
160 * Function to call when the transport service wants us to initiate 170 * Function to call when the transport service wants us to initiate
@@ -168,6 +178,11 @@ struct GNUNET_TRANSPORT_CommunicatorHandle
168 void *mq_init_cls; 178 void *mq_init_cls;
169 179
170 /** 180 /**
181 * Queue to talk to the transport service.
182 */
183 struct GNUNET_MQ_Handle *mq;
184
185 /**
171 * Maximum permissable queue length. 186 * Maximum permissable queue length.
172 */ 187 */
173 unsigned long long max_queue_length; 188 unsigned long long max_queue_length;
@@ -202,6 +217,17 @@ struct GNUNET_TRANSPORT_CommunicatorHandle
202 */ 217 */
203struct GNUNET_TRANSPORT_QueueHandle 218struct GNUNET_TRANSPORT_QueueHandle
204{ 219{
220
221 /**
222 * Kept in a DLL.
223 */
224 struct GNUNET_TRANSPORT_QueueHandle *next;
225
226 /**
227 * Kept in a DLL.
228 */
229 struct GNUNET_TRANSPORT_QueueHandle *prev;
230
205 /** 231 /**
206 * Handle this queue belongs to. 232 * Handle this queue belongs to.
207 */ 233 */
@@ -308,7 +334,7 @@ send_add_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai)
308 env = GNUNET_MQ_msg_extra (aam, 334 env = GNUNET_MQ_msg_extra (aam,
309 strlen (ai->address) + 1, 335 strlen (ai->address) + 1,
310 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS); 336 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS);
311 aam->expiration = GNUNET_TIME_relative_to_nbo (ai->expiration); 337 aam->expiration = GNUNET_TIME_relative_hton (ai->expiration);
312 aam->nt = htonl ((uint32_t) ai->nt); 338 aam->nt = htonl ((uint32_t) ai->nt);
313 memcpy (&aam[1], 339 memcpy (&aam[1],
314 ai->address, 340 ai->address,
@@ -334,7 +360,7 @@ send_del_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai)
334 return; 360 return;
335 env = GNUNET_MQ_msg (dam, 361 env = GNUNET_MQ_msg (dam,
336 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS); 362 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS);
337 dam.aid = htonl (ai->aid); 363 dam->aid = htonl (ai->aid);
338 GNUNET_MQ_send (ai->ch->mq, 364 GNUNET_MQ_send (ai->ch->mq,
339 env); 365 env);
340} 366}
@@ -352,18 +378,18 @@ send_add_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
352 struct GNUNET_MQ_Envelope *env; 378 struct GNUNET_MQ_Envelope *env;
353 struct GNUNET_TRANSPORT_AddQueueMessage *aqm; 379 struct GNUNET_TRANSPORT_AddQueueMessage *aqm;
354 380
355 if (NULL == ai->ch->mq) 381 if (NULL == qh->ch->mq)
356 return; 382 return;
357 env = GNUNET_MQ_msg_extra (aqm, 383 env = GNUNET_MQ_msg_extra (aqm,
358 strlen (ai->address) + 1, 384 strlen (qh->address) + 1,
359 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_QUEUE); 385 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP);
360 aqm.receiver = qh->peer; 386 aqm->receiver = qh->peer;
361 aqm.nt = htonl ((uint32_t) qh->nt); 387 aqm->nt = htonl ((uint32_t) qh->nt);
362 aqm.qid = htonl (qh->qid); 388 aqm->qid = htonl (qh->queue_id);
363 memcpy (&aqm[1], 389 memcpy (&aqm[1],
364 ai->address, 390 qh->address,
365 strlen (ai->address) + 1); 391 strlen (qh->address) + 1);
366 GNUNET_MQ_send (ai->ch->mq, 392 GNUNET_MQ_send (qh->ch->mq,
367 env); 393 env);
368} 394}
369 395
@@ -380,13 +406,13 @@ send_del_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
380 struct GNUNET_MQ_Envelope *env; 406 struct GNUNET_MQ_Envelope *env;
381 struct GNUNET_TRANSPORT_DelQueueMessage *dqm; 407 struct GNUNET_TRANSPORT_DelQueueMessage *dqm;
382 408
383 if (NULL == ai->ch->mq) 409 if (NULL == qh->ch->mq)
384 return; 410 return;
385 env = GNUNET_MQ_msg (dqm, 411 env = GNUNET_MQ_msg (dqm,
386 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_QUEUE); 412 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN);
387 dqm.qid = htonl (qh->qid); 413 dqm->qid = htonl (qh->queue_id);
388 dqm.receiver = qh->peer; 414 dqm->receiver = qh->peer;
389 GNUNET_MQ_send (ai->ch->mq, 415 GNUNET_MQ_send (qh->ch->mq,
390 env); 416 env);
391} 417}
392 418
@@ -444,7 +470,8 @@ error_handler (void *cls,
444 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; 470 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
445 471
446 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 472 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
447 "MQ failure, reconnecting to transport service.\n"); 473 "MQ failure %d, reconnecting to transport service.\n",
474 error);
448 disconnect (ch); 475 disconnect (ch);
449 /* TODO: maybe do this with exponential backoff/delay */ 476 /* TODO: maybe do this with exponential backoff/delay */
450 reconnect (ch); 477 reconnect (ch);
@@ -460,7 +487,7 @@ error_handler (void *cls,
460 */ 487 */
461static void 488static void
462handle_incoming_ack (void *cls, 489handle_incoming_ack (void *cls,
463 struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack) 490 const struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack)
464{ 491{
465 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; 492 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
466 493
@@ -470,7 +497,7 @@ handle_incoming_ack (void *cls,
470 { 497 {
471 if ( (fc->id == incoming_ack->fc_id) && 498 if ( (fc->id == incoming_ack->fc_id) &&
472 (0 == memcmp (&fc->sender, 499 (0 == memcmp (&fc->sender,
473 incoming_ack->sender, 500 &incoming_ack->sender,
474 sizeof (struct GNUNET_PeerIdentity))) ) 501 sizeof (struct GNUNET_PeerIdentity))) )
475 { 502 {
476 GNUNET_CONTAINER_DLL_remove (ch->fc_head, 503 GNUNET_CONTAINER_DLL_remove (ch->fc_head,
@@ -499,11 +526,12 @@ handle_incoming_ack (void *cls,
499 */ 526 */
500static int 527static int
501check_create_queue (void *cls, 528check_create_queue (void *cls,
502 struct GNUNET_TRANSPORT_CreateQueue *cq) 529 const struct GNUNET_TRANSPORT_CreateQueue *cq)
503{ 530{
504 uint16_t len = ntohs (cq->header.size) - sizeof (*cq); 531 uint16_t len = ntohs (cq->header.size) - sizeof (*cq);
505 const char *addr = (const char *) &cq[1]; 532 const char *addr = (const char *) &cq[1];
506 533
534 (void) cls;
507 if ( (0 == len) || 535 if ( (0 == len) ||
508 ('\0' != addr[len-1]) ) 536 ('\0' != addr[len-1]) )
509 { 537 {
@@ -522,11 +550,13 @@ check_create_queue (void *cls,
522 */ 550 */
523static void 551static void
524handle_create_queue (void *cls, 552handle_create_queue (void *cls,
525 struct GNUNET_TRANSPORT_CreateQueue *cq) 553 const struct GNUNET_TRANSPORT_CreateQueue *cq)
526{ 554{
527 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; 555 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
528 const char *addr = (const char *) &cq[1]; 556 const char *addr = (const char *) &cq[1];
529 557 struct GNUNET_TRANSPORT_CreateQueueResponse *cqr;
558 struct GNUNET_MQ_Envelope *env;
559
530 if (GNUNET_OK != 560 if (GNUNET_OK !=
531 ch->mq_init (ch->mq_init_cls, 561 ch->mq_init (ch->mq_init_cls,
532 &cq->receiver, 562 &cq->receiver,
@@ -535,8 +565,17 @@ handle_create_queue (void *cls,
535 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 565 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
536 "Address `%s' invalid for this communicator\n", 566 "Address `%s' invalid for this communicator\n",
537 addr); 567 addr);
538 // TODO: do we notify the transport!? 568 env = GNUNET_MQ_msg (cqr,
569 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL);
539 } 570 }
571 else
572 {
573 env = GNUNET_MQ_msg (cqr,
574 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK);
575 }
576 cqr->request_id = cq->request_id;
577 GNUNET_MQ_send (ch->mq,
578 env);
540} 579}
541 580
542 581
@@ -550,11 +589,12 @@ handle_create_queue (void *cls,
550 */ 589 */
551static int 590static int
552check_send_msg (void *cls, 591check_send_msg (void *cls,
553 struct GNUNET_TRANSPORT_SendMessageTo *smt) 592 const struct GNUNET_TRANSPORT_SendMessageTo *smt)
554{ 593{
555 uint16_t len = ntohs (smt->header.size) - sizeof (*smt); 594 uint16_t len = ntohs (smt->header.size) - sizeof (*smt);
556 const struct GNUNET_MessageHeader *mh = (const struct GNUNET_MessageHeader *) &smt[1]; 595 const struct GNUNET_MessageHeader *mh = (const struct GNUNET_MessageHeader *) &smt[1];
557 596
597 (void) cls;
558 if (ntohs (mh->size) != len) 598 if (ntohs (mh->size) != len)
559 { 599 {
560 GNUNET_break (0); 600 GNUNET_break (0);
@@ -584,9 +624,9 @@ send_ack (struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
584 624
585 env = GNUNET_MQ_msg (ack, 625 env = GNUNET_MQ_msg (ack,
586 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK); 626 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK);
587 ack->status = htonl (GNUNET_OK); 627 ack->status = htonl (status);
588 ack->mid = ap->mid; 628 ack->mid = mid;
589 ack->receiver = ap->receiver; 629 ack->receiver = *receiver;
590 GNUNET_MQ_send (ch->mq, 630 GNUNET_MQ_send (ch->mq,
591 env); 631 env);
592} 632}
@@ -623,18 +663,18 @@ send_ack_cb (void *cls)
623 */ 663 */
624static void 664static void
625handle_send_msg (void *cls, 665handle_send_msg (void *cls,
626 struct GNUNET_TRANSPORT_SendMessageTo *smt) 666 const struct GNUNET_TRANSPORT_SendMessageTo *smt)
627{ 667{
628 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; 668 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
629 const struct GNUNET_MessageHeader *mh; 669 const struct GNUNET_MessageHeader *mh;
630 struct GNUNET_MQ_Envelope *env; 670 struct GNUNET_MQ_Envelope *env;
631 struct AckPending *ap; 671 struct AckPending *ap;
632 struct QueueHandle *qh; 672 struct GNUNET_TRANSPORT_QueueHandle *qh;
633 673
634 for (qh = ch->queue_head;NULL != qh; qh = qh->next) 674 for (qh = ch->queue_head;NULL != qh; qh = qh->next)
635 if ( (qh->queue_id == smt->qid) && 675 if ( (qh->queue_id == smt->qid) &&
636 (0 == memcmp (&qh->peer, 676 (0 == memcmp (&qh->peer,
637 &smt->target, 677 &smt->receiver,
638 sizeof (struct GNUNET_PeerIdentity))) ) 678 sizeof (struct GNUNET_PeerIdentity))) )
639 break; 679 break;
640 if (NULL == qh) 680 if (NULL == qh)
@@ -653,7 +693,7 @@ handle_send_msg (void *cls,
653 ap->receiver = smt->receiver; 693 ap->receiver = smt->receiver;
654 ap->mid = smt->mid; 694 ap->mid = smt->mid;
655 GNUNET_CONTAINER_DLL_insert (ch->ap_head, 695 GNUNET_CONTAINER_DLL_insert (ch->ap_head,
656 cp->ap_tail, 696 ch->ap_tail,
657 ap); 697 ap);
658 mh = (const struct GNUNET_MessageHeader *) &smt[1]; 698 mh = (const struct GNUNET_MessageHeader *) &smt[1];
659 env = GNUNET_MQ_msg_copy (mh); 699 env = GNUNET_MQ_msg_copy (mh);
@@ -679,7 +719,7 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
679 struct GNUNET_TRANSPORT_IncomingMessageAck, 719 struct GNUNET_TRANSPORT_IncomingMessageAck,
680 ch), 720 ch),
681 GNUNET_MQ_hd_var_size (create_queue, 721 GNUNET_MQ_hd_var_size (create_queue,
682 GNUNET_MESSAGE_TYPE_TRANSPORT_CREATE_QUEUE, 722 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE,
683 struct GNUNET_TRANSPORT_CreateQueue, 723 struct GNUNET_TRANSPORT_CreateQueue,
684 ch), 724 ch),
685 GNUNET_MQ_hd_var_size (send_msg, 725 GNUNET_MQ_hd_var_size (send_msg,
@@ -688,12 +728,24 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
688 ch), 728 ch),
689 GNUNET_MQ_handler_end() 729 GNUNET_MQ_handler_end()
690 }; 730 };
731 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam;
732 struct GNUNET_MQ_Envelope *env;
691 733
692 ch->mq = GNUNET_CLIENT_connect (cfg, 734 ch->mq = GNUNET_CLIENT_connect (ch->cfg,
693 "transport", 735 "transport",
694 handlers, 736 handlers,
695 &error_handler, 737 &error_handler,
696 ch); 738 ch);
739 if (NULL == ch->mq)
740 return;
741 env = GNUNET_MQ_msg_extra (cam,
742 strlen (ch->addr_prefix) + 1,
743 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR);
744 memcpy (&cam[1],
745 ch->addr_prefix,
746 strlen (ch->addr_prefix) + 1);
747 GNUNET_MQ_send (ch->mq,
748 env);
697 for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; 749 for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head;
698 NULL != ai; 750 NULL != ai;
699 ai = ai->next) 751 ai = ai->next)
@@ -709,7 +761,9 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
709 * Connect to the transport service. 761 * Connect to the transport service.
710 * 762 *
711 * @param cfg configuration to use 763 * @param cfg configuration to use
712 * @param name name of the communicator that is connecting 764 * @param config_section section of the configuration to use for options
765 * @param addr_prefix address prefix for addresses supported by this
766 * communicator, could be NULL for incoming-only communicators
713 * @param mtu maximum message size supported by communicator, 0 if 767 * @param mtu maximum message size supported by communicator, 0 if
714 * sending is not supported, SIZE_MAX for no MTU 768 * sending is not supported, SIZE_MAX for no MTU
715 * @param mq_init function to call to initialize a message queue given 769 * @param mq_init function to call to initialize a message queue given
@@ -720,7 +774,8 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
720 */ 774 */
721struct GNUNET_TRANSPORT_CommunicatorHandle * 775struct GNUNET_TRANSPORT_CommunicatorHandle *
722GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, 776GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
723 const char *name, 777 const char *config_section,
778 const char *addr_prefix,
724 size_t mtu, 779 size_t mtu,
725 GNUNET_TRANSPORT_CommunicatorMqInit mq_init, 780 GNUNET_TRANSPORT_CommunicatorMqInit mq_init,
726 void *mq_init_cls) 781 void *mq_init_cls)
@@ -729,14 +784,15 @@ GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle
729 784
730 ch = GNUNET_new (struct GNUNET_TRANSPORT_CommunicatorHandle); 785 ch = GNUNET_new (struct GNUNET_TRANSPORT_CommunicatorHandle);
731 ch->cfg = cfg; 786 ch->cfg = cfg;
732 ch->name = name; 787 ch->config_section = config_section;
788 ch->addr_prefix = addr_prefix;
733 ch->mtu = mtu; 789 ch->mtu = mtu;
734 ch->mq_init = mq_init; 790 ch->mq_init = mq_init;
735 ch->mq_init_cls = mq_init_cls; 791 ch->mq_init_cls = mq_init_cls;
736 reconnect (ch); 792 reconnect (ch);
737 if (GNUNET_OK != 793 if (GNUNET_OK !=
738 GNUNET_CONFIGURATION_get_value_number (cfg, 794 GNUNET_CONFIGURATION_get_value_number (cfg,
739 name, 795 config_section,
740 "MAX_QUEUE_LENGTH", 796 "MAX_QUEUE_LENGTH",
741 &ch->max_queue_length)) 797 &ch->max_queue_length))
742 ch->max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; 798 ch->max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
@@ -798,32 +854,15 @@ GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandl
798 struct GNUNET_TRANSPORT_IncomingMessage *im; 854 struct GNUNET_TRANSPORT_IncomingMessage *im;
799 uint16_t msize; 855 uint16_t msize;
800 856
801 if (NULL == ai->ch->mq) 857 if (NULL == ch->mq)
802 return GNUNET_SYSERR; 858 return GNUNET_SYSERR;
803 if (NULL != cb) 859 if ( (NULL == cb) &&
860 (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length) )
804 { 861 {
805 struct FlowControl *fc; 862 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
806 863 "Dropping message: transprot is too slow, queue length %llu exceeded\n",
807 im->fc_on = htonl (GNUNET_YES); 864 ch->max_queue_length);
808 im->fc_id = ai->ch->fc_gen++; 865 return GNUNET_NO;
809 fc = GNUNET_new (struct FlowControl);
810 fc->sender = *sender;
811 fc->id = im->fc_id;
812 fc->cb = cb;
813 fc->cb_cls = cb_cls;
814 GNUNET_CONTAINER_DLL_insert (ch->fc_head,
815 ch->fc_tail,
816 fc);
817 }
818 else
819 {
820 if (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length)
821 {
822 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
823 "Dropping message: transprot is too slow, queue length %u exceeded\n",
824 ch->max_queue_length);
825 return GNUNET_NO;
826 }
827 } 866 }
828 867
829 msize = ntohs (msg->size); 868 msize = ntohs (msg->size);
@@ -839,7 +878,22 @@ GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandl
839 memcpy (&im[1], 878 memcpy (&im[1],
840 msg, 879 msg,
841 msize); 880 msize);
842 GNUNET_MQ_send (ai->ch->mq, 881 if (NULL != cb)
882 {
883 struct FlowControl *fc;
884
885 im->fc_on = htonl (GNUNET_YES);
886 im->fc_id = ch->fc_gen++;
887 fc = GNUNET_new (struct FlowControl);
888 fc->sender = *sender;
889 fc->id = im->fc_id;
890 fc->cb = cb;
891 fc->cb_cls = cb_cls;
892 GNUNET_CONTAINER_DLL_insert (ch->fc_head,
893 ch->fc_tail,
894 fc);
895 }
896 GNUNET_MQ_send (ch->mq,
843 env); 897 env);
844 return GNUNET_OK; 898 return GNUNET_OK;
845} 899}
@@ -927,9 +981,9 @@ GNUNET_TRANSPORT_communicator_address_add (struct GNUNET_TRANSPORT_CommunicatorH
927 ai->address = GNUNET_strdup (address); 981 ai->address = GNUNET_strdup (address);
928 ai->nt = nt; 982 ai->nt = nt;
929 ai->expiration = expiration; 983 ai->expiration = expiration;
930 ai->aid = handle->aid_gen++; 984 ai->aid = ch->aid_gen++;
931 GNUNET_CONTAINER_DLL_insert (handle->ai_head, 985 GNUNET_CONTAINER_DLL_insert (ch->ai_head,
932 handle->ai_tail, 986 ch->ai_tail,
933 ai); 987 ai);
934 send_add_address (ai); 988 send_add_address (ai);
935 return ai; 989 return ai;
diff --git a/src/transport/transport_api2_core.c b/src/transport/transport_api2_core.c
new file mode 100644
index 000000000..78d8dcce0
--- /dev/null
+++ b/src/transport/transport_api2_core.c
@@ -0,0 +1,938 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file transport/transport_api_core.c
21 * @brief library to access the transport service for message exchange
22 * @author Christian Grothoff
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_constants.h"
27#include "gnunet_arm_service.h"
28#include "gnunet_hello_lib.h"
29#include "gnunet_protocols.h"
30#include "gnunet_transport_core_service.h"
31#include "transport.h"
32
33#define LOG(kind,...) GNUNET_log_from (kind, "transport-api-core",__VA_ARGS__)
34
35/**
36 * How large to start with for the hashmap of neighbours.
37 */
38#define STARTING_NEIGHBOURS_SIZE 16
39
40
41/**
42 * Entry in hash table of all of our current (connected) neighbours.
43 */
44struct Neighbour
45{
46
47 /**
48 * Identity of this neighbour.
49 */
50 struct GNUNET_PeerIdentity id;
51
52 /**
53 * Overall transport handle.
54 */
55 struct GNUNET_TRANSPORT_CoreHandle *h;
56
57 /**
58 * Active message queue for the peer.
59 */
60 struct GNUNET_MQ_Handle *mq;
61
62 /**
63 * Envelope with the message we are currently transmitting (or NULL).
64 */
65 struct GNUNET_MQ_Envelope *env;
66
67 /**
68 * Closure for @e mq handlers.
69 */
70 void *handlers_cls;
71
72 /**
73 * Entry in our readyness heap (which is sorted by @e next_ready
74 * value). NULL if there is no pending transmission request for
75 * this neighbour or if we're waiting for @e is_ready to become
76 * true AFTER the @e out_tracker suggested that this peer's quota
77 * has been satisfied (so once @e is_ready goes to #GNUNET_YES,
78 * we should immediately go back into the heap).
79 */
80 struct GNUNET_CONTAINER_HeapNode *hn;
81
82 /**
83 * Task to trigger MQ when we have enough bandwidth for the
84 * next transmission.
85 */
86 struct GNUNET_SCHEDULER_Task *timeout_task;
87
88 /**
89 * Outbound bandwidh tracker.
90 */
91 struct GNUNET_BANDWIDTH_Tracker out_tracker;
92
93 /**
94 * Sending consumed more bytes on wire than payload was announced
95 * This overhead is added to the delay of next sending operation
96 */
97 unsigned long long traffic_overhead;
98
99 /**
100 * Is this peer currently ready to receive a message?
101 */
102 int is_ready;
103
104 /**
105 * Size of the message in @e env.
106 */
107 uint16_t env_size;
108
109};
110
111
112
113/**
114 * Handle for the transport service (includes all of the
115 * state for the transport service).
116 */
117struct GNUNET_TRANSPORT_CoreHandle
118{
119
120 /**
121 * Closure for the callbacks.
122 */
123 void *cls;
124
125 /**
126 * Functions to call for received data (template for
127 * new message queues).
128 */
129 struct GNUNET_MQ_MessageHandler *handlers;
130
131 /**
132 * function to call on connect events
133 */
134 GNUNET_TRANSPORT_NotifyConnect nc_cb;
135
136 /**
137 * function to call on disconnect events
138 */
139 GNUNET_TRANSPORT_NotifyDisconnect nd_cb;
140
141 /**
142 * function to call on excess bandwidth events
143 */
144 GNUNET_TRANSPORT_NotifyExcessBandwidth neb_cb;
145
146 /**
147 * My client connection to the transport service.
148 */
149 struct GNUNET_MQ_Handle *mq;
150
151 /**
152 * My configuration.
153 */
154 const struct GNUNET_CONFIGURATION_Handle *cfg;
155
156 /**
157 * Hash map of the current connected neighbours of this peer.
158 * Maps peer identities to `struct Neighbour` entries.
159 */
160 struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
161
162 /**
163 * Peer identity as assumed by this process, or all zeros.
164 */
165 struct GNUNET_PeerIdentity self;
166
167 /**
168 * ID of the task trying to reconnect to the service.
169 */
170 struct GNUNET_SCHEDULER_Task *reconnect_task;
171
172 /**
173 * Delay until we try to reconnect.
174 */
175 struct GNUNET_TIME_Relative reconnect_delay;
176
177 /**
178 * Should we check that @e self matches what the service thinks?
179 * (if #GNUNET_NO, then @e self is all zeros!).
180 */
181 int check_self;
182
183};
184
185
186/**
187 * Function that will schedule the job that will try
188 * to connect us again to the client.
189 *
190 * @param h transport service to reconnect
191 */
192static void
193disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h);
194
195
196/**
197 * Get the neighbour list entry for the given peer
198 *
199 * @param h our context
200 * @param peer peer to look up
201 * @return NULL if no such peer entry exists
202 */
203static struct Neighbour *
204neighbour_find (struct GNUNET_TRANSPORT_CoreHandle *h,
205 const struct GNUNET_PeerIdentity *peer)
206{
207 return GNUNET_CONTAINER_multipeermap_get (h->neighbours,
208 peer);
209}
210
211
212/**
213 * Function called by the bandwidth tracker if we have excess
214 * bandwidth.
215 *
216 * @param cls the `struct Neighbour` that has excess bandwidth
217 */
218static void
219notify_excess_cb (void *cls)
220{
221 struct Neighbour *n = cls;
222 struct GNUNET_TRANSPORT_CoreHandle *h = n->h;
223
224 LOG (GNUNET_ERROR_TYPE_DEBUG,
225 "Notifying CORE that more bandwidth is available for %s\n",
226 GNUNET_i2s (&n->id));
227
228 if (NULL != h->neb_cb)
229 h->neb_cb (h->cls,
230 &n->id,
231 n->handlers_cls);
232}
233
234
235/**
236 * Iterator over hash map entries, for deleting state of a neighbour.
237 *
238 * @param cls the `struct GNUNET_TRANSPORT_CoreHandle *`
239 * @param key peer identity
240 * @param value value in the hash map, the neighbour entry to delete
241 * @return #GNUNET_YES if we should continue to
242 * iterate,
243 * #GNUNET_NO if not.
244 */
245static int
246neighbour_delete (void *cls,
247 const struct GNUNET_PeerIdentity *key,
248 void *value)
249{
250 struct GNUNET_TRANSPORT_CoreHandle *handle = cls;
251 struct Neighbour *n = value;
252
253 LOG (GNUNET_ERROR_TYPE_DEBUG,
254 "Dropping entry for neighbour `%s'.\n",
255 GNUNET_i2s (key));
256 GNUNET_BANDWIDTH_tracker_notification_stop (&n->out_tracker);
257 if (NULL != handle->nd_cb)
258 handle->nd_cb (handle->cls,
259 &n->id,
260 n->handlers_cls);
261 if (NULL != n->timeout_task)
262 {
263 GNUNET_SCHEDULER_cancel (n->timeout_task);
264 n->timeout_task = NULL;
265 }
266 if (NULL != n->env)
267 {
268 GNUNET_MQ_send_cancel (n->env);
269 n->env = NULL;
270 }
271 GNUNET_MQ_destroy (n->mq);
272 GNUNET_assert (NULL == n->mq);
273 GNUNET_assert (GNUNET_YES ==
274 GNUNET_CONTAINER_multipeermap_remove (handle->neighbours,
275 key,
276 n));
277 GNUNET_free (n);
278 return GNUNET_YES;
279}
280
281
282/**
283 * Generic error handler, called with the appropriate
284 * error code and the same closure specified at the creation of
285 * the message queue.
286 * Not every message queue implementation supports an error handler.
287 *
288 * @param cls closure with the `struct GNUNET_TRANSPORT_CoreHandle *`
289 * @param error error code
290 */
291static void
292mq_error_handler (void *cls,
293 enum GNUNET_MQ_Error error)
294{
295 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
296
297 LOG (GNUNET_ERROR_TYPE_DEBUG,
298 "Error receiving from transport service, disconnecting temporarily.\n");
299 disconnect_and_schedule_reconnect (h);
300}
301
302
303/**
304 * A message from the handler's message queue to a neighbour was
305 * transmitted. Now trigger (possibly delayed) notification of the
306 * neighbour's message queue that we are done and thus ready for
307 * the next message.
308 *
309 * @param cls the `struct Neighbour` where the message was sent
310 */
311static void
312notify_send_done_fin (void *cls)
313{
314 struct Neighbour *n = cls;
315
316 n->timeout_task = NULL;
317 n->is_ready = GNUNET_YES;
318 GNUNET_MQ_impl_send_continue (n->mq);
319}
320
321
322/**
323 * A message from the handler's message queue to a neighbour was
324 * transmitted. Now trigger (possibly delayed) notification of the
325 * neighbour's message queue that we are done and thus ready for
326 * the next message.
327 *
328 * @param cls the `struct Neighbour` where the message was sent
329 */
330static void
331notify_send_done (void *cls)
332{
333 struct Neighbour *n = cls;
334 struct GNUNET_TIME_Relative delay;
335
336 n->timeout_task = NULL;
337 if (NULL != n->env)
338 {
339 GNUNET_BANDWIDTH_tracker_consume (&n->out_tracker,
340 n->env_size + n->traffic_overhead);
341 n->env = NULL;
342 n->traffic_overhead = 0;
343 }
344 delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker,
345 128);
346 if (0 == delay.rel_value_us)
347 {
348 n->is_ready = GNUNET_YES;
349 GNUNET_MQ_impl_send_continue (n->mq);
350 return;
351 }
352 GNUNET_MQ_impl_send_in_flight (n->mq);
353 /* cannot send even a small message without violating
354 quota, wait a before allowing MQ to send next message */
355 n->timeout_task = GNUNET_SCHEDULER_add_delayed (delay,
356 &notify_send_done_fin,
357 n);
358}
359
360
361/**
362 * Implement sending functionality of a message queue.
363 * Called one message at a time. Should send the @a msg
364 * to the transport service and then notify the queue
365 * once we are ready for the next one.
366 *
367 * @param mq the message queue
368 * @param msg the message to send
369 * @param impl_state state of the implementation
370 */
371static void
372mq_send_impl (struct GNUNET_MQ_Handle *mq,
373 const struct GNUNET_MessageHeader *msg,
374 void *impl_state)
375{
376 struct Neighbour *n = impl_state;
377 struct GNUNET_TRANSPORT_CoreHandle *h = n->h;
378 struct OutboundMessage *obm;
379 uint16_t msize;
380
381 GNUNET_assert (GNUNET_YES == n->is_ready);
382 msize = ntohs (msg->size);
383 if (msize >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*obm))
384 {
385 GNUNET_break (0);
386 GNUNET_MQ_impl_send_continue (mq);
387 return;
388 }
389 GNUNET_assert (NULL == n->env);
390 n->env = GNUNET_MQ_msg_nested_mh (obm,
391 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
392 msg);
393 obm->reserved = htonl (0);
394 obm->timeout = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_MINUTES); /* FIXME: to be removed */
395 obm->peer = n->id;
396 GNUNET_assert (NULL == n->timeout_task);
397 n->is_ready = GNUNET_NO;
398 n->env_size = ntohs (msg->size);
399 GNUNET_MQ_notify_sent (n->env,
400 &notify_send_done,
401 n);
402 GNUNET_MQ_send (h->mq,
403 n->env);
404 LOG (GNUNET_ERROR_TYPE_DEBUG,
405 "Queued message of type %u for neighbour `%s'.\n",
406 ntohs (msg->type),
407 GNUNET_i2s (&n->id));
408}
409
410
411/**
412 * Handle destruction of a message queue. Implementations must not
413 * free @a mq, but should take care of @a impl_state.
414 *
415 * @param mq the message queue to destroy
416 * @param impl_state state of the implementation
417 */
418static void
419mq_destroy_impl (struct GNUNET_MQ_Handle *mq,
420 void *impl_state)
421{
422 struct Neighbour *n = impl_state;
423
424 GNUNET_assert (mq == n->mq);
425 n->mq = NULL;
426}
427
428
429/**
430 * Implementation function that cancels the currently sent message.
431 * Should basically undo whatever #mq_send_impl() did.
432 *
433 * @param mq message queue
434 * @param impl_state state specific to the implementation
435 */
436static void
437mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
438 void *impl_state)
439{
440 struct Neighbour *n = impl_state;
441
442 GNUNET_assert (GNUNET_NO == n->is_ready);
443 if (NULL != n->env)
444 {
445 GNUNET_MQ_send_cancel (n->env);
446 n->env = NULL;
447 }
448
449 n->is_ready = GNUNET_YES;
450}
451
452
453/**
454 * We had an error processing a message we forwarded from a peer to
455 * the CORE service. We should just complain about it but otherwise
456 * continue processing.
457 *
458 * @param cls closure
459 * @param error error code
460 */
461static void
462peer_mq_error_handler (void *cls,
463 enum GNUNET_MQ_Error error)
464{
465 /* struct Neighbour *n = cls; */
466
467 GNUNET_break_op (0);
468}
469
470
471/**
472 * The outbound quota has changed in a way that may require
473 * us to reset the timeout. Update the timeout.
474 *
475 * @param cls the `struct Neighbour` for which the timeout changed
476 */
477static void
478outbound_bw_tracker_update (void *cls)
479{
480 struct Neighbour *n = cls;
481 struct GNUNET_TIME_Relative delay;
482
483 if (NULL == n->timeout_task)
484 return;
485 delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker,
486 128);
487 GNUNET_SCHEDULER_cancel (n->timeout_task);
488 n->timeout_task = GNUNET_SCHEDULER_add_delayed (delay,
489 &notify_send_done,
490 n);
491}
492
493
494/**
495 * Function we use for handling incoming connect messages.
496 *
497 * @param cls closure, a `struct GNUNET_TRANSPORT_Handle *`
498 * @param cim message received
499 */
500static void
501handle_connect (void *cls,
502 const struct ConnectInfoMessage *cim)
503{
504 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
505 struct Neighbour *n;
506
507 LOG (GNUNET_ERROR_TYPE_DEBUG,
508 "Receiving CONNECT message for `%s' with quota %u\n",
509 GNUNET_i2s (&cim->id),
510 ntohl (cim->quota_out.value__));
511 n = neighbour_find (h,
512 &cim->id);
513 if (NULL != n)
514 {
515 GNUNET_break (0);
516 disconnect_and_schedule_reconnect (h);
517 return;
518 }
519 n = GNUNET_new (struct Neighbour);
520 n->id = cim->id;
521 n->h = h;
522 n->is_ready = GNUNET_YES;
523 n->traffic_overhead = 0;
524 GNUNET_BANDWIDTH_tracker_init2 (&n->out_tracker,
525 &outbound_bw_tracker_update,
526 n,
527 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
528 MAX_BANDWIDTH_CARRY_S,
529 &notify_excess_cb,
530 n);
531 GNUNET_assert (GNUNET_OK ==
532 GNUNET_CONTAINER_multipeermap_put (h->neighbours,
533 &n->id,
534 n,
535 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
536
537 GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker,
538 cim->quota_out);
539 n->mq = GNUNET_MQ_queue_for_callbacks (&mq_send_impl,
540 &mq_destroy_impl,
541 &mq_cancel_impl,
542 n,
543 h->handlers,
544 &peer_mq_error_handler,
545 n);
546 if (NULL != h->nc_cb)
547 {
548 n->handlers_cls = h->nc_cb (h->cls,
549 &n->id,
550 n->mq);
551 GNUNET_MQ_set_handlers_closure (n->mq,
552 n->handlers_cls);
553 }
554}
555
556
557/**
558 * Function we use for handling incoming disconnect messages.
559 *
560 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
561 * @param dim message received
562 */
563static void
564handle_disconnect (void *cls,
565 const struct DisconnectInfoMessage *dim)
566{
567 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
568 struct Neighbour *n;
569
570 GNUNET_break (ntohl (dim->reserved) == 0);
571 LOG (GNUNET_ERROR_TYPE_DEBUG,
572 "Receiving DISCONNECT message for `%s'.\n",
573 GNUNET_i2s (&dim->peer));
574 n = neighbour_find (h,
575 &dim->peer);
576 if (NULL == n)
577 {
578 GNUNET_break (0);
579 disconnect_and_schedule_reconnect (h);
580 return;
581 }
582 GNUNET_assert (GNUNET_YES ==
583 neighbour_delete (h,
584 &dim->peer,
585 n));
586}
587
588
589/**
590 * Function we use for handling incoming send-ok messages.
591 *
592 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
593 * @param okm message received
594 */
595static void
596handle_send_ok (void *cls,
597 const struct SendOkMessage *okm)
598{
599 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
600 struct Neighbour *n;
601 uint32_t bytes_msg;
602 uint32_t bytes_physical;
603
604 bytes_msg = ntohl (okm->bytes_msg);
605 bytes_physical = ntohl (okm->bytes_physical);
606 LOG (GNUNET_ERROR_TYPE_DEBUG,
607 "Receiving SEND_OK message, transmission to %s %s.\n",
608 GNUNET_i2s (&okm->peer),
609 (GNUNET_OK == ntohl (okm->success))
610 ? "succeeded"
611 : "failed");
612 n = neighbour_find (h,
613 &okm->peer);
614 if (NULL == n)
615 {
616 /* We should never get a 'SEND_OK' for a peer that we are not
617 connected to */
618 GNUNET_break (0);
619 disconnect_and_schedule_reconnect (h);
620 return;
621 }
622 if (bytes_physical > bytes_msg)
623 {
624 LOG (GNUNET_ERROR_TYPE_DEBUG,
625 "Overhead for %u byte message was %u\n",
626 (unsigned int) bytes_msg,
627 (unsigned int) (bytes_physical - bytes_msg));
628 n->traffic_overhead += bytes_physical - bytes_msg;
629 }
630}
631
632
633/**
634 * Function we use for checking incoming "inbound" messages.
635 *
636 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
637 * @param im message received
638 */
639static int
640check_recv (void *cls,
641 const struct InboundMessage *im)
642{
643 const struct GNUNET_MessageHeader *imm;
644 uint16_t size;
645
646 size = ntohs (im->header.size) - sizeof (*im);
647 if (size < sizeof (struct GNUNET_MessageHeader))
648 {
649 GNUNET_break (0);
650 return GNUNET_SYSERR;
651 }
652 imm = (const struct GNUNET_MessageHeader *) &im[1];
653 if (ntohs (imm->size) != size)
654 {
655 GNUNET_break (0);
656 return GNUNET_SYSERR;
657 }
658 return GNUNET_OK;
659}
660
661
662/**
663 * Function we use for handling incoming messages.
664 *
665 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
666 * @param im message received
667 */
668static void
669handle_recv (void *cls,
670 const struct InboundMessage *im)
671{
672 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
673 const struct GNUNET_MessageHeader *imm
674 = (const struct GNUNET_MessageHeader *) &im[1];
675 struct Neighbour *n;
676
677 LOG (GNUNET_ERROR_TYPE_DEBUG,
678 "Received message of type %u with %u bytes from `%s'.\n",
679 (unsigned int) ntohs (imm->type),
680 (unsigned int) ntohs (imm->size),
681 GNUNET_i2s (&im->peer));
682 n = neighbour_find (h,
683 &im->peer);
684 if (NULL == n)
685 {
686 GNUNET_break (0);
687 disconnect_and_schedule_reconnect (h);
688 return;
689 }
690 GNUNET_MQ_inject_message (n->mq,
691 imm);
692}
693
694
695/**
696 * Function we use for handling incoming set quota messages.
697 *
698 * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *`
699 * @param msg message received
700 */
701static void
702handle_set_quota (void *cls,
703 const struct QuotaSetMessage *qm)
704{
705 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
706 struct Neighbour *n;
707
708 n = neighbour_find (h,
709 &qm->peer);
710 if (NULL == n)
711 {
712 GNUNET_break (0);
713 disconnect_and_schedule_reconnect (h);
714 return;
715 }
716 LOG (GNUNET_ERROR_TYPE_DEBUG,
717 "Receiving SET_QUOTA message for `%s' with quota %u\n",
718 GNUNET_i2s (&qm->peer),
719 (unsigned int) ntohl (qm->quota.value__));
720 GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker,
721 qm->quota);
722}
723
724
725/**
726 * Try again to connect to transport service.
727 *
728 * @param cls the handle to the transport service
729 */
730static void
731reconnect (void *cls)
732{
733 struct GNUNET_TRANSPORT_CoreHandle *h = cls;
734 struct GNUNET_MQ_MessageHandler handlers[] = {
735 GNUNET_MQ_hd_fixed_size (connect,
736 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT,
737 struct ConnectInfoMessage,
738 h),
739 GNUNET_MQ_hd_fixed_size (disconnect,
740 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT,
741 struct DisconnectInfoMessage,
742 h),
743 GNUNET_MQ_hd_fixed_size (send_ok,
744 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK,
745 struct SendOkMessage,
746 h),
747 GNUNET_MQ_hd_var_size (recv,
748 GNUNET_MESSAGE_TYPE_TRANSPORT_RECV,
749 struct InboundMessage,
750 h),
751 GNUNET_MQ_hd_fixed_size (set_quota,
752 GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA,
753 struct QuotaSetMessage,
754 h),
755 GNUNET_MQ_handler_end ()
756 };
757 struct GNUNET_MQ_Envelope *env;
758 struct StartMessage *s;
759 uint32_t options;
760
761 h->reconnect_task = NULL;
762 LOG (GNUNET_ERROR_TYPE_DEBUG,
763 "Connecting to transport service.\n");
764 GNUNET_assert (NULL == h->mq);
765 h->mq = GNUNET_CLIENT_connect (h->cfg,
766 "transport",
767 handlers,
768 &mq_error_handler,
769 h);
770 if (NULL == h->mq)
771 return;
772 env = GNUNET_MQ_msg (s,
773 GNUNET_MESSAGE_TYPE_TRANSPORT_START);
774 options = 0;
775 if (h->check_self)
776 options |= 1;
777 if (NULL != h->handlers)
778 options |= 2;
779 s->options = htonl (options);
780 s->self = h->self;
781 GNUNET_MQ_send (h->mq,
782 env);
783}
784
785
786/**
787 * Disconnect from the transport service.
788 *
789 * @param h transport service to reconnect
790 */
791static void
792disconnect (struct GNUNET_TRANSPORT_CoreHandle *h)
793{
794 GNUNET_CONTAINER_multipeermap_iterate (h->neighbours,
795 &neighbour_delete,
796 h);
797 if (NULL != h->mq)
798 {
799 GNUNET_MQ_destroy (h->mq);
800 h->mq = NULL;
801 }
802}
803
804
805/**
806 * Function that will schedule the job that will try
807 * to connect us again to the client.
808 *
809 * @param h transport service to reconnect
810 */
811static void
812disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h)
813{
814 GNUNET_assert (NULL == h->reconnect_task);
815 disconnect (h);
816 LOG (GNUNET_ERROR_TYPE_DEBUG,
817 "Scheduling task to reconnect to transport service in %s.\n",
818 GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay,
819 GNUNET_YES));
820 h->reconnect_task =
821 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
822 &reconnect,
823 h);
824 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
825}
826
827
828/**
829 * Checks if a given peer is connected to us and get the message queue.
830 *
831 * @param handle connection to transport service
832 * @param peer the peer to check
833 * @return NULL if disconnected, otherwise message queue for @a peer
834 */
835struct GNUNET_MQ_Handle *
836GNUNET_TRANSPORT_core_get_mq (struct GNUNET_TRANSPORT_CoreHandle *handle,
837 const struct GNUNET_PeerIdentity *peer)
838{
839 struct Neighbour *n;
840
841 n = neighbour_find (handle,
842 peer);
843 if (NULL == n)
844 return NULL;
845 return n->mq;
846}
847
848
849/**
850 * Connect to the transport service. Note that the connection may
851 * complete (or fail) asynchronously.
852 *
853 * @param cfg configuration to use
854 * @param self our own identity (API should check that it matches
855 * the identity found by transport), or NULL (no check)
856 * @param cls closure for the callbacks
857 * @param rec receive function to call
858 * @param nc function to call on connect events
859 * @param nd function to call on disconnect events
860 * @param neb function to call if we have excess bandwidth to a peer
861 * @return NULL on error
862 */
863struct GNUNET_TRANSPORT_CoreHandle *
864GNUNET_TRANSPORT_core_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
865 const struct GNUNET_PeerIdentity *self,
866 const struct GNUNET_MQ_MessageHandler *handlers,
867 void *cls,
868 GNUNET_TRANSPORT_NotifyConnect nc,
869 GNUNET_TRANSPORT_NotifyDisconnect nd,
870 GNUNET_TRANSPORT_NotifyExcessBandwidth neb)
871{
872 struct GNUNET_TRANSPORT_CoreHandle *h;
873 unsigned int i;
874
875 h = GNUNET_new (struct GNUNET_TRANSPORT_CoreHandle);
876 if (NULL != self)
877 {
878 h->self = *self;
879 h->check_self = GNUNET_YES;
880 }
881 h->cfg = cfg;
882 h->cls = cls;
883 h->nc_cb = nc;
884 h->nd_cb = nd;
885 h->neb_cb = neb;
886 h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
887 if (NULL != handlers)
888 {
889 for (i=0;NULL != handlers[i].cb; i++) ;
890 h->handlers = GNUNET_new_array (i + 1,
891 struct GNUNET_MQ_MessageHandler);
892 GNUNET_memcpy (h->handlers,
893 handlers,
894 i * sizeof (struct GNUNET_MQ_MessageHandler));
895 }
896 LOG (GNUNET_ERROR_TYPE_DEBUG,
897 "Connecting to transport service\n");
898 reconnect (h);
899 if (NULL == h->mq)
900 {
901 GNUNET_free_non_null (h->handlers);
902 GNUNET_free (h);
903 return NULL;
904 }
905 h->neighbours =
906 GNUNET_CONTAINER_multipeermap_create (STARTING_NEIGHBOURS_SIZE,
907 GNUNET_YES);
908 return h;
909}
910
911
912/**
913 * Disconnect from the transport service.
914 *
915 * @param handle handle to the service as returned from #GNUNET_TRANSPORT_core_connect()
916 */
917void
918GNUNET_TRANSPORT_core_disconnect (struct GNUNET_TRANSPORT_CoreHandle *handle)
919{
920 LOG (GNUNET_ERROR_TYPE_DEBUG,
921 "Transport disconnect called!\n");
922 /* this disconnects all neighbours... */
923 disconnect (handle);
924 /* and now we stop trying to connect again... */
925 if (NULL != handle->reconnect_task)
926 {
927 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
928 handle->reconnect_task = NULL;
929 }
930 GNUNET_CONTAINER_multipeermap_destroy (handle->neighbours);
931 handle->neighbours = NULL;
932 GNUNET_free_non_null (handle->handlers);
933 handle->handlers = NULL;
934 GNUNET_free (handle);
935}
936
937
938/* end of transport_api_core.c */
diff --git a/src/transport/transport_api2_monitor.c b/src/transport/transport_api2_monitor.c
new file mode 100644
index 000000000..d7b13ec74
--- /dev/null
+++ b/src/transport/transport_api2_monitor.c
@@ -0,0 +1,313 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file transport/transport_api2_monitor.c
21 * @brief implementation of the gnunet_transport_monitor_service.h API
22 * @author Christian Grothoff
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_protocols.h"
27#include "gnunet_transport_monitor_service.h"
28#include "transport.h"
29
30
31/**
32 * Opaque handle to the transport service for monitors.
33 */
34struct GNUNET_TRANSPORT_MonitorContext
35{
36 /**
37 * Our configuration.
38 */
39 const struct GNUNET_CONFIGURATION_Handle *cfg;
40
41 /**
42 * Queue to talk to the transport service.
43 */
44 struct GNUNET_MQ_Handle *mq;
45
46 /**
47 * Peer we monitor, all zeros for "all"
48 */
49 struct GNUNET_PeerIdentity peer;
50
51 /**
52 * #GNUNET_YES to return the current state and then end.
53 */
54 int one_shot;
55
56 /**
57 * Function to call with monitor data.
58 */
59 GNUNET_TRANSPORT_MonitorCallback cb;
60
61 /**
62 * Closure for @e cb.
63 */
64 void *cb_cls;
65
66};
67
68
69/**
70 * (re)connect our monitor to the transport service
71 *
72 * @param mc handle to reconnect
73 */
74static void
75reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc);
76
77
78/**
79 * Send message to the transport service about our montoring
80 * desire.
81 *
82 * @param ai address to delete
83 */
84static void
85send_start_monitor (struct GNUNET_TRANSPORT_MonitorContext *mc)
86{
87 struct GNUNET_MQ_Envelope *env;
88 struct GNUNET_TRANSPORT_MonitorStart *smm;
89
90 if (NULL == mc->mq)
91 return;
92 env = GNUNET_MQ_msg (smm,
93 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START);
94 smm->one_shot = htonl ((uint32_t) mc->one_shot);
95 smm->peer = mc->peer;
96 GNUNET_MQ_send (mc->mq,
97 env);
98}
99
100
101/**
102 * Disconnect from the transport service.
103 *
104 * @param mc service to disconnect from
105 */
106static void
107disconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
108{
109 if (NULL == mc->mq)
110 return;
111 GNUNET_MQ_destroy (mc->mq);
112 mc->mq = NULL;
113}
114
115
116/**
117 * Function called on MQ errors. Reconnects to the service.
118 *
119 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
120 * @param error what error happened?
121 */
122static void
123error_handler (void *cls,
124 enum GNUNET_MQ_Error error)
125{
126 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
127
128 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
129 "MQ failure %d, reconnecting to transport service.\n",
130 error);
131 disconnect (mc);
132 /* TODO: maybe do this with exponential backoff/delay */
133 reconnect (mc);
134}
135
136
137/**
138 * Transport service sends us information about what is going on.
139 * Check if @a md is well-formed.
140 *
141 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
142 * @param md the monitor data we got
143 * @return #GNUNET_OK if @a smt is well-formed
144 */
145static int
146check_monitor_data (void *cls,
147 const struct GNUNET_TRANSPORT_MonitorData *md)
148{
149 uint16_t len = ntohs (md->header.size) - sizeof (*md);
150 const char *addr = (const char *) &md[1];
151
152 (void) cls;
153 if ( (0 == len) ||
154 ('\0' != addr[len-1]) )
155 {
156 GNUNET_break (0);
157 return GNUNET_SYSERR;
158 }
159 return GNUNET_OK;
160}
161
162
163/**
164 * Transport service sends us information about what is going on.
165 *
166 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
167 * @param md monitor data
168 */
169static void
170handle_monitor_data (void *cls,
171 const struct GNUNET_TRANSPORT_MonitorData *md)
172{
173 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
174 struct GNUNET_TRANSPORT_MonitorInformation mi;
175
176 mi.address = (const char *) &md[1];
177 mi.nt = (enum GNUNET_ATS_Network_Type) ntohl (md->nt);
178 mi.is_inbound = (int) ntohl (md->is_inbound);
179 mi.num_msg_pending = ntohl (md->num_msg_pending);
180 mi.num_bytes_pending = ntohl (md->num_bytes_pending);
181 mi.last_validation = GNUNET_TIME_absolute_ntoh (md->last_validation);
182 mi.valid_until = GNUNET_TIME_absolute_ntoh (md->valid_until);
183 mi.next_validation = GNUNET_TIME_absolute_ntoh (md->next_validation);
184 mi.rtt = GNUNET_TIME_relative_ntoh (md->rtt);
185 mc->cb (mc->cb_cls,
186 &md->peer,
187 &mi);
188}
189
190
191/**
192 * One shot was requested, and transport service is done.
193 *
194 * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *`
195 * @param me end message
196 */
197static void
198handle_monitor_end (void *cls,
199 const struct GNUNET_MessageHeader *me)
200{
201 struct GNUNET_TRANSPORT_MonitorContext *mc = cls;
202
203 if (GNUNET_YES != mc->one_shot)
204 {
205 GNUNET_break (0);
206 disconnect (mc);
207 reconnect (mc);
208 return;
209 }
210 mc->cb (mc->cb_cls,
211 NULL,
212 NULL);
213 GNUNET_TRANSPORT_monitor_cancel (mc);
214}
215
216
217/**
218 * (re)connect our monitor to the transport service
219 *
220 * @param mc handle to reconnect
221 */
222static void
223reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc)
224{
225 struct GNUNET_MQ_MessageHandler handlers[] = {
226 GNUNET_MQ_hd_var_size (monitor_data,
227 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA,
228 struct GNUNET_TRANSPORT_MonitorData,
229 mc),
230 GNUNET_MQ_hd_fixed_size (monitor_end,
231 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END,
232 struct GNUNET_MessageHeader,
233 mc),
234 GNUNET_MQ_handler_end()
235 };
236
237 mc->mq = GNUNET_CLIENT_connect (mc->cfg,
238 "transport",
239 handlers,
240 &error_handler,
241 mc);
242 if (NULL == mc->mq)
243 return;
244 send_start_monitor (mc);
245}
246
247
248/**
249 * Return information about a specific peer or all peers currently known to
250 * transport service once or in monitoring mode. To obtain information about
251 * a specific peer, a peer identity can be passed. To obtain information about
252 * all peers currently known to transport service, NULL can be passed as peer
253 * identity.
254 *
255 * For each peer, the callback is called with information about the address used
256 * to communicate with this peer, the state this peer is currently in and the
257 * the current timeout for this state.
258 *
259 * Upon completion, the #GNUNET_TRANSPORT_PeerIterateCallback is called one
260 * more time with `NULL`. After this, the operation must no longer be
261 * explicitly canceled.
262 *
263 * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the
264 * the peer_callback!
265 *
266 * @param cfg configuration to use
267 * @param peer a specific peer identity to obtain information for,
268 * NULL for all peers
269 * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL),
270 * #GNUNET_NO to monitor peers continuously
271 * @param cb function to call with the results
272 * @param cb_cls closure for @a mc
273 */
274struct GNUNET_TRANSPORT_MonitorContext *
275GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
276 const struct GNUNET_PeerIdentity *peer,
277 int one_shot,
278 GNUNET_TRANSPORT_MonitorCallback cb,
279 void *cb_cls)
280{
281 struct GNUNET_TRANSPORT_MonitorContext *mc;
282
283 mc = GNUNET_new (struct GNUNET_TRANSPORT_MonitorContext);
284 mc->cfg = cfg;
285 if (NULL != peer)
286 mc->peer = *peer;
287 mc->one_shot = one_shot;
288 mc->cb = cb;
289 mc->cb_cls = cb_cls;
290 reconnect (mc);
291 if (NULL == mc->mq)
292 {
293 GNUNET_free (mc);
294 return NULL;
295 }
296 return mc;
297}
298
299
300
301/**
302 * Cancel request to monitor peers
303 *
304 * @param pmc handle for the request to cancel
305 */
306void
307GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *mc)
308{
309 disconnect (mc);
310 GNUNET_free (mc);
311}
312
313/* end of transport_api2_monitor.c */
diff --git a/src/transport/transport_api_core.c b/src/transport/transport_api_core.c
index b7edc3cc1..2e897d94a 100644
--- a/src/transport/transport_api_core.c
+++ b/src/transport/transport_api_core.c
@@ -11,7 +11,7 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/ 17*/
@@ -136,17 +136,17 @@ struct GNUNET_TRANSPORT_CoreHandle
136 /** 136 /**
137 * function to call on connect events 137 * function to call on connect events
138 */ 138 */
139 GNUNET_TRANSPORT_NotifyConnecT nc_cb; 139 GNUNET_TRANSPORT_NotifyConnect nc_cb;
140 140
141 /** 141 /**
142 * function to call on disconnect events 142 * function to call on disconnect events
143 */ 143 */
144 GNUNET_TRANSPORT_NotifyDisconnecT nd_cb; 144 GNUNET_TRANSPORT_NotifyDisconnect nd_cb;
145 145
146 /** 146 /**
147 * function to call on excess bandwidth events 147 * function to call on excess bandwidth events
148 */ 148 */
149 GNUNET_TRANSPORT_NotifyExcessBandwidtH neb_cb; 149 GNUNET_TRANSPORT_NotifyExcessBandwidth neb_cb;
150 150
151 /** 151 /**
152 * My client connection to the transport service. 152 * My client connection to the transport service.
@@ -551,7 +551,8 @@ handle_connect (void *cls,
551 "Receiving CONNECT message for `%s' with quota %u\n", 551 "Receiving CONNECT message for `%s' with quota %u\n",
552 GNUNET_i2s (&cim->id), 552 GNUNET_i2s (&cim->id),
553 ntohl (cim->quota_out.value__)); 553 ntohl (cim->quota_out.value__));
554 n = neighbour_find (h, &cim->id); 554 n = neighbour_find (h,
555 &cim->id);
555 if (NULL != n) 556 if (NULL != n)
556 { 557 {
557 GNUNET_break (0); 558 GNUNET_break (0);
@@ -896,9 +897,9 @@ GNUNET_TRANSPORT_core_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
896 const struct GNUNET_PeerIdentity *self, 897 const struct GNUNET_PeerIdentity *self,
897 const struct GNUNET_MQ_MessageHandler *handlers, 898 const struct GNUNET_MQ_MessageHandler *handlers,
898 void *cls, 899 void *cls,
899 GNUNET_TRANSPORT_NotifyConnecT nc, 900 GNUNET_TRANSPORT_NotifyConnect nc,
900 GNUNET_TRANSPORT_NotifyDisconnecT nd, 901 GNUNET_TRANSPORT_NotifyDisconnect nd,
901 GNUNET_TRANSPORT_NotifyExcessBandwidtH neb) 902 GNUNET_TRANSPORT_NotifyExcessBandwidth neb)
902{ 903{
903 struct GNUNET_TRANSPORT_CoreHandle *h; 904 struct GNUNET_TRANSPORT_CoreHandle *h;
904 unsigned int i; 905 unsigned int i;
diff --git a/src/util/configuration.c b/src/util/configuration.c
index e00bbd64a..197c664db 100644
--- a/src/util/configuration.c
+++ b/src/util/configuration.c
@@ -138,6 +138,41 @@ GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg)
138 138
139 139
140/** 140/**
141 * Parse a configuration file @a filename and run the function
142 * @a cb with the resulting configuration object. Then free the
143 * configuration object and return the status value from @a cb.
144 *
145 * @param filename configuration to parse, NULL for "default"
146 * @param cb function to run
147 * @param cb_cls closure for @a cb
148 * @return #GNUNET_SYSERR if parsing the configuration failed,
149 * otherwise return value from @a cb.
150 */
151int
152GNUNET_CONFIGURATION_parse_and_run (const char *filename,
153 GNUNET_CONFIGURATION_Callback cb,
154 void *cb_cls)
155{
156 struct GNUNET_CONFIGURATION_Handle *cfg;
157 int ret;
158
159 cfg = GNUNET_CONFIGURATION_create ();
160 if (GNUNET_OK !=
161 GNUNET_CONFIGURATION_load (cfg,
162 filename))
163 {
164 GNUNET_break (0);
165 GNUNET_CONFIGURATION_destroy (cfg);
166 return GNUNET_SYSERR;
167 }
168 ret = cb (cb_cls,
169 cfg);
170 GNUNET_CONFIGURATION_destroy (cfg);
171 return ret;
172}
173
174
175/**
141 * De-serializes configuration 176 * De-serializes configuration
142 * 177 *
143 * @param cfg configuration to update 178 * @param cfg configuration to update
@@ -522,7 +557,7 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg,
522 GNUNET_free (fn); 557 GNUNET_free (fn);
523 GNUNET_free (cfg_buf); 558 GNUNET_free (cfg_buf);
524 LOG (GNUNET_ERROR_TYPE_WARNING, 559 LOG (GNUNET_ERROR_TYPE_WARNING,
525 "Writing configration to file `%s' failed\n", 560 "Writing configuration to file `%s' failed\n",
526 filename); 561 filename);
527 cfg->dirty = GNUNET_SYSERR; /* last write failed */ 562 cfg->dirty = GNUNET_SYSERR; /* last write failed */
528 return GNUNET_SYSERR; 563 return GNUNET_SYSERR;
@@ -893,22 +928,27 @@ GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg,
893 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 928 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
894 */ 929 */
895int 930int
896GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle 931GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle *cfg,
897 *cfg, const char *section, 932 const char *section,
898 const char *option, 933 const char *option,
899 unsigned long long *number) 934 unsigned long long *number)
900{ 935{
901 struct ConfigEntry *e; 936 struct ConfigEntry *e;
937 char dummy[2];
902 938
903 if (NULL == (e = find_entry (cfg, section, option))) 939 if (NULL == (e = find_entry (cfg, section, option)))
904 return GNUNET_SYSERR; 940 return GNUNET_SYSERR;
905 if (NULL == e->val) 941 if (NULL == e->val)
906 return GNUNET_SYSERR; 942 return GNUNET_SYSERR;
907 if (1 != SSCANF (e->val, "%llu", number)) 943 if (1 != SSCANF (e->val,
944 "%llu%1s",
945 number,
946 dummy))
908 return GNUNET_SYSERR; 947 return GNUNET_SYSERR;
909 return GNUNET_OK; 948 return GNUNET_OK;
910} 949}
911 950
951
912/** 952/**
913 * Get a configuration value that should be a floating point number. 953 * Get a configuration value that should be a floating point number.
914 * 954 *
@@ -919,18 +959,22 @@ GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle
919 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 959 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
920 */ 960 */
921int 961int
922GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle 962GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle *cfg,
923 *cfg, const char *section, 963 const char *section,
924 const char *option, 964 const char *option,
925 float *number) 965 float *number)
926{ 966{
927 struct ConfigEntry *e; 967 struct ConfigEntry *e;
928 968 char dummy[2];
969
929 if (NULL == (e = find_entry (cfg, section, option))) 970 if (NULL == (e = find_entry (cfg, section, option)))
930 return GNUNET_SYSERR; 971 return GNUNET_SYSERR;
931 if (NULL == e->val) 972 if (NULL == e->val)
932 return GNUNET_SYSERR; 973 return GNUNET_SYSERR;
933 if (1 != SSCANF (e->val, "%f", number)) 974 if (1 != SSCANF (e->val,
975 "%f%1s",
976 number,
977 dummy))
934 return GNUNET_SYSERR; 978 return GNUNET_SYSERR;
935 return GNUNET_OK; 979 return GNUNET_OK;
936} 980}
diff --git a/src/util/disk.c b/src/util/disk.c
index e0227be70..dc38d1137 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -2668,28 +2668,19 @@ GNUNET_DISK_internal_file_handle_ (const struct GNUNET_DISK_FileHandle *fh,
2668 2668
2669 2669
2670/** 2670/**
2671 * Remove the directory given under @a option in 2671 * Helper function for #GNUNET_DISK_purge_cfg_dir.
2672 * section [PATHS] in configuration under @a cfg_filename
2673 * 2672 *
2674 * @param cfg_filename configuration file to parse 2673 * @param cls a `const char *` with the option to purge
2675 * @param option option with the dir name to purge 2674 * @param cfg our configuration
2675 * @return #GNUNET_OK on success
2676 */ 2676 */
2677void 2677static int
2678GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, 2678purge_cfg_dir (void *cls,
2679 const char *option) 2679 const struct GNUNET_CONFIGURATION_Handle *cfg)
2680{ 2680{
2681 struct GNUNET_CONFIGURATION_Handle *cfg; 2681 const char *option = cls;
2682 char *tmpname; 2682 char *tmpname;
2683 2683
2684 cfg = GNUNET_CONFIGURATION_create ();
2685 if (GNUNET_OK !=
2686 GNUNET_CONFIGURATION_load (cfg,
2687 cfg_filename))
2688 {
2689 GNUNET_break (0);
2690 GNUNET_CONFIGURATION_destroy (cfg);
2691 return;
2692 }
2693 if (GNUNET_OK != 2684 if (GNUNET_OK !=
2694 GNUNET_CONFIGURATION_get_value_filename (cfg, 2685 GNUNET_CONFIGURATION_get_value_filename (cfg,
2695 "PATHS", 2686 "PATHS",
@@ -2699,10 +2690,8 @@ GNUNET_DISK_purge_cfg_dir (const char *cfg_filename,
2699 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2690 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2700 "PATHS", 2691 "PATHS",
2701 option); 2692 option);
2702 GNUNET_CONFIGURATION_destroy (cfg); 2693 return GNUNET_NO;
2703 return;
2704 } 2694 }
2705 GNUNET_CONFIGURATION_destroy (cfg);
2706 if (GNUNET_SYSERR == 2695 if (GNUNET_SYSERR ==
2707 GNUNET_DISK_directory_remove (tmpname)) 2696 GNUNET_DISK_directory_remove (tmpname))
2708 { 2697 {
@@ -2710,11 +2699,29 @@ GNUNET_DISK_purge_cfg_dir (const char *cfg_filename,
2710 "remove", 2699 "remove",
2711 tmpname); 2700 tmpname);
2712 GNUNET_free (tmpname); 2701 GNUNET_free (tmpname);
2713 return; 2702 return GNUNET_OK;
2714 } 2703 }
2715 GNUNET_free (tmpname); 2704 GNUNET_free (tmpname);
2705 return GNUNET_OK;
2716} 2706}
2717 2707
2718 2708
2709/**
2710 * Remove the directory given under @a option in
2711 * section [PATHS] in configuration under @a cfg_filename
2712 *
2713 * @param cfg_filename configuration file to parse
2714 * @param option option with the dir name to purge
2715 */
2716void
2717GNUNET_DISK_purge_cfg_dir (const char *cfg_filename,
2718 const char *option)
2719{
2720 GNUNET_break (GNUNET_OK ==
2721 GNUNET_CONFIGURATION_parse_and_run (cfg_filename,
2722 &purge_cfg_dir,
2723 (void *) option));
2724}
2725
2719 2726
2720/* end of disk.c */ 2727/* end of disk.c */
diff --git a/src/util/getopt.c b/src/util/getopt.c
index 036e0f4be..4a7f35f51 100644
--- a/src/util/getopt.c
+++ b/src/util/getopt.c
@@ -866,7 +866,7 @@ GNgetopt_long (int argc,
866 * @param argc number of arguments 866 * @param argc number of arguments
867 * @param argv actual arguments 867 * @param argv actual arguments
868 * @return index into argv with first non-option 868 * @return index into argv with first non-option
869 * argument, or -1 on error 869 * argument, or #GNUNET_SYSERR on error
870 */ 870 */
871int 871int
872GNUNET_GETOPT_run (const char *binaryOptions, 872GNUNET_GETOPT_run (const char *binaryOptions,
@@ -967,9 +967,9 @@ GNUNET_GETOPT_run (const char *binaryOptions,
967 GNUNET_free (seen); 967 GNUNET_free (seen);
968 968
969 /* call cleaners, if available */ 969 /* call cleaners, if available */
970 for (count = 0; NULL != allOptions[count].name; count++) 970 for (unsigned int i = 0; NULL != allOptions[i].name; i++)
971 if (NULL != allOptions[count].cleaner) 971 if (NULL != allOptions[i].cleaner)
972 allOptions[count].cleaner (allOptions[count].scls); 972 allOptions[i].cleaner (allOptions[i].scls);
973 973
974 if (GNUNET_OK != cont) 974 if (GNUNET_OK != cont)
975 return cont; 975 return cont;
diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c
index 32cce65dd..661521c45 100644
--- a/src/util/getopt_helpers.c
+++ b/src/util/getopt_helpers.c
@@ -108,9 +108,10 @@ format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
108 (void) value; 108 (void) value;
109 if (NULL != about) 109 if (NULL != about)
110 { 110 {
111 printf ("%s\n%s\n", ctx->binaryOptions, gettext (about)); 111 printf ("%s\n%s\n",
112 printf (_ 112 ctx->binaryOptions,
113 ("Arguments mandatory for long options are also mandatory for short options.\n")); 113 gettext (about));
114 printf (_("Arguments mandatory for long options are also mandatory for short options.\n"));
114 } 115 }
115 i = 0; 116 i = 0;
116 opt = ctx->allOptions; 117 opt = ctx->allOptions;
@@ -549,11 +550,13 @@ set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
549 const char *value) 550 const char *value)
550{ 551{
551 unsigned long long *val = scls; 552 unsigned long long *val = scls;
553 char dummy[2];
552 554
553 (void) ctx; 555 (void) ctx;
554 if (1 != SSCANF (value, 556 if (1 != SSCANF (value,
555 "%llu", 557 "%llu%1s",
556 val)) 558 val,
559 dummy))
557 { 560 {
558 FPRINTF (stderr, 561 FPRINTF (stderr,
559 _("You must pass a number to the `%s' option.\n"), 562 _("You must pass a number to the `%s' option.\n"),
@@ -746,6 +749,7 @@ set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
746 const char *value) 749 const char *value)
747{ 750{
748 unsigned int *val = scls; 751 unsigned int *val = scls;
752 char dummy[2];
749 753
750 (void) ctx; 754 (void) ctx;
751 if('-' == *value) 755 if('-' == *value)
@@ -756,8 +760,9 @@ set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
756 return GNUNET_SYSERR; 760 return GNUNET_SYSERR;
757 } 761 }
758 if (1 != SSCANF (value, 762 if (1 != SSCANF (value,
759 "%u", 763 "%u%1s",
760 val)) 764 val,
765 dummy))
761 { 766 {
762 FPRINTF (stderr, 767 FPRINTF (stderr,
763 _("You must pass a number to the `%s' option.\n"), 768 _("You must pass a number to the `%s' option.\n"),
@@ -820,11 +825,13 @@ set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
820{ 825{
821 uint16_t *val = scls; 826 uint16_t *val = scls;
822 unsigned int v; 827 unsigned int v;
828 char dummy[2];
823 829
824 (void) ctx; 830 (void) ctx;
825 if (1 != SSCANF (value, 831 if (1 != SSCANF (value,
826 "%u", 832 "%u%1s",
827 &v)) 833 &v,
834 dummy))
828 { 835 {
829 FPRINTF (stderr, 836 FPRINTF (stderr,
830 _("You must pass a number to the `%s' option.\n"), 837 _("You must pass a number to the `%s' option.\n"),
diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c
index d907bd8d9..3b871ce33 100644
--- a/src/util/gnunet-service-resolver.c
+++ b/src/util/gnunet-service-resolver.c
@@ -364,7 +364,7 @@ lookup_dns_servers (char ***server_addrs)
364 GNUNET_DISK_file_close (fh); 364 GNUNET_DISK_file_close (fh);
365 return -1; 365 return -1;
366 } 366 }
367 if (bytes_read > SIZE_MAX) 367 if ((size_t) bytes_read > SIZE_MAX)
368 { 368 {
369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
370 "/etc/resolv.conf file too large to mmap. " 370 "/etc/resolv.conf file too large to mmap. "
@@ -379,7 +379,7 @@ lookup_dns_servers (char ***server_addrs)
379 *server_addrs = NULL; 379 *server_addrs = NULL;
380 read_offset = 0; 380 read_offset = 0;
381 num_dns_servers = 0; 381 num_dns_servers = 0;
382 while (read_offset < bytes_read) 382 while (read_offset < (size_t) bytes_read)
383 { 383 {
384 const char *newline; 384 const char *newline;
385 size_t line_len; 385 size_t line_len;
@@ -648,11 +648,16 @@ try_cache (const char *hostname,
648 struct ResolveCache *pos; 648 struct ResolveCache *pos;
649 struct ResolveCache *next; 649 struct ResolveCache *next;
650 int found; 650 int found;
651 int in_hosts;
651 652
653 in_hosts = GNUNET_NO;
652 for (pos = hosts_head; NULL != pos; pos = pos->next) 654 for (pos = hosts_head; NULL != pos; pos = pos->next)
653 if (0 == strcmp (pos->hostname, 655 if (0 == strcmp (pos->hostname,
654 hostname)) 656 hostname))
657 {
658 in_hosts = GNUNET_YES;
655 break; 659 break;
660 }
656 if (NULL == pos) 661 if (NULL == pos)
657 { 662 {
658 next = cache_head; 663 next = cache_head;
@@ -673,7 +678,8 @@ try_cache (const char *hostname,
673 hostname); 678 hostname);
674 return GNUNET_NO; 679 return GNUNET_NO;
675 } 680 }
676 if (cache_head != pos) 681 if ( (GNUNET_NO == in_hosts) &&
682 (cache_head != pos) )
677 { 683 {
678 /* move result to head to achieve LRU for cache eviction */ 684 /* move result to head to achieve LRU for cache eviction */
679 GNUNET_CONTAINER_DLL_remove (cache_head, 685 GNUNET_CONTAINER_DLL_remove (cache_head,
@@ -1313,7 +1319,7 @@ extract_hosts (const char *line,
1313 if (NULL != c) 1319 if (NULL != c)
1314 line_len = c - line; 1320 line_len = c - line;
1315 /* ignore leading whitespace */ 1321 /* ignore leading whitespace */
1316 while ( (0 > line_len) && 1322 while ( (0 < line_len) &&
1317 isspace ((unsigned char) *line) ) 1323 isspace ((unsigned char) *line) )
1318 { 1324 {
1319 line++; 1325 line++;
@@ -1382,7 +1388,7 @@ load_etc_hosts (void)
1382 GNUNET_DISK_file_close (fh); 1388 GNUNET_DISK_file_close (fh);
1383 return; 1389 return;
1384 } 1390 }
1385 if (bytes_read > SIZE_MAX) 1391 if ((size_t) bytes_read > SIZE_MAX)
1386 { 1392 {
1387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1388 "/etc/hosts file too large to mmap. " 1394 "/etc/hosts file too large to mmap. "
@@ -1395,7 +1401,7 @@ load_etc_hosts (void)
1395 GNUNET_DISK_MAP_TYPE_READ, 1401 GNUNET_DISK_MAP_TYPE_READ,
1396 (size_t) bytes_read); 1402 (size_t) bytes_read);
1397 read_offset = 0; 1403 read_offset = 0;
1398 while (read_offset < bytes_read) 1404 while (read_offset < (size_t) bytes_read)
1399 { 1405 {
1400 const char *newline; 1406 const char *newline;
1401 size_t line_len; 1407 size_t line_len;
diff --git a/src/util/service.c b/src/util/service.c
index 20cc1036d..b61168570 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -1175,8 +1175,9 @@ setup_service (struct GNUNET_SERVICE_Handle *sh)
1175 const char *nfds; 1175 const char *nfds;
1176 unsigned int cnt; 1176 unsigned int cnt;
1177 int flags; 1177 int flags;
1178 char dummy[2];
1178#endif 1179#endif
1179 1180
1180 if (GNUNET_CONFIGURATION_have_value 1181 if (GNUNET_CONFIGURATION_have_value
1181 (sh->cfg, 1182 (sh->cfg,
1182 sh->service_name, 1183 sh->service_name,
@@ -1203,8 +1204,9 @@ setup_service (struct GNUNET_SERVICE_Handle *sh)
1203 errno = 0; 1204 errno = 0;
1204 if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) && 1205 if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1205 (1 == SSCANF (nfds, 1206 (1 == SSCANF (nfds,
1206 "%u", 1207 "%u%1s",
1207 &cnt)) && 1208 &cnt,
1209 dummy)) &&
1208 (cnt > 0) && 1210 (cnt > 0) &&
1209 (cnt < FD_SETSIZE) && 1211 (cnt < FD_SETSIZE) &&
1210 (cnt + 4 < FD_SETSIZE) ) 1212 (cnt + 4 < FD_SETSIZE) )
@@ -1813,8 +1815,9 @@ GNUNET_SERVICE_run_ (int argc,
1813 opt_cfg_filename = GNUNET_strdup (cfg_filename); 1815 opt_cfg_filename = GNUNET_strdup (cfg_filename);
1814 if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_filename)) 1816 if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_filename))
1815 { 1817 {
1816 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, 1818 if (GNUNET_SYSERR ==
1817 opt_cfg_filename)) 1819 GNUNET_CONFIGURATION_load (cfg,
1820 opt_cfg_filename))
1818 { 1821 {
1819 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1822 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1820 _("Malformed configuration file `%s', exit ...\n"), 1823 _("Malformed configuration file `%s', exit ...\n"),
@@ -1824,8 +1827,9 @@ GNUNET_SERVICE_run_ (int argc,
1824 } 1827 }
1825 else 1828 else
1826 { 1829 {
1827 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, 1830 if (GNUNET_SYSERR ==
1828 NULL)) 1831 GNUNET_CONFIGURATION_load (cfg,
1832 NULL))
1829 { 1833 {
1830 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1831 _("Malformed configuration, exit ...\n")); 1835 _("Malformed configuration, exit ...\n"));
diff --git a/src/util/strings.c b/src/util/strings.c
index b7a7fcb8b..3f85384e1 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -1262,6 +1262,7 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1262 int ret; 1262 int ret;
1263 char *port_colon; 1263 char *port_colon;
1264 unsigned int port; 1264 unsigned int port;
1265 char dummy[2];
1265 1266
1266 if (addrlen < 6) 1267 if (addrlen < 6)
1267 return GNUNET_SYSERR; 1268 return GNUNET_SYSERR;
@@ -1286,7 +1287,10 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1286 _("IPv6 address did contain ']' before ':' to separate port number\n")); 1287 _("IPv6 address did contain ']' before ':' to separate port number\n"));
1287 return GNUNET_SYSERR; 1288 return GNUNET_SYSERR;
1288 } 1289 }
1289 ret = SSCANF (port_colon, ":%u", &port); 1290 ret = SSCANF (port_colon,
1291 ":%u%1s",
1292 &port,
1293 dummy);
1290 if ( (1 != ret) || (port > 65535) ) 1294 if ( (1 != ret) || (port > 65535) )
1291 { 1295 {
1292 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1296 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1332,16 +1336,18 @@ GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
1332 unsigned int temps[4]; 1336 unsigned int temps[4];
1333 unsigned int port; 1337 unsigned int port;
1334 unsigned int cnt; 1338 unsigned int cnt;
1339 char dummy[2];
1335 1340
1336 if (addrlen < 9) 1341 if (addrlen < 9)
1337 return GNUNET_SYSERR; 1342 return GNUNET_SYSERR;
1338 cnt = SSCANF (zt_addr, 1343 cnt = SSCANF (zt_addr,
1339 "%u.%u.%u.%u:%u", 1344 "%u.%u.%u.%u:%u%1s",
1340 &temps[0], 1345 &temps[0],
1341 &temps[1], 1346 &temps[1],
1342 &temps[2], 1347 &temps[2],
1343 &temps[3], 1348 &temps[3],
1344 &port); 1349 &port,
1350 dummy);
1345 if (5 != cnt) 1351 if (5 != cnt)
1346 return GNUNET_SYSERR; 1352 return GNUNET_SYSERR;
1347 for (cnt = 0; cnt < 4; cnt++) 1353 for (cnt = 0; cnt < 4; cnt++)
@@ -1563,7 +1569,9 @@ parse_port_policy (const char *port_policy,
1563 } 1569 }
1564 if (2 == sscanf (pos, 1570 if (2 == sscanf (pos,
1565 "%u-%u%1s", 1571 "%u-%u%1s",
1566 &s, &e, eol)) 1572 &s,
1573 &e,
1574 eol))
1567 { 1575 {
1568 if ( (0 == s) || 1576 if ( (0 == s) ||
1569 (s > 0xFFFF) || 1577 (s > 0xFFFF) ||
@@ -1629,7 +1637,8 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1629 int colon; 1637 int colon;
1630 int end; 1638 int end;
1631 char *routeList; 1639 char *routeList;
1632 1640 char dummy[2];
1641
1633 if (NULL == routeListX) 1642 if (NULL == routeListX)
1634 return NULL; 1643 return NULL;
1635 len = strlen (routeListX); 1644 len = strlen (routeListX);
@@ -1664,7 +1673,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1664 } 1673 }
1665 cnt = 1674 cnt =
1666 SSCANF (&routeList[pos], 1675 SSCANF (&routeList[pos],
1667 "%u.%u.%u.%u/%u.%u.%u.%u", 1676 "%u.%u.%u.%u/%u.%u.%u.%u%1s",
1668 &temps[0], 1677 &temps[0],
1669 &temps[1], 1678 &temps[1],
1670 &temps[2], 1679 &temps[2],
@@ -1672,7 +1681,8 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1672 &temps[4], 1681 &temps[4],
1673 &temps[5], 1682 &temps[5],
1674 &temps[6], 1683 &temps[6],
1675 &temps[7]); 1684 &temps[7],
1685 dummy);
1676 if (8 == cnt) 1686 if (8 == cnt)
1677 { 1687 {
1678 for (j = 0; j < 8; j++) 1688 for (j = 0; j < 8; j++)
@@ -1698,12 +1708,13 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1698 /* try second notation */ 1708 /* try second notation */
1699 cnt = 1709 cnt =
1700 SSCANF (&routeList[pos], 1710 SSCANF (&routeList[pos],
1701 "%u.%u.%u.%u/%u", 1711 "%u.%u.%u.%u/%u%1s",
1702 &temps[0], 1712 &temps[0],
1703 &temps[1], 1713 &temps[1],
1704 &temps[2], 1714 &temps[2],
1705 &temps[3], 1715 &temps[3],
1706 &slash); 1716 &slash,
1717 dummy);
1707 if (5 == cnt) 1718 if (5 == cnt)
1708 { 1719 {
1709 for (j = 0; j < 4; j++) 1720 for (j = 0; j < 4; j++)
@@ -1747,11 +1758,12 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1747 slash = 32; 1758 slash = 32;
1748 cnt = 1759 cnt =
1749 SSCANF (&routeList[pos], 1760 SSCANF (&routeList[pos],
1750 "%u.%u.%u.%u", 1761 "%u.%u.%u.%u%1s",
1751 &temps[0], 1762 &temps[0],
1752 &temps[1], 1763 &temps[1],
1753 &temps[2], 1764 &temps[2],
1754 &temps[3]); 1765 &temps[3],
1766 dummy);
1755 if (4 == cnt) 1767 if (4 == cnt)
1756 { 1768 {
1757 for (j = 0; j < 4; j++) 1769 for (j = 0; j < 4; j++)
@@ -1826,7 +1838,8 @@ GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1826 unsigned int off; 1838 unsigned int off;
1827 int save; 1839 int save;
1828 int colon; 1840 int colon;
1829 1841 char dummy[2];
1842
1830 if (NULL == routeListX) 1843 if (NULL == routeListX)
1831 return NULL; 1844 return NULL;
1832 len = strlen (routeListX); 1845 len = strlen (routeListX);
@@ -1886,7 +1899,11 @@ GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1886 if (ret <= 0) 1899 if (ret <= 0)
1887 { 1900 {
1888 save = errno; 1901 save = errno;
1889 if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits > 128)) 1902 if ( (1 != SSCANF (&routeList[slash + 1],
1903 "%u%1s",
1904 &bits,
1905 dummy)) ||
1906 (bits > 128) )
1890 { 1907 {
1891 if (0 == ret) 1908 if (0 == ret)
1892 LOG (GNUNET_ERROR_TYPE_WARNING, 1909 LOG (GNUNET_ERROR_TYPE_WARNING,