- merge; service API change
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Fri, 20 Jan 2017 06:00:54 +0000 (07:00 +0100)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Fri, 20 Jan 2017 06:00:54 +0000 (07:00 +0100)
276 files changed:
AUTHORS
ChangeLog
README
configure.ac
contrib/.gitignore
contrib/no_forcestart.conf
contrib/ssh-config [new file with mode: 0644]
contrib/ssh-keys
doc/man/Makefile.am
doc/man/gnunet-nat-auto.1 [new file with mode: 0644]
doc/man/gnunet-nat.1
doc/man/gnunet-transport.1
doc/structure.dot
po/POTFILES.in
po/de.po
po/es.po
po/fr.po
po/sv.po
po/vi.po
po/zh_CN.po
src/Makefile.am
src/arm/.gitignore
src/arm/arm_api.c
src/arm/arm_monitor_api.c
src/arm/gnunet-arm.c
src/arm/test_exponential_backoff.c
src/ats-tests/.gitignore
src/ats-tests/ats-testing.c
src/ats-tests/ats-testing.h
src/ats/.gitignore
src/ats/ats_api_connectivity.c
src/ats/ats_api_performance.c
src/ats/ats_api_scheduling.c
src/auction/.gitignore [new file with mode: 0644]
src/auction/Makefile.am [new file with mode: 0644]
src/auction/auction.conf [new file with mode: 0644]
src/auction/auction.h [new file with mode: 0644]
src/auction/gnunet-auction-create.c [new file with mode: 0644]
src/auction/gnunet-auction-info.c [new file with mode: 0644]
src/auction/gnunet-auction-join.c [new file with mode: 0644]
src/auction/gnunet-service-auction.c [new file with mode: 0644]
src/auction/test_auction_api.c [new file with mode: 0644]
src/auction/test_auction_create.sh [new file with mode: 0755]
src/cadet/Makefile.am
src/cadet/cadet.h
src/cadet/cadet_api.c
src/cadet/cadet_common.c
src/cadet/cadet_protocol.h
src/cadet/gnunet-cadet.c
src/cadet/gnunet-service-cadet-new.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_channel.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_channel.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_connection.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_connection.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_core.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_core.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_dht.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_dht.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_hello.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_hello.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_paths.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_paths.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_peer.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_peer.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_tunnels.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_tunnels.h [new file with mode: 0644]
src/cadet/gnunet-service-cadet_channel.c
src/cadet/gnunet-service-cadet_channel.h
src/cadet/gnunet-service-cadet_connection.c
src/cadet/gnunet-service-cadet_connection.h
src/cadet/gnunet-service-cadet_dht.c
src/cadet/gnunet-service-cadet_hello.h
src/cadet/gnunet-service-cadet_local.c
src/cadet/gnunet-service-cadet_local.h
src/cadet/gnunet-service-cadet_peer.c
src/cadet/gnunet-service-cadet_peer.h
src/cadet/gnunet-service-cadet_tunnel.c
src/cadet/gnunet-service-cadet_tunnel.h
src/cadet/test_cadet.conf
src/cadet/test_cadet_local.c
src/consensus/consensus_api.c
src/conversation/conversation_api.c
src/conversation/conversation_api_call.c
src/core/.gitignore
src/core/Makefile.am
src/core/core_api.c
src/core/core_api_2.c [deleted file]
src/core/core_api_monitor_peers.c
src/core/core_api_mq.c [deleted file]
src/core/test_core_api.c
src/core/test_core_api_reliability.c
src/core/test_core_api_send_to_self.c
src/core/test_core_api_start_only.c
src/core/test_core_defaults.conf
src/core/test_core_quota_compliance.c
src/credential/credential_api.c
src/datacache/.gitignore [new file with mode: 0644]
src/datacache/plugin_datacache_heap.c
src/datastore/.gitignore
src/datastore/datastore_api.c
src/datastore/plugin_datastore_heap.c
src/dht/.gitignore
src/dht/Makefile.am
src/dht/dht_api.c
src/dht/gnunet-service-dht_hello.c
src/dht/gnunet-service-dht_neighbours.c
src/dht/gnunet-service-dht_routing.c
src/dht/gnunet-service-wdht_neighbours.c
src/dht/gnunet-service-xdht_neighbours.c
src/dht/plugin_block_dht.c
src/dns/.gitignore
src/dns/dns_api.c
src/dv/dv_api.c
src/dv/gnunet-service-dv.c
src/exit/gnunet-daemon-exit.c
src/fragmentation/.gitignore [new file with mode: 0644]
src/fs/fs_download.c
src/fs/fs_list_indexed.c
src/fs/fs_publish.c
src/fs/fs_search.c
src/fs/fs_unindex.c
src/fs/gnunet-service-fs.c
src/gns/gns.conf.in
src/gns/gns_api.c
src/gns/gnunet-service-gns.c
src/gns/gnunet-service-gns_reverser.c
src/gnsrecord/.gitignore [new file with mode: 0644]
src/hello/.gitignore
src/hostlist/.gitignore
src/hostlist/gnunet-daemon-hostlist.c
src/hostlist/gnunet-daemon-hostlist_client.c
src/hostlist/gnunet-daemon-hostlist_client.h
src/hostlist/gnunet-daemon-hostlist_server.c
src/hostlist/gnunet-daemon-hostlist_server.h
src/hostlist/test_gnunet_daemon_hostlist_learning.c
src/identity-provider/identity_provider_api.c
src/identity/.gitignore
src/identity/identity_api.c
src/include/Makefile.am
src/include/gnunet_cadet_service.h
src/include/gnunet_client_lib.h
src/include/gnunet_common.h
src/include/gnunet_constants.h
src/include/gnunet_container_lib.h
src/include/gnunet_core_service.h
src/include/gnunet_crypto_lib.h
src/include/gnunet_mq_lib.h
src/include/gnunet_nat_auto_service.h [new file with mode: 0644]
src/include/gnunet_nat_lib.h [deleted file]
src/include/gnunet_nat_service.h
src/include/gnunet_peerinfo_service.h
src/include/gnunet_protocols.h
src/include/gnunet_signatures.h
src/json/.gitignore [new file with mode: 0644]
src/jsonapi/.gitignore [new file with mode: 0644]
src/multicast/gnunet-service-multicast.c
src/multicast/multicast_api.c
src/my/.gitignore [new file with mode: 0644]
src/namecache/.gitignore
src/namecache/namecache_api.c
src/namestore/.gitignore
src/namestore/namestore_api.c
src/namestore/namestore_api_monitor.c
src/nat-auto/.gitignore [new file with mode: 0644]
src/nat-auto/Makefile.am [new file with mode: 0644]
src/nat-auto/gnunet-nat-auto.c [new file with mode: 0644]
src/nat-auto/gnunet-nat-auto_legacy.c [new file with mode: 0644]
src/nat-auto/gnunet-nat-server.c [new file with mode: 0644]
src/nat-auto/gnunet-service-nat-auto.c [new file with mode: 0644]
src/nat-auto/gnunet-service-nat-auto_legacy.c [new file with mode: 0644]
src/nat-auto/nat-auto.conf.in [new file with mode: 0644]
src/nat-auto/nat-auto.h [new file with mode: 0644]
src/nat-auto/nat_auto_api.c [new file with mode: 0644]
src/nat-auto/nat_auto_api_test.c [new file with mode: 0644]
src/nat/Makefile.am
src/nat/gnunet-nat-server.c [deleted file]
src/nat/gnunet-nat.c
src/nat/gnunet-service-nat.c
src/nat/gnunet-service-nat.h [new file with mode: 0644]
src/nat/gnunet-service-nat_externalip.c [new file with mode: 0644]
src/nat/gnunet-service-nat_externalip.h [new file with mode: 0644]
src/nat/gnunet-service-nat_helper.c
src/nat/gnunet-service-nat_mini.h
src/nat/nat.c [deleted file]
src/nat/nat.conf.in
src/nat/nat.h
src/nat/nat_api.c
src/nat/nat_api_stun.c
src/nat/nat_api_test.c [deleted file]
src/nat/nat_auto.c [deleted file]
src/nat/nat_mini.c [deleted file]
src/nat/nat_stun.c [deleted file]
src/nat/nat_test.c [deleted file]
src/nse/.gitignore
src/nse/gnunet-service-nse.c
src/nse/nse_api.c
src/peerinfo-tool/.gitignore
src/peerinfo-tool/Makefile.am
src/peerinfo/.gitignore
src/peerinfo/peerinfo_api.c
src/peerinfo/peerinfo_api_notify.c
src/peerstore/.gitignore
src/peerstore/peerstore_api.c
src/pq/.gitignore [new file with mode: 0644]
src/psyc/psyc_api.c
src/psycstore/gnunet-service-psycstore.c
src/psycstore/psycstore_api.c
src/regex/.gitignore
src/regex/regex_api_announce.c
src/regex/regex_api_search.c
src/revocation/gnunet-service-revocation.c
src/revocation/revocation_api.c
src/revocation/test_revocation.c
src/rps/rps_api.c
src/scalarproduct/scalarproduct_api.c
src/secretsharing/secretsharing_api.c
src/set/Makefile.am
src/set/set_api.c
src/social/gnunet-social.c
src/social/social_api.c
src/statistics/.gitignore
src/statistics/statistics_api.c
src/template/.gitignore
src/testbed-logger/.gitignore
src/testbed-logger/testbed_logger_api.c
src/testbed/.gitignore
src/testbed/gnunet-service-testbed_connectionpool.c
src/testbed/testbed_api.c
src/testbed/testbed_api_barriers.c
src/testing/.gitignore
src/topology/.gitignore
src/topology/gnunet-daemon-topology.c
src/transport/.gitignore
src/transport/Makefile.am
src/transport/gnunet-service-transport_neighbours.c
src/transport/gnunet-transport.c
src/transport/plugin_transport_http_server.c
src/transport/plugin_transport_tcp.c
src/transport/plugin_transport_udp.c
src/transport/plugin_transport_udp.h
src/transport/plugin_transport_udp_broadcasting.c
src/transport/transport.conf.in
src/transport/transport_api_address_to_string.c
src/transport/transport_api_blacklist.c
src/transport/transport_api_core.c
src/transport/transport_api_hello_get.c
src/transport/transport_api_manipulation.c
src/transport/transport_api_monitor_peers.c
src/transport/transport_api_monitor_plugins.c
src/transport/transport_api_offer_hello.c
src/tun/.gitignore [new file with mode: 0644]
src/util/.gitignore
src/util/Makefile.am
src/util/client.c [new file with mode: 0644]
src/util/client_new.c [deleted file]
src/util/common_logging.c
src/util/container_heap.c
src/util/container_multishortmap.c [new file with mode: 0644]
src/util/mq.c
src/util/resolver_api.c
src/util/test_client.c
src/util/test_container_heap.c
src/util/test_server.c
src/util/test_server_disconnect.c
src/util/test_server_with_client.c
src/util/test_server_with_client_unix.c
src/util/test_service.c
src/util/test_socks.c
src/vpn/gnunet-service-vpn.c
src/vpn/vpn.conf.in
src/vpn/vpn_api.c
src/zonemaster/.gitignore [new file with mode: 0644]
src/zonemaster/Makefile.am [new file with mode: 0644]
src/zonemaster/gnunet-service-zonemaster.c [new file with mode: 0644]
src/zonemaster/zonemaster.conf.in [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index 24314e1c6fc7e587b0718813cca1c87b028f8447..f5ec48bc66def0cbf680187df4cc6bff7a3b7b6b 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -36,7 +36,7 @@ Antti Salonen
 Blake Matheny <bmatheny@mobocracy.net>
 Bertrand Marc <beberking@gmail.com>
 Clytie Siddall <clytie@riverland.net.au>
-Daniel Golle
+Daniel Golle <daniel@makrotopia.org>
 David Brodski
 David Kuehling <dvdkhlng@gmx.de>
 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
@@ -110,8 +110,8 @@ new GNU in Net: Nicklas Larsson <whybill@gmail.com>
 Maintainers:
 FreeBSD         : Kirill Ponomarew <ponomarew@oberon.net>
 Debian GNU/Linux: Daniel Baumann <daniel.baumann@panthera-systems.net>
+OpenWrt/LEDE    : Daniel Golle <daniel@makrotopia.org>
 OS X            : Jussi Eloranta <eloranta@cc.jyu.fi>
-Gentoo          : N. 'ng0' Gillmann <ngillmann@runbox.com>
 
 
 If you have contributed and are not listed here, please
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a44065ec22c1e156ef49d31872b197753285e7d9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -0,0 +1,3 @@
+Sat Jan  7 16:41:34 CET 2017
+       Converting NAT library to new NAT service (and
+       splitting of nat-auto service for auto-configuration). -CG
diff --git a/README b/README
index 9f260a94057c33f7896ede3d40d88a03e325e35d..a72d8b3b828d91e41dc9b8f90f5fd0ac8fb5aafa 100644 (file)
--- a/README
+++ b/README
@@ -4,13 +4,16 @@
 What is GNUnet?
 ===============
 
-GNUnet is peer-to-peer framework focusing on security.  The first and
-primary application for GNUnet is anonymous file-sharing.  GNUnet is
-currently developed by a worldwide group of independent free software
-developers.  GNUnet is a GNU package (http://www.gnu.org/).
+GNUnet is peer-to-peer framework providing a network abstractions and
+applications focusing on security and privacy.  So far, we have
+created applications for anonymous file-sharing, decentralized naming
+and identity management, decentralized and confidential telephony and
+tunneling IP traffic over GNUnet.  GNUnet is currently developed by a
+worldwide group of independent free software developers.  GNUnet is a
+GNU package (http://www.gnu.org/).
 
 This is an ALPHA release.  There are known and significant bugs as
-well as many missing features in this release.
+well as many missing features in this release.  
 
 Additional documentation about GNUnet can be found at
 https://gnunet.org/.
@@ -80,7 +83,7 @@ actual GNUnet compilation and installation process with:
 
 $ export GNUNET_PREFIX=/usr/local/lib # or other directory of your choice
 # addgroup gnunetdns
-# adduser gnunet gnunet
+# adduser --system --home "/var/lib/gnunet" --group gnunet --shell /bin/sh
 # ./configure --prefix=$GNUNET_PREFIX/.. --with-extractor=$LE_PREFIX
 $ make
 # make install
index 761086e32d9707b7f3a8333dd6febf5f97bf63be..924b06849caf6277ce523a0b6786c56a5c8debf2 100644 (file)
@@ -1551,6 +1551,7 @@ src/ats/Makefile
 src/ats/ats.conf
 src/ats-tool/Makefile
 src/ats-tests/Makefile
+src/auction/Makefile
 src/block/Makefile
 src/cadet/Makefile
 src/cadet/cadet.conf
@@ -1598,6 +1599,8 @@ src/namestore/Makefile
 src/namestore/namestore.conf
 src/nat/Makefile
 src/nat/nat.conf
+src/nat-auto/Makefile
+src/nat-auto/nat-auto.conf
 src/nse/Makefile
 src/nse/nse.conf
 src/peerinfo/Makefile
@@ -1643,6 +1646,8 @@ src/util/Makefile
 src/util/resolver.conf
 src/vpn/Makefile
 src/vpn/vpn.conf
+src/zonemaster/Makefile
+src/zonemaster/zonemaster.conf
 src/rest/Makefile
 src/identity-provider/Makefile
 pkgconfig/Makefile
@@ -1727,6 +1732,12 @@ then
   AC_MSG_NOTICE([NOTICE: bluetooth library not found.  bluetooth support will not be compiled.])
 fi
 
+# jansson
+if test "x$jansson" = "x0"
+then
+  AC_MSG_NOTICE([NOTICE: jansson library not found.  json support will not be compiled.])
+fi
+
 #gnutls
 if test x$gnutls != xtrue
 then
index d8a442c35ca22b875e1b88031e4f0a7c65e9a5aa..50dd6d9fc6021e1b13c166cf2d0cce7f4c3cbfd2 100644 (file)
@@ -3,3 +3,5 @@ gnunet_pyexpect.py
 pydiffer.py
 terminate.py
 timeout_watchdog
+gnunet_pyexpect.py
+gnunet_pyexpect.pyc
index 7de3f15095a4d7b2b6fc65a4e03cebeeb7d2f523..e21187ed21d18cb18a155027f73cfdf709a34774 100644 (file)
@@ -33,3 +33,6 @@ FORCESTART = NO
 
 [gns]
 FORCESTART = NO
+
+[zonemaster]
+FORCESTART = NO
\ No newline at end of file
diff --git a/contrib/ssh-config b/contrib/ssh-config
new file mode 100644 (file)
index 0000000..857354b
--- /dev/null
@@ -0,0 +1,33 @@
+# ~/.ssh/config for buildbots
+
+Host *.buildbot.gnunet
+  User root
+
+Host debian-amd64-grothoff.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20004
+
+Host debian-i686-wachs.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20000
+
+Host ubuntu-amd64-wachs.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20003
+
+Host opensuse-amd64-wachs.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20002
+
+Host freebsd-amd64-wachs.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20006
+
+Host debian-powerpc-wachs.buildbot.gnunet
+  Hostname powerpcbot.decentralise.rennes.inria.fr
+
+Host debian-armv7l-evans.buildbot.gnunet
+  Hostname efikamxbot.decentralise.rennes.inria.fr
+
+Host debian-sparc64-wachs.buildbot.gnunet
+  Hostname sparcbot.decentralise.rennes.inria.fr
index 6d4ed354e84281c23e0c3f062129afc01825f4c9..7c273e6881204ba96a0e0352801a53a02e48938c 100644 (file)
@@ -16,3 +16,4 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqlkUztOQ65gRvfxI6gwkP+095eEEc5DtHzZd1x9e7
 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQ2JbS5dNBxiSRGeNIE+VvvJBUStgndjduH2HmGyy7Z7VGNrykSDgjkcLj1+808zWzkniUZTUKvH5uT4rjSYrc8Au2l65e+J6gYypaOhn7oQKW9KQ3P7K8VpHSc407iQk0fM6bmpRKcd5GK0U6mlpi3nKvPhd9JttwfeNF6HWo4goCuYXdnLmWIimP6BBg6dZRBqO0y00bjSlMJmHnlQXI3YUBvceB3tBe6hOaEx5X3pCpE9CPaAUp6pAohHv97k6Dq7OcXeJulDaHKYvEGTCOq5v3V4zSYH4tJCrAO5OL83fsoAwn70l2qy+BkuThhiud2cff/jL1gB1+oU06s42N bart@voyager
 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC4/0jIkaaWtGolhWJPijpaPA1QHeQNlaZTc3wlCr/PGnFxY/TfXMKwEFX+JBvtYAuBsD+NXshKUssFtDSSQ5ljqbjGfA1SFv7ueRcuEVfg8MSTic7crHo23afjYWC9GND0LFDwy8IGrT6QtmbOV1cACTDk3GRcFT3wK2ZsTYAlsq7o+TTfD6A2OncqQGyIrgZl+eNx3je19xQ6OK+RTOXhvsNx77IdOluNkItAS8XEJpqnrYAqrqrtX5eyzHkwmPvu/gxrjO55YuXXXj4yramy5j++SkjH1y1XXMdAl1zNsDwT4U0/bNLm/0vvMQ8qgEVOak6vq+Qw0iyIyJP6RFI/J2S/mISCGyasAWULynhFP0DaCwFkFOnn3tv+A+caoxYKUU3nD+zD2q04FaIaOastTbDfeUSseHeKX08mSHxcPd/alYKcXA+Qm9SWsHGHJ8PAMPJNOcMwtkgGDKKzKJLW6CTUIEgl9BZXs0GXv1erAYu7zqNCRU/PWIKV2J509sk65dkykDRDkHMJ1esG+2Rg094hbNHsB4uoRZjlibS/9WYEOdn1eLt2xAvMXa1Vs8RpysMfv98zJabz8+mADf5u1prLGk9zSQA7akVoFe6OLqnQBVJr1E5simMZaCqZBYbYfgTveo8xtPZw7NDcH6/xrV2j0sN2xGHfkRFpuMpnCQ== burdges@gmail.com
 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4UL53uXZCis1C9VNWJjVXTtyRHVmzFmg3vajTXrRF6LBYpEtDRA3OCtzCsj88AlL2VEtIiBWBqZrntE0TKDia1Czru3sM1ieKCra1F1GlSj4Yk+7VaRSS1hGwMBUb0zyaiIHjizGH45+zL5TXeAiGbeiF/iiRJJG/qQ+txTXVg51QLuMv9W5wKs9Dz+o+vbbUwVaauJo/TmhVz1VFjqhQBOt9N/CtaTe84B1716/d/YTZLH1bmjxMja+a6aCyABaPM5JcMNYEZT2UMCP5fTyJRUpfNlimpdRkcxaA5/K8AKTW7R35cQpLrngnnOChUB+KT6683omDr2edXGqkWNsZ grothoff@firefly
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvbeMnZGlujN9IsLxUSTuHBUESoN6ZTXmEFi/GkBKp9RQ7xZAS84JDcV0GFddiCfTHGQL04mkeYXkof5d9NkMWjtTvQ9QFtUgGOqI3PbGCGW83vSwJHsqVbfbv5uqFCODjpTx4/WiJNkEpN/HgE2eIYFcm+Dcpo1vTgC26LjdMfqUaAGv/OTmKWmaMqyOzc4MXuUiBQT83oTfn2zSWDEOJG67yULqg5jMzaXqzPbhsaokBIPehks0bJR/q7OWNwDQJyM1oTKeRIh0ZmC0qYwGu/vlc3rYW4cp//ErAXG5iPfCXXUySUc0DTFHazzkNzUStuUwugznxuUCgbvg2tu5WEnrh/PpzIMuvNaUk2ZSDq00hHDrpVJyKKCih2d1cGV+qs9XFjDoD6Ch2NiSdPnG7fSsTxVw1SB7/APuMqfXWrQDfT5ee5xOKGzKOxQckGihQi39kmqf4WjNESOw4tmhNFZOee9dpC7ESYSpG/3zK8WG6FDln1nU6rHGjVgaSK6HwZUOsneS2fntiQZR2olzEY9+ybL1vh1fk6pkhS78X/PiwS3cSiu4q7JWJ4tUiB0T/cHAFBaODDKHXmEaGefLrPBWLLFRdjbnepWo1d0k1z/NLVovXDCGlF4IOBKqcImIffods/jTpH0hjU/vBjIQHH3Ii0J6vtGJw9whcNAGQfw== t3sserakt@posteo.de
index ff1e462b777e08de49f52cb335f17394f94cebe5..c40363b59b51a7ba87cbb49e9ca495be65640be6 100644 (file)
@@ -25,6 +25,7 @@ man_MANS = \
   gnunet-namestore.1 \
   gnunet-namestore-fcfsd.1 \
   gnunet-nat.1 \
+  gnunet-nat-auto.1 \
   gnunet-nat-server.1 \
   gnunet-peerinfo.1 \
   gnunet-publish.1 \
diff --git a/doc/man/gnunet-nat-auto.1 b/doc/man/gnunet-nat-auto.1
new file mode 100644 (file)
index 0000000..249d54d
--- /dev/null
@@ -0,0 +1,69 @@
+.TH GNUNET\-NAT\-AUTO 1 "6 Jan 2017" "GNUnet"
+
+.SH NAME
+gnunet\-nat\-auto \- autoconfigure and test NAT traversal
+
+.SH SYNOPSIS
+.B gnunet\-nat\-auto
+.RI [ options ]
+.br
+
+.SH DESCRIPTION
+
+This tool allows testing various NAT traversal functions, as well
+as attempting auto\-configuration.
+
+.SH OPTIONS
+.B
+.IP "\-a,  \-\-auto"
+Attempt auto\-configuration for NAT traversal.
+
+.B
+.IP "\-c FILENAME,  \-\-config=FILENAME"
+Use the configuration file FILENAME.
+
+.B
+.IP "\-S NAME,  \-\-section=NAME"
+Name of the configuration section with details about the configuration to test. For example "transport-tcp".
+
+.IP "\-t,  \-\-tcp"
+Use TCP.
+
+.B
+.IP "\-u,  \-\-udp"
+Use UDP.
+
+.B
+.IP "\-w,  \-\-write"
+Write configuration to configuration file, useful in combination with autoconfiguration (\-a).
+
+.SH EXAMPLES
+.PP
+
+\fBAutomatic configuration:\fR
+
+Probe and write result to configuration:
+
+  # gnunet\-nat\-auto \-aw
+
+
+\fBTest configuration:\fR
+
+Test TCP configuration:
+
+  # gnunet\-nat\-auto -t \-S transport-tcp
+
+Test HTTP configuration:
+
+  # gnunet\-nat\-auto -t \-S transport-http
+
+Test UDP configuration:
+
+  # gnunet\-nat\-auto -u \-S transport-udp
+
+
+.SH BUGS
+Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <gnunet\-developers@gnu.org>
+
+.SH SEE ALSO
+gnunet\-transport(1) gnunet\-nat(1)
index 5bdbb21eb33fc6d12a0d84aa8b06907995b49728..0a9053444c7bece8173ae252c52428a4ae80682c 100644 (file)
@@ -14,9 +14,6 @@ This tool allows testing various NAT traversal functions, as well
 as attempting auto\-configuration.
 
 .SH OPTIONS
-.B
-.IP "\-a,  \-\-auto"
-Attempt auto\-configuration for NAT traversal.
 
 .B
 .IP "\-b ADDRESS,  \-\-bind=ADDRESS"
@@ -39,8 +36,8 @@ Assuming we are listening at ADDRESS for connection reversal requests.
 Ask the peer at ADDRESS for connection reversal, using the local address for the target address of the reversal.
 
 .B
-.IP "\-p ADDRESS,  \-\-punch=ADDRESS"
-A hole was punched manually through the NAT. We should use ADDRESS as our external hostname and port for advertising for incoming requests. The special hostname 'AUTO' can be used to indicate that GNUnet should determine the external IP address by other means (such as upnpc), and just take the port number from ADDRESS.
+.IP "\-S NAME,  \-\-section=NAME"
+Name of section in configuration file to use for additional options.
 
 .B
 .IP "\-s,  \-\-stun"
@@ -54,10 +51,6 @@ Use TCP.
 .IP "\-u,  \-\-udp"
 Use UDP.
 
-.B
-.IP "\-w,  \-\-write"
-Write configuration to configuration file, useful in combination with autoconfiguration (\-a).
-
 .B
 .IP "\-W,  \-\-watch"
 Watch for connection reversal requests.  
@@ -81,13 +74,17 @@ We are bound to "127.0.0.1:8080" on UDP and want to obtain all applicable IP add
 
 \fBICMP-based NAT traversal:\fR
 
-Watch for connection reversal request:
+Watch for connection reversal request (you must be bound to NAT range or to wildcard, 0.0.0.0), only works for IPv4:
+
+  # gnunet-nat -Wt -i 192.168.178.12:8080
 
-  # gnunet-nat FIXME
+Initiate connection reversal request from peer at external IPv4 address 1.2.3.4, while we are running ourselves at 2.3.4.5:8080 (must use IPv4 addresses):
 
-Initiate connection reversal request:
+  # gnunet-nat -t -r 1.2.3.4:8080 -i 2.3.4.5:8080
 
-  # gnunet-nat FIXME
+Initiate connection reversal request from peer at external IPv4 address 1.2.3.4, and let the kernel fill in whatever IPv4 address we happen to have:
+
+  # gnunet-nat -t -r 1.2.3.4:8080 -i 0.0.0.0:8080 
 
 \fBManual hole punching:\fR
 
@@ -101,12 +98,6 @@ XXX:
 
   # gnunet-nat FIXME -s
 
-\fBAutomatic configuration:\fR
-
-Probe and write result to configuration:
-
-  # gnunet-nat -aw
-  
 
 .SH BUGS
 Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <gnunet\-developers@gnu.org>
index 6914481577557565ce47ffc6a981db7647ebea62..1680f9cf7503958e6beff04f846151eb7703ed48 100644 (file)
@@ -48,9 +48,6 @@ monitor session state of transport plugins
 \fB\-s\fR, \fB\-\-send\fR
 transmit (dummy) traffic as quickly as possible to the peer specified with the \-p option.  The rate will still be limited by the quota(s) determined by the peers (ATS subsystem).  Will run until CTRL\-C is pressed or until the connection to the other peer is disrupted.
 .TP
-\fB\-t\fR, \fB\-\-test\fR
-test transport configuration.  With this flag, the tool will check if each of the configured transport plugins has a working address.  Plugins that do not have a listen port configured will be ignored.  The test is performed with the help of an external server (by default running on gnunet.org) which tries to contact the local machine.  The test can only work if the local GNUnet peer is not yet running.
-.TP
 \fB\-v\fR, \fB\-\-version\fR
 print the version number
 .TP
index 2a30c7c17a5c0ca584b6065619d1e4332196d342..e244d20b8262d43d0c84a4c4a81ea5f982d2674e 100644 (file)
@@ -41,8 +41,9 @@ splines = true;
   dv -> ats;
   dns -> tun;
   dns -> dnsstub;
-  gns [shape=house];
-  gns -> namestore;
+  zonemaster [shape=house];
+  zonemaster -> namestore;
+  zonemaster -> dht;
   gns -> dns;
   gns -> dht;
   gns -> block [style=dotted,color=blue];
index b3cc2b3ee7ed606f4ae9bcae028c214c5d7e39c5..eb78c2ec6c7c73f33bb6bafdaad547e6a7a80c3c 100644 (file)
@@ -28,6 +28,10 @@ src/ats-tests/ats-testing-traffic.c
 src/ats-tests/gnunet-ats-sim.c
 src/ats-tests/gnunet-solver-eval.c
 src/ats-tool/gnunet-ats.c
+src/auction/gnunet-auction-create.c
+src/auction/gnunet-auction-info.c
+src/auction/gnunet-auction-join.c
+src/auction/gnunet-service-auction.c
 src/block/block.c
 src/block/plugin_block_template.c
 src/block/plugin_block_test.c
@@ -62,10 +66,8 @@ src/conversation/gnunet-service-conversation.c
 src/conversation/microphone.c
 src/conversation/plugin_gnsrecord_conversation.c
 src/conversation/speaker.c
-src/core/core_api_2.c
 src/core/core_api.c
 src/core/core_api_monitor_peers.c
-src/core/core_api_mq.c
 src/core/gnunet-core.c
 src/core/gnunet-service-core.c
 src/core/gnunet-service-core_kx.c
@@ -241,23 +243,25 @@ src/namestore/plugin_namestore_flat.c
 src/namestore/plugin_namestore_postgres.c
 src/namestore/plugin_namestore_sqlite.c
 src/namestore/plugin_rest_namestore.c
+src/nat-auto/gnunet-nat-auto.c
+src/nat-auto/gnunet-nat-auto_legacy.c
+src/nat-auto/gnunet-nat-server.c
+src/nat-auto/gnunet-service-nat-auto.c
+src/nat-auto/gnunet-service-nat-auto_legacy.c
+src/nat-auto/nat_auto_api.c
+src/nat-auto/nat_auto_api_test.c
 src/nat/gnunet-helper-nat-client.c
 src/nat/gnunet-helper-nat-client-windows.c
 src/nat/gnunet-helper-nat-server.c
 src/nat/gnunet-helper-nat-server-windows.c
 src/nat/gnunet-nat.c
-src/nat/gnunet-nat-server.c
 src/nat/gnunet-service-nat.c
+src/nat/gnunet-service-nat_externalip.c
 src/nat/gnunet-service-nat_helper.c
+src/nat/gnunet-service-nat_mini.c
 src/nat/gnunet-service-nat_stun.c
 src/nat/nat_api.c
 src/nat/nat_api_stun.c
-src/nat/nat_api_test.c
-src/nat/nat_auto.c
-src/nat/nat.c
-src/nat/nat_mini.c
-src/nat/nat_stun.c
-src/nat/nat_test.c
 src/nse/gnunet-nse.c
 src/nse/gnunet-nse-profiler.c
 src/nse/gnunet-service-nse.c
@@ -422,7 +426,7 @@ src/tun/regex.c
 src/tun/tun.c
 src/util/bandwidth.c
 src/util/bio.c
-src/util/client_new.c
+src/util/client.c
 src/util/common_allocation.c
 src/util/common_endian.c
 src/util/common_logging.c
@@ -493,6 +497,7 @@ src/vpn/gnunet-helper-vpn-windows.c
 src/vpn/gnunet-service-vpn.c
 src/vpn/gnunet-vpn.c
 src/vpn/vpn_api.c
+src/zonemaster/gnunet-service-zonemaster.c
 src/fs/fs_api.h
 src/include/gnunet_common.h
 src/include/gnunet_mq_lib.h
index 58a71e4f7557bd1ec1ad3eb81b6c563b10b977f8..037a902885ff5ee63d01f5a3e2e0d63cb03ce1ca 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -10,7 +10,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.10.1\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2016-11-27 09:18+0100\n"
+"POT-Creation-Date: 2017-01-12 17:19+0100\n"
 "PO-Revision-Date: 2015-03-08 16:16+0100\n"
 "Last-Translator: Mario Blättermann <mario.blaettermann@gmail.com>\n"
 "Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
@@ -252,21 +252,20 @@ msgstr ""
 #: src/arm/gnunet-service-arm.c:393 src/arm/gnunet-service-arm.c:399
 #: src/transport/plugin_transport_tcp.c:652
 #: src/transport/plugin_transport_tcp.c:658
-#: src/transport/plugin_transport_tcp.c:3299 src/util/service.c:584
-#: src/util/service.c:590 src/util/service_new.c:637
-#: src/util/service_new.c:643
+#: src/transport/plugin_transport_tcp.c:3309 src/util/service.c:584
+#: src/util/service.c:590 src/util/service_new.c:637 src/util/service_new.c:643
 #, c-format
 msgid "Require valid port number for service `%s' in configuration!\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:430 src/transport/plugin_transport_tcp.c:689
-#: src/util/client_new.c:464 src/util/service.c:621 src/util/service_new.c:682
+#: src/util/client.c:464 src/util/service.c:621 src/util/service_new.c:682
 #, c-format
 msgid "UNIXPATH `%s' too long, maximum length is %llu\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:434 src/transport/plugin_transport_tcp.c:693
-#: src/util/client_new.c:469 src/util/service.c:625 src/util/service_new.c:687
+#: src/util/client.c:469 src/util/service.c:625 src/util/service_new.c:687
 #, c-format
 msgid "Using `%s' instead\n"
 msgstr ""
@@ -286,7 +285,7 @@ msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:513
-#: src/transport/plugin_transport_http_server.c:2617
+#: src/transport/plugin_transport_http_server.c:2620
 #: src/transport/plugin_transport_tcp.c:772 src/util/service.c:704
 #: src/util/service_new.c:782
 #, c-format
@@ -294,7 +293,7 @@ msgid "Failed to resolve `%s': %s\n"
 msgstr "»%s« konnte nicht aufgelöst werden: %s\n"
 
 #: src/arm/gnunet-service-arm.c:532
-#: src/transport/plugin_transport_http_server.c:2635
+#: src/transport/plugin_transport_http_server.c:2638
 #: src/transport/plugin_transport_tcp.c:791 src/util/service.c:723
 #: src/util/service_new.c:802
 #, fuzzy, c-format
@@ -388,13 +387,11 @@ msgid ""
 "%llu\n"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3293
-#: src/ats-tests/gnunet-solver-eval.c:935
+#: src/ats/gnunet-ats-solver-eval.c:3293 src/ats-tests/gnunet-solver-eval.c:935
 msgid "solver to use"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3296
-#: src/ats-tests/gnunet-solver-eval.c:938
+#: src/ats/gnunet-ats-solver-eval.c:3296 src/ats-tests/gnunet-solver-eval.c:938
 #: src/ats-tests/gnunet-solver-eval.c:941
 msgid "experiment to use"
 msgstr ""
@@ -499,12 +496,12 @@ msgstr ""
 msgid "Invalid %s configuration %f\n"
 msgstr " gconfig\tGTK Konfiguration\n"
 
-#: src/ats-tests/ats-testing.c:441
+#: src/ats-tests/ats-testing.c:422
 #, c-format
 msgid "Connected master [%u] with slave [%u]\n"
 msgstr ""
 
-#: src/ats-tests/ats-testing.c:448
+#: src/ats-tests/ats-testing.c:429
 #, fuzzy, c-format
 msgid "Failed to connect master peer [%u] with slave [%u]\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
@@ -561,7 +558,7 @@ msgid "Quota for network `%11s' (in/out): %10s / %10s\n"
 msgstr ""
 
 #: src/ats-tool/gnunet-ats.c:748 src/ats-tool/gnunet-ats.c:761
-#: src/transport/gnunet-transport.c:1476
+#: src/transport/gnunet-transport.c:1255
 #, fuzzy, c-format
 msgid "Failed to parse peer identity `%s'\n"
 msgstr "Fehler beim Parsen der Gerätedaten von `%s' bei %s:%d.\n"
@@ -643,6 +640,37 @@ msgstr ""
 msgid "Print information about ATS state"
 msgstr "Informationen über andere GNUnet Knoten ausgeben."
 
+#: src/auction/gnunet-auction-create.c:69
+msgid "description of the item to be sold"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:72
+msgid "mapping of possible prices"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:75
+msgid "max duration per round"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:78
+msgid "duration until auction starts"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:81
+msgid "number of items to sell, 0 for first price auction"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:84
+msgid "public auction outcome"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:94 src/auction/gnunet-auction-info.c:76
+#: src/auction/gnunet-auction-join.c:76
+#: src/conversation/gnunet-conversation-test.c:243
+#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
+msgid "help text"
+msgstr "Hilfetext"
+
 #: src/cadet/gnunet-cadet.c:511
 #, fuzzy, c-format
 msgid "Invalid target `%s'\n"
@@ -697,7 +725,7 @@ msgstr ""
 msgid "provide information about all tunnels"
 msgstr "Informationen über andere GNUnet Knoten ausgeben."
 
-#: src/cadet/gnunet-service-cadet_peer.c:681
+#: src/cadet/gnunet-service-cadet_peer.c:686
 msgid "Wrong CORE service\n"
 msgstr ""
 
@@ -1020,11 +1048,6 @@ msgid ""
 "played back to you..."
 msgstr ""
 
-#: src/conversation/gnunet-conversation-test.c:243
-#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
-msgid "help text"
-msgstr "Hilfetext"
-
 #: src/conversation/gnunet_gst.c:630
 #: src/conversation/gnunet-helper-audio-playback-gst.c:357
 #, c-format
@@ -1222,7 +1245,7 @@ msgstr "Ungültiges Befehlszeilenargument »%s«\n"
 msgid "Failed to connect to CORE service!\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1677
+#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1456
 msgid "provide information about all current connections (continuously)"
 msgstr ""
 
@@ -1493,7 +1516,7 @@ msgstr ""
 #: src/testbed/gnunet-daemon-testbed-underlay.c:56
 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:52
 #: src/util/crypto_ecc_setup.c:41 src/util/crypto_mpi.c:39
-#: src/include/gnunet_common.h:681 src/include/gnunet_common.h:690
+#: src/include/gnunet_common.h:691 src/include/gnunet_common.h:700
 #: src/scalarproduct/scalarproduct.h:35
 #, c-format
 msgid "`%s' failed at %s:%d with error: %s\n"
@@ -1893,8 +1916,7 @@ msgstr ""
 msgid "Prints all packets that go through the DHT."
 msgstr ""
 
-#: src/dht/gnunet_dht_profiler.c:1161
-#: src/testbed/gnunet-testbed-profiler.c:255
+#: src/dht/gnunet_dht_profiler.c:1161 src/testbed/gnunet-testbed-profiler.c:255
 #, c-format
 msgid "Exiting as the number of peers is %u\n"
 msgstr ""
@@ -2074,8 +2096,7 @@ msgstr ""
 msgid "# GET requests given to datacache"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_hello.c:84
-#: src/dht/gnunet-service-xdht_hello.c:82
+#: src/dht/gnunet-service-dht_hello.c:84 src/dht/gnunet-service-xdht_hello.c:82
 msgid "# HELLOs obtained from peerinfo"
 msgstr ""
 
@@ -2147,38 +2168,38 @@ msgstr "# Client Trace-Anfragen empfangen"
 msgid "# P2P PUT bytes received"
 msgstr "# Bytes empfangen über TCP"
 
-#: src/dht/gnunet-service-dht_neighbours.c:1854
+#: src/dht/gnunet-service-dht_neighbours.c:1858
 msgid "# FIND PEER requests ignored due to Bloomfilter"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:1862
+#: src/dht/gnunet-service-dht_neighbours.c:1866
 msgid "# FIND PEER requests ignored due to lack of HELLO"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2018
+#: src/dht/gnunet-service-dht_neighbours.c:2022
 #, fuzzy
 msgid "# P2P GET requests received"
 msgstr "# Client Trace-Anfragen empfangen"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2022
+#: src/dht/gnunet-service-dht_neighbours.c:2026
 #, fuzzy
 msgid "# P2P GET bytes received"
 msgstr "# Bytes empfangen über TCP"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2097
+#: src/dht/gnunet-service-dht_neighbours.c:2101
 msgid "# P2P FIND PEER requests processed"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2120
+#: src/dht/gnunet-service-dht_neighbours.c:2124
 #, fuzzy
 msgid "# P2P GET requests ONLY routed"
 msgstr "# dht Anfragen weitergeleitet"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2222
+#: src/dht/gnunet-service-dht_neighbours.c:2226
 msgid "# P2P RESULTS received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2226
+#: src/dht/gnunet-service-dht_neighbours.c:2230
 #, fuzzy
 msgid "# P2P RESULT bytes received"
 msgstr "# Bytes empfangen über TCP"
@@ -2188,35 +2209,35 @@ msgstr "# Bytes empfangen über TCP"
 msgid "# Network size estimates received"
 msgstr "# verschlüsselter PING Nachrichten empfangen"
 
-#: src/dht/gnunet-service-dht_routing.c:218
+#: src/dht/gnunet-service-dht_routing.c:220
 msgid "# Good REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:227
+#: src/dht/gnunet-service-dht_routing.c:229
 msgid "# Duplicate REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:233
+#: src/dht/gnunet-service-dht_routing.c:235
 msgid "# Invalid REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:239
+#: src/dht/gnunet-service-dht_routing.c:241
 msgid "# Irrelevant REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:251
+#: src/dht/gnunet-service-dht_routing.c:253
 msgid "# Unsupported REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:327
+#: src/dht/gnunet-service-dht_routing.c:329
 msgid "# Entries removed from routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:409
+#: src/dht/gnunet-service-dht_routing.c:411
 msgid "# Entries added to routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:427
+#: src/dht/gnunet-service-dht_routing.c:429
 #, fuzzy
 msgid "# DHT requests combined"
 msgstr "# dht Anfragen weitergeleitet"
@@ -2330,16 +2351,16 @@ msgid ""
 "SUPU %s, %s, %d, trail->prev_hop = %s"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:142
+#: src/dht/plugin_block_dht.c:144
 #, fuzzy, c-format
 msgid "Block not of type %u\n"
 msgstr "Kein Transport des Typs %d bekannt.\n"
 
-#: src/dht/plugin_block_dht.c:149
+#: src/dht/plugin_block_dht.c:151
 msgid "Size mismatch for block\n"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:159
+#: src/dht/plugin_block_dht.c:161
 #, c-format
 msgid "Block of type %u is malformed\n"
 msgstr ""
@@ -3472,7 +3493,7 @@ msgid "Option `%s' is required when using option `%s'.\n"
 msgstr "Option `%s' macht keinen Sinn ohne die Option `%s'.\n"
 
 #: src/fs/gnunet-publish.c:849 src/fs/gnunet-publish.c:857
-#: src/transport/gnunet-transport.c:1517 src/transport/gnunet-transport.c:1542
+#: src/transport/gnunet-transport.c:1296 src/transport/gnunet-transport.c:1321
 #, c-format
 msgid "Option `%s' makes no sense without option `%s'.\n"
 msgstr "Die Option »%s« ergibt keinen Sinn ohne die Option »%s«.\n"
@@ -4003,41 +4024,41 @@ msgstr "Beschädigte Antwort auf `%s' von Knoten `%s' empfangen.\n"
 msgid "Received unsupported DNS request from %s\n"
 msgstr "Unbekannte Anfrageart %d empfangen bei %s:%d\n"
 
-#: src/gns/gnunet-dns2gns.c:709
+#: src/gns/gnunet-dns2gns.c:712
 msgid "No ego configured for `dns2gns` subsystem\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:737
+#: src/gns/gnunet-dns2gns.c:740
 #, fuzzy
 msgid "No DNS server specified!\n"
 msgstr "Keine Schlüsselwörter angegeben!\n"
 
-#: src/gns/gnunet-dns2gns.c:758
+#: src/gns/gnunet-dns2gns.c:761
 #, fuzzy
 msgid "No valid GNS zone specified!\n"
 msgstr "Keine Schlüsselwörter angegeben!\n"
 
-#: src/gns/gnunet-dns2gns.c:779
+#: src/gns/gnunet-dns2gns.c:782
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:785
 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:785
+#: src/gns/gnunet-dns2gns.c:788
 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:788
+#: src/gns/gnunet-dns2gns.c:791
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:791
+#: src/gns/gnunet-dns2gns.c:794
 msgid "Public key of the GNS zone to use (overrides default)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:804
+#: src/gns/gnunet-dns2gns.c:807
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4199,83 +4220,85 @@ msgstr ""
 msgid "Unsupported HTTP method `%s'\n"
 msgstr "Kommando `%s' wird nicht unterstützt. Vorgang wird abgebrochen.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2167
+#: src/gns/gnunet-gns-proxy.c:2168
 #, fuzzy, c-format
 msgid "Unable to import private key from file `%s'\n"
 msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':"
 
-#: src/gns/gnunet-gns-proxy.c:2197
+#: src/gns/gnunet-gns-proxy.c:2198
 #, fuzzy, c-format
 msgid "Unable to import certificate %s\n"
 msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2370
+#: src/gns/gnunet-gns-proxy.c:2371
 #, fuzzy, c-format
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2389 src/rest/gnunet-rest-server.c:533
+#: src/gns/gnunet-gns-proxy.c:2390 src/rest/gnunet-rest-server.c:533
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "Fehler beim Starten der Collection.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2709
+#: src/gns/gnunet-gns-proxy.c:2710
 #, c-format
 msgid "Unsupported socks version %d\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2738
+#: src/gns/gnunet-gns-proxy.c:2739
 #, fuzzy, c-format
 msgid "Unsupported socks command %d\n"
 msgstr "Kommando `%s' wird nicht unterstützt. Vorgang wird abgebrochen.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2756 src/gns/gnunet-gns-proxy.c:2785
+#: src/gns/gnunet-gns-proxy.c:2757 src/gns/gnunet-gns-proxy.c:2786
 msgid "SSL connection to plain IPv4 address requested\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2836
+#: src/gns/gnunet-gns-proxy.c:2837
 #, c-format
 msgid "Unsupported socks address type %d\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3171
+#: src/gns/gnunet-gns-proxy.c:3172
 msgid "No ego configured for `shorten-zone`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3211 src/gns/gnunet-service-gns.c:1093
-#: src/gns/gnunet-service-gns.c:1149
+#: src/gns/gnunet-gns-proxy.c:3212 src/gns/gnunet-service-gns.c:493
+#: src/gns/gnunet-service-gns.c:548
 #, c-format
 msgid "No ego configured for `%s`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3273
+#: src/gns/gnunet-gns-proxy.c:3274
 #, fuzzy, c-format
 msgid "Failed to load SSL/TLS key and certificate from `%s'\n"
 msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n"
 
-#: src/gns/gnunet-gns-proxy.c:3313
+#: src/gns/gnunet-gns-proxy.c:3314
 msgid "listen on specified port (default: 7777)"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3316
+#: src/gns/gnunet-gns-proxy.c:3317
 msgid "pem file to use as CA"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3335
+#: src/gns/gnunet-gns-proxy.c:3336
 msgid "GNUnet GNS proxy"
 msgstr ""
 
-#: src/gns/gnunet-service-gns.c:1187
+#: src/gns/gnunet-service-gns.c:585
+#: src/zonemaster/gnunet-service-zonemaster.c:705
 #, fuzzy
 msgid "Failed to connect to the namestore!\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/gns/gnunet-service-gns.c:1195
+#: src/gns/gnunet-service-gns.c:593
 #, fuzzy
 msgid "Failed to connect to the namecache!\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/gns/gnunet-service-gns.c:1228
+#: src/gns/gnunet-service-gns.c:612
+#: src/zonemaster/gnunet-service-zonemaster.c:740
 #, fuzzy
 msgid "Could not connect to DHT!\n"
 msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n"
@@ -5118,8 +5141,7 @@ msgstr ""
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:979
-#: src/peerinfo-tool/gnunet-peerinfo.c:775
+#: src/namestore/gnunet-namestore.c:979 src/peerinfo-tool/gnunet-peerinfo.c:775
 #, fuzzy, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "Ungültiger Parameter: `%s'\n"
@@ -5275,221 +5297,296 @@ msgstr "Sqlite-Datenbank läuft\n"
 msgid "Namestore REST API initialized\n"
 msgstr " Verbindung fehlgeschlagen\n"
 
-#: src/nat/gnunet-nat.c:159
-msgid "GNUnet NAT traversal autoconfigure daemon"
+#: src/nat-auto/gnunet-nat-auto.c:192
+#, fuzzy
+msgid "Suggested configuration changes:\n"
+msgstr ""
+"Einen Wert aus der Konfigurationsdatei auf der Standardausgabe ausgeben"
+
+#: src/nat-auto/gnunet-nat-auto.c:220
+#, fuzzy, c-format
+msgid "Failed to write configuration to `%s'\n"
+msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':"
+
+#: src/nat-auto/gnunet-nat-auto.c:227
+#, fuzzy, c-format
+msgid "Wrote updated configuration to `%s'\n"
+msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:345
+#, fuzzy
+msgid "run autoconfiguration"
+msgstr "# Freunde in Konfiguration"
+
+#: src/nat-auto/gnunet-nat-auto.c:348
+msgid "section name providing the configuration for the adapter"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:351 src/nat/gnunet-nat.c:436
+msgid "use TCP"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:321
+#: src/nat-auto/gnunet-nat-auto.c:354 src/nat/gnunet-nat.c:439
+msgid "use UDP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:357
+msgid "write configuration file (for autoconfiguration)"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:369
+msgid "GNUnet NAT traversal autoconfiguration"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:403
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:681
+#: src/nat-auto/nat_auto_api_test.c:405
+#, fuzzy
+msgid "Failed to connect to `gnunet-nat-server'\n"
+msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:518
+#: src/nat-auto/nat_auto_api_test.c:520
+#, c-format
+msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:568
+#: src/nat-auto/nat_auto_api_test.c:569
+#, fuzzy
+msgid "NAT test failed to start NAT library\n"
+msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n"
+
+#: src/nat-auto/gnunet-nat-server.c:336
 #, c-format
 msgid "Please pass valid port number as the first argument! (got `%s')\n"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:363
+#: src/nat-auto/gnunet-nat-server.c:386
 msgid "GNUnet NAT traversal test helper daemon"
 msgstr ""
 
-#: src/nat/nat_api.c:880 src/nat/nat.c:2010
+#: src/nat-auto/gnunet-service-nat-auto.c:342
+#, fuzzy
+msgid "UPnP client `upnpc` command not found, disabling UPnP\n"
+msgstr "Kommando `%s' wurde nicht gefunden!\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:385
+msgid "NAT traversal with ICMP Server succeeded.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:386
+msgid "NAT traversal with ICMP Server failed.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:405
+msgid "Testing connection reversal with ICMP server.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:437
+#, fuzzy, c-format
+msgid "Detected external IP `%s'\n"
+msgstr "Ungültiger RPC `%s' empfangen.\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:572
+msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:590
+#, c-format
+msgid "Detected internal network address `%s'.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:724
+msgid "upnpc found, enabling its use\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:725
+#, fuzzy
+msgid "upnpc not found\n"
+msgstr "Kommando `%s' wurde nicht gefunden!\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:762
+msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:774
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:834
+msgid "test_icmp_server not possible, as we are not behind NAT\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:786
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:846
+msgid "No working gnunet-helper-nat-server found\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:823
+msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/nat_auto_api.c:76
 msgid "Operation Successful"
 msgstr ""
 
-#: src/nat/nat_api.c:882 src/nat/nat.c:2012
-msgid "Internal Failure (IPC, ...)"
+#: src/nat-auto/nat_auto_api.c:78
+msgid "IPC failure"
 msgstr ""
 
-#: src/nat/nat_api.c:884 src/nat/nat.c:2014
+#: src/nat-auto/nat_auto_api.c:80
 msgid "Failure in network subsystem, check permissions."
 msgstr ""
 
-#: src/nat/nat_api.c:886 src/nat/nat.c:2016
+#: src/nat-auto/nat_auto_api.c:82
 msgid "Encountered timeout while performing operation"
 msgstr ""
 
-#: src/nat/nat_api.c:888 src/nat/nat.c:2018
+#: src/nat-auto/nat_auto_api.c:84
 msgid "detected that we are offline"
 msgstr ""
 
-#: src/nat/nat_api.c:890 src/nat/nat.c:2020
+#: src/nat-auto/nat_auto_api.c:86
 #, fuzzy
 msgid "`upnpc` command not found"
 msgstr "Kommando `%s' wurde nicht gefunden!\n"
 
-#: src/nat/nat_api.c:892 src/nat/nat.c:2022
+#: src/nat-auto/nat_auto_api.c:88
 #, fuzzy
 msgid "Failed to run `upnpc` command"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/nat/nat_api.c:894 src/nat/nat.c:2024
+#: src/nat-auto/nat_auto_api.c:90
 msgid "`upnpc' command took too long, process killed"
 msgstr ""
 
-#: src/nat/nat_api.c:896 src/nat/nat.c:2026
+#: src/nat-auto/nat_auto_api.c:92
 msgid "`upnpc' command failed to establish port mapping"
 msgstr ""
 
-#: src/nat/nat_api.c:898 src/nat/nat.c:2028
+#: src/nat-auto/nat_auto_api.c:94
 msgid "`external-ip' command not found"
 msgstr ""
 
-#: src/nat/nat_api.c:900 src/nat/nat.c:2030
+#: src/nat-auto/nat_auto_api.c:96
 #, fuzzy
 msgid "Failed to run `external-ip` command"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/nat/nat_api.c:902 src/nat/nat.c:2032
+#: src/nat-auto/nat_auto_api.c:98
 #, fuzzy
 msgid "`external-ip' command output invalid"
 msgstr "Kommando `%s' wurde nicht gefunden!\n"
 
-#: src/nat/nat_api.c:904 src/nat/nat.c:2034
+#: src/nat-auto/nat_auto_api.c:100
 msgid "no valid address was returned by `external-ip'"
 msgstr ""
 
-#: src/nat/nat_api.c:906 src/nat/nat.c:2036
+#: src/nat-auto/nat_auto_api.c:102
 #, fuzzy
 msgid "Could not determine interface with internal/local network address"
 msgstr "Öffentliche IP-Adresse konnte nicht ermittelt werden.\n"
 
-#: src/nat/nat_api.c:908 src/nat/nat.c:2038
+#: src/nat-auto/nat_auto_api.c:104
 msgid "No functioning gnunet-helper-nat-server installation found"
 msgstr ""
 
-#: src/nat/nat_api.c:910 src/nat/nat.c:2040
+#: src/nat-auto/nat_auto_api.c:106
 msgid "NAT test could not be initialized"
 msgstr ""
 
-#: src/nat/nat_api.c:912 src/nat/nat.c:2042
+#: src/nat-auto/nat_auto_api.c:108
 msgid "NAT test timeout reached"
 msgstr ""
 
-#: src/nat/nat_api.c:914 src/nat/nat.c:2044
+#: src/nat-auto/nat_auto_api.c:110
 msgid "could not register NAT"
 msgstr ""
 
-#: src/nat/nat_api.c:916 src/nat/nat.c:2046
+#: src/nat-auto/nat_auto_api.c:112
 msgid "No working gnunet-helper-nat-client installation found"
 msgstr ""
 
-#: src/nat/nat_auto.c:385
-msgid "NAT traversal with ICMP Server succeeded.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:386
-msgid "NAT traversal with ICMP Server failed.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:405
-msgid "Testing connection reversal with ICMP server.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:437
+#: src/nat-auto/nat_auto_api_test.c:477
 #, fuzzy, c-format
-msgid "Detected external IP `%s'\n"
-msgstr "Ungültiger RPC `%s' empfangen.\n"
+msgid "Failed to find valid PORT in section `%s'\n"
+msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n"
 
-#: src/nat/nat_auto.c:572
-msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+#: src/nat/gnunet-nat.c:424
+msgid "which IP and port are we locally using to bind/listen to"
 msgstr ""
 
-#: src/nat/nat_auto.c:590
-#, c-format
-msgid "Detected internal network address `%s'.\n"
+#: src/nat/gnunet-nat.c:427
+msgid "which remote IP and port should be asked for connection reversal"
 msgstr ""
 
-#: src/nat/nat_auto.c:681 src/nat/nat_test.c:403
-#, fuzzy
-msgid "Failed to connect to `gnunet-nat-server'\n"
-msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
-
-#: src/nat/nat_auto.c:724
-msgid "upnpc found, enabling its use\n"
+#: src/nat/gnunet-nat.c:430
+msgid ""
+"name of configuration section to find additional options, such as manual "
+"host punching data"
 msgstr ""
 
-#: src/nat/nat_auto.c:725
-#, fuzzy
-msgid "upnpc not found\n"
-msgstr "Kommando `%s' wurde nicht gefunden!\n"
-
-#: src/nat/nat_auto.c:762
-msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+#: src/nat/gnunet-nat.c:433
+msgid "enable STUN processing"
 msgstr ""
 
-#: src/nat/nat_auto.c:774 src/nat/nat_auto.c:834
-msgid "test_icmp_server not possible, as we are not behind NAT\n"
+#: src/nat/gnunet-nat.c:442
+msgid "watch for connection reversal requests"
 msgstr ""
 
-#: src/nat/nat_auto.c:786 src/nat/nat_auto.c:846
-msgid "No working gnunet-helper-nat-server found\n"
+#: src/nat/gnunet-nat.c:454
+msgid "GNUnet NAT traversal autoconfigure daemon"
 msgstr ""
 
-#: src/nat/nat_auto.c:823
-msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+#: src/nat/gnunet-service-nat.c:1313
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1019
+#: src/nat/gnunet-service-nat.c:1323
 #, c-format
-msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
+msgid "Invalid port number in punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1070
-#, fuzzy, c-format
-msgid "Failed to start %s\n"
-msgstr "Fehler beim Starten der Collection.\n"
-
-#: src/nat/nat.c:1327
-msgid "Error while running upnp client:\n"
+#: src/nat/gnunet-service-nat.c:1339
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks `]')\n"
 msgstr ""
 
-#: src/nat/nat.c:1402
-#, fuzzy, c-format
-msgid "Failed to run upnp client for port %u\n"
-msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n"
-
-#: src/nat/nat.c:1546
-msgid "malformed"
+#: src/nat/gnunet-service-nat.c:1350
+#, c-format
+msgid "Malformed punched hole specification `%s' (IPv6 address invalid)"
 msgstr ""
 
-#: src/nat/nat.c:1600
+#: src/nat/gnunet-service-nat.c:1803
+#, fuzzy
+msgid "Connection reversal request failed\n"
+msgstr " Verbindung fehlgeschlagen\n"
+
+#: src/nat/gnunet-service-nat.c:1876
 msgid ""
 "UPnP enabled in configuration, but UPnP client `upnpc` command not found, "
-"disabling UPnP \n"
+"disabling UPnP\n"
 msgstr ""
 
-#: src/nat/nat.c:1726 src/nat/nat.c:1739
+#: src/nat/gnunet-service-nat_helper.c:186
 #, c-format
-msgid ""
-"Configuration requires `%s', but binary is not installed properly (SUID bit "
-"not set).  Option disabled.\n"
-msgstr ""
-
-#: src/nat/nat.c:1903
-msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n"
+msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/nat.c:1919
-#, c-format
-msgid "Running gnunet-helper-nat-client %s %s %u\n"
-msgstr ""
+#: src/nat/gnunet-service-nat_helper.c:260
+#, fuzzy, c-format
+msgid "Failed to start %s\n"
+msgstr "Fehler beim Starten der Collection.\n"
 
-#: src/nat/nat_mini.c:205
+#: src/nat/gnunet-service-nat_mini.c:196
 #, fuzzy
 msgid "`external-ip' command not found\n"
 msgstr "Kommando `%s' wurde nicht gefunden!\n"
 
-#: src/nat/nat_mini.c:611
+#: src/nat/gnunet-service-nat_mini.c:654
 #, fuzzy
 msgid "`upnpc' command not found\n"
 msgstr "Kommando `%s' wurde nicht gefunden!\n"
 
-#: src/nat/nat_test.c:518
-#, c-format
-msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
-msgstr ""
-
-#: src/nat/nat_test.c:568
-#, fuzzy
-msgid "NAT test failed to start NAT library\n"
-msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n"
-
 #: src/nse/gnunet-nse.c:122
 msgid "Show network size estimates from NSE service."
 msgstr ""
@@ -7256,175 +7353,152 @@ msgstr ""
 msgid "# validations succeeded"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:486
+#: src/transport/gnunet-transport.c:418
 #, c-format
 msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:496
+#: src/transport/gnunet-transport.c:428
 #, c-format
 msgid "Received %llu bytes/s (%llu bytes in %s)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:540
+#: src/transport/gnunet-transport.c:472
 #, fuzzy, c-format
 msgid "Failed to connect to `%s'\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/transport/gnunet-transport.c:553
+#: src/transport/gnunet-transport.c:485
 #, fuzzy, c-format
 msgid "Failed to resolve address for peer `%s'\n"
 msgstr "Adresse des Knotens `%s' konnte nicht ermittelt werden.\n"
 
-#: src/transport/gnunet-transport.c:565
+#: src/transport/gnunet-transport.c:499
 #, fuzzy
 msgid "Failed to list connections, timeout occured\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/transport/gnunet-transport.c:588
-#, c-format
-msgid "NAT plugin `%s' reports: %s\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:675
-msgid "No transport plugins configured, peer will never communicate\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:689
-#, c-format
-msgid "No port configured for plugin `%s', cannot test it\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:714
-#, fuzzy
-msgid "Failed to start resolver!\n"
-msgstr "Fehler beim Starten der Collection.\n"
-
-#: src/transport/gnunet-transport.c:750
+#: src/transport/gnunet-transport.c:532
 #, c-format
 msgid "Transmitting %u bytes\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:784
+#: src/transport/gnunet-transport.c:566
 #, c-format
 msgid ""
 "Successfully connected to `%s', starting to send benchmark data in %u Kb "
 "blocks\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:815
+#: src/transport/gnunet-transport.c:597
 #, c-format
 msgid "Disconnected from peer `%s' while benchmarking\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:839 src/transport/gnunet-transport.c:868
+#: src/transport/gnunet-transport.c:621 src/transport/gnunet-transport.c:650
 #, c-format
 msgid "%24s: %-17s %4s   (%u connections in total)\n"
 msgstr "%24s: %-17s %4s   (%u Verbindungen insgesamt)\n"
 
-#: src/transport/gnunet-transport.c:841
+#: src/transport/gnunet-transport.c:623
 msgid "Connected to"
 msgstr "Verbunden mit"
 
-#: src/transport/gnunet-transport.c:870
+#: src/transport/gnunet-transport.c:652
 msgid "Disconnected from"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:905
+#: src/transport/gnunet-transport.c:687
 #, fuzzy, c-format
 msgid "Received %u bytes\n"
 msgstr "Dateien aus dem GNUnet herunterladen."
 
-#: src/transport/gnunet-transport.c:942
+#: src/transport/gnunet-transport.c:724
 #, c-format
 msgid "Peer `%s': %s %s in state `%s' until %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:954
+#: src/transport/gnunet-transport.c:736
 #, c-format
 msgid "Peer `%s': %s %s\n"
 msgstr "Knoten »%s«: %s %s\n"
 
-#: src/transport/gnunet-transport.c:1366
+#: src/transport/gnunet-transport.c:1150
 #, fuzzy
 msgid "Monitor disconnected from transport service. Reconnecting.\n"
 msgstr "Verbindung zum Transportdienst konnte nicht hergestellt werden\n"
 
-#: src/transport/gnunet-transport.c:1488
+#: src/transport/gnunet-transport.c:1267
 #, c-format
 msgid ""
 "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, "
 "%s, %s %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1501
+#: src/transport/gnunet-transport.c:1280
 #, c-format
 msgid ""
 "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s, %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1529
+#: src/transport/gnunet-transport.c:1308
 #, fuzzy
 msgid "Failed to connect to transport service for disconnection\n"
 msgstr "Verbindung zum Transportdienst konnte nicht hergestellt werden\n"
 
-#: src/transport/gnunet-transport.c:1535
+#: src/transport/gnunet-transport.c:1314
 msgid "Blacklisting request in place, stop with CTRL-C\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1558 src/transport/gnunet-transport.c:1588
-#: src/transport/gnunet-transport.c:1641
+#: src/transport/gnunet-transport.c:1337 src/transport/gnunet-transport.c:1367
+#: src/transport/gnunet-transport.c:1420
 msgid "Failed to connect to transport service\n"
 msgstr "Verbindung zum Transportdienst konnte nicht hergestellt werden\n"
 
-#: src/transport/gnunet-transport.c:1595
+#: src/transport/gnunet-transport.c:1374
 msgid "Starting to receive benchmark data\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1665
+#: src/transport/gnunet-transport.c:1444
 #, fuzzy
 msgid "print information for all peers (instead of only connected peers)"
 msgstr "Informationen über verbundene Knoten ausgeben."
 
-#: src/transport/gnunet-transport.c:1668
+#: src/transport/gnunet-transport.c:1447
 msgid "measure how fast we are receiving data from all peers (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1671
+#: src/transport/gnunet-transport.c:1450
 msgid "disconnect from a peer"
 msgstr "Verbindung zu einem Knoten trennen"
 
-#: src/transport/gnunet-transport.c:1674
+#: src/transport/gnunet-transport.c:1453
 msgid "provide information about all current connections (once)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1680
+#: src/transport/gnunet-transport.c:1459
 msgid ""
 "provide information about all connects and disconnect events (continuously)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1683
+#: src/transport/gnunet-transport.c:1462
 msgid "do not resolve hostnames"
 msgstr "Keine Rechnernamen auflösen"
 
-#: src/transport/gnunet-transport.c:1686
+#: src/transport/gnunet-transport.c:1465
 #: src/transport/gnunet-transport-profiler.c:631
 msgid "peer identity"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1689
+#: src/transport/gnunet-transport.c:1468
 msgid "monitor plugin sessions"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1692
+#: src/transport/gnunet-transport.c:1471
 msgid "send data for benchmarking to the other peer (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1695
-msgid "test transport configuration (involves external server)"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:1706
+#: src/transport/gnunet-transport.c:1482
 #: src/transport/gnunet-transport-profiler.c:642
 msgid "Direct access to transport service."
 msgstr "Direkter Zugriff auf den Transportdienst"
@@ -7458,9 +7532,9 @@ msgstr ""
 
 #: src/transport/plugin_transport_http_client.c:1477
 #: src/transport/plugin_transport_http_server.c:2248
-#: src/transport/plugin_transport_http_server.c:3457
-#: src/transport/plugin_transport_tcp.c:3365
-#: src/transport/plugin_transport_tcp.c:3372
+#: src/transport/plugin_transport_http_server.c:3462
+#: src/transport/plugin_transport_tcp.c:3375
+#: src/transport/plugin_transport_tcp.c:3382
 msgid "TCP_STEALTH not supported on this platform.\n"
 msgstr ""
 
@@ -7470,13 +7544,13 @@ msgid "Could not initialize curl multi handle, failed to start %s plugin!\n"
 msgstr ""
 
 #: src/transport/plugin_transport_http_client.c:2167
-#: src/transport/plugin_transport_http_server.c:3172
+#: src/transport/plugin_transport_http_server.c:3177
 #, fuzzy, c-format
 msgid "Shutting down plugin `%s'\n"
 msgstr "Collection `%s' begonnen.\n"
 
 #: src/transport/plugin_transport_http_client.c:2184
-#: src/transport/plugin_transport_http_server.c:3242
+#: src/transport/plugin_transport_http_server.c:3247
 #, fuzzy, c-format
 msgid "Shutdown for plugin `%s' complete\n"
 msgstr "GNUnet wurde erfolgreich heruntergefahren.\n"
@@ -7519,70 +7593,70 @@ msgstr ""
 msgid "Could not load or create server certificate! Loading plugin failed!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2583
+#: src/transport/plugin_transport_http_server.c:2586
 msgid "Require valid port number for service in configuration!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2748
+#: src/transport/plugin_transport_http_server.c:2751
 #, c-format
 msgid "Found %u addresses to report to NAT service\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2832
-#: src/transport/plugin_transport_udp.c:3600
+#: src/transport/plugin_transport_http_server.c:2837
+#: src/transport/plugin_transport_udp.c:3623
 msgid "Disabling IPv6 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2938
+#: src/transport/plugin_transport_http_server.c:2943
 #, c-format
 msgid "IPv4 support is %s\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2953
+#: src/transport/plugin_transport_http_server.c:2958
 #, c-format
 msgid "IPv6 support is %s\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2959
+#: src/transport/plugin_transport_http_server.c:2964
 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"
 msgstr ""
 "Weder IPv4 noch IPv6 sind aktiviert! Bearbeiten Sie die Konfiguration\n"
 
-#: src/transport/plugin_transport_http_server.c:2970
+#: src/transport/plugin_transport_http_server.c:2975
 msgid "Port is required! Fix in configuration\n"
 msgstr "Port ist erforderlich! Bearbeiten Sie die Konfiguration\n"
 
-#: src/transport/plugin_transport_http_server.c:2976
+#: src/transport/plugin_transport_http_server.c:2981
 #, c-format
 msgid "Using port %u\n"
 msgstr "Port %u wird verwendet\n"
 
-#: src/transport/plugin_transport_http_server.c:2995
+#: src/transport/plugin_transport_http_server.c:3000
 #, c-format
 msgid "Specific IPv4 address `%s' in configuration file is invalid!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3030
+#: src/transport/plugin_transport_http_server.c:3035
 #, c-format
 msgid "Specific IPv6 address `%s' in configuration file is invalid!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3105
+#: src/transport/plugin_transport_http_server.c:3110
 #, c-format
 msgid "Using external hostname `%s'\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3126
+#: src/transport/plugin_transport_http_server.c:3131
 #, fuzzy, c-format
 msgid "Notifying transport only about hostname `%s'\n"
 msgstr "Teste Transport(e) %s\n"
 
-#: src/transport/plugin_transport_http_server.c:3143
+#: src/transport/plugin_transport_http_server.c:3148
 #, c-format
 msgid "Maximum number of connections is %u\n"
 msgstr "Maximale Anzahl der Verbindungen ist %u\n"
 
-#: src/transport/plugin_transport_http_server.c:3469
+#: src/transport/plugin_transport_http_server.c:3474
 msgid "Unable to compile URL regex\n"
 msgstr ""
 
@@ -7632,160 +7706,160 @@ msgstr "# Bytes gesendet über SMTP"
 msgid "# bytes dropped by SMTP (outgoing)"
 msgstr "# Bytes verworfen von SMTP (ausgehend)"
 
-#: src/transport/plugin_transport_tcp.c:1051
-#: src/transport/plugin_transport_tcp.c:2362
+#: src/transport/plugin_transport_tcp.c:1060
+#: src/transport/plugin_transport_tcp.c:2379
 #, c-format
 msgid "Unexpected address length: %u bytes\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1234
-#: src/transport/plugin_transport_tcp.c:1458
-#: src/transport/plugin_transport_tcp.c:2633
-#: src/transport/plugin_transport_tcp.c:3490
+#: src/transport/plugin_transport_tcp.c:1243
+#: src/transport/plugin_transport_tcp.c:1467
+#: src/transport/plugin_transport_tcp.c:2643
+#: src/transport/plugin_transport_tcp.c:3498
 msgid "# TCP sessions active"
 msgstr "# aktive TCP-Sitzungen"
 
-#: src/transport/plugin_transport_tcp.c:1276
-#: src/transport/plugin_transport_tcp.c:1440
-#: src/transport/plugin_transport_tcp.c:1564
-#: src/transport/plugin_transport_tcp.c:1637
-#: src/transport/plugin_transport_tcp.c:1737
-#: src/transport/plugin_transport_tcp.c:1762
+#: src/transport/plugin_transport_tcp.c:1285
+#: src/transport/plugin_transport_tcp.c:1449
+#: src/transport/plugin_transport_tcp.c:1573
+#: src/transport/plugin_transport_tcp.c:1646
+#: src/transport/plugin_transport_tcp.c:1746
+#: src/transport/plugin_transport_tcp.c:1771
 msgid "# bytes currently in TCP buffers"
 msgstr "# Bytes derzeit in TCP-Puffern"
 
-#: src/transport/plugin_transport_tcp.c:1279
+#: src/transport/plugin_transport_tcp.c:1288
 msgid "# bytes discarded by TCP (disconnect)"
 msgstr "# Bytes verworfen von TCP (unterbrochen)"
 
-#: src/transport/plugin_transport_tcp.c:1567
+#: src/transport/plugin_transport_tcp.c:1576
 msgid "# bytes discarded by TCP (timeout)"
 msgstr "# Bytes verworfen von TCP (Zeitüberschreitung)"
 
-#: src/transport/plugin_transport_tcp.c:1641
+#: src/transport/plugin_transport_tcp.c:1650
 msgid "# bytes transmitted via TCP"
 msgstr "# Bytes über TCP übertragen"
 
-#: src/transport/plugin_transport_tcp.c:2032
+#: src/transport/plugin_transport_tcp.c:2041
 msgid "# requests to create session with invalid address"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2200
+#: src/transport/plugin_transport_tcp.c:2217
 msgid "# transport-service disconnect requests for TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2692
+#: src/transport/plugin_transport_tcp.c:2702
 #, fuzzy
 msgid "# TCP WELCOME messages received"
 msgstr "# verschlüsselter PONG Nachrichten empfangen"
 
-#: src/transport/plugin_transport_tcp.c:2883
+#: src/transport/plugin_transport_tcp.c:2893
 msgid "# bytes received via TCP"
 msgstr "# Bytes empfangen über TCP"
 
-#: src/transport/plugin_transport_tcp.c:2934
-#: src/transport/plugin_transport_tcp.c:2992
+#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:3002
 #, fuzzy
 msgid "# TCP server connections active"
 msgstr " Verbindung fehlgeschlagen\n"
 
-#: src/transport/plugin_transport_tcp.c:2938
+#: src/transport/plugin_transport_tcp.c:2948
 #, fuzzy
 msgid "# TCP server connect events"
 msgstr "# verbundener Knoten"
 
-#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:2954
 msgid "TCP connection limit reached, suspending server\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2946
+#: src/transport/plugin_transport_tcp.c:2956
 msgid "# TCP service suspended"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2986
+#: src/transport/plugin_transport_tcp.c:2996
 msgid "# TCP service resumed"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2996
+#: src/transport/plugin_transport_tcp.c:3006
 msgid "# network-level TCP disconnect events"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3315
+#: src/transport/plugin_transport_tcp.c:3325
 msgid "Failed to start service.\n"
 msgstr "Fehler beim Starten des Dienstes.\n"
 
-#: src/transport/plugin_transport_tcp.c:3478
+#: src/transport/plugin_transport_tcp.c:3486
 #, c-format
 msgid "TCP transport listening on port %llu\n"
 msgstr "TCP-Transportdienst wartet auf Port %llu\n"
 
-#: src/transport/plugin_transport_tcp.c:3482
+#: src/transport/plugin_transport_tcp.c:3490
 msgid "TCP transport not listening on any port (client only)\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3486
+#: src/transport/plugin_transport_tcp.c:3494
 #, c-format
 msgid "TCP transport advertises itself as being on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:170
+#: src/transport/plugin_transport_udp_broadcasting.c:169
 #, fuzzy
 msgid "# Multicast HELLO beacons received via UDP"
 msgstr "# Bytes empfangen über TCP"
 
-#: src/transport/plugin_transport_udp_broadcasting.c:546
+#: src/transport/plugin_transport_udp_broadcasting.c:545
 msgid ""
 "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:567
+#: src/transport/plugin_transport_udp_broadcasting.c:566
 #, fuzzy, c-format
 msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n"
 msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n"
 
-#: src/transport/plugin_transport_udp.c:3344
+#: src/transport/plugin_transport_udp.c:3367
 #, c-format
 msgid ""
 "UDP could not transmit message to `%s': Network seems down, please check "
 "your network configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3358
+#: src/transport/plugin_transport_udp.c:3381
 msgid ""
 "UDP could not transmit IPv6 message! Please check your network configuration "
 "and disable IPv6 if your connection does not have a global IPv6 address\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3676
-#: src/transport/plugin_transport_udp.c:3775
+#: src/transport/plugin_transport_udp.c:3699
+#: src/transport/plugin_transport_udp.c:3798
 #, fuzzy, c-format
 msgid "Failed to bind UDP socket to %s: %s\n"
 msgstr "UDP-Sockets können nicht geöffnet werden\n"
 
-#: src/transport/plugin_transport_udp.c:3694
+#: src/transport/plugin_transport_udp.c:3717
 msgid "Disabling IPv4 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3785
+#: src/transport/plugin_transport_udp.c:3808
 msgid "Failed to open UDP sockets\n"
 msgstr "UDP-Sockets können nicht geöffnet werden\n"
 
-#: src/transport/plugin_transport_udp.c:3857
-#: src/transport/plugin_transport_udp.c:3871
+#: src/transport/plugin_transport_udp.c:3879
+#: src/transport/plugin_transport_udp.c:3893
 msgid "must be in [0,65535]"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3903
+#: src/transport/plugin_transport_udp.c:3925
 #, fuzzy
 msgid "must be valid IPv4 address"
 msgstr "»%s« ist keine gültige IP-Adresse.\n"
 
-#: src/transport/plugin_transport_udp.c:3930
+#: src/transport/plugin_transport_udp.c:3952
 #, fuzzy
 msgid "must be valid IPv6 address"
 msgstr "»%s« ist keine gültige IP-Adresse.\n"
 
-#: src/transport/plugin_transport_udp.c:3996
+#: src/transport/plugin_transport_udp.c:4018
 #, fuzzy
 msgid "Failed to create UDP network sockets\n"
 msgstr "UDP-Sockets können nicht geöffnet werden\n"
@@ -7905,7 +7979,7 @@ msgstr ""
 msgid "Metadata `%s' failed to deserialize"
 msgstr ""
 
-#: src/util/client_new.c:864
+#: src/util/client.c:864
 #, c-format
 msgid "Need a non-empty hostname for service `%s'.\n"
 msgstr ""
@@ -8683,42 +8757,42 @@ msgstr "IPv6-Adresse enthält keine gültige Portnummer nach dem letzten »:«\n
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "Ungültige Antwort auf `%s' von `%s'\n"
 
-#: src/util/strings.c:1475 src/util/strings.c:1491
+#: src/util/strings.c:1541 src/util/strings.c:1557
 msgid "Port not in range\n"
 msgstr "Port außerhalb des Bereichs\n"
 
-#: src/util/strings.c:1500
+#: src/util/strings.c:1566
 #, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1583 src/util/strings.c:1614 src/util/strings.c:1662
-#: src/util/strings.c:1683
+#: src/util/strings.c:1649 src/util/strings.c:1680 src/util/strings.c:1728
+#: src/util/strings.c:1749
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "Ungültiges Format für IP: »%s«\n"
 
-#: src/util/strings.c:1640
+#: src/util/strings.c:1706
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "Ungültige Netzwerk-Notation ('/%d ist nicht gültig in IPv4 CIDR)."
 
-#: src/util/strings.c:1692
+#: src/util/strings.c:1758
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "Ungültiges Format für IP: `%s'\n"
 
-#: src/util/strings.c:1744
+#: src/util/strings.c:1810
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "Ungültige Netzwerk-Notation (endet nicht mit »;«: »%s«)\n"
 
-#: src/util/strings.c:1794
+#: src/util/strings.c:1860
 #, fuzzy, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "Falsches Format `%s' für Netzmaske: %s\n"
 
-#: src/util/strings.c:1825
+#: src/util/strings.c:1891
 #, fuzzy, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "Falsches Format `%s' für Netzwerk: %s\n"
@@ -8902,21 +8976,29 @@ msgid "Setup tunnels via VPN."
 msgstr "Tunnel über VPN einrichten."
 
 #: src/include/gnunet_common.h:645 src/include/gnunet_common.h:652
-#: src/include/gnunet_common.h:660
+#: src/include/gnunet_common.h:662 src/include/gnunet_common.h:670
 #, fuzzy, c-format
 msgid "Assertion failed at %s:%d.\n"
 msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n"
 
-#: src/include/gnunet_common.h:672
+#: src/include/gnunet_common.h:682
 #, fuzzy, c-format
 msgid "External protocol violation detected at %s:%d.\n"
 msgstr "Protokollverletzung auf Socket. Kommando erwartet.\n"
 
-#: src/include/gnunet_common.h:699 src/include/gnunet_common.h:708
+#: src/include/gnunet_common.h:709 src/include/gnunet_common.h:718
 #, fuzzy, c-format
 msgid "`%s' failed on file `%s' at %s:%d with error: %s\n"
 msgstr "`%s' schlug bei Datei `%s' fehl. Ort: %s:%d. Fehler: %s\n"
 
+#, fuzzy
+#~ msgid "Failed to run upnp client for port %u\n"
+#~ msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n"
+
+#, fuzzy
+#~ msgid "Failed to start resolver!\n"
+#~ msgstr "Fehler beim Starten der Collection.\n"
+
 #, fuzzy
 #~ msgid "Unable to initialize Postgres: %s\n"
 #~ msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n"
index 8df52f5c995b955ff7042caba6f680bf9cacbcc9..89ed32c0e9846c5c1a882b1cfce9f42205eea8a9 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.9.5a\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2016-11-27 09:18+0100\n"
+"POT-Creation-Date: 2017-01-12 17:19+0100\n"
 "PO-Revision-Date: 2013-02-23 17:50+0100\n"
 "Last-Translator: Miguel Ángel Arruga Vivas <rosen644835@gmail.com>\n"
 "Language-Team: Spanish <es@li.org>\n"
@@ -260,9 +260,8 @@ msgstr ""
 #: src/arm/gnunet-service-arm.c:393 src/arm/gnunet-service-arm.c:399
 #: src/transport/plugin_transport_tcp.c:652
 #: src/transport/plugin_transport_tcp.c:658
-#: src/transport/plugin_transport_tcp.c:3299 src/util/service.c:584
-#: src/util/service.c:590 src/util/service_new.c:637
-#: src/util/service_new.c:643
+#: src/transport/plugin_transport_tcp.c:3309 src/util/service.c:584
+#: src/util/service.c:590 src/util/service_new.c:637 src/util/service_new.c:643
 #, c-format
 msgid "Require valid port number for service `%s' in configuration!\n"
 msgstr ""
@@ -270,14 +269,14 @@ msgstr ""
 "configuración!\n"
 
 #: src/arm/gnunet-service-arm.c:430 src/transport/plugin_transport_tcp.c:689
-#: src/util/client_new.c:464 src/util/service.c:621 src/util/service_new.c:682
+#: src/util/client.c:464 src/util/service.c:621 src/util/service_new.c:682
 #, c-format
 msgid "UNIXPATH `%s' too long, maximum length is %llu\n"
 msgstr ""
 "La ruta tipo UNIX «%s» es demasiado larga, la longitud máxima es %llu\n"
 
 #: src/arm/gnunet-service-arm.c:434 src/transport/plugin_transport_tcp.c:693
-#: src/util/client_new.c:469 src/util/service.c:625 src/util/service_new.c:687
+#: src/util/client.c:469 src/util/service.c:625 src/util/service_new.c:687
 #, c-format
 msgid "Using `%s' instead\n"
 msgstr "Usando «%s» en su defecto\n"
@@ -301,7 +300,7 @@ msgstr ""
 "uno es necesario\n"
 
 #: src/arm/gnunet-service-arm.c:513
-#: src/transport/plugin_transport_http_server.c:2617
+#: src/transport/plugin_transport_http_server.c:2620
 #: src/transport/plugin_transport_tcp.c:772 src/util/service.c:704
 #: src/util/service_new.c:782
 #, c-format
@@ -309,7 +308,7 @@ msgid "Failed to resolve `%s': %s\n"
 msgstr "Se produjo un fallo al resolver «%s»: %s\n"
 
 #: src/arm/gnunet-service-arm.c:532
-#: src/transport/plugin_transport_http_server.c:2635
+#: src/transport/plugin_transport_http_server.c:2638
 #: src/transport/plugin_transport_tcp.c:791 src/util/service.c:723
 #: src/util/service_new.c:802
 #, c-format
@@ -416,14 +415,12 @@ msgstr ""
 "No hay configurada una cuota de salida para la red «%s», asignando el ancho "
 "de banda predeterminado %llu\n"
 
-#: src/ats/gnunet-ats-solver-eval.c:3293
-#: src/ats-tests/gnunet-solver-eval.c:935
+#: src/ats/gnunet-ats-solver-eval.c:3293 src/ats-tests/gnunet-solver-eval.c:935
 #, fuzzy
 msgid "solver to use"
 msgstr "valor a establecer"
 
-#: src/ats/gnunet-ats-solver-eval.c:3296
-#: src/ats-tests/gnunet-solver-eval.c:938
+#: src/ats/gnunet-ats-solver-eval.c:3296 src/ats-tests/gnunet-solver-eval.c:938
 #: src/ats-tests/gnunet-solver-eval.c:941
 msgid "experiment to use"
 msgstr ""
@@ -540,12 +537,12 @@ msgstr "La cuota de salida configurada para la red «%s» es %llu\n"
 msgid "Invalid %s configuration %f\n"
 msgstr "Se produjo un fallo al cargar la configuración de %s\n"
 
-#: src/ats-tests/ats-testing.c:441
+#: src/ats-tests/ats-testing.c:422
 #, c-format
 msgid "Connected master [%u] with slave [%u]\n"
 msgstr ""
 
-#: src/ats-tests/ats-testing.c:448
+#: src/ats-tests/ats-testing.c:429
 #, fuzzy, c-format
 msgid "Failed to connect master peer [%u] with slave [%u]\n"
 msgstr "Fallo al conectar a gnunetd.\n"
@@ -610,7 +607,7 @@ msgid "Quota for network `%11s' (in/out): %10s / %10s\n"
 msgstr "Cuota para la red «%11s» (entrada/salida): %10s / %10s\n"
 
 #: src/ats-tool/gnunet-ats.c:748 src/ats-tool/gnunet-ats.c:761
-#: src/transport/gnunet-transport.c:1476
+#: src/transport/gnunet-transport.c:1255
 #, c-format
 msgid "Failed to parse peer identity `%s'\n"
 msgstr "Se produjo un fallo al procesar la identidad del par «%s»\n"
@@ -701,6 +698,38 @@ msgstr "salida prolija (incluye las propiedades de direcciones del ATS)"
 msgid "Print information about ATS state"
 msgstr "Imprime información acerca del estado del ATS"
 
+#: src/auction/gnunet-auction-create.c:69
+msgid "description of the item to be sold"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:72
+msgid "mapping of possible prices"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:75
+msgid "max duration per round"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:78
+msgid "duration until auction starts"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:81
+msgid "number of items to sell, 0 for first price auction"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:84
+#, fuzzy
+msgid "public auction outcome"
+msgstr "_Opciones"
+
+#: src/auction/gnunet-auction-create.c:94 src/auction/gnunet-auction-info.c:76
+#: src/auction/gnunet-auction-join.c:76
+#: src/conversation/gnunet-conversation-test.c:243
+#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
+msgid "help text"
+msgstr "texto de ayuda"
+
 #: src/cadet/gnunet-cadet.c:511
 #, fuzzy, c-format
 msgid "Invalid target `%s'\n"
@@ -756,7 +785,7 @@ msgstr "proveer información acerca de un túnel en particular"
 msgid "provide information about all tunnels"
 msgstr "proveer información acerca de un túnel en particular"
 
-#: src/cadet/gnunet-service-cadet_peer.c:681
+#: src/cadet/gnunet-service-cadet_peer.c:686
 msgid "Wrong CORE service\n"
 msgstr "Servicio principal (CORE) erróneo\n"
 
@@ -1085,11 +1114,6 @@ msgid ""
 "played back to you..."
 msgstr ""
 
-#: src/conversation/gnunet-conversation-test.c:243
-#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
-msgid "help text"
-msgstr "texto de ayuda"
-
 #: src/conversation/gnunet_gst.c:630
 #: src/conversation/gnunet-helper-audio-playback-gst.c:357
 #, c-format
@@ -1299,7 +1323,7 @@ msgid "Failed to connect to CORE service!\n"
 msgstr "¡Se produjo un fallo al conectar con el servicio DHT!\n"
 
 # Miguel: ¿Quizá continuamente fuese mejor?
-#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1677
+#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1456
 msgid "provide information about all current connections (continuously)"
 msgstr ""
 "provee información sobre todas las conexiones actuales (de forma continua)"
@@ -1564,7 +1588,7 @@ msgstr "Caché de datos de montículo (heap) ejecutándose\n"
 #: src/testbed/gnunet-daemon-testbed-underlay.c:56
 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:52
 #: src/util/crypto_ecc_setup.c:41 src/util/crypto_mpi.c:39
-#: src/include/gnunet_common.h:681 src/include/gnunet_common.h:690
+#: src/include/gnunet_common.h:691 src/include/gnunet_common.h:700
 #: src/scalarproduct/scalarproduct.h:35
 #, c-format
 msgid "`%s' failed at %s:%d with error: %s\n"
@@ -1976,8 +2000,7 @@ msgstr "cuanto tiempo debe ejecutarse el comando de monitorización"
 msgid "Prints all packets that go through the DHT."
 msgstr "Imprime todos los paquetes que pasan por la DHT."
 
-#: src/dht/gnunet_dht_profiler.c:1161
-#: src/testbed/gnunet-testbed-profiler.c:255
+#: src/dht/gnunet_dht_profiler.c:1161 src/testbed/gnunet-testbed-profiler.c:255
 #, fuzzy, c-format
 msgid "Exiting as the number of peers is %u\n"
 msgstr "El número máximo de conexiones es %u\n"
@@ -2161,8 +2184,7 @@ msgstr "¡Tipo de bloque no soportado (%u) en respuesta local!\n"
 msgid "# GET requests given to datacache"
 msgstr "# Peticiones «GET» realizadas a la caché de datos"
 
-#: src/dht/gnunet-service-dht_hello.c:84
-#: src/dht/gnunet-service-xdht_hello.c:82
+#: src/dht/gnunet-service-dht_hello.c:84 src/dht/gnunet-service-xdht_hello.c:82
 msgid "# HELLOs obtained from peerinfo"
 msgstr "# «HELLO» obtenidos de «peerinfo»"
 
@@ -2229,36 +2251,36 @@ msgstr "# Peticiones «PUT» P2P recibidas"
 msgid "# P2P PUT bytes received"
 msgstr "# Peticiones «PUT» P2P recibidas"
 
-#: src/dht/gnunet-service-dht_neighbours.c:1854
+#: src/dht/gnunet-service-dht_neighbours.c:1858
 msgid "# FIND PEER requests ignored due to Bloomfilter"
 msgstr "# Peticiones «FIND PEER» ignoradas debido a «Bloomfilter»"
 
-#: src/dht/gnunet-service-dht_neighbours.c:1862
+#: src/dht/gnunet-service-dht_neighbours.c:1866
 msgid "# FIND PEER requests ignored due to lack of HELLO"
 msgstr "# Peticiones «FIND PEER» ignoradas debido a falta de «HELLO»"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2018
+#: src/dht/gnunet-service-dht_neighbours.c:2022
 msgid "# P2P GET requests received"
 msgstr "# Peticiones «GET» P2P recibidas"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2022
+#: src/dht/gnunet-service-dht_neighbours.c:2026
 #, fuzzy
 msgid "# P2P GET bytes received"
 msgstr "# Peticiones «GET» P2P recibidas"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2097
+#: src/dht/gnunet-service-dht_neighbours.c:2101
 msgid "# P2P FIND PEER requests processed"
 msgstr "# Peticiones «FIND PEER» P2P procesadas"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2120
+#: src/dht/gnunet-service-dht_neighbours.c:2124
 msgid "# P2P GET requests ONLY routed"
 msgstr "# Peticiones «GET» P2P SOLAMENTE encaminadas"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2222
+#: src/dht/gnunet-service-dht_neighbours.c:2226
 msgid "# P2P RESULTS received"
 msgstr "# Resultados (RESULTS) P2P recibidos"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2226
+#: src/dht/gnunet-service-dht_neighbours.c:2230
 #, fuzzy
 msgid "# P2P RESULT bytes received"
 msgstr "# Resultados (RESULTS) P2P recibidos"
@@ -2267,41 +2289,41 @@ msgstr "# Resultados (RESULTS) P2P recibidos"
 msgid "# Network size estimates received"
 msgstr "# Estimaciones del tamaño de red recibidas"
 
-#: src/dht/gnunet-service-dht_routing.c:218
+#: src/dht/gnunet-service-dht_routing.c:220
 msgid "# Good REPLIES matched against routing table"
 msgstr ""
 "# Buenas respuestas (REPLIES) encontradas en la tabla de encaminamiento"
 
-#: src/dht/gnunet-service-dht_routing.c:227
+#: src/dht/gnunet-service-dht_routing.c:229
 msgid "# Duplicate REPLIES matched against routing table"
 msgstr ""
 "# Respuestas (REPLIES) duplicadas encontradas en la tabla de encaminamiento"
 
-#: src/dht/gnunet-service-dht_routing.c:233
+#: src/dht/gnunet-service-dht_routing.c:235
 msgid "# Invalid REPLIES matched against routing table"
 msgstr ""
 "# Respuestas (REPLIES) no válidas encontradas en la tabla de encaminamiento"
 
-#: src/dht/gnunet-service-dht_routing.c:239
+#: src/dht/gnunet-service-dht_routing.c:241
 msgid "# Irrelevant REPLIES matched against routing table"
 msgstr ""
 "# Respuestas (REPLIES) irrelevantes encontradas en la tabla de encaminamiento"
 
-#: src/dht/gnunet-service-dht_routing.c:251
+#: src/dht/gnunet-service-dht_routing.c:253
 msgid "# Unsupported REPLIES matched against routing table"
 msgstr ""
 "# Respuestas (REPLIES) no soportadas encontradas en la tabla de "
 "encaminamiento"
 
-#: src/dht/gnunet-service-dht_routing.c:327
+#: src/dht/gnunet-service-dht_routing.c:329
 msgid "# Entries removed from routing table"
 msgstr "# Entradas eliminadas de la tabla de encaminamiento"
 
-#: src/dht/gnunet-service-dht_routing.c:409
+#: src/dht/gnunet-service-dht_routing.c:411
 msgid "# Entries added to routing table"
 msgstr "# Entradas añadidas a la tabla de encaminamiento"
 
-#: src/dht/gnunet-service-dht_routing.c:427
+#: src/dht/gnunet-service-dht_routing.c:429
 msgid "# DHT requests combined"
 msgstr "# Peticiones a la DHT combinadas"
 
@@ -2414,16 +2436,16 @@ msgid ""
 "SUPU %s, %s, %d, trail->prev_hop = %s"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:142
+#: src/dht/plugin_block_dht.c:144
 #, c-format
 msgid "Block not of type %u\n"
 msgstr "El bloque no es del tipo %u\n"
 
-#: src/dht/plugin_block_dht.c:149
+#: src/dht/plugin_block_dht.c:151
 msgid "Size mismatch for block\n"
 msgstr "Discrepancias de tamaños para el bloque\n"
 
-#: src/dht/plugin_block_dht.c:159
+#: src/dht/plugin_block_dht.c:161
 #, c-format
 msgid "Block of type %u is malformed\n"
 msgstr "El bloque del tipo %u está mal formado\n"
@@ -3593,7 +3615,7 @@ msgid "Option `%s' is required when using option `%s'.\n"
 msgstr "La opción «%s» es obligatoria cuando se usa la opción «%s».\n"
 
 #: src/fs/gnunet-publish.c:849 src/fs/gnunet-publish.c:857
-#: src/transport/gnunet-transport.c:1517 src/transport/gnunet-transport.c:1542
+#: src/transport/gnunet-transport.c:1296 src/transport/gnunet-transport.c:1321
 #, c-format
 msgid "Option `%s' makes no sense without option `%s'.\n"
 msgstr "La opción «%s» no tiene sentido sin la opción «%s».\n"
@@ -4119,45 +4141,45 @@ msgstr "Recibida petición DNS mal formada de %s\n"
 msgid "Received unsupported DNS request from %s\n"
 msgstr "Recibida petición DNS no soportada de %s\n"
 
-#: src/gns/gnunet-dns2gns.c:709
+#: src/gns/gnunet-dns2gns.c:712
 msgid "No ego configured for `dns2gns` subsystem\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:737
+#: src/gns/gnunet-dns2gns.c:740
 #, fuzzy
 msgid "No DNS server specified!\n"
 msgstr "¡Ninguna palabra clave especificada!\n"
 
-#: src/gns/gnunet-dns2gns.c:758
+#: src/gns/gnunet-dns2gns.c:761
 #, fuzzy
 msgid "No valid GNS zone specified!\n"
 msgstr "¡Ninguna palabra clave especificada!\n"
 
-#: src/gns/gnunet-dns2gns.c:779
+#: src/gns/gnunet-dns2gns.c:782
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr "IP del resolvedor recursivo DNS a usar (requerido)"
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:785
 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu"
 msgstr ""
 "Sufijo FCFS autoritativo a usar (opcional); predeterminado: fcfs.zkey.eu"
 
-#: src/gns/gnunet-dns2gns.c:785
+#: src/gns/gnunet-dns2gns.c:788
 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu"
 msgstr "Sufijo DNS autoritativo a usar (opcional); predeterminado: zkey.eu"
 
-#: src/gns/gnunet-dns2gns.c:788
+#: src/gns/gnunet-dns2gns.c:791
 #, fuzzy
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 "Puerto UDP en el que escuchar para peticiones DNS entrantes; predeterminado: "
 "53"
 
-#: src/gns/gnunet-dns2gns.c:791
+#: src/gns/gnunet-dns2gns.c:794
 msgid "Public key of the GNS zone to use (overrides default)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:804
+#: src/gns/gnunet-dns2gns.c:807
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr "Pasarela GNUnet DNS-a-GNS (un servidor DNS)"
 
@@ -4321,83 +4343,85 @@ msgstr ""
 msgid "Unsupported HTTP method `%s'\n"
 msgstr "Tipo no soportado «%s»\n"
 
-#: src/gns/gnunet-gns-proxy.c:2167
+#: src/gns/gnunet-gns-proxy.c:2168
 #, c-format
 msgid "Unable to import private key from file `%s'\n"
 msgstr "No se pudo importar la clave privada del fichero «%s»\n"
 
-#: src/gns/gnunet-gns-proxy.c:2197
+#: src/gns/gnunet-gns-proxy.c:2198
 #, c-format
 msgid "Unable to import certificate %s\n"
 msgstr "No se pudo importar el certificado %s\n"
 
-#: src/gns/gnunet-gns-proxy.c:2370
+#: src/gns/gnunet-gns-proxy.c:2371
 #, fuzzy, c-format
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "Se produjo un fallo al iniciar el servidor HTTP\n"
 
-#: src/gns/gnunet-gns-proxy.c:2389 src/rest/gnunet-rest-server.c:533
+#: src/gns/gnunet-gns-proxy.c:2390 src/rest/gnunet-rest-server.c:533
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "Se produjo un fallo al conectar con GNS\n"
 
-#: src/gns/gnunet-gns-proxy.c:2709
+#: src/gns/gnunet-gns-proxy.c:2710
 #, fuzzy, c-format
 msgid "Unsupported socks version %d\n"
 msgstr "Tipo de bloque %u no soportado\n"
 
-#: src/gns/gnunet-gns-proxy.c:2738
+#: src/gns/gnunet-gns-proxy.c:2739
 #, fuzzy, c-format
 msgid "Unsupported socks command %d\n"
 msgstr "Tipo de bloque %u no soportado\n"
 
-#: src/gns/gnunet-gns-proxy.c:2756 src/gns/gnunet-gns-proxy.c:2785
+#: src/gns/gnunet-gns-proxy.c:2757 src/gns/gnunet-gns-proxy.c:2786
 msgid "SSL connection to plain IPv4 address requested\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2836
+#: src/gns/gnunet-gns-proxy.c:2837
 #, fuzzy, c-format
 msgid "Unsupported socks address type %d\n"
 msgstr "Tipo de bloque %u no soportado\n"
 
-#: src/gns/gnunet-gns-proxy.c:3171
+#: src/gns/gnunet-gns-proxy.c:3172
 msgid "No ego configured for `shorten-zone`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3211 src/gns/gnunet-service-gns.c:1093
-#: src/gns/gnunet-service-gns.c:1149
+#: src/gns/gnunet-gns-proxy.c:3212 src/gns/gnunet-service-gns.c:493
+#: src/gns/gnunet-service-gns.c:548
 #, fuzzy, c-format
 msgid "No ego configured for `%s`\n"
 msgstr ""
 "Ningún puerto fue configurado para el módulo «%s», no se puede probar\n"
 
-#: src/gns/gnunet-gns-proxy.c:3273
+#: src/gns/gnunet-gns-proxy.c:3274
 #, fuzzy, c-format
 msgid "Failed to load SSL/TLS key and certificate from `%s'\n"
 msgstr "Se produjo un fallo al leer la lista de amigos de «%s»\n"
 
-#: src/gns/gnunet-gns-proxy.c:3313
+#: src/gns/gnunet-gns-proxy.c:3314
 msgid "listen on specified port (default: 7777)"
 msgstr "escuchar en el puerto especificado (predeterminado: 7777)"
 
-#: src/gns/gnunet-gns-proxy.c:3316
+#: src/gns/gnunet-gns-proxy.c:3317
 msgid "pem file to use as CA"
 msgstr "fichero pem para usar como autoridad de certificación (CA)"
 
-#: src/gns/gnunet-gns-proxy.c:3335
+#: src/gns/gnunet-gns-proxy.c:3336
 msgid "GNUnet GNS proxy"
 msgstr "Proxy GNUnet GNS"
 
-#: src/gns/gnunet-service-gns.c:1187
+#: src/gns/gnunet-service-gns.c:585
+#: src/zonemaster/gnunet-service-zonemaster.c:705
 msgid "Failed to connect to the namestore!\n"
 msgstr "¡Se produjo un fallo al conectar con el almacén de nombres!\n"
 
-#: src/gns/gnunet-service-gns.c:1195
+#: src/gns/gnunet-service-gns.c:593
 #, fuzzy
 msgid "Failed to connect to the namecache!\n"
 msgstr "¡Se produjo un fallo al conectar con el almacén de nombres!\n"
 
-#: src/gns/gnunet-service-gns.c:1228
+#: src/gns/gnunet-service-gns.c:612
+#: src/zonemaster/gnunet-service-zonemaster.c:740
 msgid "Could not connect to DHT!\n"
 msgstr "¡No se pudo conectar a la DHT!\n"
 
@@ -5279,8 +5303,7 @@ msgstr "borrar"
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr "Parámetro no válido «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:979
-#: src/peerinfo-tool/gnunet-peerinfo.c:775
+#: src/namestore/gnunet-namestore.c:979 src/peerinfo-tool/gnunet-peerinfo.c:775
 #, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "URI no válida: «%s»\n"
@@ -5444,232 +5467,306 @@ msgstr "Base de datos de plantilla ejecutándose\n"
 msgid "Namestore REST API initialized\n"
 msgstr "Conexión fallida\n"
 
-#: src/nat/gnunet-nat.c:159
+#: src/nat-auto/gnunet-nat-auto.c:192
 #, fuzzy
-msgid "GNUnet NAT traversal autoconfigure daemon"
+msgid "Suggested configuration changes:\n"
+msgstr "Configuración de GNUnet"
+
+#: src/nat-auto/gnunet-nat-auto.c:220
+#, fuzzy, c-format
+msgid "Failed to write configuration to `%s'\n"
+msgstr "Se produjo un fallo al guardar la nueva configuración al disco"
+
+#: src/nat-auto/gnunet-nat-auto.c:227
+#, fuzzy, c-format
+msgid "Wrote updated configuration to `%s'\n"
+msgstr "No se pudo acceder al fichero de configuración «%s»\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:345
+#, fuzzy
+msgid "run autoconfiguration"
+msgstr "Configuración de GNUnet"
+
+#: src/nat-auto/gnunet-nat-auto.c:348
+msgid "section name providing the configuration for the adapter"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:351 src/nat/gnunet-nat.c:436
+msgid "use TCP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:354 src/nat/gnunet-nat.c:439
+msgid "use UDP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:357
+#, fuzzy
+msgid "write configuration file (for autoconfiguration)"
+msgstr "¡Ninguna aplicación definida en la configuración!\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:369
+#, fuzzy
+msgid "GNUnet NAT traversal autoconfiguration"
 msgstr "Demonio de ayuda en las pruebas de recorrido NAT de GNUnet"
 
-#: src/nat/gnunet-nat-server.c:321
+#: src/nat-auto/gnunet-nat-auto_legacy.c:403
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:681
+#: src/nat-auto/nat_auto_api_test.c:405
+msgid "Failed to connect to `gnunet-nat-server'\n"
+msgstr "Se produjo un fallo al conectar con «gnunet-nat-server»\n"
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:518
+#: src/nat-auto/nat_auto_api_test.c:520
+#, c-format
+msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
+msgstr ""
+"Se produjo un fallo al crear el «socket» de escucha asociado a «%s» para "
+"pruebas NAT: %s\n"
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:568
+#: src/nat-auto/nat_auto_api_test.c:569
+#, fuzzy
+msgid "NAT test failed to start NAT library\n"
+msgstr "El almacén de nombres no pudo añadir el registro\n"
+
+#: src/nat-auto/gnunet-nat-server.c:336
 #, c-format
 msgid "Please pass valid port number as the first argument! (got `%s')\n"
 msgstr ""
 "¡Por favor, pase un número de puerto válido como primer parámetro! (se "
 "obtuvo «%s»)\n"
 
-#: src/nat/gnunet-nat-server.c:363
+#: src/nat-auto/gnunet-nat-server.c:386
 msgid "GNUnet NAT traversal test helper daemon"
 msgstr "Demonio de ayuda en las pruebas de recorrido NAT de GNUnet"
 
-#: src/nat/nat_api.c:880 src/nat/nat.c:2010
+#: src/nat-auto/gnunet-service-nat-auto.c:342
+#, fuzzy
+msgid "UPnP client `upnpc` command not found, disabling UPnP\n"
+msgstr "comando «upnpc» no encontrado\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:385
+msgid "NAT traversal with ICMP Server succeeded.\n"
+msgstr "Recorrido NAT con servidor ICMP satisfactorio.\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:386
+msgid "NAT traversal with ICMP Server failed.\n"
+msgstr "Recorrido NAT con servidor ICMP fallido.\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:405
+msgid "Testing connection reversal with ICMP server.\n"
+msgstr "Probando conexión inversa con el servidor ICMP.\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:437
+#, c-format
+msgid "Detected external IP `%s'\n"
+msgstr "Detectada IP externa «%s»\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:572
+msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+msgstr ""
+"Este sistema tiene una dirección IPv6 global, fijando IPv6 a habilitado.\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:590
+#, c-format
+msgid "Detected internal network address `%s'.\n"
+msgstr "Detectada dirección de la red interna «%s».\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:724
+msgid "upnpc found, enabling its use\n"
+msgstr "«upnpc» encontrado, habilitando su uso\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:725
+msgid "upnpc not found\n"
+msgstr "«upnpc» no encontrado\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:762
+msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:774
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:834
+msgid "test_icmp_server not possible, as we are not behind NAT\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:786
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:846
+msgid "No working gnunet-helper-nat-server found\n"
+msgstr "No se ha encontrado un «gnunet-helper-nat-server» funcional\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:823
+msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/nat_auto_api.c:76
 msgid "Operation Successful"
 msgstr ""
 
-#: src/nat/nat_api.c:882 src/nat/nat.c:2012
-msgid "Internal Failure (IPC, ...)"
+#: src/nat-auto/nat_auto_api.c:78
+msgid "IPC failure"
 msgstr ""
 
-#: src/nat/nat_api.c:884 src/nat/nat.c:2014
+#: src/nat-auto/nat_auto_api.c:80
 msgid "Failure in network subsystem, check permissions."
 msgstr ""
 
-#: src/nat/nat_api.c:886 src/nat/nat.c:2016
+#: src/nat-auto/nat_auto_api.c:82
 msgid "Encountered timeout while performing operation"
 msgstr ""
 
-#: src/nat/nat_api.c:888 src/nat/nat.c:2018
+#: src/nat-auto/nat_auto_api.c:84
 msgid "detected that we are offline"
 msgstr ""
 
-#: src/nat/nat_api.c:890 src/nat/nat.c:2020
+#: src/nat-auto/nat_auto_api.c:86
 #, fuzzy
 msgid "`upnpc` command not found"
 msgstr "comando «upnpc» no encontrado\n"
 
-#: src/nat/nat_api.c:892 src/nat/nat.c:2022
+#: src/nat-auto/nat_auto_api.c:88
 #, fuzzy
 msgid "Failed to run `upnpc` command"
 msgstr "Se produjo un fallo al ejecutar «%s»\n"
 
-#: src/nat/nat_api.c:894 src/nat/nat.c:2024
+#: src/nat-auto/nat_auto_api.c:90
 #, fuzzy
 msgid "`upnpc' command took too long, process killed"
 msgstr "comando «upnpc» no encontrado\n"
 
-#: src/nat/nat_api.c:896 src/nat/nat.c:2026
+#: src/nat-auto/nat_auto_api.c:92
 msgid "`upnpc' command failed to establish port mapping"
 msgstr ""
 
-#: src/nat/nat_api.c:898 src/nat/nat.c:2028
+#: src/nat-auto/nat_auto_api.c:94
 #, fuzzy
 msgid "`external-ip' command not found"
 msgstr "comando «external-ip» no encontrado\n"
 
-#: src/nat/nat_api.c:900 src/nat/nat.c:2030
+#: src/nat-auto/nat_auto_api.c:96
 #, fuzzy
 msgid "Failed to run `external-ip` command"
 msgstr "Se produjo un fallo al ejecutar «%s»\n"
 
-#: src/nat/nat_api.c:902 src/nat/nat.c:2032
+#: src/nat-auto/nat_auto_api.c:98
 #, fuzzy
 msgid "`external-ip' command output invalid"
 msgstr "comando «external-ip» no encontrado\n"
 
-#: src/nat/nat_api.c:904 src/nat/nat.c:2034
+#: src/nat-auto/nat_auto_api.c:100
 msgid "no valid address was returned by `external-ip'"
 msgstr ""
 
-#: src/nat/nat_api.c:906 src/nat/nat.c:2036
+#: src/nat-auto/nat_auto_api.c:102
 #, fuzzy
 msgid "Could not determine interface with internal/local network address"
 msgstr "No se pudo determinar la ruta de instalación de los módulos.\n"
 
-#: src/nat/nat_api.c:908 src/nat/nat.c:2038
+#: src/nat-auto/nat_auto_api.c:104
 #, fuzzy
 msgid "No functioning gnunet-helper-nat-server installation found"
 msgstr "No se ha encontrado un «gnunet-helper-nat-server» funcional\n"
 
-#: src/nat/nat_api.c:910 src/nat/nat.c:2040
+#: src/nat-auto/nat_auto_api.c:106
 msgid "NAT test could not be initialized"
 msgstr ""
 
-#: src/nat/nat_api.c:912 src/nat/nat.c:2042
+#: src/nat-auto/nat_auto_api.c:108
 msgid "NAT test timeout reached"
 msgstr ""
 
-#: src/nat/nat_api.c:914 src/nat/nat.c:2044
+#: src/nat-auto/nat_auto_api.c:110
 msgid "could not register NAT"
 msgstr ""
 
-#: src/nat/nat_api.c:916 src/nat/nat.c:2046
+#: src/nat-auto/nat_auto_api.c:112
 #, fuzzy
 msgid "No working gnunet-helper-nat-client installation found"
 msgstr "No se ha encontrado un «gnunet-helper-nat-server» funcional\n"
 
-#: src/nat/nat_auto.c:385
-msgid "NAT traversal with ICMP Server succeeded.\n"
-msgstr "Recorrido NAT con servidor ICMP satisfactorio.\n"
-
-#: src/nat/nat_auto.c:386
-msgid "NAT traversal with ICMP Server failed.\n"
-msgstr "Recorrido NAT con servidor ICMP fallido.\n"
-
-#: src/nat/nat_auto.c:405
-msgid "Testing connection reversal with ICMP server.\n"
-msgstr "Probando conexión inversa con el servidor ICMP.\n"
-
-#: src/nat/nat_auto.c:437
-#, c-format
-msgid "Detected external IP `%s'\n"
-msgstr "Detectada IP externa «%s»\n"
+#: src/nat-auto/nat_auto_api_test.c:477
+#, fuzzy, c-format
+msgid "Failed to find valid PORT in section `%s'\n"
+msgstr "¡Se produjo un fallo al buscar la opción %s en la sección %s!\n"
 
-#: src/nat/nat_auto.c:572
-msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+#: src/nat/gnunet-nat.c:424
+msgid "which IP and port are we locally using to bind/listen to"
 msgstr ""
-"Este sistema tiene una dirección IPv6 global, fijando IPv6 a habilitado.\n"
-
-#: src/nat/nat_auto.c:590
-#, c-format
-msgid "Detected internal network address `%s'.\n"
-msgstr "Detectada dirección de la red interna «%s».\n"
-
-#: src/nat/nat_auto.c:681 src/nat/nat_test.c:403
-msgid "Failed to connect to `gnunet-nat-server'\n"
-msgstr "Se produjo un fallo al conectar con «gnunet-nat-server»\n"
-
-#: src/nat/nat_auto.c:724
-msgid "upnpc found, enabling its use\n"
-msgstr "«upnpc» encontrado, habilitando su uso\n"
 
-#: src/nat/nat_auto.c:725
-msgid "upnpc not found\n"
-msgstr "«upnpc» no encontrado\n"
+#: src/nat/gnunet-nat.c:427
+msgid "which remote IP and port should be asked for connection reversal"
+msgstr ""
 
-#: src/nat/nat_auto.c:762
-msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+#: src/nat/gnunet-nat.c:430
+msgid ""
+"name of configuration section to find additional options, such as manual "
+"host punching data"
 msgstr ""
 
-#: src/nat/nat_auto.c:774 src/nat/nat_auto.c:834
-msgid "test_icmp_server not possible, as we are not behind NAT\n"
+#: src/nat/gnunet-nat.c:433
+msgid "enable STUN processing"
 msgstr ""
 
-#: src/nat/nat_auto.c:786 src/nat/nat_auto.c:846
-msgid "No working gnunet-helper-nat-server found\n"
-msgstr "No se ha encontrado un «gnunet-helper-nat-server» funcional\n"
+#: src/nat/gnunet-nat.c:442
+#, fuzzy
+msgid "watch for connection reversal requests"
+msgstr "# pares desconectados debido a petición externa"
 
-#: src/nat/nat_auto.c:823
-msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
-msgstr ""
+#: src/nat/gnunet-nat.c:454
+#, fuzzy
+msgid "GNUnet NAT traversal autoconfigure daemon"
+msgstr "Demonio de ayuda en las pruebas de recorrido NAT de GNUnet"
 
-#: src/nat/nat.c:1019
+#: src/nat/gnunet-service-nat.c:1313
 #, c-format
-msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
-msgstr "«gnunet-helper-nat-server» generó la dirección mal formada «%s»\n"
+msgid "Malformed punched hole specification `%s' (lacks port)\n"
+msgstr ""
 
-#: src/nat/nat.c:1070
-#, c-format
-msgid "Failed to start %s\n"
-msgstr "Se produjo un fallo al arrancar %s\n"
+#: src/nat/gnunet-service-nat.c:1323
+#, fuzzy, c-format
+msgid "Invalid port number in punched hole specification `%s' (lacks port)\n"
+msgstr ""
+"Puerto inválido \"%s\" en la especificación de la lista local, probando el "
+"puerto %d.\n"
 
-#: src/nat/nat.c:1327
-msgid "Error while running upnp client:\n"
+#: src/nat/gnunet-service-nat.c:1339
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks `]')\n"
 msgstr ""
 
-#: src/nat/nat.c:1402
-#, fuzzy, c-format
-msgid "Failed to run upnp client for port %u\n"
+#: src/nat/gnunet-service-nat.c:1350
+#, c-format
+msgid "Malformed punched hole specification `%s' (IPv6 address invalid)"
 msgstr ""
-"Se produjo un fallo al inicializar la clave de la máquina desde el par %u\n"
 
-#: src/nat/nat.c:1546
-msgid "malformed"
-msgstr "mal formado"
+#: src/nat/gnunet-service-nat.c:1803
+#, fuzzy
+msgid "Connection reversal request failed\n"
+msgstr "Colección detenida.\n"
 
-#: src/nat/nat.c:1600
+#: src/nat/gnunet-service-nat.c:1876
 msgid ""
 "UPnP enabled in configuration, but UPnP client `upnpc` command not found, "
-"disabling UPnP \n"
+"disabling UPnP\n"
 msgstr ""
 
-#: src/nat/nat.c:1726 src/nat/nat.c:1739
+#: src/nat/gnunet-service-nat_helper.c:186
 #, c-format
-msgid ""
-"Configuration requires `%s', but binary is not installed properly (SUID bit "
-"not set).  Option disabled.\n"
-msgstr ""
-"La configuración requiere «%s», pero el binario no está instalado de forma "
-"correcta (SUID bit no activado).  Opción deshabilitada.\n"
-
-#: src/nat/nat.c:1903
-msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n"
-msgstr ""
-"Direcciones internas IP no conocidas, no se puede usar el método del "
-"recorrido NAT ICMP\n"
+msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
+msgstr "«gnunet-helper-nat-server» generó la dirección mal formada «%s»\n"
 
-#: src/nat/nat.c:1919
+#: src/nat/gnunet-service-nat_helper.c:260
 #, c-format
-msgid "Running gnunet-helper-nat-client %s %s %u\n"
-msgstr "Ejecutando gnunet-helper-nat-client %s %s %u\n"
+msgid "Failed to start %s\n"
+msgstr "Se produjo un fallo al arrancar %s\n"
 
-#: src/nat/nat_mini.c:205
+#: src/nat/gnunet-service-nat_mini.c:196
 msgid "`external-ip' command not found\n"
 msgstr "comando «external-ip» no encontrado\n"
 
-#: src/nat/nat_mini.c:611
+#: src/nat/gnunet-service-nat_mini.c:654
 msgid "`upnpc' command not found\n"
 msgstr "comando «upnpc» no encontrado\n"
 
-#: src/nat/nat_test.c:518
-#, c-format
-msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
-msgstr ""
-"Se produjo un fallo al crear el «socket» de escucha asociado a «%s» para "
-"pruebas NAT: %s\n"
-
-#: src/nat/nat_test.c:568
-#, fuzzy
-msgid "NAT test failed to start NAT library\n"
-msgstr "El almacén de nombres no pudo añadir el registro\n"
-
 #: src/nse/gnunet-nse.c:122
 #, fuzzy
 msgid "Show network size estimates from NSE service."
@@ -7504,59 +7601,38 @@ msgstr "# Mensajes PONG omitidos, firma expirada"
 msgid "# validations succeeded"
 msgstr "# revalidaciones de direcciones iniciadas"
 
-#: src/transport/gnunet-transport.c:486
+#: src/transport/gnunet-transport.c:418
 #, c-format
 msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n"
 msgstr "Transmitidos %llu bytes/s (%llu bytes en %s)\n"
 
-#: src/transport/gnunet-transport.c:496
+#: src/transport/gnunet-transport.c:428
 #, c-format
 msgid "Received %llu bytes/s (%llu bytes in %s)\n"
 msgstr "Recibidos %llu bytes/s (%llu bytes en %s)\n"
 
-#: src/transport/gnunet-transport.c:540
+#: src/transport/gnunet-transport.c:472
 #, c-format
 msgid "Failed to connect to `%s'\n"
 msgstr "Se produjo un fallo al conectar con «%s»\n"
 
-#: src/transport/gnunet-transport.c:553
+#: src/transport/gnunet-transport.c:485
 #, c-format
 msgid "Failed to resolve address for peer `%s'\n"
 msgstr "Se produjo un fallo al resolver la dirección para el par «%s»\n"
 
 # Miguel: La traducción no es literal, pero me parece más correcta
 # en castellano.
-#: src/transport/gnunet-transport.c:565
+#: src/transport/gnunet-transport.c:499
 msgid "Failed to list connections, timeout occured\n"
 msgstr "No se pudieron listar las conexiones, expiró el plazo\n"
 
-#: src/transport/gnunet-transport.c:588
-#, fuzzy, c-format
-msgid "NAT plugin `%s' reports: %s\n"
-msgstr "Módulo de transporte: «%s» puerto %llu\n"
-
-#: src/transport/gnunet-transport.c:675
-msgid "No transport plugins configured, peer will never communicate\n"
-msgstr ""
-"No hay módulos de transporte configurados, el par nunca se comunicará\n"
-
-#: src/transport/gnunet-transport.c:689
-#, c-format
-msgid "No port configured for plugin `%s', cannot test it\n"
-msgstr ""
-"Ningún puerto fue configurado para el módulo «%s», no se puede probar\n"
-
-#: src/transport/gnunet-transport.c:714
-#, fuzzy
-msgid "Failed to start resolver!\n"
-msgstr "Se produjo un fallo al arrancar %s\n"
-
-#: src/transport/gnunet-transport.c:750
+#: src/transport/gnunet-transport.c:532
 #, fuzzy, c-format
 msgid "Transmitting %u bytes\n"
 msgstr "Transmitiendo %u bytes a %s\n"
 
-#: src/transport/gnunet-transport.c:784
+#: src/transport/gnunet-transport.c:566
 #, c-format
 msgid ""
 "Successfully connected to `%s', starting to send benchmark data in %u Kb "
@@ -7565,46 +7641,46 @@ msgstr ""
 "Conectado satisfactoriamente a «%s», empezando a mandar datos de prueba en "
 "bloques de %u Kb\n"
 
-#: src/transport/gnunet-transport.c:815
+#: src/transport/gnunet-transport.c:597
 #, c-format
 msgid "Disconnected from peer `%s' while benchmarking\n"
 msgstr "Desconectado del par «%s» mientras probaba\n"
 
-#: src/transport/gnunet-transport.c:839 src/transport/gnunet-transport.c:868
+#: src/transport/gnunet-transport.c:621 src/transport/gnunet-transport.c:650
 #, c-format
 msgid "%24s: %-17s %4s   (%u connections in total)\n"
 msgstr "%24s: %-17s %4s   (%u conexiones en total)\n"
 
-#: src/transport/gnunet-transport.c:841
+#: src/transport/gnunet-transport.c:623
 msgid "Connected to"
 msgstr "Conectado a"
 
-#: src/transport/gnunet-transport.c:870
+#: src/transport/gnunet-transport.c:652
 msgid "Disconnected from"
 msgstr "Desconectado de"
 
-#: src/transport/gnunet-transport.c:905
+#: src/transport/gnunet-transport.c:687
 #, fuzzy, c-format
 msgid "Received %u bytes\n"
 msgstr "Recibidos %u bytes de %s\n"
 
-#: src/transport/gnunet-transport.c:942
+#: src/transport/gnunet-transport.c:724
 #, c-format
 msgid "Peer `%s': %s %s in state `%s' until %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:954
+#: src/transport/gnunet-transport.c:736
 #, c-format
 msgid "Peer `%s': %s %s\n"
 msgstr "Par «%s»: %s %s\n"
 
-#: src/transport/gnunet-transport.c:1366
+#: src/transport/gnunet-transport.c:1150
 #, fuzzy
 msgid "Monitor disconnected from transport service. Reconnecting.\n"
 msgstr ""
 "El cliente se desconectó del servicio principal, tratando de reconectar.\n"
 
-#: src/transport/gnunet-transport.c:1488
+#: src/transport/gnunet-transport.c:1267
 #, fuzzy, c-format
 msgid ""
 "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, "
@@ -7613,7 +7689,7 @@ msgstr ""
 "Múltiples operaciones introducidas. Por favor, seleccione únicamente una "
 "operación: %s, %s, %s, %s, %s, %s\n"
 
-#: src/transport/gnunet-transport.c:1501
+#: src/transport/gnunet-transport.c:1280
 #, fuzzy, c-format
 msgid ""
 "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s, %s\n"
@@ -7621,72 +7697,68 @@ msgstr ""
 "Ninguna operación introducida. Por favor, seleccione alguna operación: %s, "
 "%s, %s, %s, %s, %s\n"
 
-#: src/transport/gnunet-transport.c:1529
+#: src/transport/gnunet-transport.c:1308
 #, fuzzy
 msgid "Failed to connect to transport service for disconnection\n"
 msgstr "Se produjo un fallo al conectar con el servicio de transporte\n"
 
-#: src/transport/gnunet-transport.c:1535
+#: src/transport/gnunet-transport.c:1314
 msgid "Blacklisting request in place, stop with CTRL-C\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1558 src/transport/gnunet-transport.c:1588
-#: src/transport/gnunet-transport.c:1641
+#: src/transport/gnunet-transport.c:1337 src/transport/gnunet-transport.c:1367
+#: src/transport/gnunet-transport.c:1420
 msgid "Failed to connect to transport service\n"
 msgstr "Se produjo un fallo al conectar con el servicio de transporte\n"
 
-#: src/transport/gnunet-transport.c:1595
+#: src/transport/gnunet-transport.c:1374
 msgid "Starting to receive benchmark data\n"
 msgstr "Empezando a recibir datos de prueba\n"
 
-#: src/transport/gnunet-transport.c:1665
+#: src/transport/gnunet-transport.c:1444
 #, fuzzy
 msgid "print information for all peers (instead of only connected peers)"
 msgstr "Imprime información sobre los pares conectados."
 
-#: src/transport/gnunet-transport.c:1668
+#: src/transport/gnunet-transport.c:1447
 msgid "measure how fast we are receiving data from all peers (until CTRL-C)"
 msgstr "medir cómo de rápido recibimos datos de todos los pares (hasta CTRL-C)"
 
-#: src/transport/gnunet-transport.c:1671
+#: src/transport/gnunet-transport.c:1450
 #, fuzzy
 msgid "disconnect from a peer"
 msgstr "conectar a un par"
 
-#: src/transport/gnunet-transport.c:1674
+#: src/transport/gnunet-transport.c:1453
 msgid "provide information about all current connections (once)"
 msgstr "provee información sobre todas las conexiones actuales (una vez)"
 
-#: src/transport/gnunet-transport.c:1680
+#: src/transport/gnunet-transport.c:1459
 msgid ""
 "provide information about all connects and disconnect events (continuously)"
 msgstr ""
 "provee información sobre todas los eventos de conexión y desconexión "
 "(continuamente)"
 
-#: src/transport/gnunet-transport.c:1683
+#: src/transport/gnunet-transport.c:1462
 msgid "do not resolve hostnames"
 msgstr "no resolver nombres de máquinas"
 
-#: src/transport/gnunet-transport.c:1686
+#: src/transport/gnunet-transport.c:1465
 #: src/transport/gnunet-transport-profiler.c:631
 msgid "peer identity"
 msgstr "identidad del par"
 
-#: src/transport/gnunet-transport.c:1689
+#: src/transport/gnunet-transport.c:1468
 #, fuzzy
 msgid "monitor plugin sessions"
 msgstr "# sesiones wlan pendientes"
 
-#: src/transport/gnunet-transport.c:1692
+#: src/transport/gnunet-transport.c:1471
 msgid "send data for benchmarking to the other peer (until CTRL-C)"
 msgstr "enviar data para prueba a otro par (hasta CTRL-C)"
 
-#: src/transport/gnunet-transport.c:1695
-msgid "test transport configuration (involves external server)"
-msgstr "probar configuración de transporte (requiere un servidor externo)"
-
-#: src/transport/gnunet-transport.c:1706
+#: src/transport/gnunet-transport.c:1482
 #: src/transport/gnunet-transport-profiler.c:642
 msgid "Direct access to transport service."
 msgstr "Acceso directo al servicio de transporte."
@@ -7722,9 +7794,9 @@ msgstr "tamaño del mensaje"
 
 #: src/transport/plugin_transport_http_client.c:1477
 #: src/transport/plugin_transport_http_server.c:2248
-#: src/transport/plugin_transport_http_server.c:3457
-#: src/transport/plugin_transport_tcp.c:3365
-#: src/transport/plugin_transport_tcp.c:3372
+#: src/transport/plugin_transport_http_server.c:3462
+#: src/transport/plugin_transport_tcp.c:3375
+#: src/transport/plugin_transport_tcp.c:3382
 msgid "TCP_STEALTH not supported on this platform.\n"
 msgstr ""
 
@@ -7736,13 +7808,13 @@ msgstr ""
 "módulo %s!\n"
 
 #: src/transport/plugin_transport_http_client.c:2167
-#: src/transport/plugin_transport_http_server.c:3172
+#: src/transport/plugin_transport_http_server.c:3177
 #, c-format
 msgid "Shutting down plugin `%s'\n"
 msgstr "Finalizando el módulo «%s»\n"
 
 #: src/transport/plugin_transport_http_client.c:2184
-#: src/transport/plugin_transport_http_server.c:3242
+#: src/transport/plugin_transport_http_server.c:3247
 #, c-format
 msgid "Shutdown for plugin `%s' complete\n"
 msgstr "Finalización del módulo «%s» completa\n"
@@ -7793,73 +7865,73 @@ msgstr ""
 msgid "Could not load or create server certificate! Loading plugin failed!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2583
+#: src/transport/plugin_transport_http_server.c:2586
 msgid "Require valid port number for service in configuration!\n"
 msgstr "¡Se necesita un puerto válido para el servicio en la configuración!\n"
 
-#: src/transport/plugin_transport_http_server.c:2748
+#: src/transport/plugin_transport_http_server.c:2751
 #, c-format
 msgid "Found %u addresses to report to NAT service\n"
 msgstr "Encontradas %u direcciones para comunicar al servicio NAT\n"
 
-#: src/transport/plugin_transport_http_server.c:2832
-#: src/transport/plugin_transport_udp.c:3600
+#: src/transport/plugin_transport_http_server.c:2837
+#: src/transport/plugin_transport_udp.c:3623
 msgid "Disabling IPv6 since it is not supported on this system!\n"
 msgstr "¡Deshabilitando IPv6 ya que no está soportado en este sistema!\n"
 
-#: src/transport/plugin_transport_http_server.c:2938
+#: src/transport/plugin_transport_http_server.c:2943
 #, c-format
 msgid "IPv4 support is %s\n"
 msgstr "El soporte IPv4 es %s\n"
 
-#: src/transport/plugin_transport_http_server.c:2953
+#: src/transport/plugin_transport_http_server.c:2958
 #, c-format
 msgid "IPv6 support is %s\n"
 msgstr "El soporte IPv6 es %s\n"
 
-#: src/transport/plugin_transport_http_server.c:2959
+#: src/transport/plugin_transport_http_server.c:2964
 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"
 msgstr "¡Ni IPv4 ni IPv6 están habilitadas! Corrija la configuración\n"
 
-#: src/transport/plugin_transport_http_server.c:2970
+#: src/transport/plugin_transport_http_server.c:2975
 msgid "Port is required! Fix in configuration\n"
 msgstr "¡El puerto es necesario! Corrija la configuración\n"
 
-#: src/transport/plugin_transport_http_server.c:2976
+#: src/transport/plugin_transport_http_server.c:2981
 #, c-format
 msgid "Using port %u\n"
 msgstr "Usando puerto %u\n"
 
-#: src/transport/plugin_transport_http_server.c:2995
+#: src/transport/plugin_transport_http_server.c:3000
 #, c-format
 msgid "Specific IPv4 address `%s' in configuration file is invalid!\n"
 msgstr ""
 "¡La dirección IPv4 «%s» especificada en el fichero de configuración no es "
 "válida!\n"
 
-#: src/transport/plugin_transport_http_server.c:3030
+#: src/transport/plugin_transport_http_server.c:3035
 #, c-format
 msgid "Specific IPv6 address `%s' in configuration file is invalid!\n"
 msgstr ""
 "¡La dirección IPv6 «%s» especificada en el fichero de configuración no es "
 "válida!\n"
 
-#: src/transport/plugin_transport_http_server.c:3105
+#: src/transport/plugin_transport_http_server.c:3110
 #, c-format
 msgid "Using external hostname `%s'\n"
 msgstr "Usando nombre de máquina externo «%s»\n"
 
-#: src/transport/plugin_transport_http_server.c:3126
+#: src/transport/plugin_transport_http_server.c:3131
 #, c-format
 msgid "Notifying transport only about hostname `%s'\n"
 msgstr "Notificando al transporte sólo el nombre de máquina «%s»\n"
 
-#: src/transport/plugin_transport_http_server.c:3143
+#: src/transport/plugin_transport_http_server.c:3148
 #, c-format
 msgid "Maximum number of connections is %u\n"
 msgstr "El número máximo de conexiones es %u\n"
 
-#: src/transport/plugin_transport_http_server.c:3469
+#: src/transport/plugin_transport_http_server.c:3474
 #, fuzzy
 msgid "Unable to compile URL regex\n"
 msgstr "¡Imposible obtener «HELLO» del par!\n"
@@ -7909,119 +7981,119 @@ msgstr "# bytes enviados vía SMTP"
 msgid "# bytes dropped by SMTP (outgoing)"
 msgstr "# bytes omitidos por SMTP (salientes)"
 
-#: src/transport/plugin_transport_tcp.c:1051
-#: src/transport/plugin_transport_tcp.c:2362
+#: src/transport/plugin_transport_tcp.c:1060
+#: src/transport/plugin_transport_tcp.c:2379
 #, c-format
 msgid "Unexpected address length: %u bytes\n"
 msgstr "Longitud de dirección inesperada: %u bytes\n"
 
-#: src/transport/plugin_transport_tcp.c:1234
-#: src/transport/plugin_transport_tcp.c:1458
-#: src/transport/plugin_transport_tcp.c:2633
-#: src/transport/plugin_transport_tcp.c:3490
+#: src/transport/plugin_transport_tcp.c:1243
+#: src/transport/plugin_transport_tcp.c:1467
+#: src/transport/plugin_transport_tcp.c:2643
+#: src/transport/plugin_transport_tcp.c:3498
 msgid "# TCP sessions active"
 msgstr "# Sesiones TCP activas"
 
-#: src/transport/plugin_transport_tcp.c:1276
-#: src/transport/plugin_transport_tcp.c:1440
-#: src/transport/plugin_transport_tcp.c:1564
-#: src/transport/plugin_transport_tcp.c:1637
-#: src/transport/plugin_transport_tcp.c:1737
-#: src/transport/plugin_transport_tcp.c:1762
+#: src/transport/plugin_transport_tcp.c:1285
+#: src/transport/plugin_transport_tcp.c:1449
+#: src/transport/plugin_transport_tcp.c:1573
+#: src/transport/plugin_transport_tcp.c:1646
+#: src/transport/plugin_transport_tcp.c:1746
+#: src/transport/plugin_transport_tcp.c:1771
 msgid "# bytes currently in TCP buffers"
 msgstr "# bytes actualmente en los buffer TCP"
 
-#: src/transport/plugin_transport_tcp.c:1279
+#: src/transport/plugin_transport_tcp.c:1288
 msgid "# bytes discarded by TCP (disconnect)"
 msgstr "# bytes descartados por TCP (desconectado)"
 
-#: src/transport/plugin_transport_tcp.c:1567
+#: src/transport/plugin_transport_tcp.c:1576
 msgid "# bytes discarded by TCP (timeout)"
 msgstr "# bytes omitidos por TCP (expirados)"
 
-#: src/transport/plugin_transport_tcp.c:1641
+#: src/transport/plugin_transport_tcp.c:1650
 msgid "# bytes transmitted via TCP"
 msgstr "# bytes recibidos vía TCP"
 
-#: src/transport/plugin_transport_tcp.c:2032
+#: src/transport/plugin_transport_tcp.c:2041
 msgid "# requests to create session with invalid address"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2200
+#: src/transport/plugin_transport_tcp.c:2217
 msgid "# transport-service disconnect requests for TCP"
 msgstr "# peticiones de desconexión del servicio de transporte por TCP"
 
-#: src/transport/plugin_transport_tcp.c:2692
+#: src/transport/plugin_transport_tcp.c:2702
 msgid "# TCP WELCOME messages received"
 msgstr "# Mensajes «WELCOME» TCP recibidos"
 
-#: src/transport/plugin_transport_tcp.c:2883
+#: src/transport/plugin_transport_tcp.c:2893
 msgid "# bytes received via TCP"
 msgstr "# bytes recibidos vía TCP"
 
-#: src/transport/plugin_transport_tcp.c:2934
-#: src/transport/plugin_transport_tcp.c:2992
+#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:3002
 #, fuzzy
 msgid "# TCP server connections active"
 msgstr "# conexiones «stream» activas"
 
-#: src/transport/plugin_transport_tcp.c:2938
+#: src/transport/plugin_transport_tcp.c:2948
 #, fuzzy
 msgid "# TCP server connect events"
 msgstr "# Pares conectados"
 
-#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:2954
 msgid "TCP connection limit reached, suspending server\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2946
+#: src/transport/plugin_transport_tcp.c:2956
 msgid "# TCP service suspended"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2986
+#: src/transport/plugin_transport_tcp.c:2996
 msgid "# TCP service resumed"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2996
+#: src/transport/plugin_transport_tcp.c:3006
 msgid "# network-level TCP disconnect events"
 msgstr "# eventos de desconexión TCP a nivel de red"
 
-#: src/transport/plugin_transport_tcp.c:3315
+#: src/transport/plugin_transport_tcp.c:3325
 msgid "Failed to start service.\n"
 msgstr "Se produjo un fallo al iniciar el servicio.\n"
 
-#: src/transport/plugin_transport_tcp.c:3478
+#: src/transport/plugin_transport_tcp.c:3486
 #, c-format
 msgid "TCP transport listening on port %llu\n"
 msgstr "Transporte TCP escuchando en el puerto %llu\n"
 
-#: src/transport/plugin_transport_tcp.c:3482
+#: src/transport/plugin_transport_tcp.c:3490
 msgid "TCP transport not listening on any port (client only)\n"
 msgstr "Transporte TCP no escuchando en ningún puerto (únicamente cliente)\n"
 
-#: src/transport/plugin_transport_tcp.c:3486
+#: src/transport/plugin_transport_tcp.c:3494
 #, c-format
 msgid "TCP transport advertises itself as being on port %llu\n"
 msgstr "El transporte TCP anuncia que está en el puerto %llu\n"
 
-#: src/transport/plugin_transport_udp_broadcasting.c:170
+#: src/transport/plugin_transport_udp_broadcasting.c:169
 #, fuzzy
 msgid "# Multicast HELLO beacons received via UDP"
 msgstr "# beacons HELLO multicast IPv6 recibidos vía UDP"
 
-#: src/transport/plugin_transport_udp_broadcasting.c:546
+#: src/transport/plugin_transport_udp_broadcasting.c:545
 msgid ""
 "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:567
+#: src/transport/plugin_transport_udp_broadcasting.c:566
 #, c-format
 msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n"
 msgstr ""
 "Se produjo un fallo al establecer la opción de «broadcast» IPv4 para el "
 "«socket» en el puerto %d\n"
 
-#: src/transport/plugin_transport_udp.c:3344
+#: src/transport/plugin_transport_udp.c:3367
 #, c-format
 msgid ""
 "UDP could not transmit message to `%s': Network seems down, please check "
@@ -8030,7 +8102,7 @@ msgstr ""
 "UDP no pudo transmitir el mensaje a «%s»: La red parece caída, por favor, "
 "compruebe su configuración de red\n"
 
-#: src/transport/plugin_transport_udp.c:3358
+#: src/transport/plugin_transport_udp.c:3381
 #, fuzzy
 msgid ""
 "UDP could not transmit IPv6 message! Please check your network configuration "
@@ -8040,37 +8112,37 @@ msgstr ""
 "configuración de red y deshabilite IPv6 si su conexión carece de una "
 "dirección IPv6 global\n"
 
-#: src/transport/plugin_transport_udp.c:3676
-#: src/transport/plugin_transport_udp.c:3775
+#: src/transport/plugin_transport_udp.c:3699
+#: src/transport/plugin_transport_udp.c:3798
 #, fuzzy, c-format
 msgid "Failed to bind UDP socket to %s: %s\n"
 msgstr "Se produjo un fallo al abrir los «sockets» UDP\n"
 
-#: src/transport/plugin_transport_udp.c:3694
+#: src/transport/plugin_transport_udp.c:3717
 #, fuzzy
 msgid "Disabling IPv4 since it is not supported on this system!\n"
 msgstr "¡Deshabilitando IPv6 ya que no está soportado en este sistema!\n"
 
-#: src/transport/plugin_transport_udp.c:3785
+#: src/transport/plugin_transport_udp.c:3808
 msgid "Failed to open UDP sockets\n"
 msgstr "Se produjo un fallo al abrir los «sockets» UDP\n"
 
-#: src/transport/plugin_transport_udp.c:3857
-#: src/transport/plugin_transport_udp.c:3871
+#: src/transport/plugin_transport_udp.c:3879
+#: src/transport/plugin_transport_udp.c:3893
 msgid "must be in [0,65535]"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3903
+#: src/transport/plugin_transport_udp.c:3925
 #, fuzzy
 msgid "must be valid IPv4 address"
 msgstr "«%s» no es una dirección IP válida.\n"
 
-#: src/transport/plugin_transport_udp.c:3930
+#: src/transport/plugin_transport_udp.c:3952
 #, fuzzy
 msgid "must be valid IPv6 address"
 msgstr "«%s» no es una dirección IP válida.\n"
 
-#: src/transport/plugin_transport_udp.c:3996
+#: src/transport/plugin_transport_udp.c:4018
 #, fuzzy
 msgid "Failed to create UDP network sockets\n"
 msgstr "Se produjo un fallo al crear una nueva firma"
@@ -8194,7 +8266,7 @@ msgstr "Los metadatos serializados «%s» son mayores de lo permitido (%u>%u)"
 msgid "Metadata `%s' failed to deserialize"
 msgstr "Se produjo un fallo al deserializar los metadatos «%s»"
 
-#: src/util/client_new.c:864
+#: src/util/client.c:864
 #, c-format
 msgid "Need a non-empty hostname for service `%s'.\n"
 msgstr "Se necesita un nombre de máquina no vacío para el servicio «%s».\n"
@@ -9001,42 +9073,42 @@ msgstr ""
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "Dirección IPv6 «%s» no válida: %s\n"
 
-#: src/util/strings.c:1475 src/util/strings.c:1491
+#: src/util/strings.c:1541 src/util/strings.c:1557
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1500
+#: src/util/strings.c:1566
 #, fuzzy, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr "Se produjo un fallo al iniciar el servicio «%s»\n"
 
-#: src/util/strings.c:1583 src/util/strings.c:1614 src/util/strings.c:1662
-#: src/util/strings.c:1683
+#: src/util/strings.c:1649 src/util/strings.c:1680 src/util/strings.c:1728
+#: src/util/strings.c:1749
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "Formato no válido para la IP: «%s»\n"
 
-#: src/util/strings.c:1640
+#: src/util/strings.c:1706
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "Notación de red no válida («/%d» no es válido en IPv4 CIDR)."
 
-#: src/util/strings.c:1692
+#: src/util/strings.c:1758
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "Formato de tiempo no válido «%s»\n"
 
-#: src/util/strings.c:1744
+#: src/util/strings.c:1810
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "Notación de red no válida (no termina con «;»: «%s»)\n"
 
-#: src/util/strings.c:1794
+#: src/util/strings.c:1860
 #, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "Formato «%s» erroneo para máscara de red\n"
 
-#: src/util/strings.c:1825
+#: src/util/strings.c:1891
 #, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "Formato «%s» erroneo para red\n"
@@ -9223,21 +9295,65 @@ msgid "Setup tunnels via VPN."
 msgstr "Configurar túneles vía VPN."
 
 #: src/include/gnunet_common.h:645 src/include/gnunet_common.h:652
-#: src/include/gnunet_common.h:660
+#: src/include/gnunet_common.h:662 src/include/gnunet_common.h:670
 #, c-format
 msgid "Assertion failed at %s:%d.\n"
 msgstr "Aserción fallida en %s:%d.\n"
 
-#: src/include/gnunet_common.h:672
+#: src/include/gnunet_common.h:682
 #, c-format
 msgid "External protocol violation detected at %s:%d.\n"
 msgstr "Violación externa del protocolo detectada en %s:%d.\n"
 
-#: src/include/gnunet_common.h:699 src/include/gnunet_common.h:708
+#: src/include/gnunet_common.h:709 src/include/gnunet_common.h:718
 #, c-format
 msgid "`%s' failed on file `%s' at %s:%d with error: %s\n"
 msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 
+#, fuzzy
+#~ msgid "Failed to run upnp client for port %u\n"
+#~ msgstr ""
+#~ "Se produjo un fallo al inicializar la clave de la máquina desde el par "
+#~ "%u\n"
+
+#~ msgid "malformed"
+#~ msgstr "mal formado"
+
+#~ msgid ""
+#~ "Configuration requires `%s', but binary is not installed properly (SUID "
+#~ "bit not set).  Option disabled.\n"
+#~ msgstr ""
+#~ "La configuración requiere «%s», pero el binario no está instalado de "
+#~ "forma correcta (SUID bit no activado).  Opción deshabilitada.\n"
+
+#~ msgid ""
+#~ "Internal IP address not known, cannot use ICMP NAT traversal method\n"
+#~ msgstr ""
+#~ "Direcciones internas IP no conocidas, no se puede usar el método del "
+#~ "recorrido NAT ICMP\n"
+
+#~ msgid "Running gnunet-helper-nat-client %s %s %u\n"
+#~ msgstr "Ejecutando gnunet-helper-nat-client %s %s %u\n"
+
+#, fuzzy
+#~ msgid "NAT plugin `%s' reports: %s\n"
+#~ msgstr "Módulo de transporte: «%s» puerto %llu\n"
+
+#~ msgid "No transport plugins configured, peer will never communicate\n"
+#~ msgstr ""
+#~ "No hay módulos de transporte configurados, el par nunca se comunicará\n"
+
+#~ msgid "No port configured for plugin `%s', cannot test it\n"
+#~ msgstr ""
+#~ "Ningún puerto fue configurado para el módulo «%s», no se puede probar\n"
+
+#, fuzzy
+#~ msgid "Failed to start resolver!\n"
+#~ msgstr "Se produjo un fallo al arrancar %s\n"
+
+#~ msgid "test transport configuration (involves external server)"
+#~ msgstr "probar configuración de transporte (requiere un servidor externo)"
+
 #, fuzzy
 #~ msgid "Unable to initialize Postgres: %s\n"
 #~ msgstr "No se pudo inicializar Postgres: %s"
@@ -11276,9 +11392,6 @@ msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 #~ "Par todavía no ejecutandose, no se puede cambiar la configuración en este "
 #~ "punto."
 
-#~ msgid "Failed to write new configuration to disk."
-#~ msgstr "Se produjo un fallo al guardar la nueva configuración al disco"
-
 #~ msgid "Could not start `%s' process to copy configuration file.\n"
 #~ msgstr ""
 #~ "No se pudo iniciar el proceso «%s» para copiar el fichero de "
@@ -11528,9 +11641,6 @@ msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 #~ msgid "# failed connection attempts due to timeout"
 #~ msgstr "# conexiones fallidas debido a expiración de plazo"
 
-#~ msgid "# peers disconnected due to external request"
-#~ msgstr "# pares desconectados debido a petición externa"
-
 #~ msgid "# peers disconnected due to timeout"
 #~ msgstr "# pares desconectados debido a expiración de plazo"
 
@@ -11549,9 +11659,6 @@ msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 #~ msgid "Found valid IPv4 NAT address (creating session)!\n"
 #~ msgstr "¡Encontrada una dirección NAT IPv4 válida (creando sesión)!\n"
 
-#~ msgid "Failed to find option %s in section %s!\n"
-#~ msgstr "¡Se produjo un fallo al buscar la opción %s en la sección %s!\n"
-
 #~ msgid "# wlan session timeouts"
 #~ msgstr "# expiraciones de plazo en sesiones wlan"
 
@@ -11836,10 +11943,6 @@ msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 #~ msgid "# HTTP peers active"
 #~ msgstr "# bytes recibidos por TCP"
 
-#, fuzzy
-#~ msgid "Misconfigured address to bind to in configuration!\n"
-#~ msgstr "¡Ninguna aplicación definida en la configuración!\n"
-
 #, fuzzy
 #~ msgid "Failed to load transport plugin for http\n"
 #~ msgstr "Imposible inicializar la aplicación '%s'\n"
@@ -12041,10 +12144,6 @@ msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 #~ "este valor más tarde. Si tienes una tarifa plana puedes configurarlo a la "
 #~ "máxima velocidad de tu conexión a Internet."
 
-#, fuzzy
-#~ msgid "Quota configuration"
-#~ msgstr "Configuración de GNUnet"
-
 #, fuzzy
 #~ msgid ""
 #~ "The GNUnet datastore contains all content that GNUnet needs to store "
@@ -12867,10 +12966,6 @@ msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 #~ "El contenido descifrado no encuentra una clave. Esto puede ser un bug o "
 #~ "un fichero introducido maliciosamente. Descarga abortada.\n"
 
-#, fuzzy
-#~ msgid "Application aborted."
-#~ msgstr "_Opciones"
-
 #~ msgid "FSUI state file `%s' had syntax error at offset %u.\n"
 #~ msgstr ""
 #~ "Fichero del estado de FSUI '%s' tiene un error de sintáxis en la "
@@ -13526,10 +13621,6 @@ msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 #~ msgid "Group:"
 #~ msgstr "Grupo:"
 
-#, fuzzy
-#~ msgid "Save configuration"
-#~ msgstr "Configuración de GNUnet"
-
 #, fuzzy
 #~ msgid "Show copyright information for gnunet-setup."
 #~ msgstr "Se produjo un error leyendo información de gnunetd.\n"
@@ -14183,11 +14274,6 @@ msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n"
 #~ msgid "Template for gnunet-clients."
 #~ msgstr "Plantilla para clientes-de-gnunet."
 
-#~ msgid "Invalid port \"%s\" in hostlist specification, trying port %d.\n"
-#~ msgstr ""
-#~ "Puerto inválido \"%s\" en la especificación de la lista local, probando "
-#~ "el puerto %d.\n"
-
 #~ msgid "Parsing HTTP response for URL `%s' failed.\n"
 #~ msgstr "Analizando HTTP de la URL '%s' se produjo un fallo.\n"
 
index a4df4ae7dd1f9443a2449ff49fc601d25c45b6d4..e287041e9486a4e11dd09cae699d29781953da42 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.10.1\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2016-11-27 09:18+0100\n"
+"POT-Creation-Date: 2017-01-12 17:19+0100\n"
 "PO-Revision-Date: 2015-12-24 01:20+0100\n"
 "Last-Translator: Stéphane  Aulery <lkppo@free.fr>\n"
 "Language-Team: French <traduc@traduc.org>\n"
@@ -244,21 +244,20 @@ msgstr ""
 #: src/arm/gnunet-service-arm.c:393 src/arm/gnunet-service-arm.c:399
 #: src/transport/plugin_transport_tcp.c:652
 #: src/transport/plugin_transport_tcp.c:658
-#: src/transport/plugin_transport_tcp.c:3299 src/util/service.c:584
-#: src/util/service.c:590 src/util/service_new.c:637
-#: src/util/service_new.c:643
+#: src/transport/plugin_transport_tcp.c:3309 src/util/service.c:584
+#: src/util/service.c:590 src/util/service_new.c:637 src/util/service_new.c:643
 #, c-format
 msgid "Require valid port number for service `%s' in configuration!\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:430 src/transport/plugin_transport_tcp.c:689
-#: src/util/client_new.c:464 src/util/service.c:621 src/util/service_new.c:682
+#: src/util/client.c:464 src/util/service.c:621 src/util/service_new.c:682
 #, c-format
 msgid "UNIXPATH `%s' too long, maximum length is %llu\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:434 src/transport/plugin_transport_tcp.c:693
-#: src/util/client_new.c:469 src/util/service.c:625 src/util/service_new.c:687
+#: src/util/client.c:469 src/util/service.c:625 src/util/service_new.c:687
 #, c-format
 msgid "Using `%s' instead\n"
 msgstr ""
@@ -278,7 +277,7 @@ msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:513
-#: src/transport/plugin_transport_http_server.c:2617
+#: src/transport/plugin_transport_http_server.c:2620
 #: src/transport/plugin_transport_tcp.c:772 src/util/service.c:704
 #: src/util/service_new.c:782
 #, c-format
@@ -286,7 +285,7 @@ msgid "Failed to resolve `%s': %s\n"
 msgstr "Résolution de « %s » échouée : %s\n"
 
 #: src/arm/gnunet-service-arm.c:532
-#: src/transport/plugin_transport_http_server.c:2635
+#: src/transport/plugin_transport_http_server.c:2638
 #: src/transport/plugin_transport_tcp.c:791 src/util/service.c:723
 #: src/util/service_new.c:802
 #, c-format
@@ -380,13 +379,11 @@ msgid ""
 "%llu\n"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3293
-#: src/ats-tests/gnunet-solver-eval.c:935
+#: src/ats/gnunet-ats-solver-eval.c:3293 src/ats-tests/gnunet-solver-eval.c:935
 msgid "solver to use"
 msgstr "solveur utilisé"
 
-#: src/ats/gnunet-ats-solver-eval.c:3296
-#: src/ats-tests/gnunet-solver-eval.c:938
+#: src/ats/gnunet-ats-solver-eval.c:3296 src/ats-tests/gnunet-solver-eval.c:938
 #: src/ats-tests/gnunet-solver-eval.c:941
 msgid "experiment to use"
 msgstr ""
@@ -491,12 +488,12 @@ msgstr ""
 msgid "Invalid %s configuration %f\n"
 msgstr "fornat invalide : « %s »\n"
 
-#: src/ats-tests/ats-testing.c:441
+#: src/ats-tests/ats-testing.c:422
 #, c-format
 msgid "Connected master [%u] with slave [%u]\n"
 msgstr ""
 
-#: src/ats-tests/ats-testing.c:448
+#: src/ats-tests/ats-testing.c:429
 #, c-format
 msgid "Failed to connect master peer [%u] with slave [%u]\n"
 msgstr ""
@@ -553,7 +550,7 @@ msgid "Quota for network `%11s' (in/out): %10s / %10s\n"
 msgstr ""
 
 #: src/ats-tool/gnunet-ats.c:748 src/ats-tool/gnunet-ats.c:761
-#: src/transport/gnunet-transport.c:1476
+#: src/transport/gnunet-transport.c:1255
 #, c-format
 msgid "Failed to parse peer identity `%s'\n"
 msgstr ""
@@ -633,6 +630,37 @@ msgstr ""
 msgid "Print information about ATS state"
 msgstr ""
 
+#: src/auction/gnunet-auction-create.c:69
+msgid "description of the item to be sold"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:72
+msgid "mapping of possible prices"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:75
+msgid "max duration per round"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:78
+msgid "duration until auction starts"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:81
+msgid "number of items to sell, 0 for first price auction"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:84
+msgid "public auction outcome"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:94 src/auction/gnunet-auction-info.c:76
+#: src/auction/gnunet-auction-join.c:76
+#: src/conversation/gnunet-conversation-test.c:243
+#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
+msgid "help text"
+msgstr ""
+
 #: src/cadet/gnunet-cadet.c:511
 #, c-format
 msgid "Invalid target `%s'\n"
@@ -684,7 +712,7 @@ msgstr ""
 msgid "provide information about all tunnels"
 msgstr ""
 
-#: src/cadet/gnunet-service-cadet_peer.c:681
+#: src/cadet/gnunet-service-cadet_peer.c:686
 msgid "Wrong CORE service\n"
 msgstr ""
 
@@ -1002,11 +1030,6 @@ msgid ""
 "played back to you..."
 msgstr ""
 
-#: src/conversation/gnunet-conversation-test.c:243
-#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
-msgid "help text"
-msgstr ""
-
 #: src/conversation/gnunet_gst.c:630
 #: src/conversation/gnunet-helper-audio-playback-gst.c:357
 #, c-format
@@ -1199,7 +1222,7 @@ msgstr ""
 msgid "Failed to connect to CORE service!\n"
 msgstr ""
 
-#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1677
+#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1456
 msgid "provide information about all current connections (continuously)"
 msgstr ""
 
@@ -1446,7 +1469,7 @@ msgstr ""
 #: src/testbed/gnunet-daemon-testbed-underlay.c:56
 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:52
 #: src/util/crypto_ecc_setup.c:41 src/util/crypto_mpi.c:39
-#: src/include/gnunet_common.h:681 src/include/gnunet_common.h:690
+#: src/include/gnunet_common.h:691 src/include/gnunet_common.h:700
 #: src/scalarproduct/scalarproduct.h:35
 #, c-format
 msgid "`%s' failed at %s:%d with error: %s\n"
@@ -1833,8 +1856,7 @@ msgstr ""
 msgid "Prints all packets that go through the DHT."
 msgstr ""
 
-#: src/dht/gnunet_dht_profiler.c:1161
-#: src/testbed/gnunet-testbed-profiler.c:255
+#: src/dht/gnunet_dht_profiler.c:1161 src/testbed/gnunet-testbed-profiler.c:255
 #, c-format
 msgid "Exiting as the number of peers is %u\n"
 msgstr ""
@@ -2010,8 +2032,7 @@ msgstr ""
 msgid "# GET requests given to datacache"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_hello.c:84
-#: src/dht/gnunet-service-xdht_hello.c:82
+#: src/dht/gnunet-service-dht_hello.c:84 src/dht/gnunet-service-xdht_hello.c:82
 msgid "# HELLOs obtained from peerinfo"
 msgstr ""
 
@@ -2076,35 +2097,35 @@ msgstr ""
 msgid "# P2P PUT bytes received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:1854
+#: src/dht/gnunet-service-dht_neighbours.c:1858
 msgid "# FIND PEER requests ignored due to Bloomfilter"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:1862
+#: src/dht/gnunet-service-dht_neighbours.c:1866
 msgid "# FIND PEER requests ignored due to lack of HELLO"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2018
+#: src/dht/gnunet-service-dht_neighbours.c:2022
 msgid "# P2P GET requests received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2022
+#: src/dht/gnunet-service-dht_neighbours.c:2026
 msgid "# P2P GET bytes received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2097
+#: src/dht/gnunet-service-dht_neighbours.c:2101
 msgid "# P2P FIND PEER requests processed"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2120
+#: src/dht/gnunet-service-dht_neighbours.c:2124
 msgid "# P2P GET requests ONLY routed"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2222
+#: src/dht/gnunet-service-dht_neighbours.c:2226
 msgid "# P2P RESULTS received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2226
+#: src/dht/gnunet-service-dht_neighbours.c:2230
 msgid "# P2P RESULT bytes received"
 msgstr ""
 
@@ -2112,35 +2133,35 @@ msgstr ""
 msgid "# Network size estimates received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:218
+#: src/dht/gnunet-service-dht_routing.c:220
 msgid "# Good REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:227
+#: src/dht/gnunet-service-dht_routing.c:229
 msgid "# Duplicate REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:233
+#: src/dht/gnunet-service-dht_routing.c:235
 msgid "# Invalid REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:239
+#: src/dht/gnunet-service-dht_routing.c:241
 msgid "# Irrelevant REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:251
+#: src/dht/gnunet-service-dht_routing.c:253
 msgid "# Unsupported REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:327
+#: src/dht/gnunet-service-dht_routing.c:329
 msgid "# Entries removed from routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:409
+#: src/dht/gnunet-service-dht_routing.c:411
 msgid "# Entries added to routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:427
+#: src/dht/gnunet-service-dht_routing.c:429
 msgid "# DHT requests combined"
 msgstr ""
 
@@ -2267,16 +2288,16 @@ msgstr ""
 "\n"
 "SUPU %s, %s, %d,my_identity = %s"
 
-#: src/dht/plugin_block_dht.c:142
+#: src/dht/plugin_block_dht.c:144
 #, c-format
 msgid "Block not of type %u\n"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:149
+#: src/dht/plugin_block_dht.c:151
 msgid "Size mismatch for block\n"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:159
+#: src/dht/plugin_block_dht.c:161
 #, c-format
 msgid "Block of type %u is malformed\n"
 msgstr ""
@@ -3350,7 +3371,7 @@ msgid "Option `%s' is required when using option `%s'.\n"
 msgstr ""
 
 #: src/fs/gnunet-publish.c:849 src/fs/gnunet-publish.c:857
-#: src/transport/gnunet-transport.c:1517 src/transport/gnunet-transport.c:1542
+#: src/transport/gnunet-transport.c:1296 src/transport/gnunet-transport.c:1321
 #, c-format
 msgid "Option `%s' makes no sense without option `%s'.\n"
 msgstr ""
@@ -3836,39 +3857,39 @@ msgstr ""
 msgid "Received unsupported DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:709
+#: src/gns/gnunet-dns2gns.c:712
 msgid "No ego configured for `dns2gns` subsystem\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:737
+#: src/gns/gnunet-dns2gns.c:740
 msgid "No DNS server specified!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:758
+#: src/gns/gnunet-dns2gns.c:761
 msgid "No valid GNS zone specified!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:779
+#: src/gns/gnunet-dns2gns.c:782
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:785
 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:785
+#: src/gns/gnunet-dns2gns.c:788
 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:788
+#: src/gns/gnunet-dns2gns.c:791
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:791
+#: src/gns/gnunet-dns2gns.c:794
 msgid "Public key of the GNS zone to use (overrides default)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:804
+#: src/gns/gnunet-dns2gns.c:807
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4027,80 +4048,82 @@ msgstr ""
 msgid "Unsupported HTTP method `%s'\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2167
+#: src/gns/gnunet-gns-proxy.c:2168
 #, c-format
 msgid "Unable to import private key from file `%s'\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2197
+#: src/gns/gnunet-gns-proxy.c:2198
 #, c-format
 msgid "Unable to import certificate %s\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2370
+#: src/gns/gnunet-gns-proxy.c:2371
 #, c-format
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2389 src/rest/gnunet-rest-server.c:533
+#: src/gns/gnunet-gns-proxy.c:2390 src/rest/gnunet-rest-server.c:533
 msgid "Failed to pass client to MHD\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2709
+#: src/gns/gnunet-gns-proxy.c:2710
 #, c-format
 msgid "Unsupported socks version %d\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2738
+#: src/gns/gnunet-gns-proxy.c:2739
 #, c-format
 msgid "Unsupported socks command %d\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2756 src/gns/gnunet-gns-proxy.c:2785
+#: src/gns/gnunet-gns-proxy.c:2757 src/gns/gnunet-gns-proxy.c:2786
 msgid "SSL connection to plain IPv4 address requested\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2836
+#: src/gns/gnunet-gns-proxy.c:2837
 #, c-format
 msgid "Unsupported socks address type %d\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3171
+#: src/gns/gnunet-gns-proxy.c:3172
 msgid "No ego configured for `shorten-zone`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3211 src/gns/gnunet-service-gns.c:1093
-#: src/gns/gnunet-service-gns.c:1149
+#: src/gns/gnunet-gns-proxy.c:3212 src/gns/gnunet-service-gns.c:493
+#: src/gns/gnunet-service-gns.c:548
 #, c-format
 msgid "No ego configured for `%s`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3273
+#: src/gns/gnunet-gns-proxy.c:3274
 #, c-format
 msgid "Failed to load SSL/TLS key and certificate from `%s'\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3313
+#: src/gns/gnunet-gns-proxy.c:3314
 msgid "listen on specified port (default: 7777)"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3316
+#: src/gns/gnunet-gns-proxy.c:3317
 msgid "pem file to use as CA"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3335
+#: src/gns/gnunet-gns-proxy.c:3336
 msgid "GNUnet GNS proxy"
 msgstr ""
 
-#: src/gns/gnunet-service-gns.c:1187
+#: src/gns/gnunet-service-gns.c:585
+#: src/zonemaster/gnunet-service-zonemaster.c:705
 msgid "Failed to connect to the namestore!\n"
 msgstr ""
 
-#: src/gns/gnunet-service-gns.c:1195
+#: src/gns/gnunet-service-gns.c:593
 msgid "Failed to connect to the namecache!\n"
 msgstr ""
 
-#: src/gns/gnunet-service-gns.c:1228
+#: src/gns/gnunet-service-gns.c:612
+#: src/zonemaster/gnunet-service-zonemaster.c:740
 msgid "Could not connect to DHT!\n"
 msgstr ""
 
@@ -4918,8 +4941,7 @@ msgstr "supprimer"
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:979
-#: src/peerinfo-tool/gnunet-peerinfo.c:775
+#: src/namestore/gnunet-namestore.c:979 src/peerinfo-tool/gnunet-peerinfo.c:775
 #, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "URI invalide « %s »\n"
@@ -5071,211 +5093,282 @@ msgstr ""
 msgid "Namestore REST API initialized\n"
 msgstr ""
 
-#: src/nat/gnunet-nat.c:159
-msgid "GNUnet NAT traversal autoconfigure daemon"
+#: src/nat-auto/gnunet-nat-auto.c:192
+msgid "Suggested configuration changes:\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:220
+#, fuzzy, c-format
+msgid "Failed to write configuration to `%s'\n"
+msgstr "fornat invalide : « %s »\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:227
+#, c-format
+msgid "Wrote updated configuration to `%s'\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:345
+#, fuzzy
+msgid "run autoconfiguration"
+msgstr "fornat invalide : « %s »\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:348
+msgid "section name providing the configuration for the adapter"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:351 src/nat/gnunet-nat.c:436
+msgid "use TCP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:354 src/nat/gnunet-nat.c:439
+msgid "use UDP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:357
+msgid "write configuration file (for autoconfiguration)"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:369
+msgid "GNUnet NAT traversal autoconfiguration"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:403
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:681
+#: src/nat-auto/nat_auto_api_test.c:405
+msgid "Failed to connect to `gnunet-nat-server'\n"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:321
+#: src/nat-auto/gnunet-nat-auto_legacy.c:518
+#: src/nat-auto/nat_auto_api_test.c:520
+#, c-format
+msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:568
+#: src/nat-auto/nat_auto_api_test.c:569
+msgid "NAT test failed to start NAT library\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-server.c:336
 #, c-format
 msgid "Please pass valid port number as the first argument! (got `%s')\n"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:363
+#: src/nat-auto/gnunet-nat-server.c:386
 msgid "GNUnet NAT traversal test helper daemon"
 msgstr ""
 
-#: src/nat/nat_api.c:880 src/nat/nat.c:2010
+#: src/nat-auto/gnunet-service-nat-auto.c:342
+msgid "UPnP client `upnpc` command not found, disabling UPnP\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:385
+msgid "NAT traversal with ICMP Server succeeded.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:386
+msgid "NAT traversal with ICMP Server failed.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:405
+msgid "Testing connection reversal with ICMP server.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:437
+#, c-format
+msgid "Detected external IP `%s'\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:572
+msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:590
+#, c-format
+msgid "Detected internal network address `%s'.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:724
+msgid "upnpc found, enabling its use\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:725
+msgid "upnpc not found\n"
+msgstr "upnpc introuvable\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:762
+msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:774
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:834
+msgid "test_icmp_server not possible, as we are not behind NAT\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:786
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:846
+msgid "No working gnunet-helper-nat-server found\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:823
+msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/nat_auto_api.c:76
 msgid "Operation Successful"
 msgstr ""
 
-#: src/nat/nat_api.c:882 src/nat/nat.c:2012
-msgid "Internal Failure (IPC, ...)"
+#: src/nat-auto/nat_auto_api.c:78
+msgid "IPC failure"
 msgstr ""
 
-#: src/nat/nat_api.c:884 src/nat/nat.c:2014
+#: src/nat-auto/nat_auto_api.c:80
 msgid "Failure in network subsystem, check permissions."
 msgstr ""
 
-#: src/nat/nat_api.c:886 src/nat/nat.c:2016
+#: src/nat-auto/nat_auto_api.c:82
 msgid "Encountered timeout while performing operation"
 msgstr ""
 
-#: src/nat/nat_api.c:888 src/nat/nat.c:2018
+#: src/nat-auto/nat_auto_api.c:84
 msgid "detected that we are offline"
 msgstr ""
 
-#: src/nat/nat_api.c:890 src/nat/nat.c:2020
+#: src/nat-auto/nat_auto_api.c:86
 msgid "`upnpc` command not found"
 msgstr ""
 
-#: src/nat/nat_api.c:892 src/nat/nat.c:2022
+#: src/nat-auto/nat_auto_api.c:88
 msgid "Failed to run `upnpc` command"
 msgstr ""
 
-#: src/nat/nat_api.c:894 src/nat/nat.c:2024
+#: src/nat-auto/nat_auto_api.c:90
 msgid "`upnpc' command took too long, process killed"
 msgstr ""
 
-#: src/nat/nat_api.c:896 src/nat/nat.c:2026
+#: src/nat-auto/nat_auto_api.c:92
 msgid "`upnpc' command failed to establish port mapping"
 msgstr ""
 
-#: src/nat/nat_api.c:898 src/nat/nat.c:2028
+#: src/nat-auto/nat_auto_api.c:94
 msgid "`external-ip' command not found"
 msgstr ""
 
-#: src/nat/nat_api.c:900 src/nat/nat.c:2030
+#: src/nat-auto/nat_auto_api.c:96
 msgid "Failed to run `external-ip` command"
 msgstr ""
 
-#: src/nat/nat_api.c:902 src/nat/nat.c:2032
+#: src/nat-auto/nat_auto_api.c:98
 msgid "`external-ip' command output invalid"
 msgstr ""
 
-#: src/nat/nat_api.c:904 src/nat/nat.c:2034
+#: src/nat-auto/nat_auto_api.c:100
 msgid "no valid address was returned by `external-ip'"
 msgstr ""
 
-#: src/nat/nat_api.c:906 src/nat/nat.c:2036
+#: src/nat-auto/nat_auto_api.c:102
 msgid "Could not determine interface with internal/local network address"
 msgstr ""
 
-#: src/nat/nat_api.c:908 src/nat/nat.c:2038
+#: src/nat-auto/nat_auto_api.c:104
 msgid "No functioning gnunet-helper-nat-server installation found"
 msgstr ""
 
-#: src/nat/nat_api.c:910 src/nat/nat.c:2040
+#: src/nat-auto/nat_auto_api.c:106
 msgid "NAT test could not be initialized"
 msgstr ""
 
-#: src/nat/nat_api.c:912 src/nat/nat.c:2042
+#: src/nat-auto/nat_auto_api.c:108
 msgid "NAT test timeout reached"
 msgstr ""
 
-#: src/nat/nat_api.c:914 src/nat/nat.c:2044
+#: src/nat-auto/nat_auto_api.c:110
 msgid "could not register NAT"
 msgstr ""
 
-#: src/nat/nat_api.c:916 src/nat/nat.c:2046
+#: src/nat-auto/nat_auto_api.c:112
 msgid "No working gnunet-helper-nat-client installation found"
 msgstr ""
 
-#: src/nat/nat_auto.c:385
-msgid "NAT traversal with ICMP Server succeeded.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:386
-msgid "NAT traversal with ICMP Server failed.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:405
-msgid "Testing connection reversal with ICMP server.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:437
-#, c-format
-msgid "Detected external IP `%s'\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:572
-msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
-msgstr ""
+#: src/nat-auto/nat_auto_api_test.c:477
+#, fuzzy, c-format
+msgid "Failed to find valid PORT in section `%s'\n"
+msgstr "Résolution de « %s » échouée : %s\n"
 
-#: src/nat/nat_auto.c:590
-#, c-format
-msgid "Detected internal network address `%s'.\n"
+#: src/nat/gnunet-nat.c:424
+msgid "which IP and port are we locally using to bind/listen to"
 msgstr ""
 
-#: src/nat/nat_auto.c:681 src/nat/nat_test.c:403
-msgid "Failed to connect to `gnunet-nat-server'\n"
+#: src/nat/gnunet-nat.c:427
+msgid "which remote IP and port should be asked for connection reversal"
 msgstr ""
 
-#: src/nat/nat_auto.c:724
-msgid "upnpc found, enabling its use\n"
+#: src/nat/gnunet-nat.c:430
+msgid ""
+"name of configuration section to find additional options, such as manual "
+"host punching data"
 msgstr ""
 
-#: src/nat/nat_auto.c:725
-msgid "upnpc not found\n"
-msgstr "upnpc introuvable\n"
-
-#: src/nat/nat_auto.c:762
-msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+#: src/nat/gnunet-nat.c:433
+msgid "enable STUN processing"
 msgstr ""
 
-#: src/nat/nat_auto.c:774 src/nat/nat_auto.c:834
-msgid "test_icmp_server not possible, as we are not behind NAT\n"
+#: src/nat/gnunet-nat.c:442
+msgid "watch for connection reversal requests"
 msgstr ""
 
-#: src/nat/nat_auto.c:786 src/nat/nat_auto.c:846
-msgid "No working gnunet-helper-nat-server found\n"
+#: src/nat/gnunet-nat.c:454
+msgid "GNUnet NAT traversal autoconfigure daemon"
 msgstr ""
 
-#: src/nat/nat_auto.c:823
-msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+#: src/nat/gnunet-service-nat.c:1313
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1019
+#: src/nat/gnunet-service-nat.c:1323
 #, c-format
-msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
+msgid "Invalid port number in punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1070
+#: src/nat/gnunet-service-nat.c:1339
 #, c-format
-msgid "Failed to start %s\n"
-msgstr "Échec du démarrage de %s\n"
-
-#: src/nat/nat.c:1327
-msgid "Error while running upnp client:\n"
+msgid "Malformed punched hole specification `%s' (lacks `]')\n"
 msgstr ""
 
-#: src/nat/nat.c:1402
+#: src/nat/gnunet-service-nat.c:1350
 #, c-format
-msgid "Failed to run upnp client for port %u\n"
+msgid "Malformed punched hole specification `%s' (IPv6 address invalid)"
 msgstr ""
 
-#: src/nat/nat.c:1546
-msgid "malformed"
-msgstr "malformé"
+#: src/nat/gnunet-service-nat.c:1803
+msgid "Connection reversal request failed\n"
+msgstr ""
 
-#: src/nat/nat.c:1600
+#: src/nat/gnunet-service-nat.c:1876
 msgid ""
 "UPnP enabled in configuration, but UPnP client `upnpc` command not found, "
-"disabling UPnP \n"
+"disabling UPnP\n"
 msgstr ""
 
-#: src/nat/nat.c:1726 src/nat/nat.c:1739
+#: src/nat/gnunet-service-nat_helper.c:186
 #, c-format
-msgid ""
-"Configuration requires `%s', but binary is not installed properly (SUID bit "
-"not set).  Option disabled.\n"
-msgstr ""
-
-#: src/nat/nat.c:1903
-msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n"
+msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/nat.c:1919
+#: src/nat/gnunet-service-nat_helper.c:260
 #, c-format
-msgid "Running gnunet-helper-nat-client %s %s %u\n"
-msgstr ""
+msgid "Failed to start %s\n"
+msgstr "Échec du démarrage de %s\n"
 
-#: src/nat/nat_mini.c:205
+#: src/nat/gnunet-service-nat_mini.c:196
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/nat_mini.c:611
+#: src/nat/gnunet-service-nat_mini.c:654
 msgid "`upnpc' command not found\n"
 msgstr ""
 
-#: src/nat/nat_test.c:518
-#, c-format
-msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
-msgstr ""
-
-#: src/nat/nat_test.c:568
-msgid "NAT test failed to start NAT library\n"
-msgstr ""
-
 #: src/nse/gnunet-nse.c:122
 msgid "Show network size estimates from NSE service."
 msgstr ""
@@ -6974,171 +7067,148 @@ msgstr ""
 msgid "# validations succeeded"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:486
+#: src/transport/gnunet-transport.c:418
 #, c-format
 msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:496
+#: src/transport/gnunet-transport.c:428
 #, c-format
 msgid "Received %llu bytes/s (%llu bytes in %s)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:540
+#: src/transport/gnunet-transport.c:472
 #, c-format
 msgid "Failed to connect to `%s'\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:553
+#: src/transport/gnunet-transport.c:485
 #, c-format
 msgid "Failed to resolve address for peer `%s'\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:565
+#: src/transport/gnunet-transport.c:499
 msgid "Failed to list connections, timeout occured\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:588
-#, c-format
-msgid "NAT plugin `%s' reports: %s\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:675
-msgid "No transport plugins configured, peer will never communicate\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:689
-#, c-format
-msgid "No port configured for plugin `%s', cannot test it\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:714
-#, fuzzy
-msgid "Failed to start resolver!\n"
-msgstr "Échec du démarrage de %s\n"
-
-#: src/transport/gnunet-transport.c:750
+#: src/transport/gnunet-transport.c:532
 #, c-format
 msgid "Transmitting %u bytes\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:784
+#: src/transport/gnunet-transport.c:566
 #, c-format
 msgid ""
 "Successfully connected to `%s', starting to send benchmark data in %u Kb "
 "blocks\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:815
+#: src/transport/gnunet-transport.c:597
 #, c-format
 msgid "Disconnected from peer `%s' while benchmarking\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:839 src/transport/gnunet-transport.c:868
+#: src/transport/gnunet-transport.c:621 src/transport/gnunet-transport.c:650
 #, c-format
 msgid "%24s: %-17s %4s   (%u connections in total)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:841
+#: src/transport/gnunet-transport.c:623
 msgid "Connected to"
 msgstr "Connecté à"
 
-#: src/transport/gnunet-transport.c:870
+#: src/transport/gnunet-transport.c:652
 msgid "Disconnected from"
 msgstr "Déconnecté de"
 
-#: src/transport/gnunet-transport.c:905
+#: src/transport/gnunet-transport.c:687
 #, fuzzy, c-format
 msgid "Received %u bytes\n"
 msgstr "%s message(s) reçu(s)\n"
 
-#: src/transport/gnunet-transport.c:942
+#: src/transport/gnunet-transport.c:724
 #, c-format
 msgid "Peer `%s': %s %s in state `%s' until %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:954
+#: src/transport/gnunet-transport.c:736
 #, c-format
 msgid "Peer `%s': %s %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1366
+#: src/transport/gnunet-transport.c:1150
 msgid "Monitor disconnected from transport service. Reconnecting.\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1488
+#: src/transport/gnunet-transport.c:1267
 #, c-format
 msgid ""
 "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, "
 "%s, %s %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1501
+#: src/transport/gnunet-transport.c:1280
 #, c-format
 msgid ""
 "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s, %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1529
+#: src/transport/gnunet-transport.c:1308
 msgid "Failed to connect to transport service for disconnection\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1535
+#: src/transport/gnunet-transport.c:1314
 msgid "Blacklisting request in place, stop with CTRL-C\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1558 src/transport/gnunet-transport.c:1588
-#: src/transport/gnunet-transport.c:1641
+#: src/transport/gnunet-transport.c:1337 src/transport/gnunet-transport.c:1367
+#: src/transport/gnunet-transport.c:1420
 msgid "Failed to connect to transport service\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1595
+#: src/transport/gnunet-transport.c:1374
 msgid "Starting to receive benchmark data\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1665
+#: src/transport/gnunet-transport.c:1444
 msgid "print information for all peers (instead of only connected peers)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1668
+#: src/transport/gnunet-transport.c:1447
 msgid "measure how fast we are receiving data from all peers (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1671
+#: src/transport/gnunet-transport.c:1450
 msgid "disconnect from a peer"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1674
+#: src/transport/gnunet-transport.c:1453
 msgid "provide information about all current connections (once)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1680
+#: src/transport/gnunet-transport.c:1459
 msgid ""
 "provide information about all connects and disconnect events (continuously)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1683
+#: src/transport/gnunet-transport.c:1462
 msgid "do not resolve hostnames"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1686
+#: src/transport/gnunet-transport.c:1465
 #: src/transport/gnunet-transport-profiler.c:631
 msgid "peer identity"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1689
+#: src/transport/gnunet-transport.c:1468
 msgid "monitor plugin sessions"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1692
+#: src/transport/gnunet-transport.c:1471
 msgid "send data for benchmarking to the other peer (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1695
-msgid "test transport configuration (involves external server)"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:1706
+#: src/transport/gnunet-transport.c:1482
 #: src/transport/gnunet-transport-profiler.c:642
 msgid "Direct access to transport service."
 msgstr ""
@@ -7171,9 +7241,9 @@ msgstr ""
 
 #: src/transport/plugin_transport_http_client.c:1477
 #: src/transport/plugin_transport_http_server.c:2248
-#: src/transport/plugin_transport_http_server.c:3457
-#: src/transport/plugin_transport_tcp.c:3365
-#: src/transport/plugin_transport_tcp.c:3372
+#: src/transport/plugin_transport_http_server.c:3462
+#: src/transport/plugin_transport_tcp.c:3375
+#: src/transport/plugin_transport_tcp.c:3382
 msgid "TCP_STEALTH not supported on this platform.\n"
 msgstr ""
 
@@ -7183,13 +7253,13 @@ msgid "Could not initialize curl multi handle, failed to start %s plugin!\n"
 msgstr ""
 
 #: src/transport/plugin_transport_http_client.c:2167
-#: src/transport/plugin_transport_http_server.c:3172
+#: src/transport/plugin_transport_http_server.c:3177
 #, c-format
 msgid "Shutting down plugin `%s'\n"
 msgstr ""
 
 #: src/transport/plugin_transport_http_client.c:2184
-#: src/transport/plugin_transport_http_server.c:3242
+#: src/transport/plugin_transport_http_server.c:3247
 #, c-format
 msgid "Shutdown for plugin `%s' complete\n"
 msgstr ""
@@ -7232,69 +7302,69 @@ msgstr ""
 msgid "Could not load or create server certificate! Loading plugin failed!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2583
+#: src/transport/plugin_transport_http_server.c:2586
 msgid "Require valid port number for service in configuration!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2748
+#: src/transport/plugin_transport_http_server.c:2751
 #, c-format
 msgid "Found %u addresses to report to NAT service\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2832
-#: src/transport/plugin_transport_udp.c:3600
+#: src/transport/plugin_transport_http_server.c:2837
+#: src/transport/plugin_transport_udp.c:3623
 msgid "Disabling IPv6 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2938
+#: src/transport/plugin_transport_http_server.c:2943
 #, c-format
 msgid "IPv4 support is %s\n"
 msgstr "Prise en charge d’IPv4 %s\n"
 
-#: src/transport/plugin_transport_http_server.c:2953
+#: src/transport/plugin_transport_http_server.c:2958
 #, c-format
 msgid "IPv6 support is %s\n"
 msgstr "Prise en charge d’IPv6 %s\n"
 
-#: src/transport/plugin_transport_http_server.c:2959
+#: src/transport/plugin_transport_http_server.c:2964
 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2970
+#: src/transport/plugin_transport_http_server.c:2975
 msgid "Port is required! Fix in configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2976
+#: src/transport/plugin_transport_http_server.c:2981
 #, c-format
 msgid "Using port %u\n"
 msgstr "Utilisation du port %u\n"
 
-#: src/transport/plugin_transport_http_server.c:2995
+#: src/transport/plugin_transport_http_server.c:3000
 #, c-format
 msgid "Specific IPv4 address `%s' in configuration file is invalid!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3030
+#: src/transport/plugin_transport_http_server.c:3035
 #, c-format
 msgid "Specific IPv6 address `%s' in configuration file is invalid!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3105
+#: src/transport/plugin_transport_http_server.c:3110
 #, c-format
 msgid "Using external hostname `%s'\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3126
+#: src/transport/plugin_transport_http_server.c:3131
 #, c-format
 msgid "Notifying transport only about hostname `%s'\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3143
+#: src/transport/plugin_transport_http_server.c:3148
 #, c-format
 msgid "Maximum number of connections is %u\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3469
+#: src/transport/plugin_transport_http_server.c:3474
 msgid "Unable to compile URL regex\n"
 msgstr ""
 
@@ -7340,157 +7410,157 @@ msgstr ""
 msgid "# bytes dropped by SMTP (outgoing)"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1051
-#: src/transport/plugin_transport_tcp.c:2362
+#: src/transport/plugin_transport_tcp.c:1060
+#: src/transport/plugin_transport_tcp.c:2379
 #, c-format
 msgid "Unexpected address length: %u bytes\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1234
-#: src/transport/plugin_transport_tcp.c:1458
-#: src/transport/plugin_transport_tcp.c:2633
-#: src/transport/plugin_transport_tcp.c:3490
+#: src/transport/plugin_transport_tcp.c:1243
+#: src/transport/plugin_transport_tcp.c:1467
+#: src/transport/plugin_transport_tcp.c:2643
+#: src/transport/plugin_transport_tcp.c:3498
 msgid "# TCP sessions active"
 msgstr "# Session TCP active"
 
-#: src/transport/plugin_transport_tcp.c:1276
-#: src/transport/plugin_transport_tcp.c:1440
-#: src/transport/plugin_transport_tcp.c:1564
-#: src/transport/plugin_transport_tcp.c:1637
-#: src/transport/plugin_transport_tcp.c:1737
-#: src/transport/plugin_transport_tcp.c:1762
+#: src/transport/plugin_transport_tcp.c:1285
+#: src/transport/plugin_transport_tcp.c:1449
+#: src/transport/plugin_transport_tcp.c:1573
+#: src/transport/plugin_transport_tcp.c:1646
+#: src/transport/plugin_transport_tcp.c:1746
+#: src/transport/plugin_transport_tcp.c:1771
 msgid "# bytes currently in TCP buffers"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1279
+#: src/transport/plugin_transport_tcp.c:1288
 msgid "# bytes discarded by TCP (disconnect)"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1567
+#: src/transport/plugin_transport_tcp.c:1576
 msgid "# bytes discarded by TCP (timeout)"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1641
+#: src/transport/plugin_transport_tcp.c:1650
 msgid "# bytes transmitted via TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2032
+#: src/transport/plugin_transport_tcp.c:2041
 msgid "# requests to create session with invalid address"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2200
+#: src/transport/plugin_transport_tcp.c:2217
 msgid "# transport-service disconnect requests for TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2692
+#: src/transport/plugin_transport_tcp.c:2702
 msgid "# TCP WELCOME messages received"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2883
+#: src/transport/plugin_transport_tcp.c:2893
 msgid "# bytes received via TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2934
-#: src/transport/plugin_transport_tcp.c:2992
+#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:3002
 #, fuzzy
 msgid "# TCP server connections active"
 msgstr "# Session TCP active"
 
-#: src/transport/plugin_transport_tcp.c:2938
+#: src/transport/plugin_transport_tcp.c:2948
 msgid "# TCP server connect events"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:2954
 msgid "TCP connection limit reached, suspending server\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2946
+#: src/transport/plugin_transport_tcp.c:2956
 msgid "# TCP service suspended"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2986
+#: src/transport/plugin_transport_tcp.c:2996
 msgid "# TCP service resumed"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2996
+#: src/transport/plugin_transport_tcp.c:3006
 msgid "# network-level TCP disconnect events"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3315
+#: src/transport/plugin_transport_tcp.c:3325
 msgid "Failed to start service.\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3478
+#: src/transport/plugin_transport_tcp.c:3486
 #, c-format
 msgid "TCP transport listening on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3482
+#: src/transport/plugin_transport_tcp.c:3490
 msgid "TCP transport not listening on any port (client only)\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3486
+#: src/transport/plugin_transport_tcp.c:3494
 #, c-format
 msgid "TCP transport advertises itself as being on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:170
+#: src/transport/plugin_transport_udp_broadcasting.c:169
 msgid "# Multicast HELLO beacons received via UDP"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:546
+#: src/transport/plugin_transport_udp_broadcasting.c:545
 msgid ""
 "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:567
+#: src/transport/plugin_transport_udp_broadcasting.c:566
 #, c-format
 msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3344
+#: src/transport/plugin_transport_udp.c:3367
 #, c-format
 msgid ""
 "UDP could not transmit message to `%s': Network seems down, please check "
 "your network configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3358
+#: src/transport/plugin_transport_udp.c:3381
 msgid ""
 "UDP could not transmit IPv6 message! Please check your network configuration "
 "and disable IPv6 if your connection does not have a global IPv6 address\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3676
-#: src/transport/plugin_transport_udp.c:3775
+#: src/transport/plugin_transport_udp.c:3699
+#: src/transport/plugin_transport_udp.c:3798
 #, fuzzy, c-format
 msgid "Failed to bind UDP socket to %s: %s\n"
 msgstr "Résolution de « %s » échouée : %s\n"
 
-#: src/transport/plugin_transport_udp.c:3694
+#: src/transport/plugin_transport_udp.c:3717
 msgid "Disabling IPv4 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3785
+#: src/transport/plugin_transport_udp.c:3808
 msgid "Failed to open UDP sockets\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3857
-#: src/transport/plugin_transport_udp.c:3871
+#: src/transport/plugin_transport_udp.c:3879
+#: src/transport/plugin_transport_udp.c:3893
 msgid "must be in [0,65535]"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3903
+#: src/transport/plugin_transport_udp.c:3925
 #, fuzzy
 msgid "must be valid IPv4 address"
 msgstr "adresse invalide"
 
-#: src/transport/plugin_transport_udp.c:3930
+#: src/transport/plugin_transport_udp.c:3952
 #, fuzzy
 msgid "must be valid IPv6 address"
 msgstr "adresse invalide"
 
-#: src/transport/plugin_transport_udp.c:3996
+#: src/transport/plugin_transport_udp.c:4018
 msgid "Failed to create UDP network sockets\n"
 msgstr ""
 
@@ -7600,7 +7670,7 @@ msgstr ""
 msgid "Metadata `%s' failed to deserialize"
 msgstr ""
 
-#: src/util/client_new.c:864
+#: src/util/client.c:864
 #, c-format
 msgid "Need a non-empty hostname for service `%s'.\n"
 msgstr ""
@@ -8360,42 +8430,42 @@ msgstr ""
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr ""
 
-#: src/util/strings.c:1475 src/util/strings.c:1491
+#: src/util/strings.c:1541 src/util/strings.c:1557
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1500
+#: src/util/strings.c:1566
 #, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1583 src/util/strings.c:1614 src/util/strings.c:1662
-#: src/util/strings.c:1683
+#: src/util/strings.c:1649 src/util/strings.c:1680 src/util/strings.c:1728
+#: src/util/strings.c:1749
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1640
+#: src/util/strings.c:1706
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr ""
 
-#: src/util/strings.c:1692
+#: src/util/strings.c:1758
 #, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "fornat invalide : « %s »\n"
 
-#: src/util/strings.c:1744
+#: src/util/strings.c:1810
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr ""
 
-#: src/util/strings.c:1794
+#: src/util/strings.c:1860
 #, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr ""
 
-#: src/util/strings.c:1825
+#: src/util/strings.c:1891
 #, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr ""
@@ -8569,21 +8639,28 @@ msgid "Setup tunnels via VPN."
 msgstr "Configurer des tunnels via VPN."
 
 #: src/include/gnunet_common.h:645 src/include/gnunet_common.h:652
-#: src/include/gnunet_common.h:660
+#: src/include/gnunet_common.h:662 src/include/gnunet_common.h:670
 #, c-format
 msgid "Assertion failed at %s:%d.\n"
 msgstr ""
 
-#: src/include/gnunet_common.h:672
+#: src/include/gnunet_common.h:682
 #, c-format
 msgid "External protocol violation detected at %s:%d.\n"
 msgstr ""
 
-#: src/include/gnunet_common.h:699 src/include/gnunet_common.h:708
+#: src/include/gnunet_common.h:709 src/include/gnunet_common.h:718
 #, c-format
 msgid "`%s' failed on file `%s' at %s:%d with error: %s\n"
 msgstr ""
 
+#~ msgid "malformed"
+#~ msgstr "malformé"
+
+#, fuzzy
+#~ msgid "Failed to start resolver!\n"
+#~ msgstr "Échec du démarrage de %s\n"
+
 #, fuzzy
 #~ msgid "Failed to start NAT test for plugin `%s'\n"
 #~ msgstr "Résolution de « %s » échouée\n"
index 5b3effdae691b59e757f900981ca3b1345f0bb82..6cf121b0e68795e8c9129c351d8aa0b7462b69d7 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GNUnet 0.7.0b\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2016-11-27 09:18+0100\n"
+"POT-Creation-Date: 2017-01-12 17:19+0100\n"
 "PO-Revision-Date: 2006-01-21 17:16+0100\n"
 "Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -251,21 +251,20 @@ msgstr ""
 #: src/arm/gnunet-service-arm.c:393 src/arm/gnunet-service-arm.c:399
 #: src/transport/plugin_transport_tcp.c:652
 #: src/transport/plugin_transport_tcp.c:658
-#: src/transport/plugin_transport_tcp.c:3299 src/util/service.c:584
-#: src/util/service.c:590 src/util/service_new.c:637
-#: src/util/service_new.c:643
+#: src/transport/plugin_transport_tcp.c:3309 src/util/service.c:584
+#: src/util/service.c:590 src/util/service_new.c:637 src/util/service_new.c:643
 #, c-format
 msgid "Require valid port number for service `%s' in configuration!\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:430 src/transport/plugin_transport_tcp.c:689
-#: src/util/client_new.c:464 src/util/service.c:621 src/util/service_new.c:682
+#: src/util/client.c:464 src/util/service.c:621 src/util/service_new.c:682
 #, c-format
 msgid "UNIXPATH `%s' too long, maximum length is %llu\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:434 src/transport/plugin_transport_tcp.c:693
-#: src/util/client_new.c:469 src/util/service.c:625 src/util/service_new.c:687
+#: src/util/client.c:469 src/util/service.c:625 src/util/service_new.c:687
 #, fuzzy, c-format
 msgid "Using `%s' instead\n"
 msgstr "%s: flagga \"%s\" är tvetydig\n"
@@ -285,7 +284,7 @@ msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:513
-#: src/transport/plugin_transport_http_server.c:2617
+#: src/transport/plugin_transport_http_server.c:2620
 #: src/transport/plugin_transport_tcp.c:772 src/util/service.c:704
 #: src/util/service_new.c:782
 #, fuzzy, c-format
@@ -293,7 +292,7 @@ msgid "Failed to resolve `%s': %s\n"
 msgstr "Misslyckades att leverera \"%s\" meddelande.\n"
 
 #: src/arm/gnunet-service-arm.c:532
-#: src/transport/plugin_transport_http_server.c:2635
+#: src/transport/plugin_transport_http_server.c:2638
 #: src/transport/plugin_transport_tcp.c:791 src/util/service.c:723
 #: src/util/service_new.c:802
 #, fuzzy, c-format
@@ -388,13 +387,11 @@ msgid ""
 "%llu\n"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3293
-#: src/ats-tests/gnunet-solver-eval.c:935
+#: src/ats/gnunet-ats-solver-eval.c:3293 src/ats-tests/gnunet-solver-eval.c:935
 msgid "solver to use"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3296
-#: src/ats-tests/gnunet-solver-eval.c:938
+#: src/ats/gnunet-ats-solver-eval.c:3296 src/ats-tests/gnunet-solver-eval.c:938
 #: src/ats-tests/gnunet-solver-eval.c:941
 msgid "experiment to use"
 msgstr ""
@@ -500,12 +497,12 @@ msgstr ""
 msgid "Invalid %s configuration %f\n"
 msgstr "Kunde inte spara konfigurationsfil \"%s\":"
 
-#: src/ats-tests/ats-testing.c:441
+#: src/ats-tests/ats-testing.c:422
 #, c-format
 msgid "Connected master [%u] with slave [%u]\n"
 msgstr ""
 
-#: src/ats-tests/ats-testing.c:448
+#: src/ats-tests/ats-testing.c:429
 #, fuzzy, c-format
 msgid "Failed to connect master peer [%u] with slave [%u]\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
@@ -562,7 +559,7 @@ msgid "Quota for network `%11s' (in/out): %10s / %10s\n"
 msgstr ""
 
 #: src/ats-tool/gnunet-ats.c:748 src/ats-tool/gnunet-ats.c:761
-#: src/transport/gnunet-transport.c:1476
+#: src/transport/gnunet-transport.c:1255
 #, fuzzy, c-format
 msgid "Failed to parse peer identity `%s'\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
@@ -648,6 +645,38 @@ msgstr ""
 msgid "Print information about ATS state"
 msgstr "Skriv ut information om GNUnets motparter."
 
+#: src/auction/gnunet-auction-create.c:69
+msgid "description of the item to be sold"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:72
+msgid "mapping of possible prices"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:75
+msgid "max duration per round"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:78
+msgid "duration until auction starts"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:81
+msgid "number of items to sell, 0 for first price auction"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:84
+msgid "public auction outcome"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:94 src/auction/gnunet-auction-info.c:76
+#: src/auction/gnunet-auction-join.c:76
+#: src/conversation/gnunet-conversation-test.c:243
+#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
+#, fuzzy
+msgid "help text"
+msgstr "hjälptext för -t"
+
 #: src/cadet/gnunet-cadet.c:511
 #, fuzzy, c-format
 msgid "Invalid target `%s'\n"
@@ -704,7 +733,7 @@ msgstr "Skriv ut information om GNUnets motparter."
 msgid "provide information about all tunnels"
 msgstr "Skriv ut information om GNUnets motparter."
 
-#: src/cadet/gnunet-service-cadet_peer.c:681
+#: src/cadet/gnunet-service-cadet_peer.c:686
 msgid "Wrong CORE service\n"
 msgstr ""
 
@@ -1029,12 +1058,6 @@ msgid ""
 "played back to you..."
 msgstr ""
 
-#: src/conversation/gnunet-conversation-test.c:243
-#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
-#, fuzzy
-msgid "help text"
-msgstr "hjälptext för -t"
-
 #: src/conversation/gnunet_gst.c:630
 #: src/conversation/gnunet-helper-audio-playback-gst.c:357
 #, c-format
@@ -1241,7 +1264,7 @@ msgstr "Ogiltiga kommandoradsargument:\n"
 msgid "Failed to connect to CORE service!\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1677
+#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1456
 #, fuzzy
 msgid "provide information about all current connections (continuously)"
 msgstr "Skriv ut information om GNUnets motparter."
@@ -1523,7 +1546,7 @@ msgstr ""
 #: src/testbed/gnunet-daemon-testbed-underlay.c:56
 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:52
 #: src/util/crypto_ecc_setup.c:41 src/util/crypto_mpi.c:39
-#: src/include/gnunet_common.h:681 src/include/gnunet_common.h:690
+#: src/include/gnunet_common.h:691 src/include/gnunet_common.h:700
 #: src/scalarproduct/scalarproduct.h:35
 #, c-format
 msgid "`%s' failed at %s:%d with error: %s\n"
@@ -1923,8 +1946,7 @@ msgstr ""
 msgid "Prints all packets that go through the DHT."
 msgstr ""
 
-#: src/dht/gnunet_dht_profiler.c:1161
-#: src/testbed/gnunet-testbed-profiler.c:255
+#: src/dht/gnunet_dht_profiler.c:1161 src/testbed/gnunet-testbed-profiler.c:255
 #, fuzzy, c-format
 msgid "Exiting as the number of peers is %u\n"
 msgstr "Maximalt antal chattklienter uppnått.\n"
@@ -2109,8 +2131,7 @@ msgstr ""
 msgid "# GET requests given to datacache"
 msgstr "# byte mottogs via TCP"
 
-#: src/dht/gnunet-service-dht_hello.c:84
-#: src/dht/gnunet-service-xdht_hello.c:82
+#: src/dht/gnunet-service-dht_hello.c:84 src/dht/gnunet-service-xdht_hello.c:82
 #, fuzzy
 msgid "# HELLOs obtained from peerinfo"
 msgstr "Meddelande mottaget från klient är ogiltig.\n"
@@ -2186,40 +2207,40 @@ msgstr "# byte mottogs via TCP"
 msgid "# P2P PUT bytes received"
 msgstr "# byte mottogs via TCP"
 
-#: src/dht/gnunet-service-dht_neighbours.c:1854
+#: src/dht/gnunet-service-dht_neighbours.c:1858
 msgid "# FIND PEER requests ignored due to Bloomfilter"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:1862
+#: src/dht/gnunet-service-dht_neighbours.c:1866
 msgid "# FIND PEER requests ignored due to lack of HELLO"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2018
+#: src/dht/gnunet-service-dht_neighbours.c:2022
 #, fuzzy
 msgid "# P2P GET requests received"
 msgstr "# byte mottogs via TCP"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2022
+#: src/dht/gnunet-service-dht_neighbours.c:2026
 #, fuzzy
 msgid "# P2P GET bytes received"
 msgstr "# byte mottogs via TCP"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2097
+#: src/dht/gnunet-service-dht_neighbours.c:2101
 #, fuzzy
 msgid "# P2P FIND PEER requests processed"
 msgstr "# byte mottogs via TCP"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2120
+#: src/dht/gnunet-service-dht_neighbours.c:2124
 #, fuzzy
 msgid "# P2P GET requests ONLY routed"
 msgstr "# byte mottogs via TCP"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2222
+#: src/dht/gnunet-service-dht_neighbours.c:2226
 #, fuzzy
 msgid "# P2P RESULTS received"
 msgstr "# krypterade PONG-meddelanden mottagna"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2226
+#: src/dht/gnunet-service-dht_neighbours.c:2230
 #, fuzzy
 msgid "# P2P RESULT bytes received"
 msgstr "# krypterade PONG-meddelanden mottagna"
@@ -2229,35 +2250,35 @@ msgstr "# krypterade PONG-meddelanden mottagna"
 msgid "# Network size estimates received"
 msgstr "# byte mottogs via TCP"
 
-#: src/dht/gnunet-service-dht_routing.c:218
+#: src/dht/gnunet-service-dht_routing.c:220
 msgid "# Good REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:227
+#: src/dht/gnunet-service-dht_routing.c:229
 msgid "# Duplicate REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:233
+#: src/dht/gnunet-service-dht_routing.c:235
 msgid "# Invalid REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:239
+#: src/dht/gnunet-service-dht_routing.c:241
 msgid "# Irrelevant REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:251
+#: src/dht/gnunet-service-dht_routing.c:253
 msgid "# Unsupported REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:327
+#: src/dht/gnunet-service-dht_routing.c:329
 msgid "# Entries removed from routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:409
+#: src/dht/gnunet-service-dht_routing.c:411
 msgid "# Entries added to routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:427
+#: src/dht/gnunet-service-dht_routing.c:429
 #, fuzzy
 msgid "# DHT requests combined"
 msgstr "# byte mottogs via TCP"
@@ -2371,16 +2392,16 @@ msgid ""
 "SUPU %s, %s, %d, trail->prev_hop = %s"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:142
+#: src/dht/plugin_block_dht.c:144
 #, fuzzy, c-format
 msgid "Block not of type %u\n"
 msgstr "Ingen transport av typ %d är känd.\n"
 
-#: src/dht/plugin_block_dht.c:149
+#: src/dht/plugin_block_dht.c:151
 msgid "Size mismatch for block\n"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:159
+#: src/dht/plugin_block_dht.c:161
 #, c-format
 msgid "Block of type %u is malformed\n"
 msgstr ""
@@ -3515,7 +3536,7 @@ msgid "Option `%s' is required when using option `%s'.\n"
 msgstr "Kommando \"%s\" kräver ett argument (\"%s\").\n"
 
 #: src/fs/gnunet-publish.c:849 src/fs/gnunet-publish.c:857
-#: src/transport/gnunet-transport.c:1517 src/transport/gnunet-transport.c:1542
+#: src/transport/gnunet-transport.c:1296 src/transport/gnunet-transport.c:1321
 #, c-format
 msgid "Option `%s' makes no sense without option `%s'.\n"
 msgstr ""
@@ -4034,41 +4055,41 @@ msgstr "Mottog ogiltig \"%s\" begäran (storlek %d)\n"
 msgid "Received unsupported DNS request from %s\n"
 msgstr "Mottog okänd typ av begäran %d vid %s:%d\n"
 
-#: src/gns/gnunet-dns2gns.c:709
+#: src/gns/gnunet-dns2gns.c:712
 msgid "No ego configured for `dns2gns` subsystem\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:737
+#: src/gns/gnunet-dns2gns.c:740
 #, fuzzy
 msgid "No DNS server specified!\n"
 msgstr "Inga nyckelord angivna!\n"
 
-#: src/gns/gnunet-dns2gns.c:758
+#: src/gns/gnunet-dns2gns.c:761
 #, fuzzy
 msgid "No valid GNS zone specified!\n"
 msgstr "Inga nyckelord angivna!\n"
 
-#: src/gns/gnunet-dns2gns.c:779
+#: src/gns/gnunet-dns2gns.c:782
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:785
 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:785
+#: src/gns/gnunet-dns2gns.c:788
 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:788
+#: src/gns/gnunet-dns2gns.c:791
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:791
+#: src/gns/gnunet-dns2gns.c:794
 msgid "Public key of the GNS zone to use (overrides default)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:804
+#: src/gns/gnunet-dns2gns.c:807
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4233,83 +4254,85 @@ msgstr ""
 msgid "Unsupported HTTP method `%s'\n"
 msgstr "Kommando \"%s\" stöds ej.  Avbryter.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2167
+#: src/gns/gnunet-gns-proxy.c:2168
 #, fuzzy, c-format
 msgid "Unable to import private key from file `%s'\n"
 msgstr "Kunde inte skapa användarkonto:"
 
-#: src/gns/gnunet-gns-proxy.c:2197
+#: src/gns/gnunet-gns-proxy.c:2198
 #, fuzzy, c-format
 msgid "Unable to import certificate %s\n"
 msgstr "Kunde inte spara konfigurationsfil \"%s\":"
 
-#: src/gns/gnunet-gns-proxy.c:2370
+#: src/gns/gnunet-gns-proxy.c:2371
 #, fuzzy, c-format
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2389 src/rest/gnunet-rest-server.c:533
+#: src/gns/gnunet-gns-proxy.c:2390 src/rest/gnunet-rest-server.c:533
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2709
+#: src/gns/gnunet-gns-proxy.c:2710
 #, fuzzy, c-format
 msgid "Unsupported socks version %d\n"
 msgstr "Kommando \"%s\" stöds ej.  Avbryter.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2738
+#: src/gns/gnunet-gns-proxy.c:2739
 #, fuzzy, c-format
 msgid "Unsupported socks command %d\n"
 msgstr "Kommando \"%s\" stöds ej.  Avbryter.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2756 src/gns/gnunet-gns-proxy.c:2785
+#: src/gns/gnunet-gns-proxy.c:2757 src/gns/gnunet-gns-proxy.c:2786
 msgid "SSL connection to plain IPv4 address requested\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2836
+#: src/gns/gnunet-gns-proxy.c:2837
 #, fuzzy, c-format
 msgid "Unsupported socks address type %d\n"
 msgstr "Kommando \"%s\" stöds ej.  Avbryter.\n"
 
-#: src/gns/gnunet-gns-proxy.c:3171
+#: src/gns/gnunet-gns-proxy.c:3172
 msgid "No ego configured for `shorten-zone`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3211 src/gns/gnunet-service-gns.c:1093
-#: src/gns/gnunet-service-gns.c:1149
+#: src/gns/gnunet-gns-proxy.c:3212 src/gns/gnunet-service-gns.c:493
+#: src/gns/gnunet-service-gns.c:548
 #, c-format
 msgid "No ego configured for `%s`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3273
+#: src/gns/gnunet-gns-proxy.c:3274
 #, fuzzy, c-format
 msgid "Failed to load SSL/TLS key and certificate from `%s'\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/gns/gnunet-gns-proxy.c:3313
+#: src/gns/gnunet-gns-proxy.c:3314
 msgid "listen on specified port (default: 7777)"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3316
+#: src/gns/gnunet-gns-proxy.c:3317
 msgid "pem file to use as CA"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3335
+#: src/gns/gnunet-gns-proxy.c:3336
 msgid "GNUnet GNS proxy"
 msgstr ""
 
-#: src/gns/gnunet-service-gns.c:1187
+#: src/gns/gnunet-service-gns.c:585
+#: src/zonemaster/gnunet-service-zonemaster.c:705
 #, fuzzy
 msgid "Failed to connect to the namestore!\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/gns/gnunet-service-gns.c:1195
+#: src/gns/gnunet-service-gns.c:593
 #, fuzzy
 msgid "Failed to connect to the namecache!\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/gns/gnunet-service-gns.c:1228
+#: src/gns/gnunet-service-gns.c:612
+#: src/zonemaster/gnunet-service-zonemaster.c:740
 #, fuzzy
 msgid "Could not connect to DHT!\n"
 msgstr "Kunde inte ansluta till gnunetd.\n"
@@ -5156,8 +5179,7 @@ msgstr ""
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr "Ogiltigt argument: \"%s\"\n"
 
-#: src/namestore/gnunet-namestore.c:979
-#: src/peerinfo-tool/gnunet-peerinfo.c:775
+#: src/namestore/gnunet-namestore.c:979 src/peerinfo-tool/gnunet-peerinfo.c:775
 #, fuzzy, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "Ogiltiga argument: "
@@ -5316,221 +5338,297 @@ msgstr ""
 msgid "Namestore REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
 
-#: src/nat/gnunet-nat.c:159
-msgid "GNUnet NAT traversal autoconfigure daemon"
+#: src/nat-auto/gnunet-nat-auto.c:192
+#, fuzzy
+msgid "Suggested configuration changes:\n"
+msgstr "Konfigurationsfil \"%s\" skapad.\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:220
+#, fuzzy, c-format
+msgid "Failed to write configuration to `%s'\n"
+msgstr "Kunde inte spara konfiguration!"
+
+#: src/nat-auto/gnunet-nat-auto.c:227
+#, fuzzy, c-format
+msgid "Wrote updated configuration to `%s'\n"
+msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:345
+#, fuzzy
+msgid "run autoconfiguration"
+msgstr "GNUnet-konfiguration"
+
+#: src/nat-auto/gnunet-nat-auto.c:348
+msgid "section name providing the configuration for the adapter"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:351 src/nat/gnunet-nat.c:436
+msgid "use TCP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:354 src/nat/gnunet-nat.c:439
+msgid "use UDP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:357
+#, fuzzy
+msgid "write configuration file (for autoconfiguration)"
+msgstr "Inga applikationer definierade i konfiguration!\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:369
+#, fuzzy
+msgid "GNUnet NAT traversal autoconfiguration"
+msgstr "GNUnet-konfiguration"
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:403
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:681
+#: src/nat-auto/nat_auto_api_test.c:405
+#, fuzzy
+msgid "Failed to connect to `gnunet-nat-server'\n"
+msgstr "Misslyckades att ansluta till gnunetd.\n"
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:518
+#: src/nat-auto/nat_auto_api_test.c:520
+#, c-format
+msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:321
+#: src/nat-auto/gnunet-nat-auto_legacy.c:568
+#: src/nat-auto/nat_auto_api_test.c:569
+#, fuzzy
+msgid "NAT test failed to start NAT library\n"
+msgstr "Misslyckades att starta samling.\n"
+
+#: src/nat-auto/gnunet-nat-server.c:336
 #, c-format
 msgid "Please pass valid port number as the first argument! (got `%s')\n"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:363
+#: src/nat-auto/gnunet-nat-server.c:386
 msgid "GNUnet NAT traversal test helper daemon"
 msgstr ""
 
-#: src/nat/nat_api.c:880 src/nat/nat.c:2010
+#: src/nat-auto/gnunet-service-nat-auto.c:342
+#, fuzzy
+msgid "UPnP client `upnpc` command not found, disabling UPnP\n"
+msgstr "Kommando \"%s\" hittades inte!\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:385
+msgid "NAT traversal with ICMP Server succeeded.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:386
+msgid "NAT traversal with ICMP Server failed.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:405
+#, fuzzy
+msgid "Testing connection reversal with ICMP server.\n"
+msgstr "Skriv ut information om GNUnets motparter."
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:437
+#, fuzzy, c-format
+msgid "Detected external IP `%s'\n"
+msgstr "Mottog ogiltig RPC \"%s\".\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:572
+msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:590
+#, c-format
+msgid "Detected internal network address `%s'.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:724
+msgid "upnpc found, enabling its use\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:725
+#, fuzzy
+msgid "upnpc not found\n"
+msgstr "Kommando \"%s\" hittades inte!\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:762
+msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:774
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:834
+msgid "test_icmp_server not possible, as we are not behind NAT\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:786
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:846
+msgid "No working gnunet-helper-nat-server found\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:823
+msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/nat_auto_api.c:76
 msgid "Operation Successful"
 msgstr ""
 
-#: src/nat/nat_api.c:882 src/nat/nat.c:2012
-msgid "Internal Failure (IPC, ...)"
+#: src/nat-auto/nat_auto_api.c:78
+msgid "IPC failure"
 msgstr ""
 
-#: src/nat/nat_api.c:884 src/nat/nat.c:2014
+#: src/nat-auto/nat_auto_api.c:80
 msgid "Failure in network subsystem, check permissions."
 msgstr ""
 
-#: src/nat/nat_api.c:886 src/nat/nat.c:2016
+#: src/nat-auto/nat_auto_api.c:82
 msgid "Encountered timeout while performing operation"
 msgstr ""
 
-#: src/nat/nat_api.c:888 src/nat/nat.c:2018
+#: src/nat-auto/nat_auto_api.c:84
 msgid "detected that we are offline"
 msgstr ""
 
-#: src/nat/nat_api.c:890 src/nat/nat.c:2020
+#: src/nat-auto/nat_auto_api.c:86
 #, fuzzy
 msgid "`upnpc` command not found"
 msgstr "Kommando \"%s\" hittades inte!\n"
 
-#: src/nat/nat_api.c:892 src/nat/nat.c:2022
+#: src/nat-auto/nat_auto_api.c:88
 #, fuzzy
 msgid "Failed to run `upnpc` command"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/nat/nat_api.c:894 src/nat/nat.c:2024
+#: src/nat-auto/nat_auto_api.c:90
 #, fuzzy
 msgid "`upnpc' command took too long, process killed"
 msgstr "Kommando \"%s\" hittades inte!\n"
 
-#: src/nat/nat_api.c:896 src/nat/nat.c:2026
+#: src/nat-auto/nat_auto_api.c:92
 msgid "`upnpc' command failed to establish port mapping"
 msgstr ""
 
-#: src/nat/nat_api.c:898 src/nat/nat.c:2028
+#: src/nat-auto/nat_auto_api.c:94
 #, fuzzy
 msgid "`external-ip' command not found"
 msgstr "Kommando \"%s\" hittades inte!\n"
 
-#: src/nat/nat_api.c:900 src/nat/nat.c:2030
+#: src/nat-auto/nat_auto_api.c:96
 #, fuzzy
 msgid "Failed to run `external-ip` command"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/nat/nat_api.c:902 src/nat/nat.c:2032
+#: src/nat-auto/nat_auto_api.c:98
 msgid "`external-ip' command output invalid"
 msgstr ""
 
-#: src/nat/nat_api.c:904 src/nat/nat.c:2034
+#: src/nat-auto/nat_auto_api.c:100
 msgid "no valid address was returned by `external-ip'"
 msgstr ""
 
-#: src/nat/nat_api.c:906 src/nat/nat.c:2036
+#: src/nat-auto/nat_auto_api.c:102
 #, fuzzy
 msgid "Could not determine interface with internal/local network address"
 msgstr "Kunde inte fastställa min publika IPv6-adress.\n"
 
-#: src/nat/nat_api.c:908 src/nat/nat.c:2038
+#: src/nat-auto/nat_auto_api.c:104
 msgid "No functioning gnunet-helper-nat-server installation found"
 msgstr ""
 
-#: src/nat/nat_api.c:910 src/nat/nat.c:2040
+#: src/nat-auto/nat_auto_api.c:106
 msgid "NAT test could not be initialized"
 msgstr ""
 
-#: src/nat/nat_api.c:912 src/nat/nat.c:2042
+#: src/nat-auto/nat_auto_api.c:108
 msgid "NAT test timeout reached"
 msgstr ""
 
-#: src/nat/nat_api.c:914 src/nat/nat.c:2044
+#: src/nat-auto/nat_auto_api.c:110
 msgid "could not register NAT"
 msgstr ""
 
-#: src/nat/nat_api.c:916 src/nat/nat.c:2046
+#: src/nat-auto/nat_auto_api.c:112
 msgid "No working gnunet-helper-nat-client installation found"
 msgstr ""
 
-#: src/nat/nat_auto.c:385
-msgid "NAT traversal with ICMP Server succeeded.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:386
-msgid "NAT traversal with ICMP Server failed.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:405
-#, fuzzy
-msgid "Testing connection reversal with ICMP server.\n"
-msgstr "Skriv ut information om GNUnets motparter."
-
-#: src/nat/nat_auto.c:437
+#: src/nat-auto/nat_auto_api_test.c:477
 #, fuzzy, c-format
-msgid "Detected external IP `%s'\n"
-msgstr "Mottog ogiltig RPC \"%s\".\n"
+msgid "Failed to find valid PORT in section `%s'\n"
+msgstr "Misslyckades att binda till UDP-port %d.\n"
 
-#: src/nat/nat_auto.c:572
-msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+#: src/nat/gnunet-nat.c:424
+msgid "which IP and port are we locally using to bind/listen to"
 msgstr ""
 
-#: src/nat/nat_auto.c:590
-#, c-format
-msgid "Detected internal network address `%s'.\n"
+#: src/nat/gnunet-nat.c:427
+msgid "which remote IP and port should be asked for connection reversal"
 msgstr ""
 
-#: src/nat/nat_auto.c:681 src/nat/nat_test.c:403
-#, fuzzy
-msgid "Failed to connect to `gnunet-nat-server'\n"
-msgstr "Misslyckades att ansluta till gnunetd.\n"
-
-#: src/nat/nat_auto.c:724
-msgid "upnpc found, enabling its use\n"
+#: src/nat/gnunet-nat.c:430
+msgid ""
+"name of configuration section to find additional options, such as manual "
+"host punching data"
 msgstr ""
 
-#: src/nat/nat_auto.c:725
-#, fuzzy
-msgid "upnpc not found\n"
-msgstr "Kommando \"%s\" hittades inte!\n"
-
-#: src/nat/nat_auto.c:762
-msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+#: src/nat/gnunet-nat.c:433
+msgid "enable STUN processing"
 msgstr ""
 
-#: src/nat/nat_auto.c:774 src/nat/nat_auto.c:834
-msgid "test_icmp_server not possible, as we are not behind NAT\n"
+#: src/nat/gnunet-nat.c:442
+msgid "watch for connection reversal requests"
 msgstr ""
 
-#: src/nat/nat_auto.c:786 src/nat/nat_auto.c:846
-msgid "No working gnunet-helper-nat-server found\n"
+#: src/nat/gnunet-nat.c:454
+msgid "GNUnet NAT traversal autoconfigure daemon"
 msgstr ""
 
-#: src/nat/nat_auto.c:823
-msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+#: src/nat/gnunet-service-nat.c:1313
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1019
+#: src/nat/gnunet-service-nat.c:1323
 #, c-format
-msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
+msgid "Invalid port number in punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1070
-#, fuzzy, c-format
-msgid "Failed to start %s\n"
-msgstr "Misslyckades att starta samling.\n"
-
-#: src/nat/nat.c:1327
-msgid "Error while running upnp client:\n"
+#: src/nat/gnunet-service-nat.c:1339
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks `]')\n"
 msgstr ""
 
-#: src/nat/nat.c:1402
-#, fuzzy, c-format
-msgid "Failed to run upnp client for port %u\n"
-msgstr "Misslyckades att initiera tjänsten \"%s\".\n"
-
-#: src/nat/nat.c:1546
-msgid "malformed"
+#: src/nat/gnunet-service-nat.c:1350
+#, c-format
+msgid "Malformed punched hole specification `%s' (IPv6 address invalid)"
 msgstr ""
 
-#: src/nat/nat.c:1600
+#: src/nat/gnunet-service-nat.c:1803
+#, fuzzy
+msgid "Connection reversal request failed\n"
+msgstr "Samling stoppad.\n"
+
+#: src/nat/gnunet-service-nat.c:1876
 msgid ""
 "UPnP enabled in configuration, but UPnP client `upnpc` command not found, "
-"disabling UPnP \n"
+"disabling UPnP\n"
 msgstr ""
 
-#: src/nat/nat.c:1726 src/nat/nat.c:1739
+#: src/nat/gnunet-service-nat_helper.c:186
 #, c-format
-msgid ""
-"Configuration requires `%s', but binary is not installed properly (SUID bit "
-"not set).  Option disabled.\n"
-msgstr ""
-
-#: src/nat/nat.c:1903
-msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n"
+msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/nat.c:1919
-#, c-format
-msgid "Running gnunet-helper-nat-client %s %s %u\n"
-msgstr ""
+#: src/nat/gnunet-service-nat_helper.c:260
+#, fuzzy, c-format
+msgid "Failed to start %s\n"
+msgstr "Misslyckades att starta samling.\n"
 
-#: src/nat/nat_mini.c:205
+#: src/nat/gnunet-service-nat_mini.c:196
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/nat_mini.c:611
+#: src/nat/gnunet-service-nat_mini.c:654
 msgid "`upnpc' command not found\n"
 msgstr ""
 
-#: src/nat/nat_test.c:518
-#, c-format
-msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
-msgstr ""
-
-#: src/nat/nat_test.c:568
-#, fuzzy
-msgid "NAT test failed to start NAT library\n"
-msgstr "Misslyckades att starta samling.\n"
-
 #: src/nse/gnunet-nse.c:122
 #, fuzzy
 msgid "Show network size estimates from NSE service."
@@ -7330,182 +7428,159 @@ msgstr ""
 msgid "# validations succeeded"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:486
+#: src/transport/gnunet-transport.c:418
 #, fuzzy, c-format
 msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/transport/gnunet-transport.c:496
+#: src/transport/gnunet-transport.c:428
 #, c-format
 msgid "Received %llu bytes/s (%llu bytes in %s)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:540
+#: src/transport/gnunet-transport.c:472
 #, fuzzy, c-format
 msgid "Failed to connect to `%s'\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:553
+#: src/transport/gnunet-transport.c:485
 #, fuzzy, c-format
 msgid "Failed to resolve address for peer `%s'\n"
 msgstr "Misslyckades att binda till UDP-port %d.\n"
 
-#: src/transport/gnunet-transport.c:565
+#: src/transport/gnunet-transport.c:499
 #, fuzzy
 msgid "Failed to list connections, timeout occured\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:588
-#, fuzzy, c-format
-msgid "NAT plugin `%s' reports: %s\n"
-msgstr "Testar transport(er) %s\n"
-
-#: src/transport/gnunet-transport.c:675
-msgid "No transport plugins configured, peer will never communicate\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:689
-#, c-format
-msgid "No port configured for plugin `%s', cannot test it\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:714
-#, fuzzy
-msgid "Failed to start resolver!\n"
-msgstr "Misslyckades att starta samling.\n"
-
-#: src/transport/gnunet-transport.c:750
+#: src/transport/gnunet-transport.c:532
 #, fuzzy, c-format
 msgid "Transmitting %u bytes\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/transport/gnunet-transport.c:784
+#: src/transport/gnunet-transport.c:566
 #, c-format
 msgid ""
 "Successfully connected to `%s', starting to send benchmark data in %u Kb "
 "blocks\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:815
+#: src/transport/gnunet-transport.c:597
 #, fuzzy, c-format
 msgid "Disconnected from peer `%s' while benchmarking\n"
 msgstr "\"%s\" ansluten till \"%s\".\n"
 
-#: src/transport/gnunet-transport.c:839 src/transport/gnunet-transport.c:868
+#: src/transport/gnunet-transport.c:621 src/transport/gnunet-transport.c:650
 #, c-format
 msgid "%24s: %-17s %4s   (%u connections in total)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:841
+#: src/transport/gnunet-transport.c:623
 #, fuzzy
 msgid "Connected to"
 msgstr "\"%s\" ansluten till \"%s\".\n"
 
-#: src/transport/gnunet-transport.c:870
+#: src/transport/gnunet-transport.c:652
 #, fuzzy
 msgid "Disconnected from"
 msgstr "\"%s\" ansluten till \"%s\".\n"
 
-#: src/transport/gnunet-transport.c:905
+#: src/transport/gnunet-transport.c:687
 #, fuzzy, c-format
 msgid "Received %u bytes\n"
 msgstr "mottog ogiltigt \"%s\" meddelande\n"
 
-#: src/transport/gnunet-transport.c:942
+#: src/transport/gnunet-transport.c:724
 #, c-format
 msgid "Peer `%s': %s %s in state `%s' until %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:954
+#: src/transport/gnunet-transport.c:736
 #, fuzzy, c-format
 msgid "Peer `%s': %s %s\n"
 msgstr "Jag är ändpunkt \"%s\".\n"
 
-#: src/transport/gnunet-transport.c:1366
+#: src/transport/gnunet-transport.c:1150
 #, fuzzy
 msgid "Monitor disconnected from transport service. Reconnecting.\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:1488
+#: src/transport/gnunet-transport.c:1267
 #, c-format
 msgid ""
 "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, "
 "%s, %s %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1501
+#: src/transport/gnunet-transport.c:1280
 #, c-format
 msgid ""
 "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s, %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1529
+#: src/transport/gnunet-transport.c:1308
 #, fuzzy
 msgid "Failed to connect to transport service for disconnection\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:1535
+#: src/transport/gnunet-transport.c:1314
 msgid "Blacklisting request in place, stop with CTRL-C\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1558 src/transport/gnunet-transport.c:1588
-#: src/transport/gnunet-transport.c:1641
+#: src/transport/gnunet-transport.c:1337 src/transport/gnunet-transport.c:1367
+#: src/transport/gnunet-transport.c:1420
 #, fuzzy
 msgid "Failed to connect to transport service\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:1595
+#: src/transport/gnunet-transport.c:1374
 msgid "Starting to receive benchmark data\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1665
+#: src/transport/gnunet-transport.c:1444
 #, fuzzy
 msgid "print information for all peers (instead of only connected peers)"
 msgstr "Skriv ut information om GNUnets motparter."
 
-#: src/transport/gnunet-transport.c:1668
+#: src/transport/gnunet-transport.c:1447
 msgid "measure how fast we are receiving data from all peers (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1671
+#: src/transport/gnunet-transport.c:1450
 #, fuzzy
 msgid "disconnect from a peer"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:1674
+#: src/transport/gnunet-transport.c:1453
 #, fuzzy
 msgid "provide information about all current connections (once)"
 msgstr "Skriv ut information om GNUnets motparter."
 
-#: src/transport/gnunet-transport.c:1680
+#: src/transport/gnunet-transport.c:1459
 #, fuzzy
 msgid ""
 "provide information about all connects and disconnect events (continuously)"
 msgstr "Skriv ut information om GNUnets motparter."
 
-#: src/transport/gnunet-transport.c:1683
+#: src/transport/gnunet-transport.c:1462
 #, fuzzy
 msgid "do not resolve hostnames"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/transport/gnunet-transport.c:1686
+#: src/transport/gnunet-transport.c:1465
 #: src/transport/gnunet-transport-profiler.c:631
 msgid "peer identity"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1689
+#: src/transport/gnunet-transport.c:1468
 msgid "monitor plugin sessions"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1692
+#: src/transport/gnunet-transport.c:1471
 msgid "send data for benchmarking to the other peer (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1695
-msgid "test transport configuration (involves external server)"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:1706
+#: src/transport/gnunet-transport.c:1482
 #: src/transport/gnunet-transport-profiler.c:642
 #, fuzzy
 msgid "Direct access to transport service."
@@ -7542,9 +7617,9 @@ msgstr "meddelandestorlek"
 
 #: src/transport/plugin_transport_http_client.c:1477
 #: src/transport/plugin_transport_http_server.c:2248
-#: src/transport/plugin_transport_http_server.c:3457
-#: src/transport/plugin_transport_tcp.c:3365
-#: src/transport/plugin_transport_tcp.c:3372
+#: src/transport/plugin_transport_http_server.c:3462
+#: src/transport/plugin_transport_tcp.c:3375
+#: src/transport/plugin_transport_tcp.c:3382
 msgid "TCP_STEALTH not supported on this platform.\n"
 msgstr ""
 
@@ -7554,13 +7629,13 @@ msgid "Could not initialize curl multi handle, failed to start %s plugin!\n"
 msgstr ""
 
 #: src/transport/plugin_transport_http_client.c:2167
-#: src/transport/plugin_transport_http_server.c:3172
+#: src/transport/plugin_transport_http_server.c:3177
 #, fuzzy, c-format
 msgid "Shutting down plugin `%s'\n"
 msgstr "Testar transport(er) %s\n"
 
 #: src/transport/plugin_transport_http_client.c:2184
-#: src/transport/plugin_transport_http_server.c:3242
+#: src/transport/plugin_transport_http_server.c:3247
 #, fuzzy, c-format
 msgid "Shutdown for plugin `%s' complete\n"
 msgstr ""
@@ -7604,75 +7679,75 @@ msgstr ""
 msgid "Could not load or create server certificate! Loading plugin failed!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2583
+#: src/transport/plugin_transport_http_server.c:2586
 #, fuzzy
 msgid "Require valid port number for service in configuration!\n"
 msgstr "Inga applikationer definierade i konfiguration!\n"
 
-#: src/transport/plugin_transport_http_server.c:2748
+#: src/transport/plugin_transport_http_server.c:2751
 #, c-format
 msgid "Found %u addresses to report to NAT service\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2832
-#: src/transport/plugin_transport_udp.c:3600
+#: src/transport/plugin_transport_http_server.c:2837
+#: src/transport/plugin_transport_udp.c:3623
 msgid "Disabling IPv6 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2938
+#: src/transport/plugin_transport_http_server.c:2943
 #, c-format
 msgid "IPv4 support is %s\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2953
+#: src/transport/plugin_transport_http_server.c:2958
 #, c-format
 msgid "IPv6 support is %s\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2959
+#: src/transport/plugin_transport_http_server.c:2964
 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2970
+#: src/transport/plugin_transport_http_server.c:2975
 #, fuzzy
 msgid "Port is required! Fix in configuration\n"
 msgstr " gconfig\tGTK-konfiguration\n"
 
-#: src/transport/plugin_transport_http_server.c:2976
+#: src/transport/plugin_transport_http_server.c:2981
 #, fuzzy, c-format
 msgid "Using port %u\n"
 msgstr "Testar transport(er) %s\n"
 
-#: src/transport/plugin_transport_http_server.c:2995
+#: src/transport/plugin_transport_http_server.c:3000
 #, fuzzy, c-format
 msgid "Specific IPv4 address `%s' in configuration file is invalid!\n"
 msgstr ""
 "Du måste ange ett positivt nummer för \"%s\" i konfigurationen i sektion \"%s"
 "\".\n"
 
-#: src/transport/plugin_transport_http_server.c:3030
+#: src/transport/plugin_transport_http_server.c:3035
 #, fuzzy, c-format
 msgid "Specific IPv6 address `%s' in configuration file is invalid!\n"
 msgstr ""
 "Du måste ange ett positivt nummer för \"%s\" i konfigurationen i sektion \"%s"
 "\".\n"
 
-#: src/transport/plugin_transport_http_server.c:3105
+#: src/transport/plugin_transport_http_server.c:3110
 #, fuzzy, c-format
 msgid "Using external hostname `%s'\n"
 msgstr "Startade samling \"%s\".\n"
 
-#: src/transport/plugin_transport_http_server.c:3126
+#: src/transport/plugin_transport_http_server.c:3131
 #, fuzzy, c-format
 msgid "Notifying transport only about hostname `%s'\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/transport/plugin_transport_http_server.c:3143
+#: src/transport/plugin_transport_http_server.c:3148
 #, fuzzy, c-format
 msgid "Maximum number of connections is %u\n"
 msgstr "Maximalt antal chattklienter uppnått.\n"
 
-#: src/transport/plugin_transport_http_server.c:3469
+#: src/transport/plugin_transport_http_server.c:3474
 #, fuzzy
 msgid "Unable to compile URL regex\n"
 msgstr "Kunde inte initiera SQLite.\n"
@@ -7725,167 +7800,167 @@ msgstr "# byte skickades via TCP"
 msgid "# bytes dropped by SMTP (outgoing)"
 msgstr "# byte kastade via TCP (utgående)"
 
-#: src/transport/plugin_transport_tcp.c:1051
-#: src/transport/plugin_transport_tcp.c:2362
+#: src/transport/plugin_transport_tcp.c:1060
+#: src/transport/plugin_transport_tcp.c:2379
 #, c-format
 msgid "Unexpected address length: %u bytes\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1234
-#: src/transport/plugin_transport_tcp.c:1458
-#: src/transport/plugin_transport_tcp.c:2633
-#: src/transport/plugin_transport_tcp.c:3490
+#: src/transport/plugin_transport_tcp.c:1243
+#: src/transport/plugin_transport_tcp.c:1467
+#: src/transport/plugin_transport_tcp.c:2643
+#: src/transport/plugin_transport_tcp.c:3498
 #, fuzzy
 msgid "# TCP sessions active"
 msgstr "# sessionsnycklar accepterade"
 
-#: src/transport/plugin_transport_tcp.c:1276
-#: src/transport/plugin_transport_tcp.c:1440
-#: src/transport/plugin_transport_tcp.c:1564
-#: src/transport/plugin_transport_tcp.c:1637
-#: src/transport/plugin_transport_tcp.c:1737
-#: src/transport/plugin_transport_tcp.c:1762
+#: src/transport/plugin_transport_tcp.c:1285
+#: src/transport/plugin_transport_tcp.c:1449
+#: src/transport/plugin_transport_tcp.c:1573
+#: src/transport/plugin_transport_tcp.c:1646
+#: src/transport/plugin_transport_tcp.c:1746
+#: src/transport/plugin_transport_tcp.c:1771
 #, fuzzy
 msgid "# bytes currently in TCP buffers"
 msgstr "# byte skickades via TCP"
 
-#: src/transport/plugin_transport_tcp.c:1279
+#: src/transport/plugin_transport_tcp.c:1288
 #, fuzzy
 msgid "# bytes discarded by TCP (disconnect)"
 msgstr "# byte kastade via TCP (utgående)"
 
-#: src/transport/plugin_transport_tcp.c:1567
+#: src/transport/plugin_transport_tcp.c:1576
 #, fuzzy
 msgid "# bytes discarded by TCP (timeout)"
 msgstr "# byte kastade via TCP (utgående)"
 
-#: src/transport/plugin_transport_tcp.c:1641
+#: src/transport/plugin_transport_tcp.c:1650
 #, fuzzy
 msgid "# bytes transmitted via TCP"
 msgstr "# byte skickade av typen %d"
 
-#: src/transport/plugin_transport_tcp.c:2032
+#: src/transport/plugin_transport_tcp.c:2041
 msgid "# requests to create session with invalid address"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2200
+#: src/transport/plugin_transport_tcp.c:2217
 msgid "# transport-service disconnect requests for TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2692
+#: src/transport/plugin_transport_tcp.c:2702
 #, fuzzy
 msgid "# TCP WELCOME messages received"
 msgstr "# krypterade PONG-meddelanden mottagna"
 
-#: src/transport/plugin_transport_tcp.c:2883
+#: src/transport/plugin_transport_tcp.c:2893
 msgid "# bytes received via TCP"
 msgstr "# byte mottogs via TCP"
 
-#: src/transport/plugin_transport_tcp.c:2934
-#: src/transport/plugin_transport_tcp.c:2992
+#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:3002
 #, fuzzy
 msgid "# TCP server connections active"
 msgstr "Nätverksanslutning"
 
-#: src/transport/plugin_transport_tcp.c:2938
+#: src/transport/plugin_transport_tcp.c:2948
 #, fuzzy
 msgid "# TCP server connect events"
 msgstr "# av anslutna parter"
 
-#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:2954
 msgid "TCP connection limit reached, suspending server\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2946
+#: src/transport/plugin_transport_tcp.c:2956
 msgid "# TCP service suspended"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2986
+#: src/transport/plugin_transport_tcp.c:2996
 msgid "# TCP service resumed"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2996
+#: src/transport/plugin_transport_tcp.c:3006
 msgid "# network-level TCP disconnect events"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3315
+#: src/transport/plugin_transport_tcp.c:3325
 #, fuzzy
 msgid "Failed to start service.\n"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/transport/plugin_transport_tcp.c:3478
+#: src/transport/plugin_transport_tcp.c:3486
 #, c-format
 msgid "TCP transport listening on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3482
+#: src/transport/plugin_transport_tcp.c:3490
 msgid "TCP transport not listening on any port (client only)\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3486
+#: src/transport/plugin_transport_tcp.c:3494
 #, c-format
 msgid "TCP transport advertises itself as being on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:170
+#: src/transport/plugin_transport_udp_broadcasting.c:169
 #, fuzzy
 msgid "# Multicast HELLO beacons received via UDP"
 msgstr "# krypterade PONG-meddelanden mottagna"
 
-#: src/transport/plugin_transport_udp_broadcasting.c:546
+#: src/transport/plugin_transport_udp_broadcasting.c:545
 msgid ""
 "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:567
+#: src/transport/plugin_transport_udp_broadcasting.c:566
 #, c-format
 msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3344
+#: src/transport/plugin_transport_udp.c:3367
 #, c-format
 msgid ""
 "UDP could not transmit message to `%s': Network seems down, please check "
 "your network configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3358
+#: src/transport/plugin_transport_udp.c:3381
 msgid ""
 "UDP could not transmit IPv6 message! Please check your network configuration "
 "and disable IPv6 if your connection does not have a global IPv6 address\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3676
-#: src/transport/plugin_transport_udp.c:3775
+#: src/transport/plugin_transport_udp.c:3699
+#: src/transport/plugin_transport_udp.c:3798
 #, fuzzy, c-format
 msgid "Failed to bind UDP socket to %s: %s\n"
 msgstr "Misslyckades att binda till UDP6-port %d.\n"
 
-#: src/transport/plugin_transport_udp.c:3694
+#: src/transport/plugin_transport_udp.c:3717
 msgid "Disabling IPv4 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3785
+#: src/transport/plugin_transport_udp.c:3808
 #, fuzzy
 msgid "Failed to open UDP sockets\n"
 msgstr "Misslyckades att binda till UDP6-port %d.\n"
 
-#: src/transport/plugin_transport_udp.c:3857
-#: src/transport/plugin_transport_udp.c:3871
+#: src/transport/plugin_transport_udp.c:3879
+#: src/transport/plugin_transport_udp.c:3893
 msgid "must be in [0,65535]"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3903
+#: src/transport/plugin_transport_udp.c:3925
 #, fuzzy
 msgid "must be valid IPv4 address"
 msgstr "\"%s\" är inte tillgänglig."
 
-#: src/transport/plugin_transport_udp.c:3930
+#: src/transport/plugin_transport_udp.c:3952
 #, fuzzy
 msgid "must be valid IPv6 address"
 msgstr "\"%s\" är inte tillgänglig."
 
-#: src/transport/plugin_transport_udp.c:3996
+#: src/transport/plugin_transport_udp.c:4018
 #, fuzzy
 msgid "Failed to create UDP network sockets\n"
 msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n"
@@ -8007,7 +8082,7 @@ msgstr ""
 msgid "Metadata `%s' failed to deserialize"
 msgstr ""
 
-#: src/util/client_new.c:864
+#: src/util/client.c:864
 #, c-format
 msgid "Need a non-empty hostname for service `%s'.\n"
 msgstr ""
@@ -8782,42 +8857,42 @@ msgstr ""
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "Ogiltigt svar på \"%s\".\n"
 
-#: src/util/strings.c:1475 src/util/strings.c:1491
+#: src/util/strings.c:1541 src/util/strings.c:1557
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1500
+#: src/util/strings.c:1566
 #, fuzzy, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/util/strings.c:1583 src/util/strings.c:1614 src/util/strings.c:1662
-#: src/util/strings.c:1683
+#: src/util/strings.c:1649 src/util/strings.c:1680 src/util/strings.c:1728
+#: src/util/strings.c:1749
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "Ogiltigt format för IP: \"%s\"\n"
 
-#: src/util/strings.c:1640
+#: src/util/strings.c:1706
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "Ogiltig nätverksnotation (\"/%d\" är inte giltig i IPv4 CIDR)."
 
-#: src/util/strings.c:1692
+#: src/util/strings.c:1758
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "Ogiltigt format för IP: \"%s\"\n"
 
-#: src/util/strings.c:1744
+#: src/util/strings.c:1810
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "Ogiltig nätverksnotation (slutar inte med \";\": \"%s\")\n"
 
-#: src/util/strings.c:1794
+#: src/util/strings.c:1860
 #, fuzzy, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "Fel format \"%s\" för nätmask: %s\n"
 
-#: src/util/strings.c:1825
+#: src/util/strings.c:1891
 #, fuzzy, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "Fel format \"%s\" för nätverk: %s\n"
@@ -9006,21 +9081,33 @@ msgid "Setup tunnels via VPN."
 msgstr ""
 
 #: src/include/gnunet_common.h:645 src/include/gnunet_common.h:652
-#: src/include/gnunet_common.h:660
+#: src/include/gnunet_common.h:662 src/include/gnunet_common.h:670
 #, fuzzy, c-format
 msgid "Assertion failed at %s:%d.\n"
 msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n"
 
-#: src/include/gnunet_common.h:672
+#: src/include/gnunet_common.h:682
 #, c-format
 msgid "External protocol violation detected at %s:%d.\n"
 msgstr ""
 
-#: src/include/gnunet_common.h:699 src/include/gnunet_common.h:708
+#: src/include/gnunet_common.h:709 src/include/gnunet_common.h:718
 #, c-format
 msgid "`%s' failed on file `%s' at %s:%d with error: %s\n"
 msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n"
 
+#, fuzzy
+#~ msgid "Failed to run upnp client for port %u\n"
+#~ msgstr "Misslyckades att initiera tjänsten \"%s\".\n"
+
+#, fuzzy
+#~ msgid "NAT plugin `%s' reports: %s\n"
+#~ msgstr "Testar transport(er) %s\n"
+
+#, fuzzy
+#~ msgid "Failed to start resolver!\n"
+#~ msgstr "Misslyckades att starta samling.\n"
+
 #, fuzzy
 #~ msgid "Unable to initialize Postgres: %s\n"
 #~ msgstr "Kunde inte initiera SQLite.\n"
@@ -10250,10 +10337,6 @@ msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n"
 #~ msgid "Setting d->dead on peer `%4s'\n"
 #~ msgstr "Startade samling \"%s\".\n"
 
-#, fuzzy
-#~ msgid "Failed to write new configuration to disk."
-#~ msgstr "Kunde inte spara konfiguration!"
-
 #, fuzzy
 #~ msgid "Could not start `%s' process to copy configuration file.\n"
 #~ msgstr "Kunde inte skapa värdnyckel!\n"
@@ -10278,10 +10361,6 @@ msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n"
 #~ msgid "Could not create configuration for peer number %u on `%s'!\n"
 #~ msgstr "Kunde inte komma åt namnrymdsinformation.\n"
 
-#, fuzzy
-#~ msgid "Failed to find option %s in section %s!\n"
-#~ msgstr "Misslyckades att binda till UDP-port %d.\n"
-
 #, fuzzy
 #~ msgid "Invalid configuration option `%s' in section `%s'\n"
 #~ msgstr "Konfigurationsfil \"%s\" skapad.\n"
@@ -10461,10 +10540,6 @@ msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n"
 #~ msgid "Failed to load transport plugin for tcp\n"
 #~ msgstr "Kunde inte slå upp \"%s\": %s\n"
 
-#, fuzzy
-#~ msgid "Misconfigured address to bind to in configuration!\n"
-#~ msgstr "Inga applikationer definierade i konfiguration!\n"
-
 #, fuzzy
 #~ msgid "Failed to load transport plugin for http\n"
 #~ msgstr "Kunde inte slå upp \"%s\": %s\n"
@@ -10574,10 +10649,6 @@ msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n"
 #~ msgid "How much downstream bandwidth (in bytes/s) may be used?"
 #~ msgstr "Hur mycket CPU (i %) får användas?"
 
-#, fuzzy
-#~ msgid "Quota configuration"
-#~ msgstr "GNUnet-konfiguration"
-
 #, fuzzy
 #~ msgid "Daemon configuration: user account"
 #~ msgstr "Kunde inte skapa användarkonto:"
@@ -10586,10 +10657,6 @@ msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n"
 #~ msgid "Save configuration?"
 #~ msgstr "GNUnet-konfiguration"
 
-#, fuzzy
-#~ msgid "GNUnet Configuration"
-#~ msgstr "GNUnet-konfiguration"
-
 #~ msgid "Back"
 #~ msgstr "Tillbaka"
 
@@ -10617,10 +10684,6 @@ msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n"
 #~ msgid "Error: can't delete service: %s\n"
 #~ msgstr "Fel: kan inte ta bort tjänst: %s\n"
 
-#, fuzzy
-#~ msgid "Configuration changed. Save?"
-#~ msgstr "Konfigurationsfil \"%s\" skapad.\n"
-
 #, fuzzy
 #~ msgid "Error saving configuration."
 #~ msgstr "Kunde inte spara konfiguration!"
index 7e9b43b60938354d703ff10bb9c52c7cb454e7d7..36ba909b48717ca7386e98047d5be7109e9a19d1 100644 (file)
--- a/po/vi.po
+++ b/po/vi.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.8.0a\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2016-11-27 09:18+0100\n"
+"POT-Creation-Date: 2017-01-12 17:19+0100\n"
 "PO-Revision-Date: 2008-09-10 22:05+0930\n"
 "Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
 "Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
@@ -257,21 +257,20 @@ msgstr ""
 #: src/arm/gnunet-service-arm.c:393 src/arm/gnunet-service-arm.c:399
 #: src/transport/plugin_transport_tcp.c:652
 #: src/transport/plugin_transport_tcp.c:658
-#: src/transport/plugin_transport_tcp.c:3299 src/util/service.c:584
-#: src/util/service.c:590 src/util/service_new.c:637
-#: src/util/service_new.c:643
+#: src/transport/plugin_transport_tcp.c:3309 src/util/service.c:584
+#: src/util/service.c:590 src/util/service_new.c:637 src/util/service_new.c:643
 #, c-format
 msgid "Require valid port number for service `%s' in configuration!\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:430 src/transport/plugin_transport_tcp.c:689
-#: src/util/client_new.c:464 src/util/service.c:621 src/util/service_new.c:682
+#: src/util/client.c:464 src/util/service.c:621 src/util/service_new.c:682
 #, c-format
 msgid "UNIXPATH `%s' too long, maximum length is %llu\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:434 src/transport/plugin_transport_tcp.c:693
-#: src/util/client_new.c:469 src/util/service.c:625 src/util/service_new.c:687
+#: src/util/client.c:469 src/util/service.c:625 src/util/service_new.c:687
 #, fuzzy, c-format
 msgid "Using `%s' instead\n"
 msgstr "%s: tùy chọn « %s » là mơ hồ\n"
@@ -291,7 +290,7 @@ msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:513
-#: src/transport/plugin_transport_http_server.c:2617
+#: src/transport/plugin_transport_http_server.c:2620
 #: src/transport/plugin_transport_tcp.c:772 src/util/service.c:704
 #: src/util/service_new.c:782
 #, fuzzy, c-format
@@ -299,7 +298,7 @@ msgid "Failed to resolve `%s': %s\n"
 msgstr "Lỗi mở tập tin ghi sự kiện « %s »: %s\n"
 
 #: src/arm/gnunet-service-arm.c:532
-#: src/transport/plugin_transport_http_server.c:2635
+#: src/transport/plugin_transport_http_server.c:2638
 #: src/transport/plugin_transport_tcp.c:791 src/util/service.c:723
 #: src/util/service_new.c:802
 #, fuzzy, c-format
@@ -394,13 +393,11 @@ msgid ""
 "%llu\n"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3293
-#: src/ats-tests/gnunet-solver-eval.c:935
+#: src/ats/gnunet-ats-solver-eval.c:3293 src/ats-tests/gnunet-solver-eval.c:935
 msgid "solver to use"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3296
-#: src/ats-tests/gnunet-solver-eval.c:938
+#: src/ats/gnunet-ats-solver-eval.c:3296 src/ats-tests/gnunet-solver-eval.c:938
 #: src/ats-tests/gnunet-solver-eval.c:941
 msgid "experiment to use"
 msgstr ""
@@ -506,12 +503,12 @@ msgstr ""
 msgid "Invalid %s configuration %f\n"
 msgstr "Không thể lưu tập tin cấu hình « %s »:"
 
-#: src/ats-tests/ats-testing.c:441
+#: src/ats-tests/ats-testing.c:422
 #, c-format
 msgid "Connected master [%u] with slave [%u]\n"
 msgstr ""
 
-#: src/ats-tests/ats-testing.c:448
+#: src/ats-tests/ats-testing.c:429
 #, fuzzy, c-format
 msgid "Failed to connect master peer [%u] with slave [%u]\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
@@ -569,7 +566,7 @@ msgid "Quota for network `%11s' (in/out): %10s / %10s\n"
 msgstr ""
 
 #: src/ats-tool/gnunet-ats.c:748 src/ats-tool/gnunet-ats.c:761
-#: src/transport/gnunet-transport.c:1476
+#: src/transport/gnunet-transport.c:1255
 #, fuzzy, c-format
 msgid "Failed to parse peer identity `%s'\n"
 msgstr "Lỗi đọc danh sách bạn bè từ « %s »\n"
@@ -656,6 +653,38 @@ msgstr ""
 msgid "Print information about ATS state"
 msgstr "In ra thông tin về các đồng đẳng GNUnet."
 
+#: src/auction/gnunet-auction-create.c:69
+msgid "description of the item to be sold"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:72
+msgid "mapping of possible prices"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:75
+msgid "max duration per round"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:78
+msgid "duration until auction starts"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:81
+msgid "number of items to sell, 0 for first price auction"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:84
+#, fuzzy
+msgid "public auction outcome"
+msgstr "Ứng dụng bị hủy bỏ."
+
+#: src/auction/gnunet-auction-create.c:94 src/auction/gnunet-auction-info.c:76
+#: src/auction/gnunet-auction-join.c:76
+#: src/conversation/gnunet-conversation-test.c:243
+#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
+msgid "help text"
+msgstr ""
+
 #: src/cadet/gnunet-cadet.c:511
 #, fuzzy, c-format
 msgid "Invalid target `%s'\n"
@@ -712,7 +741,7 @@ msgstr "In ra thông tin về các đồng đẳng GNUnet."
 msgid "provide information about all tunnels"
 msgstr "In ra thông tin về các đồng đẳng GNUnet."
 
-#: src/cadet/gnunet-service-cadet_peer.c:681
+#: src/cadet/gnunet-service-cadet_peer.c:686
 msgid "Wrong CORE service\n"
 msgstr ""
 
@@ -1037,11 +1066,6 @@ msgid ""
 "played back to you..."
 msgstr ""
 
-#: src/conversation/gnunet-conversation-test.c:243
-#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
-msgid "help text"
-msgstr ""
-
 #: src/conversation/gnunet_gst.c:630
 #: src/conversation/gnunet-helper-audio-playback-gst.c:357
 #, c-format
@@ -1246,7 +1270,7 @@ msgstr "Đối số không hợp lệ cho « %s ».\n"
 msgid "Failed to connect to CORE service!\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
 
-#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1677
+#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1456
 #, fuzzy
 msgid "provide information about all current connections (continuously)"
 msgstr "In ra thông tin về các đồng đẳng GNUnet."
@@ -1531,7 +1555,7 @@ msgstr "kho dữ liệu sqlite"
 #: src/testbed/gnunet-daemon-testbed-underlay.c:56
 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:52
 #: src/util/crypto_ecc_setup.c:41 src/util/crypto_mpi.c:39
-#: src/include/gnunet_common.h:681 src/include/gnunet_common.h:690
+#: src/include/gnunet_common.h:691 src/include/gnunet_common.h:700
 #: src/scalarproduct/scalarproduct.h:35
 #, c-format
 msgid "`%s' failed at %s:%d with error: %s\n"
@@ -1943,8 +1967,7 @@ msgstr ""
 msgid "Prints all packets that go through the DHT."
 msgstr ""
 
-#: src/dht/gnunet_dht_profiler.c:1161
-#: src/testbed/gnunet-testbed-profiler.c:255
+#: src/dht/gnunet_dht_profiler.c:1161 src/testbed/gnunet-testbed-profiler.c:255
 #, fuzzy, c-format
 msgid "Exiting as the number of peers is %u\n"
 msgstr "tăng sổ tối đa các kết nối TCP/IP"
@@ -2128,8 +2151,7 @@ msgstr ""
 msgid "# GET requests given to datacache"
 msgstr "# các yêu cầu get (lấy) dht được nhận"
 
-#: src/dht/gnunet-service-dht_hello.c:84
-#: src/dht/gnunet-service-xdht_hello.c:82
+#: src/dht/gnunet-service-dht_hello.c:84 src/dht/gnunet-service-xdht_hello.c:82
 #, fuzzy
 msgid "# HELLOs obtained from peerinfo"
 msgstr "Nhận được thông báo « %s » sai từ đồng đẳng « %s ».\n"
@@ -2206,41 +2228,41 @@ msgstr "# các yêu cầu get (lấy) dht được nhận"
 msgid "# P2P PUT bytes received"
 msgstr "# các yêu cầu get (lấy) dht được nhận"
 
-#: src/dht/gnunet-service-dht_neighbours.c:1854
+#: src/dht/gnunet-service-dht_neighbours.c:1858
 #, fuzzy
 msgid "# FIND PEER requests ignored due to Bloomfilter"
 msgstr "# các yêu cầu được lọc theo bộ lọc bloom"
 
-#: src/dht/gnunet-service-dht_neighbours.c:1862
+#: src/dht/gnunet-service-dht_neighbours.c:1866
 msgid "# FIND PEER requests ignored due to lack of HELLO"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2018
+#: src/dht/gnunet-service-dht_neighbours.c:2022
 #, fuzzy
 msgid "# P2P GET requests received"
 msgstr "# các yêu cầu get (lấy) dht được nhận"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2022
+#: src/dht/gnunet-service-dht_neighbours.c:2026
 #, fuzzy
 msgid "# P2P GET bytes received"
 msgstr "# các yêu cầu get (lấy) dht được nhận"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2097
+#: src/dht/gnunet-service-dht_neighbours.c:2101
 #, fuzzy
 msgid "# P2P FIND PEER requests processed"
 msgstr "# các yêu cầu get (lấy) dht được nhận"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2120
+#: src/dht/gnunet-service-dht_neighbours.c:2124
 #, fuzzy
 msgid "# P2P GET requests ONLY routed"
 msgstr "# các yêu cầu dht được định tuyến"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2222
+#: src/dht/gnunet-service-dht_neighbours.c:2226
 #, fuzzy
 msgid "# P2P RESULTS received"
 msgstr "# Tín hiệu HTTP PUT được nhận"
 
-#: src/dht/gnunet-service-dht_neighbours.c:2226
+#: src/dht/gnunet-service-dht_neighbours.c:2230
 #, fuzzy
 msgid "# P2P RESULT bytes received"
 msgstr "# Tín hiệu HTTP PUT được nhận"
@@ -2250,35 +2272,35 @@ msgstr "# Tín hiệu HTTP PUT được nhận"
 msgid "# Network size estimates received"
 msgstr "# các yêu cầu get (lấy) dht được nhận"
 
-#: src/dht/gnunet-service-dht_routing.c:218
+#: src/dht/gnunet-service-dht_routing.c:220
 msgid "# Good REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:227
+#: src/dht/gnunet-service-dht_routing.c:229
 msgid "# Duplicate REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:233
+#: src/dht/gnunet-service-dht_routing.c:235
 msgid "# Invalid REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:239
+#: src/dht/gnunet-service-dht_routing.c:241
 msgid "# Irrelevant REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:251
+#: src/dht/gnunet-service-dht_routing.c:253
 msgid "# Unsupported REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:327
+#: src/dht/gnunet-service-dht_routing.c:329
 msgid "# Entries removed from routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:409
+#: src/dht/gnunet-service-dht_routing.c:411
 msgid "# Entries added to routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:427
+#: src/dht/gnunet-service-dht_routing.c:429
 #, fuzzy
 msgid "# DHT requests combined"
 msgstr "# các yêu cầu get (lấy) dht được nhận"
@@ -2391,16 +2413,16 @@ msgid ""
 "SUPU %s, %s, %d, trail->prev_hop = %s"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:142
+#: src/dht/plugin_block_dht.c:144
 #, fuzzy, c-format
 msgid "Block not of type %u\n"
 msgstr "Không biết truyền tải nào kiểu %d.\n"
 
-#: src/dht/plugin_block_dht.c:149
+#: src/dht/plugin_block_dht.c:151
 msgid "Size mismatch for block\n"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:159
+#: src/dht/plugin_block_dht.c:161
 #, c-format
 msgid "Block of type %u is malformed\n"
 msgstr ""
@@ -3534,7 +3556,7 @@ msgid "Option `%s' is required when using option `%s'.\n"
 msgstr "Tùy chọn « %s » cần thiết khi dùng tùy chọn « %s ».\n"
 
 #: src/fs/gnunet-publish.c:849 src/fs/gnunet-publish.c:857
-#: src/transport/gnunet-transport.c:1517 src/transport/gnunet-transport.c:1542
+#: src/transport/gnunet-transport.c:1296 src/transport/gnunet-transport.c:1321
 #, c-format
 msgid "Option `%s' makes no sense without option `%s'.\n"
 msgstr "Tùy chọn « %s » không có nghĩa khi không có tùy chọn « %s ».\n"
@@ -4077,41 +4099,41 @@ msgstr "Nhận yêu cầu định tuyến\n"
 msgid "Received unsupported DNS request from %s\n"
 msgstr "Nhận yêu cầu định tuyến\n"
 
-#: src/gns/gnunet-dns2gns.c:709
+#: src/gns/gnunet-dns2gns.c:712
 msgid "No ego configured for `dns2gns` subsystem\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:737
+#: src/gns/gnunet-dns2gns.c:740
 #, fuzzy
 msgid "No DNS server specified!\n"
 msgstr "Chưa ghi rõ từ khoá.\n"
 
-#: src/gns/gnunet-dns2gns.c:758
+#: src/gns/gnunet-dns2gns.c:761
 #, fuzzy
 msgid "No valid GNS zone specified!\n"
 msgstr "Chưa ghi rõ từ khoá.\n"
 
-#: src/gns/gnunet-dns2gns.c:779
+#: src/gns/gnunet-dns2gns.c:782
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:785
 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:785
+#: src/gns/gnunet-dns2gns.c:788
 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:788
+#: src/gns/gnunet-dns2gns.c:791
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:791
+#: src/gns/gnunet-dns2gns.c:794
 msgid "Public key of the GNS zone to use (overrides default)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:804
+#: src/gns/gnunet-dns2gns.c:807
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4276,83 +4298,85 @@ msgstr ""
 msgid "Unsupported HTTP method `%s'\n"
 msgstr "Lệnh không được hỗ trợ « %s ». Đang hủy bỏ.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2167
+#: src/gns/gnunet-gns-proxy.c:2168
 #, fuzzy, c-format
 msgid "Unable to import private key from file `%s'\n"
 msgstr "Không thể tạo tài khoản người dùng:"
 
-#: src/gns/gnunet-gns-proxy.c:2197
+#: src/gns/gnunet-gns-proxy.c:2198
 #, fuzzy, c-format
 msgid "Unable to import certificate %s\n"
 msgstr "Không thể lưu tập tin cấu hình « %s »:"
 
-#: src/gns/gnunet-gns-proxy.c:2370
+#: src/gns/gnunet-gns-proxy.c:2371
 #, fuzzy, c-format
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2389 src/rest/gnunet-rest-server.c:533
+#: src/gns/gnunet-gns-proxy.c:2390 src/rest/gnunet-rest-server.c:533
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2709
+#: src/gns/gnunet-gns-proxy.c:2710
 #, fuzzy, c-format
 msgid "Unsupported socks version %d\n"
 msgstr "Lệnh không được hỗ trợ « %s ». Đang hủy bỏ.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2738
+#: src/gns/gnunet-gns-proxy.c:2739
 #, fuzzy, c-format
 msgid "Unsupported socks command %d\n"
 msgstr "Lệnh không được hỗ trợ « %s ». Đang hủy bỏ.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2756 src/gns/gnunet-gns-proxy.c:2785
+#: src/gns/gnunet-gns-proxy.c:2757 src/gns/gnunet-gns-proxy.c:2786
 msgid "SSL connection to plain IPv4 address requested\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2836
+#: src/gns/gnunet-gns-proxy.c:2837
 #, fuzzy, c-format
 msgid "Unsupported socks address type %d\n"
 msgstr "Lệnh không được hỗ trợ « %s ». Đang hủy bỏ.\n"
 
-#: src/gns/gnunet-gns-proxy.c:3171
+#: src/gns/gnunet-gns-proxy.c:3172
 msgid "No ego configured for `shorten-zone`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3211 src/gns/gnunet-service-gns.c:1093
-#: src/gns/gnunet-service-gns.c:1149
+#: src/gns/gnunet-gns-proxy.c:3212 src/gns/gnunet-service-gns.c:493
+#: src/gns/gnunet-service-gns.c:548
 #, c-format
 msgid "No ego configured for `%s`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3273
+#: src/gns/gnunet-gns-proxy.c:3274
 #, fuzzy, c-format
 msgid "Failed to load SSL/TLS key and certificate from `%s'\n"
 msgstr "Lỗi đọc danh sách bạn bè từ « %s »\n"
 
-#: src/gns/gnunet-gns-proxy.c:3313
+#: src/gns/gnunet-gns-proxy.c:3314
 msgid "listen on specified port (default: 7777)"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3316
+#: src/gns/gnunet-gns-proxy.c:3317
 msgid "pem file to use as CA"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3335
+#: src/gns/gnunet-gns-proxy.c:3336
 msgid "GNUnet GNS proxy"
 msgstr ""
 
-#: src/gns/gnunet-service-gns.c:1187
+#: src/gns/gnunet-service-gns.c:585
+#: src/zonemaster/gnunet-service-zonemaster.c:705
 #, fuzzy
 msgid "Failed to connect to the namestore!\n"
 msgstr "Không kết nối được đến trình nền gnunetd."
 
-#: src/gns/gnunet-service-gns.c:1195
+#: src/gns/gnunet-service-gns.c:593
 #, fuzzy
 msgid "Failed to connect to the namecache!\n"
 msgstr "Không kết nối được đến trình nền gnunetd."
 
-#: src/gns/gnunet-service-gns.c:1228
+#: src/gns/gnunet-service-gns.c:612
+#: src/zonemaster/gnunet-service-zonemaster.c:740
 #, fuzzy
 msgid "Could not connect to DHT!\n"
 msgstr "Không thể kết nối tới %s:%u: %s\n"
@@ -5207,8 +5231,7 @@ msgstr ""
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr "Đối số không hợp lệ cho « %s ».\n"
 
-#: src/namestore/gnunet-namestore.c:979
-#: src/peerinfo-tool/gnunet-peerinfo.c:775
+#: src/namestore/gnunet-namestore.c:979 src/peerinfo-tool/gnunet-peerinfo.c:775
 #, fuzzy, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "Dữ liệu nhập không hợp lệ.\n"
@@ -5367,217 +5390,293 @@ msgstr "kho dữ liệu sqlite"
 msgid "Namestore REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
 
-#: src/nat/gnunet-nat.c:159
-msgid "GNUnet NAT traversal autoconfigure daemon"
+#: src/nat-auto/gnunet-nat-auto.c:192
+#, fuzzy
+msgid "Suggested configuration changes:\n"
 msgstr ""
+"\n"
+"CHƯA lưu các thay đổi trong cấu hình.\n"
 
-#: src/nat/gnunet-nat-server.c:321
+#: src/nat-auto/gnunet-nat-auto.c:220
+#, fuzzy, c-format
+msgid "Failed to write configuration to `%s'\n"
+msgstr "Lỗi lưu cấu hình."
+
+#: src/nat-auto/gnunet-nat-auto.c:227
+#, fuzzy, c-format
+msgid "Wrote updated configuration to `%s'\n"
+msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:345
+#, fuzzy
+msgid "run autoconfiguration"
+msgstr "Cấu hình hạn ngạch"
+
+#: src/nat-auto/gnunet-nat-auto.c:348
+msgid "section name providing the configuration for the adapter"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:351 src/nat/gnunet-nat.c:436
+msgid "use TCP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:354 src/nat/gnunet-nat.c:439
+msgid "use UDP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:357
+msgid "write configuration file (for autoconfiguration)"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:369
+#, fuzzy
+msgid "GNUnet NAT traversal autoconfiguration"
+msgstr "Cấu hình GNUnet"
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:403
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:681
+#: src/nat-auto/nat_auto_api_test.c:405
+#, fuzzy
+msgid "Failed to connect to `gnunet-nat-server'\n"
+msgstr "Lỗi kết nối đến gnunetd.\n"
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:518
+#: src/nat-auto/nat_auto_api_test.c:520
+#, c-format
+msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:568
+#: src/nat-auto/nat_auto_api_test.c:569
+#, fuzzy
+msgid "NAT test failed to start NAT library\n"
+msgstr "Lỗi bắt đầu thu thập.\n"
+
+#: src/nat-auto/gnunet-nat-server.c:336
 #, c-format
 msgid "Please pass valid port number as the first argument! (got `%s')\n"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:363
+#: src/nat-auto/gnunet-nat-server.c:386
 msgid "GNUnet NAT traversal test helper daemon"
 msgstr ""
 
-#: src/nat/nat_api.c:880 src/nat/nat.c:2010
+#: src/nat-auto/gnunet-service-nat-auto.c:342
+msgid "UPnP client `upnpc` command not found, disabling UPnP\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:385
+msgid "NAT traversal with ICMP Server succeeded.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:386
+msgid "NAT traversal with ICMP Server failed.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:405
+#, fuzzy
+msgid "Testing connection reversal with ICMP server.\n"
+msgstr "Cổng để liên lạc với giao diện người dùng GNUnet"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:437
+#, c-format
+msgid "Detected external IP `%s'\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:572
+msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:590
+#, fuzzy, c-format
+msgid "Detected internal network address `%s'.\n"
+msgstr "GNUnet bây giờ sử dụng địa chỉ IP %s.\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:724
+msgid "upnpc found, enabling its use\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:725
+msgid "upnpc not found\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:762
+msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:774
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:834
+msgid "test_icmp_server not possible, as we are not behind NAT\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:786
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:846
+msgid "No working gnunet-helper-nat-server found\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:823
+msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/nat_auto_api.c:76
 msgid "Operation Successful"
 msgstr ""
 
-#: src/nat/nat_api.c:882 src/nat/nat.c:2012
-msgid "Internal Failure (IPC, ...)"
+#: src/nat-auto/nat_auto_api.c:78
+msgid "IPC failure"
 msgstr ""
 
-#: src/nat/nat_api.c:884 src/nat/nat.c:2014
+#: src/nat-auto/nat_auto_api.c:80
 msgid "Failure in network subsystem, check permissions."
 msgstr ""
 
-#: src/nat/nat_api.c:886 src/nat/nat.c:2016
+#: src/nat-auto/nat_auto_api.c:82
 msgid "Encountered timeout while performing operation"
 msgstr ""
 
-#: src/nat/nat_api.c:888 src/nat/nat.c:2018
+#: src/nat-auto/nat_auto_api.c:84
 msgid "detected that we are offline"
 msgstr ""
 
-#: src/nat/nat_api.c:890 src/nat/nat.c:2020
+#: src/nat-auto/nat_auto_api.c:86
 msgid "`upnpc` command not found"
 msgstr ""
 
-#: src/nat/nat_api.c:892 src/nat/nat.c:2022
+#: src/nat-auto/nat_auto_api.c:88
 #, fuzzy
 msgid "Failed to run `upnpc` command"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/nat/nat_api.c:894 src/nat/nat.c:2024
+#: src/nat-auto/nat_auto_api.c:90
 msgid "`upnpc' command took too long, process killed"
 msgstr ""
 
-#: src/nat/nat_api.c:896 src/nat/nat.c:2026
+#: src/nat-auto/nat_auto_api.c:92
 msgid "`upnpc' command failed to establish port mapping"
 msgstr ""
 
-#: src/nat/nat_api.c:898 src/nat/nat.c:2028
+#: src/nat-auto/nat_auto_api.c:94
 msgid "`external-ip' command not found"
 msgstr ""
 
-#: src/nat/nat_api.c:900 src/nat/nat.c:2030
+#: src/nat-auto/nat_auto_api.c:96
 #, fuzzy
 msgid "Failed to run `external-ip` command"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/nat/nat_api.c:902 src/nat/nat.c:2032
+#: src/nat-auto/nat_auto_api.c:98
 msgid "`external-ip' command output invalid"
 msgstr ""
 
-#: src/nat/nat_api.c:904 src/nat/nat.c:2034
+#: src/nat-auto/nat_auto_api.c:100
 msgid "no valid address was returned by `external-ip'"
 msgstr ""
 
-#: src/nat/nat_api.c:906 src/nat/nat.c:2036
+#: src/nat-auto/nat_auto_api.c:102
 #, fuzzy
 msgid "Could not determine interface with internal/local network address"
 msgstr "Không thể truy cập đến thông tin về không gian tên.\n"
 
-#: src/nat/nat_api.c:908 src/nat/nat.c:2038
+#: src/nat-auto/nat_auto_api.c:104
 msgid "No functioning gnunet-helper-nat-server installation found"
 msgstr ""
 
-#: src/nat/nat_api.c:910 src/nat/nat.c:2040
+#: src/nat-auto/nat_auto_api.c:106
 msgid "NAT test could not be initialized"
 msgstr ""
 
-#: src/nat/nat_api.c:912 src/nat/nat.c:2042
+#: src/nat-auto/nat_auto_api.c:108
 msgid "NAT test timeout reached"
 msgstr ""
 
-#: src/nat/nat_api.c:914 src/nat/nat.c:2044
+#: src/nat-auto/nat_auto_api.c:110
 msgid "could not register NAT"
 msgstr ""
 
-#: src/nat/nat_api.c:916 src/nat/nat.c:2046
+#: src/nat-auto/nat_auto_api.c:112
 msgid "No working gnunet-helper-nat-client installation found"
 msgstr ""
 
-#: src/nat/nat_auto.c:385
-msgid "NAT traversal with ICMP Server succeeded.\n"
-msgstr ""
+#: src/nat-auto/nat_auto_api_test.c:477
+#, fuzzy, c-format
+msgid "Failed to find valid PORT in section `%s'\n"
+msgstr "Lỗi đóng kết đến cổng %s %d.\n"
 
-#: src/nat/nat_auto.c:386
-msgid "NAT traversal with ICMP Server failed.\n"
+#: src/nat/gnunet-nat.c:424
+msgid "which IP and port are we locally using to bind/listen to"
 msgstr ""
 
-#: src/nat/nat_auto.c:405
-#, fuzzy
-msgid "Testing connection reversal with ICMP server.\n"
-msgstr "Cổng để liên lạc với giao diện người dùng GNUnet"
-
-#: src/nat/nat_auto.c:437
-#, c-format
-msgid "Detected external IP `%s'\n"
+#: src/nat/gnunet-nat.c:427
+msgid "which remote IP and port should be asked for connection reversal"
 msgstr ""
 
-#: src/nat/nat_auto.c:572
-msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+#: src/nat/gnunet-nat.c:430
+msgid ""
+"name of configuration section to find additional options, such as manual "
+"host punching data"
 msgstr ""
 
-#: src/nat/nat_auto.c:590
-#, fuzzy, c-format
-msgid "Detected internal network address `%s'.\n"
-msgstr "GNUnet bây giờ sử dụng địa chỉ IP %s.\n"
-
-#: src/nat/nat_auto.c:681 src/nat/nat_test.c:403
-#, fuzzy
-msgid "Failed to connect to `gnunet-nat-server'\n"
-msgstr "Lỗi kết nối đến gnunetd.\n"
-
-#: src/nat/nat_auto.c:724
-msgid "upnpc found, enabling its use\n"
+#: src/nat/gnunet-nat.c:433
+msgid "enable STUN processing"
 msgstr ""
 
-#: src/nat/nat_auto.c:725
-msgid "upnpc not found\n"
+#: src/nat/gnunet-nat.c:442
+msgid "watch for connection reversal requests"
 msgstr ""
 
-#: src/nat/nat_auto.c:762
-msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:774 src/nat/nat_auto.c:834
-msgid "test_icmp_server not possible, as we are not behind NAT\n"
+#: src/nat/gnunet-nat.c:454
+msgid "GNUnet NAT traversal autoconfigure daemon"
 msgstr ""
 
-#: src/nat/nat_auto.c:786 src/nat/nat_auto.c:846
-msgid "No working gnunet-helper-nat-server found\n"
+#: src/nat/gnunet-service-nat.c:1313
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat_auto.c:823
-msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+#: src/nat/gnunet-service-nat.c:1323
+#, c-format
+msgid "Invalid port number in punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1019
+#: src/nat/gnunet-service-nat.c:1339
 #, c-format
-msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
+msgid "Malformed punched hole specification `%s' (lacks `]')\n"
 msgstr ""
 
-#: src/nat/nat.c:1070
-#, fuzzy, c-format
-msgid "Failed to start %s\n"
-msgstr "Lỗi bắt đầu thu thập.\n"
-
-#: src/nat/nat.c:1327
-msgid "Error while running upnp client:\n"
+#: src/nat/gnunet-service-nat.c:1350
+#, c-format
+msgid "Malformed punched hole specification `%s' (IPv6 address invalid)"
 msgstr ""
 
-#: src/nat/nat.c:1402
-#, fuzzy, c-format
-msgid "Failed to run upnp client for port %u\n"
-msgstr "Lỗi sơ khởi dịch vụ « %s ».\n"
-
-#: src/nat/nat.c:1546
-msgid "malformed"
-msgstr ""
+#: src/nat/gnunet-service-nat.c:1803
+#, fuzzy
+msgid "Connection reversal request failed\n"
+msgstr "Thu thập bị dừng.\n"
 
-#: src/nat/nat.c:1600
+#: src/nat/gnunet-service-nat.c:1876
 msgid ""
 "UPnP enabled in configuration, but UPnP client `upnpc` command not found, "
-"disabling UPnP \n"
+"disabling UPnP\n"
 msgstr ""
 
-#: src/nat/nat.c:1726 src/nat/nat.c:1739
+#: src/nat/gnunet-service-nat_helper.c:186
 #, c-format
-msgid ""
-"Configuration requires `%s', but binary is not installed properly (SUID bit "
-"not set).  Option disabled.\n"
-msgstr ""
-
-#: src/nat/nat.c:1903
-msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n"
+msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/nat.c:1919
-#, c-format
-msgid "Running gnunet-helper-nat-client %s %s %u\n"
-msgstr ""
+#: src/nat/gnunet-service-nat_helper.c:260
+#, fuzzy, c-format
+msgid "Failed to start %s\n"
+msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/nat/nat_mini.c:205
+#: src/nat/gnunet-service-nat_mini.c:196
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/nat_mini.c:611
+#: src/nat/gnunet-service-nat_mini.c:654
 msgid "`upnpc' command not found\n"
 msgstr ""
 
-#: src/nat/nat_test.c:518
-#, c-format
-msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
-msgstr ""
-
-#: src/nat/nat_test.c:568
-#, fuzzy
-msgid "NAT test failed to start NAT library\n"
-msgstr "Lỗi bắt đầu thu thập.\n"
-
 #: src/nse/gnunet-nse.c:122
 #, fuzzy
 msgid "Show network size estimates from NSE service."
@@ -7390,182 +7489,159 @@ msgstr ""
 msgid "# validations succeeded"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:486
+#: src/transport/gnunet-transport.c:418
 #, fuzzy, c-format
 msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n"
 msgstr "Đang thử tải danh sách các máy xuống « %s »\n"
 
-#: src/transport/gnunet-transport.c:496
+#: src/transport/gnunet-transport.c:428
 #, fuzzy, c-format
 msgid "Received %llu bytes/s (%llu bytes in %s)\n"
 msgstr "Nhận yêu cầu định tuyến\n"
 
-#: src/transport/gnunet-transport.c:540
+#: src/transport/gnunet-transport.c:472
 #, fuzzy, c-format
 msgid "Failed to connect to `%s'\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:553
+#: src/transport/gnunet-transport.c:485
 #, fuzzy, c-format
 msgid "Failed to resolve address for peer `%s'\n"
 msgstr "Lỗi đóng kết đến cổng %s %d.\n"
 
-#: src/transport/gnunet-transport.c:565
+#: src/transport/gnunet-transport.c:499
 #, fuzzy
 msgid "Failed to list connections, timeout occured\n"
 msgstr "Không kết nối được đến trình nền gnunetd."
 
-#: src/transport/gnunet-transport.c:588
-#, fuzzy, c-format
-msgid "NAT plugin `%s' reports: %s\n"
-msgstr "Đang nạp các truyền tải « %s »\n"
-
-#: src/transport/gnunet-transport.c:675
-msgid "No transport plugins configured, peer will never communicate\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:689
-#, c-format
-msgid "No port configured for plugin `%s', cannot test it\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:714
-#, fuzzy
-msgid "Failed to start resolver!\n"
-msgstr "Lỗi bắt đầu thu thập.\n"
-
-#: src/transport/gnunet-transport.c:750
+#: src/transport/gnunet-transport.c:532
 #, fuzzy, c-format
 msgid "Transmitting %u bytes\n"
 msgstr "Đang thử tải danh sách các máy xuống « %s »\n"
 
-#: src/transport/gnunet-transport.c:784
+#: src/transport/gnunet-transport.c:566
 #, c-format
 msgid ""
 "Successfully connected to `%s', starting to send benchmark data in %u Kb "
 "blocks\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:815
+#: src/transport/gnunet-transport.c:597
 #, fuzzy, c-format
 msgid "Disconnected from peer `%s' while benchmarking\n"
 msgstr "« %.*s » được kết nối tới « %.*s ».\n"
 
-#: src/transport/gnunet-transport.c:839 src/transport/gnunet-transport.c:868
+#: src/transport/gnunet-transport.c:621 src/transport/gnunet-transport.c:650
 #, c-format
 msgid "%24s: %-17s %4s   (%u connections in total)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:841
+#: src/transport/gnunet-transport.c:623
 #, fuzzy
 msgid "Connected to"
 msgstr "« %s » được kết nối tới « %s ».\n"
 
-#: src/transport/gnunet-transport.c:870
+#: src/transport/gnunet-transport.c:652
 #, fuzzy
 msgid "Disconnected from"
 msgstr "« %.*s » được kết nối tới « %.*s ».\n"
 
-#: src/transport/gnunet-transport.c:905
+#: src/transport/gnunet-transport.c:687
 #, fuzzy, c-format
 msgid "Received %u bytes\n"
 msgstr "Nhận yêu cầu định tuyến\n"
 
-#: src/transport/gnunet-transport.c:942
+#: src/transport/gnunet-transport.c:724
 #, c-format
 msgid "Peer `%s': %s %s in state `%s' until %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:954
+#: src/transport/gnunet-transport.c:736
 #, fuzzy, c-format
 msgid "Peer `%s': %s %s\n"
 msgstr "Tôi là đồng đẳng « %s ».\n"
 
-#: src/transport/gnunet-transport.c:1366
+#: src/transport/gnunet-transport.c:1150
 #, fuzzy
 msgid "Monitor disconnected from transport service. Reconnecting.\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:1488
+#: src/transport/gnunet-transport.c:1267
 #, c-format
 msgid ""
 "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, "
 "%s, %s %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1501
+#: src/transport/gnunet-transport.c:1280
 #, c-format
 msgid ""
 "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s, %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1529
+#: src/transport/gnunet-transport.c:1308
 #, fuzzy
 msgid "Failed to connect to transport service for disconnection\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:1535
+#: src/transport/gnunet-transport.c:1314
 msgid "Blacklisting request in place, stop with CTRL-C\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1558 src/transport/gnunet-transport.c:1588
-#: src/transport/gnunet-transport.c:1641
+#: src/transport/gnunet-transport.c:1337 src/transport/gnunet-transport.c:1367
+#: src/transport/gnunet-transport.c:1420
 #, fuzzy
 msgid "Failed to connect to transport service\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:1595
+#: src/transport/gnunet-transport.c:1374
 msgid "Starting to receive benchmark data\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1665
+#: src/transport/gnunet-transport.c:1444
 #, fuzzy
 msgid "print information for all peers (instead of only connected peers)"
 msgstr "In ra thông tin về các đồng đẳng GNUnet."
 
-#: src/transport/gnunet-transport.c:1668
+#: src/transport/gnunet-transport.c:1447
 msgid "measure how fast we are receiving data from all peers (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1671
+#: src/transport/gnunet-transport.c:1450
 #, fuzzy
 msgid "disconnect from a peer"
 msgstr "Lỗi kết nối đến gnunetd.\n"
 
-#: src/transport/gnunet-transport.c:1674
+#: src/transport/gnunet-transport.c:1453
 #, fuzzy
 msgid "provide information about all current connections (once)"
 msgstr "In ra thông tin về các đồng đẳng GNUnet."
 
-#: src/transport/gnunet-transport.c:1680
+#: src/transport/gnunet-transport.c:1459
 #, fuzzy
 msgid ""
 "provide information about all connects and disconnect events (continuously)"
 msgstr "In ra thông tin về các đồng đẳng GNUnet."
 
-#: src/transport/gnunet-transport.c:1683
+#: src/transport/gnunet-transport.c:1462
 #, fuzzy
 msgid "do not resolve hostnames"
 msgstr "không quyết định các tên máy"
 
-#: src/transport/gnunet-transport.c:1686
+#: src/transport/gnunet-transport.c:1465
 #: src/transport/gnunet-transport-profiler.c:631
 msgid "peer identity"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1689
+#: src/transport/gnunet-transport.c:1468
 msgid "monitor plugin sessions"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1692
+#: src/transport/gnunet-transport.c:1471
 msgid "send data for benchmarking to the other peer (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1695
-msgid "test transport configuration (involves external server)"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:1706
+#: src/transport/gnunet-transport.c:1482
 #: src/transport/gnunet-transport-profiler.c:642
 #, fuzzy
 msgid "Direct access to transport service."
@@ -7602,9 +7678,9 @@ msgstr "kích cỡ tin nhắn"
 
 #: src/transport/plugin_transport_http_client.c:1477
 #: src/transport/plugin_transport_http_server.c:2248
-#: src/transport/plugin_transport_http_server.c:3457
-#: src/transport/plugin_transport_tcp.c:3365
-#: src/transport/plugin_transport_tcp.c:3372
+#: src/transport/plugin_transport_http_server.c:3462
+#: src/transport/plugin_transport_tcp.c:3375
+#: src/transport/plugin_transport_tcp.c:3382
 msgid "TCP_STEALTH not supported on this platform.\n"
 msgstr ""
 
@@ -7614,13 +7690,13 @@ msgid "Could not initialize curl multi handle, failed to start %s plugin!\n"
 msgstr ""
 
 #: src/transport/plugin_transport_http_client.c:2167
-#: src/transport/plugin_transport_http_server.c:3172
+#: src/transport/plugin_transport_http_server.c:3177
 #, fuzzy, c-format
 msgid "Shutting down plugin `%s'\n"
 msgstr "Đang nạp các truyền tải « %s »\n"
 
 #: src/transport/plugin_transport_http_client.c:2184
-#: src/transport/plugin_transport_http_server.c:3242
+#: src/transport/plugin_transport_http_server.c:3247
 #, fuzzy, c-format
 msgid "Shutdown for plugin `%s' complete\n"
 msgstr "Tải lên « %s » hoàn thành, địa chỉ URI là « %s ».\n"
@@ -7663,73 +7739,73 @@ msgstr ""
 msgid "Could not load or create server certificate! Loading plugin failed!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2583
+#: src/transport/plugin_transport_http_server.c:2586
 #, fuzzy
 msgid "Require valid port number for service in configuration!\n"
 msgstr "Lỗi lưu cấu hình."
 
-#: src/transport/plugin_transport_http_server.c:2748
+#: src/transport/plugin_transport_http_server.c:2751
 #, c-format
 msgid "Found %u addresses to report to NAT service\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2832
-#: src/transport/plugin_transport_udp.c:3600
+#: src/transport/plugin_transport_http_server.c:2837
+#: src/transport/plugin_transport_udp.c:3623
 msgid "Disabling IPv6 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2938
+#: src/transport/plugin_transport_http_server.c:2943
 #, c-format
 msgid "IPv4 support is %s\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2953
+#: src/transport/plugin_transport_http_server.c:2958
 #, c-format
 msgid "IPv6 support is %s\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2959
+#: src/transport/plugin_transport_http_server.c:2964
 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2970
+#: src/transport/plugin_transport_http_server.c:2975
 #, fuzzy
 msgid "Port is required! Fix in configuration\n"
 msgstr ""
 "\n"
 "Kết thúc cấu hình.\n"
 
-#: src/transport/plugin_transport_http_server.c:2976
+#: src/transport/plugin_transport_http_server.c:2981
 #, fuzzy, c-format
 msgid "Using port %u\n"
 msgstr "Đang thử nghiệm (các) truyền tải %s\n"
 
-#: src/transport/plugin_transport_http_server.c:2995
+#: src/transport/plugin_transport_http_server.c:3000
 #, fuzzy, c-format
 msgid "Specific IPv4 address `%s' in configuration file is invalid!\n"
 msgstr "Đang thử dùng tập tin « %s » cho cấu hình MySQL.\n"
 
-#: src/transport/plugin_transport_http_server.c:3030
+#: src/transport/plugin_transport_http_server.c:3035
 #, fuzzy, c-format
 msgid "Specific IPv6 address `%s' in configuration file is invalid!\n"
 msgstr "Đang thử dùng tập tin « %s » cho cấu hình MySQL.\n"
 
-#: src/transport/plugin_transport_http_server.c:3105
+#: src/transport/plugin_transport_http_server.c:3110
 #, fuzzy, c-format
 msgid "Using external hostname `%s'\n"
 msgstr "Đang bắt đầu tài về « %s »\n"
 
-#: src/transport/plugin_transport_http_server.c:3126
+#: src/transport/plugin_transport_http_server.c:3131
 #, fuzzy, c-format
 msgid "Notifying transport only about hostname `%s'\n"
 msgstr "không quyết định các tên máy"
 
-#: src/transport/plugin_transport_http_server.c:3143
+#: src/transport/plugin_transport_http_server.c:3148
 #, fuzzy, c-format
 msgid "Maximum number of connections is %u\n"
 msgstr "tăng sổ tối đa các kết nối TCP/IP"
 
-#: src/transport/plugin_transport_http_server.c:3469
+#: src/transport/plugin_transport_http_server.c:3474
 #, fuzzy
 msgid "Unable to compile URL regex\n"
 msgstr "Không thể sơ khởi SQLite: %s.\n"
@@ -7776,167 +7852,167 @@ msgstr "# các byte đã gửi qua SMTP"
 msgid "# bytes dropped by SMTP (outgoing)"
 msgstr "# các byte loại đi bởi SMTP (đi ra)"
 
-#: src/transport/plugin_transport_tcp.c:1051
-#: src/transport/plugin_transport_tcp.c:2362
+#: src/transport/plugin_transport_tcp.c:1060
+#: src/transport/plugin_transport_tcp.c:2379
 #, fuzzy, c-format
 msgid "Unexpected address length: %u bytes\n"
 msgstr "Gặp sự kiện bất thường: %d\n"
 
-#: src/transport/plugin_transport_tcp.c:1234
-#: src/transport/plugin_transport_tcp.c:1458
-#: src/transport/plugin_transport_tcp.c:2633
-#: src/transport/plugin_transport_tcp.c:3490
+#: src/transport/plugin_transport_tcp.c:1243
+#: src/transport/plugin_transport_tcp.c:1467
+#: src/transport/plugin_transport_tcp.c:2643
+#: src/transport/plugin_transport_tcp.c:3498
 #, fuzzy
 msgid "# TCP sessions active"
 msgstr "# các khoá phiên chạy được chấp nhận"
 
-#: src/transport/plugin_transport_tcp.c:1276
-#: src/transport/plugin_transport_tcp.c:1440
-#: src/transport/plugin_transport_tcp.c:1564
-#: src/transport/plugin_transport_tcp.c:1637
-#: src/transport/plugin_transport_tcp.c:1737
-#: src/transport/plugin_transport_tcp.c:1762
+#: src/transport/plugin_transport_tcp.c:1285
+#: src/transport/plugin_transport_tcp.c:1449
+#: src/transport/plugin_transport_tcp.c:1573
+#: src/transport/plugin_transport_tcp.c:1646
+#: src/transport/plugin_transport_tcp.c:1746
+#: src/transport/plugin_transport_tcp.c:1771
 #, fuzzy
 msgid "# bytes currently in TCP buffers"
 msgstr "# các byte đã gừi qua TCP"
 
-#: src/transport/plugin_transport_tcp.c:1279
+#: src/transport/plugin_transport_tcp.c:1288
 #, fuzzy
 msgid "# bytes discarded by TCP (disconnect)"
 msgstr "# các byte loại đi bởi TCP (đi ra)"
 
-#: src/transport/plugin_transport_tcp.c:1567
+#: src/transport/plugin_transport_tcp.c:1576
 #, fuzzy
 msgid "# bytes discarded by TCP (timeout)"
 msgstr "# các byte loại đi bởi TCP (đi ra)"
 
-#: src/transport/plugin_transport_tcp.c:1641
+#: src/transport/plugin_transport_tcp.c:1650
 #, fuzzy
 msgid "# bytes transmitted via TCP"
 msgstr "# các byte được gửi"
 
-#: src/transport/plugin_transport_tcp.c:2032
+#: src/transport/plugin_transport_tcp.c:2041
 msgid "# requests to create session with invalid address"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2200
+#: src/transport/plugin_transport_tcp.c:2217
 msgid "# transport-service disconnect requests for TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2692
+#: src/transport/plugin_transport_tcp.c:2702
 #, fuzzy
 msgid "# TCP WELCOME messages received"
 msgstr "# các thông báo PONG đã mật mã được nhận"
 
-#: src/transport/plugin_transport_tcp.c:2883
+#: src/transport/plugin_transport_tcp.c:2893
 msgid "# bytes received via TCP"
 msgstr "# các byte đã nhận qua TCP"
 
-#: src/transport/plugin_transport_tcp.c:2934
-#: src/transport/plugin_transport_tcp.c:2992
+#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:3002
 #, fuzzy
 msgid "# TCP server connections active"
 msgstr "# các kết nối dht"
 
-#: src/transport/plugin_transport_tcp.c:2938
+#: src/transport/plugin_transport_tcp.c:2948
 #, fuzzy
 msgid "# TCP server connect events"
 msgstr "# của các đồng đẳng đã kết nối"
 
-#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:2954
 msgid "TCP connection limit reached, suspending server\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2946
+#: src/transport/plugin_transport_tcp.c:2956
 msgid "# TCP service suspended"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2986
+#: src/transport/plugin_transport_tcp.c:2996
 msgid "# TCP service resumed"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2996
+#: src/transport/plugin_transport_tcp.c:3006
 msgid "# network-level TCP disconnect events"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3315
+#: src/transport/plugin_transport_tcp.c:3325
 #, fuzzy
 msgid "Failed to start service.\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/transport/plugin_transport_tcp.c:3478
+#: src/transport/plugin_transport_tcp.c:3486
 #, c-format
 msgid "TCP transport listening on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3482
+#: src/transport/plugin_transport_tcp.c:3490
 msgid "TCP transport not listening on any port (client only)\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3486
+#: src/transport/plugin_transport_tcp.c:3494
 #, c-format
 msgid "TCP transport advertises itself as being on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:170
+#: src/transport/plugin_transport_udp_broadcasting.c:169
 #, fuzzy
 msgid "# Multicast HELLO beacons received via UDP"
 msgstr "# các thông báo PONG đã mật mã được nhận"
 
-#: src/transport/plugin_transport_udp_broadcasting.c:546
+#: src/transport/plugin_transport_udp_broadcasting.c:545
 msgid ""
 "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:567
+#: src/transport/plugin_transport_udp_broadcasting.c:566
 #, c-format
 msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3344
+#: src/transport/plugin_transport_udp.c:3367
 #, c-format
 msgid ""
 "UDP could not transmit message to `%s': Network seems down, please check "
 "your network configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3358
+#: src/transport/plugin_transport_udp.c:3381
 msgid ""
 "UDP could not transmit IPv6 message! Please check your network configuration "
 "and disable IPv6 if your connection does not have a global IPv6 address\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3676
-#: src/transport/plugin_transport_udp.c:3775
+#: src/transport/plugin_transport_udp.c:3699
+#: src/transport/plugin_transport_udp.c:3798
 #, fuzzy, c-format
 msgid "Failed to bind UDP socket to %s: %s\n"
 msgstr "Lỗi mở tập tin ghi sự kiện « %s »: %s\n"
 
-#: src/transport/plugin_transport_udp.c:3694
+#: src/transport/plugin_transport_udp.c:3717
 msgid "Disabling IPv4 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3785
+#: src/transport/plugin_transport_udp.c:3808
 #, fuzzy
 msgid "Failed to open UDP sockets\n"
 msgstr "Lỗi mở tập tin ghi sự kiện « %s »: %s\n"
 
-#: src/transport/plugin_transport_udp.c:3857
-#: src/transport/plugin_transport_udp.c:3871
+#: src/transport/plugin_transport_udp.c:3879
+#: src/transport/plugin_transport_udp.c:3893
 msgid "must be in [0,65535]"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3903
+#: src/transport/plugin_transport_udp.c:3925
 #, fuzzy
 msgid "must be valid IPv4 address"
 msgstr "« %s » không sẵn sàng.\n"
 
-#: src/transport/plugin_transport_udp.c:3930
+#: src/transport/plugin_transport_udp.c:3952
 #, fuzzy
 msgid "must be valid IPv6 address"
 msgstr "« %s » không sẵn sàng.\n"
 
-#: src/transport/plugin_transport_udp.c:3996
+#: src/transport/plugin_transport_udp.c:4018
 #, fuzzy
 msgid "Failed to create UDP network sockets\n"
 msgstr "Không thể tạo miền tên.\n"
@@ -8057,7 +8133,7 @@ msgstr ""
 msgid "Metadata `%s' failed to deserialize"
 msgstr ""
 
-#: src/util/client_new.c:864
+#: src/util/client.c:864
 #, c-format
 msgid "Need a non-empty hostname for service `%s'.\n"
 msgstr ""
@@ -8833,42 +8909,42 @@ msgstr ""
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n"
 
-#: src/util/strings.c:1475 src/util/strings.c:1491
+#: src/util/strings.c:1541 src/util/strings.c:1557
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1500
+#: src/util/strings.c:1566
 #, fuzzy, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/util/strings.c:1583 src/util/strings.c:1614 src/util/strings.c:1662
-#: src/util/strings.c:1683
+#: src/util/strings.c:1649 src/util/strings.c:1680 src/util/strings.c:1728
+#: src/util/strings.c:1749
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "Địa chỉ IP định dạng sai: %s\n"
 
-#: src/util/strings.c:1640
+#: src/util/strings.c:1706
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "Ký hiệu mạng sai (« /%d » không hợp lệ trong CIDR IPv4)."
 
-#: src/util/strings.c:1692
+#: src/util/strings.c:1758
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "Địa chỉ IP định dạng sai: %s\n"
 
-#: src/util/strings.c:1744
+#: src/util/strings.c:1810
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "Ký hiệu mạng sai (không kết thúc với « ; »: « %s »)\n"
 
-#: src/util/strings.c:1794
+#: src/util/strings.c:1860
 #, fuzzy, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "Mặt nạ mạng có định dạng sai « %s »: %s\n"
 
-#: src/util/strings.c:1825
+#: src/util/strings.c:1891
 #, fuzzy, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "Mạng có định dạng sai « %s »: %s\n"
@@ -9057,21 +9133,33 @@ msgid "Setup tunnels via VPN."
 msgstr ""
 
 #: src/include/gnunet_common.h:645 src/include/gnunet_common.h:652
-#: src/include/gnunet_common.h:660
+#: src/include/gnunet_common.h:662 src/include/gnunet_common.h:670
 #, fuzzy, c-format
 msgid "Assertion failed at %s:%d.\n"
 msgstr "Lỗi nội bộ : khẳng định không thành công tại %s:%d.\n"
 
-#: src/include/gnunet_common.h:672
+#: src/include/gnunet_common.h:682
 #, fuzzy, c-format
 msgid "External protocol violation detected at %s:%d.\n"
 msgstr "Lỗi nội bộ : khẳng định không thành công tại %s:%d.\n"
 
-#: src/include/gnunet_common.h:699 src/include/gnunet_common.h:708
+#: src/include/gnunet_common.h:709 src/include/gnunet_common.h:718
 #, c-format
 msgid "`%s' failed on file `%s' at %s:%d with error: %s\n"
 msgstr "« %s » thất bại ở tập tin « %s » tại %s:%d với lỗi: %s\n"
 
+#, fuzzy
+#~ msgid "Failed to run upnp client for port %u\n"
+#~ msgstr "Lỗi sơ khởi dịch vụ « %s ».\n"
+
+#, fuzzy
+#~ msgid "NAT plugin `%s' reports: %s\n"
+#~ msgstr "Đang nạp các truyền tải « %s »\n"
+
+#, fuzzy
+#~ msgid "Failed to start resolver!\n"
+#~ msgstr "Lỗi bắt đầu thu thập.\n"
+
 #, fuzzy
 #~ msgid "Unable to initialize Postgres: %s\n"
 #~ msgstr "Không thể sơ khởi SQLite: %s.\n"
@@ -10481,10 +10569,6 @@ msgstr "« %s » thất bại ở tập tin « %s » tại %s:%d với lỗi: %s
 #~ msgid "Setting d->dead on peer `%4s'\n"
 #~ msgstr "Đang bắt đầu tài lên « %s ».\n"
 
-#, fuzzy
-#~ msgid "Failed to write new configuration to disk."
-#~ msgstr "Lỗi lưu cấu hình."
-
 #, fuzzy
 #~ msgid "Could not start `%s' process to copy configuration file.\n"
 #~ msgstr "Không tìm thấy phương pháp « %s%s » trong thư viện « %s ».\n"
@@ -10532,10 +10616,6 @@ msgstr "« %s » thất bại ở tập tin « %s » tại %s:%d với lỗi: %s
 #~ msgid "Option `%s' in section `%s' not specified!\n"
 #~ msgstr "Bị từ chối đặt tùy chọn « %s » trong phần « %s » thành « %s ».\n"
 
-#, fuzzy
-#~ msgid "Failed to find option %s in section %s!\n"
-#~ msgstr "Lỗi đóng kết đến cổng %s %d.\n"
-
 #, fuzzy
 #~ msgid "Invalid configuration option `%s' in section `%s'\n"
 #~ msgstr ""
@@ -10948,9 +11028,6 @@ msgstr "« %s » thất bại ở tập tin « %s » tại %s:%d với lỗi: %s
 #~ "thì có thể đặt thành tốc độ kết nối Internet lớn nhất. Không nên đặt giá "
 #~ "trị lớn hơn số được gán cho kết nối Internet của bạn."
 
-#~ msgid "Quota configuration"
-#~ msgstr "Cấu hình hạn ngạch"
-
 #~ msgid "What is the maximum size of the datastore in MB?"
 #~ msgstr "Kho dữ liệu có kích cỡ tối đa (theo MB)?"
 
@@ -11031,9 +11108,6 @@ msgstr "« %s » thất bại ở tập tin « %s » tại %s:%d với lỗi: %s
 #~ msgid "Save configuration?"
 #~ msgstr "Lưu cấu hình không?"
 
-#~ msgid "GNUnet Configuration"
-#~ msgstr "Cấu hình GNUnet"
-
 #~ msgid "Back"
 #~ msgstr "Lùi"
 
@@ -11058,13 +11132,6 @@ msgstr "« %s » thất bại ở tập tin « %s » tại %s:%d với lỗi: %s
 #~ msgid "Do you wish to save your new configuration?"
 #~ msgstr "Bạn có muốn lưu cấu hình mới không?"
 
-#~ msgid ""
-#~ "\n"
-#~ "Your configuration changes were NOT saved.\n"
-#~ msgstr ""
-#~ "\n"
-#~ "CHƯA lưu các thay đổi trong cấu hình.\n"
-
 #~ msgid "install GNUnet as Windows service"
 #~ msgstr "cài đặt GNUnet như là một dịch vụ Windows"
 
@@ -12024,9 +12091,6 @@ msgstr "« %s » thất bại ở tập tin « %s » tại %s:%d với lỗi: %s
 #~ msgid "Revision %u"
 #~ msgstr "Bản sửa đổi %u"
 
-#~ msgid "Application aborted."
-#~ msgstr "Ứng dụng bị hủy bỏ."
-
 #~ msgid "FSUI state file `%s' had syntax error at offset %u.\n"
 #~ msgstr "Tập tin tình trạng FSUI « %s » có lỗi cú pháp tại khoảng bù %u.\n"
 
index 16fee9b24a4b9441c93cd8bfc6badf6d43dcb1a1..579bc83642f44c195e00c78b0a050219c4825289 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet-0.8.1\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2016-11-27 09:18+0100\n"
+"POT-Creation-Date: 2017-01-12 17:19+0100\n"
 "PO-Revision-Date: 2011-07-09 12:12+0800\n"
 "Last-Translator: Wylmer Wang <wantinghard@gmail.com>\n"
 "Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
@@ -250,21 +250,20 @@ msgstr ""
 #: src/arm/gnunet-service-arm.c:393 src/arm/gnunet-service-arm.c:399
 #: src/transport/plugin_transport_tcp.c:652
 #: src/transport/plugin_transport_tcp.c:658
-#: src/transport/plugin_transport_tcp.c:3299 src/util/service.c:584
-#: src/util/service.c:590 src/util/service_new.c:637
-#: src/util/service_new.c:643
+#: src/transport/plugin_transport_tcp.c:3309 src/util/service.c:584
+#: src/util/service.c:590 src/util/service_new.c:637 src/util/service_new.c:643
 #, c-format
 msgid "Require valid port number for service `%s' in configuration!\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:430 src/transport/plugin_transport_tcp.c:689
-#: src/util/client_new.c:464 src/util/service.c:621 src/util/service_new.c:682
+#: src/util/client.c:464 src/util/service.c:621 src/util/service_new.c:682
 #, c-format
 msgid "UNIXPATH `%s' too long, maximum length is %llu\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:434 src/transport/plugin_transport_tcp.c:693
-#: src/util/client_new.c:469 src/util/service.c:625 src/util/service_new.c:687
+#: src/util/client.c:469 src/util/service.c:625 src/util/service_new.c:687
 #, fuzzy, c-format
 msgid "Using `%s' instead\n"
 msgstr "%s:选项“%s”有歧义\n"
@@ -284,7 +283,7 @@ msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"
 msgstr ""
 
 #: src/arm/gnunet-service-arm.c:513
-#: src/transport/plugin_transport_http_server.c:2617
+#: src/transport/plugin_transport_http_server.c:2620
 #: src/transport/plugin_transport_tcp.c:772 src/util/service.c:704
 #: src/util/service_new.c:782
 #, fuzzy, c-format
@@ -292,7 +291,7 @@ msgid "Failed to resolve `%s': %s\n"
 msgstr "打开日志文件“%s”失败:%s\n"
 
 #: src/arm/gnunet-service-arm.c:532
-#: src/transport/plugin_transport_http_server.c:2635
+#: src/transport/plugin_transport_http_server.c:2638
 #: src/transport/plugin_transport_tcp.c:791 src/util/service.c:723
 #: src/util/service_new.c:802
 #, fuzzy, c-format
@@ -387,13 +386,11 @@ msgid ""
 "%llu\n"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3293
-#: src/ats-tests/gnunet-solver-eval.c:935
+#: src/ats/gnunet-ats-solver-eval.c:3293 src/ats-tests/gnunet-solver-eval.c:935
 msgid "solver to use"
 msgstr ""
 
-#: src/ats/gnunet-ats-solver-eval.c:3296
-#: src/ats-tests/gnunet-solver-eval.c:938
+#: src/ats/gnunet-ats-solver-eval.c:3296 src/ats-tests/gnunet-solver-eval.c:938
 #: src/ats-tests/gnunet-solver-eval.c:941
 msgid "experiment to use"
 msgstr ""
@@ -499,12 +496,12 @@ msgstr ""
 msgid "Invalid %s configuration %f\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/ats-tests/ats-testing.c:441
+#: src/ats-tests/ats-testing.c:422
 #, c-format
 msgid "Connected master [%u] with slave [%u]\n"
 msgstr ""
 
-#: src/ats-tests/ats-testing.c:448
+#: src/ats-tests/ats-testing.c:429
 #, fuzzy, c-format
 msgid "Failed to connect master peer [%u] with slave [%u]\n"
 msgstr "初始化“%s”服务失败。\n"
@@ -561,7 +558,7 @@ msgid "Quota for network `%11s' (in/out): %10s / %10s\n"
 msgstr ""
 
 #: src/ats-tool/gnunet-ats.c:748 src/ats-tool/gnunet-ats.c:761
-#: src/transport/gnunet-transport.c:1476
+#: src/transport/gnunet-transport.c:1255
 #, fuzzy, c-format
 msgid "Failed to parse peer identity `%s'\n"
 msgstr "解析配置文件“%s”失败\n"
@@ -647,6 +644,37 @@ msgstr ""
 msgid "Print information about ATS state"
 msgstr "无法获取有关用户“%s”的信息:%s\n"
 
+#: src/auction/gnunet-auction-create.c:69
+msgid "description of the item to be sold"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:72
+msgid "mapping of possible prices"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:75
+msgid "max duration per round"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:78
+msgid "duration until auction starts"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:81
+msgid "number of items to sell, 0 for first price auction"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:84
+msgid "public auction outcome"
+msgstr ""
+
+#: src/auction/gnunet-auction-create.c:94 src/auction/gnunet-auction-info.c:76
+#: src/auction/gnunet-auction-join.c:76
+#: src/conversation/gnunet-conversation-test.c:243
+#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
+msgid "help text"
+msgstr ""
+
 #: src/cadet/gnunet-cadet.c:511
 #, fuzzy, c-format
 msgid "Invalid target `%s'\n"
@@ -703,7 +731,7 @@ msgstr "无法获取有关用户“%s”的信息:%s\n"
 msgid "provide information about all tunnels"
 msgstr "无法获取有关用户“%s”的信息:%s\n"
 
-#: src/cadet/gnunet-service-cadet_peer.c:681
+#: src/cadet/gnunet-service-cadet_peer.c:686
 msgid "Wrong CORE service\n"
 msgstr ""
 
@@ -1026,11 +1054,6 @@ msgid ""
 "played back to you..."
 msgstr ""
 
-#: src/conversation/gnunet-conversation-test.c:243
-#: src/revocation/gnunet-revocation.c:550 src/template/gnunet-template.c:76
-msgid "help text"
-msgstr ""
-
 #: src/conversation/gnunet_gst.c:630
 #: src/conversation/gnunet-helper-audio-playback-gst.c:357
 #, c-format
@@ -1231,7 +1254,7 @@ msgstr "“%s”的参数无效。\n"
 msgid "Failed to connect to CORE service!\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1677
+#: src/core/gnunet-core.c:176 src/transport/gnunet-transport.c:1456
 msgid "provide information about all current connections (continuously)"
 msgstr ""
 
@@ -1483,7 +1506,7 @@ msgstr "sqlite 数据仓库"
 #: src/testbed/gnunet-daemon-testbed-underlay.c:56
 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:52
 #: src/util/crypto_ecc_setup.c:41 src/util/crypto_mpi.c:39
-#: src/include/gnunet_common.h:681 src/include/gnunet_common.h:690
+#: src/include/gnunet_common.h:691 src/include/gnunet_common.h:700
 #: src/scalarproduct/scalarproduct.h:35
 #, fuzzy, c-format
 msgid "`%s' failed at %s:%d with error: %s\n"
@@ -1876,8 +1899,7 @@ msgstr ""
 msgid "Prints all packets that go through the DHT."
 msgstr ""
 
-#: src/dht/gnunet_dht_profiler.c:1161
-#: src/testbed/gnunet-testbed-profiler.c:255
+#: src/dht/gnunet_dht_profiler.c:1161 src/testbed/gnunet-testbed-profiler.c:255
 #, fuzzy, c-format
 msgid "Exiting as the number of peers is %u\n"
 msgstr "增加 TCP/IP 的最大连接数"
@@ -2054,8 +2076,7 @@ msgstr ""
 msgid "# GET requests given to datacache"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_hello.c:84
-#: src/dht/gnunet-service-xdht_hello.c:82
+#: src/dht/gnunet-service-dht_hello.c:84 src/dht/gnunet-service-xdht_hello.c:82
 msgid "# HELLOs obtained from peerinfo"
 msgstr ""
 
@@ -2120,35 +2141,35 @@ msgstr ""
 msgid "# P2P PUT bytes received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:1854
+#: src/dht/gnunet-service-dht_neighbours.c:1858
 msgid "# FIND PEER requests ignored due to Bloomfilter"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:1862
+#: src/dht/gnunet-service-dht_neighbours.c:1866
 msgid "# FIND PEER requests ignored due to lack of HELLO"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2018
+#: src/dht/gnunet-service-dht_neighbours.c:2022
 msgid "# P2P GET requests received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2022
+#: src/dht/gnunet-service-dht_neighbours.c:2026
 msgid "# P2P GET bytes received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2097
+#: src/dht/gnunet-service-dht_neighbours.c:2101
 msgid "# P2P FIND PEER requests processed"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2120
+#: src/dht/gnunet-service-dht_neighbours.c:2124
 msgid "# P2P GET requests ONLY routed"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2222
+#: src/dht/gnunet-service-dht_neighbours.c:2226
 msgid "# P2P RESULTS received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_neighbours.c:2226
+#: src/dht/gnunet-service-dht_neighbours.c:2230
 msgid "# P2P RESULT bytes received"
 msgstr ""
 
@@ -2156,35 +2177,35 @@ msgstr ""
 msgid "# Network size estimates received"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:218
+#: src/dht/gnunet-service-dht_routing.c:220
 msgid "# Good REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:227
+#: src/dht/gnunet-service-dht_routing.c:229
 msgid "# Duplicate REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:233
+#: src/dht/gnunet-service-dht_routing.c:235
 msgid "# Invalid REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:239
+#: src/dht/gnunet-service-dht_routing.c:241
 msgid "# Irrelevant REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:251
+#: src/dht/gnunet-service-dht_routing.c:253
 msgid "# Unsupported REPLIES matched against routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:327
+#: src/dht/gnunet-service-dht_routing.c:329
 msgid "# Entries removed from routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:409
+#: src/dht/gnunet-service-dht_routing.c:411
 msgid "# Entries added to routing table"
 msgstr ""
 
-#: src/dht/gnunet-service-dht_routing.c:427
+#: src/dht/gnunet-service-dht_routing.c:429
 msgid "# DHT requests combined"
 msgstr ""
 
@@ -2295,16 +2316,16 @@ msgid ""
 "SUPU %s, %s, %d, trail->prev_hop = %s"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:142
+#: src/dht/plugin_block_dht.c:144
 #, c-format
 msgid "Block not of type %u\n"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:149
+#: src/dht/plugin_block_dht.c:151
 msgid "Size mismatch for block\n"
 msgstr ""
 
-#: src/dht/plugin_block_dht.c:159
+#: src/dht/plugin_block_dht.c:161
 #, c-format
 msgid "Block of type %u is malformed\n"
 msgstr ""
@@ -3401,7 +3422,7 @@ msgid "Option `%s' is required when using option `%s'.\n"
 msgstr ""
 
 #: src/fs/gnunet-publish.c:849 src/fs/gnunet-publish.c:857
-#: src/transport/gnunet-transport.c:1517 src/transport/gnunet-transport.c:1542
+#: src/transport/gnunet-transport.c:1296 src/transport/gnunet-transport.c:1321
 #, c-format
 msgid "Option `%s' makes no sense without option `%s'.\n"
 msgstr ""
@@ -3894,39 +3915,39 @@ msgstr ""
 msgid "Received unsupported DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:709
+#: src/gns/gnunet-dns2gns.c:712
 msgid "No ego configured for `dns2gns` subsystem\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:737
+#: src/gns/gnunet-dns2gns.c:740
 msgid "No DNS server specified!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:758
+#: src/gns/gnunet-dns2gns.c:761
 msgid "No valid GNS zone specified!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:779
+#: src/gns/gnunet-dns2gns.c:782
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:785
 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:785
+#: src/gns/gnunet-dns2gns.c:788
 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:788
+#: src/gns/gnunet-dns2gns.c:791
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:791
+#: src/gns/gnunet-dns2gns.c:794
 msgid "Public key of the GNS zone to use (overrides default)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:804
+#: src/gns/gnunet-dns2gns.c:807
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4086,83 +4107,85 @@ msgstr ""
 msgid "Unsupported HTTP method `%s'\n"
 msgstr "未知的命令“%s”。\n"
 
-#: src/gns/gnunet-gns-proxy.c:2167
+#: src/gns/gnunet-gns-proxy.c:2168
 #, fuzzy, c-format
 msgid "Unable to import private key from file `%s'\n"
 msgstr "无法创建用户账户:"
 
-#: src/gns/gnunet-gns-proxy.c:2197
+#: src/gns/gnunet-gns-proxy.c:2198
 #, fuzzy, c-format
 msgid "Unable to import certificate %s\n"
 msgstr "无法保存配置文件“%s”:"
 
-#: src/gns/gnunet-gns-proxy.c:2370
+#: src/gns/gnunet-gns-proxy.c:2371
 #, fuzzy, c-format
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/gns/gnunet-gns-proxy.c:2389 src/rest/gnunet-rest-server.c:533
+#: src/gns/gnunet-gns-proxy.c:2390 src/rest/gnunet-rest-server.c:533
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/gns/gnunet-gns-proxy.c:2709
+#: src/gns/gnunet-gns-proxy.c:2710
 #, fuzzy, c-format
 msgid "Unsupported socks version %d\n"
 msgstr "未知的命令“%s”。\n"
 
-#: src/gns/gnunet-gns-proxy.c:2738
+#: src/gns/gnunet-gns-proxy.c:2739
 #, fuzzy, c-format
 msgid "Unsupported socks command %d\n"
 msgstr "未知的命令“%s”。\n"
 
-#: src/gns/gnunet-gns-proxy.c:2756 src/gns/gnunet-gns-proxy.c:2785
+#: src/gns/gnunet-gns-proxy.c:2757 src/gns/gnunet-gns-proxy.c:2786
 msgid "SSL connection to plain IPv4 address requested\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2836
+#: src/gns/gnunet-gns-proxy.c:2837
 #, fuzzy, c-format
 msgid "Unsupported socks address type %d\n"
 msgstr "未知的命令“%s”。\n"
 
-#: src/gns/gnunet-gns-proxy.c:3171
+#: src/gns/gnunet-gns-proxy.c:3172
 msgid "No ego configured for `shorten-zone`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3211 src/gns/gnunet-service-gns.c:1093
-#: src/gns/gnunet-service-gns.c:1149
+#: src/gns/gnunet-gns-proxy.c:3212 src/gns/gnunet-service-gns.c:493
+#: src/gns/gnunet-service-gns.c:548
 #, c-format
 msgid "No ego configured for `%s`\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3273
+#: src/gns/gnunet-gns-proxy.c:3274
 #, fuzzy, c-format
 msgid "Failed to load SSL/TLS key and certificate from `%s'\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/gns/gnunet-gns-proxy.c:3313
+#: src/gns/gnunet-gns-proxy.c:3314
 msgid "listen on specified port (default: 7777)"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3316
+#: src/gns/gnunet-gns-proxy.c:3317
 msgid "pem file to use as CA"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:3335
+#: src/gns/gnunet-gns-proxy.c:3336
 msgid "GNUnet GNS proxy"
 msgstr ""
 
-#: src/gns/gnunet-service-gns.c:1187
+#: src/gns/gnunet-service-gns.c:585
+#: src/zonemaster/gnunet-service-zonemaster.c:705
 #, fuzzy
 msgid "Failed to connect to the namestore!\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/gns/gnunet-service-gns.c:1195
+#: src/gns/gnunet-service-gns.c:593
 #, fuzzy
 msgid "Failed to connect to the namecache!\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/gns/gnunet-service-gns.c:1228
+#: src/gns/gnunet-service-gns.c:612
+#: src/zonemaster/gnunet-service-zonemaster.c:740
 #, fuzzy
 msgid "Could not connect to DHT!\n"
 msgstr "无法连接到 %s:%u:%s\n"
@@ -4994,8 +5017,7 @@ msgstr ""
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr "“%s”的参数无效。\n"
 
-#: src/namestore/gnunet-namestore.c:979
-#: src/peerinfo-tool/gnunet-peerinfo.c:775
+#: src/namestore/gnunet-namestore.c:979 src/peerinfo-tool/gnunet-peerinfo.c:775
 #, fuzzy, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "无效条目。\n"
@@ -5153,215 +5175,290 @@ msgstr "sqlite 数据仓库"
 msgid "Namestore REST API initialized\n"
 msgstr ""
 
-#: src/nat/gnunet-nat.c:159
-msgid "GNUnet NAT traversal autoconfigure daemon"
+#: src/nat-auto/gnunet-nat-auto.c:192
+#, fuzzy
+msgid "Suggested configuration changes:\n"
+msgstr ""
+"\n"
+"您的配置更改没有保存。\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:220
+#, fuzzy, c-format
+msgid "Failed to write configuration to `%s'\n"
+msgstr "保存配置失败。"
+
+#: src/nat-auto/gnunet-nat-auto.c:227
+#, fuzzy, c-format
+msgid "Wrote updated configuration to `%s'\n"
+msgstr "找不到接口“%s”的一个 IP 地址。\n"
+
+#: src/nat-auto/gnunet-nat-auto.c:345
+#, fuzzy
+msgid "run autoconfiguration"
+msgstr "配额配置"
+
+#: src/nat-auto/gnunet-nat-auto.c:348
+msgid "section name providing the configuration for the adapter"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:351 src/nat/gnunet-nat.c:436
+msgid "use TCP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:354 src/nat/gnunet-nat.c:439
+msgid "use UDP"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto.c:357
+msgid "write configuration file (for autoconfiguration)"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:321
+#: src/nat-auto/gnunet-nat-auto.c:369
+#, fuzzy
+msgid "GNUnet NAT traversal autoconfiguration"
+msgstr "GNUnet 配置"
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:403
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:681
+#: src/nat-auto/nat_auto_api_test.c:405
+msgid "Failed to connect to `gnunet-nat-server'\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:518
+#: src/nat-auto/nat_auto_api_test.c:520
+#, c-format
+msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-nat-auto_legacy.c:568
+#: src/nat-auto/nat_auto_api_test.c:569
+#, fuzzy
+msgid "NAT test failed to start NAT library\n"
+msgstr "初始化“%s”服务失败。\n"
+
+#: src/nat-auto/gnunet-nat-server.c:336
 #, c-format
 msgid "Please pass valid port number as the first argument! (got `%s')\n"
 msgstr ""
 
-#: src/nat/gnunet-nat-server.c:363
+#: src/nat-auto/gnunet-nat-server.c:386
 msgid "GNUnet NAT traversal test helper daemon"
 msgstr ""
 
-#: src/nat/nat_api.c:880 src/nat/nat.c:2010
+#: src/nat-auto/gnunet-service-nat-auto.c:342
+msgid "UPnP client `upnpc` command not found, disabling UPnP\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:385
+msgid "NAT traversal with ICMP Server succeeded.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:386
+msgid "NAT traversal with ICMP Server failed.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:405
+msgid "Testing connection reversal with ICMP server.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:437
+#, c-format
+msgid "Detected external IP `%s'\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:572
+msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:590
+#, fuzzy, c-format
+msgid "Detected internal network address `%s'.\n"
+msgstr "GNUnet 现在使用 IP 地址 %s。\n"
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:724
+msgid "upnpc found, enabling its use\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:725
+msgid "upnpc not found\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:762
+msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:774
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:834
+msgid "test_icmp_server not possible, as we are not behind NAT\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:786
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:846
+msgid "No working gnunet-helper-nat-server found\n"
+msgstr ""
+
+#: src/nat-auto/gnunet-service-nat-auto_legacy.c:823
+msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+msgstr ""
+
+#: src/nat-auto/nat_auto_api.c:76
 msgid "Operation Successful"
 msgstr ""
 
-#: src/nat/nat_api.c:882 src/nat/nat.c:2012
-msgid "Internal Failure (IPC, ...)"
+#: src/nat-auto/nat_auto_api.c:78
+msgid "IPC failure"
 msgstr ""
 
-#: src/nat/nat_api.c:884 src/nat/nat.c:2014
+#: src/nat-auto/nat_auto_api.c:80
 msgid "Failure in network subsystem, check permissions."
 msgstr ""
 
-#: src/nat/nat_api.c:886 src/nat/nat.c:2016
+#: src/nat-auto/nat_auto_api.c:82
 msgid "Encountered timeout while performing operation"
 msgstr ""
 
-#: src/nat/nat_api.c:888 src/nat/nat.c:2018
+#: src/nat-auto/nat_auto_api.c:84
 msgid "detected that we are offline"
 msgstr ""
 
-#: src/nat/nat_api.c:890 src/nat/nat.c:2020
+#: src/nat-auto/nat_auto_api.c:86
 msgid "`upnpc` command not found"
 msgstr ""
 
-#: src/nat/nat_api.c:892 src/nat/nat.c:2022
+#: src/nat-auto/nat_auto_api.c:88
 #, fuzzy
 msgid "Failed to run `upnpc` command"
 msgstr "运行 %s失败:%s %d\n"
 
-#: src/nat/nat_api.c:894 src/nat/nat.c:2024
+#: src/nat-auto/nat_auto_api.c:90
 msgid "`upnpc' command took too long, process killed"
 msgstr ""
 
-#: src/nat/nat_api.c:896 src/nat/nat.c:2026
+#: src/nat-auto/nat_auto_api.c:92
 msgid "`upnpc' command failed to establish port mapping"
 msgstr ""
 
-#: src/nat/nat_api.c:898 src/nat/nat.c:2028
+#: src/nat-auto/nat_auto_api.c:94
 msgid "`external-ip' command not found"
 msgstr ""
 
-#: src/nat/nat_api.c:900 src/nat/nat.c:2030
+#: src/nat-auto/nat_auto_api.c:96
 #, fuzzy
 msgid "Failed to run `external-ip` command"
 msgstr "运行 %s失败:%s %d\n"
 
-#: src/nat/nat_api.c:902 src/nat/nat.c:2032
+#: src/nat-auto/nat_auto_api.c:98
 msgid "`external-ip' command output invalid"
 msgstr ""
 
-#: src/nat/nat_api.c:904 src/nat/nat.c:2034
+#: src/nat-auto/nat_auto_api.c:100
 msgid "no valid address was returned by `external-ip'"
 msgstr ""
 
-#: src/nat/nat_api.c:906 src/nat/nat.c:2036
+#: src/nat-auto/nat_auto_api.c:102
 #, fuzzy
 msgid "Could not determine interface with internal/local network address"
 msgstr "无法确定用户界面定义文件。"
 
-#: src/nat/nat_api.c:908 src/nat/nat.c:2038
+#: src/nat-auto/nat_auto_api.c:104
 msgid "No functioning gnunet-helper-nat-server installation found"
 msgstr ""
 
-#: src/nat/nat_api.c:910 src/nat/nat.c:2040
+#: src/nat-auto/nat_auto_api.c:106
 msgid "NAT test could not be initialized"
 msgstr ""
 
-#: src/nat/nat_api.c:912 src/nat/nat.c:2042
+#: src/nat-auto/nat_auto_api.c:108
 msgid "NAT test timeout reached"
 msgstr ""
 
-#: src/nat/nat_api.c:914 src/nat/nat.c:2044
+#: src/nat-auto/nat_auto_api.c:110
 msgid "could not register NAT"
 msgstr ""
 
-#: src/nat/nat_api.c:916 src/nat/nat.c:2046
+#: src/nat-auto/nat_auto_api.c:112
 msgid "No working gnunet-helper-nat-client installation found"
 msgstr ""
 
-#: src/nat/nat_auto.c:385
-msgid "NAT traversal with ICMP Server succeeded.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:386
-msgid "NAT traversal with ICMP Server failed.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:405
-msgid "Testing connection reversal with ICMP server.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:437
-#, c-format
-msgid "Detected external IP `%s'\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:572
-msgid "This system has a global IPv6 address, setting IPv6 to supported.\n"
-msgstr ""
-
-#: src/nat/nat_auto.c:590
+#: src/nat-auto/nat_auto_api_test.c:477
 #, fuzzy, c-format
-msgid "Detected internal network address `%s'.\n"
-msgstr "GNUnet 现在使用 IP 地址 %s。\n"
+msgid "Failed to find valid PORT in section `%s'\n"
+msgstr "解析配置文件“%s”失败\n"
 
-#: src/nat/nat_auto.c:681 src/nat/nat_test.c:403
-msgid "Failed to connect to `gnunet-nat-server'\n"
+#: src/nat/gnunet-nat.c:424
+msgid "which IP and port are we locally using to bind/listen to"
 msgstr ""
 
-#: src/nat/nat_auto.c:724
-msgid "upnpc found, enabling its use\n"
+#: src/nat/gnunet-nat.c:427
+msgid "which remote IP and port should be asked for connection reversal"
 msgstr ""
 
-#: src/nat/nat_auto.c:725
-msgid "upnpc not found\n"
+#: src/nat/gnunet-nat.c:430
+msgid ""
+"name of configuration section to find additional options, such as manual "
+"host punching data"
 msgstr ""
 
-#: src/nat/nat_auto.c:762
-msgid "test_icmp_server not possible, as we have no public IPv4 address\n"
+#: src/nat/gnunet-nat.c:433
+msgid "enable STUN processing"
 msgstr ""
 
-#: src/nat/nat_auto.c:774 src/nat/nat_auto.c:834
-msgid "test_icmp_server not possible, as we are not behind NAT\n"
+#: src/nat/gnunet-nat.c:442
+msgid "watch for connection reversal requests"
 msgstr ""
 
-#: src/nat/nat_auto.c:786 src/nat/nat_auto.c:846
-msgid "No working gnunet-helper-nat-server found\n"
+#: src/nat/gnunet-nat.c:454
+msgid "GNUnet NAT traversal autoconfigure daemon"
 msgstr ""
 
-#: src/nat/nat_auto.c:823
-msgid "test_icmp_client not possible, as we have no internal IPv4 address\n"
+#: src/nat/gnunet-service-nat.c:1313
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1019
+#: src/nat/gnunet-service-nat.c:1323
 #, c-format
-msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
+msgid "Invalid port number in punched hole specification `%s' (lacks port)\n"
 msgstr ""
 
-#: src/nat/nat.c:1070
-#, fuzzy, c-format
-msgid "Failed to start %s\n"
-msgstr "运行 %s失败:%s %d\n"
-
-#: src/nat/nat.c:1327
-msgid "Error while running upnp client:\n"
+#: src/nat/gnunet-service-nat.c:1339
+#, c-format
+msgid "Malformed punched hole specification `%s' (lacks `]')\n"
 msgstr ""
 
-#: src/nat/nat.c:1402
-#, fuzzy, c-format
-msgid "Failed to run upnp client for port %u\n"
-msgstr "初始化“%s”服务失败。\n"
+#: src/nat/gnunet-service-nat.c:1350
+#, c-format
+msgid "Malformed punched hole specification `%s' (IPv6 address invalid)"
+msgstr ""
 
-#: src/nat/nat.c:1546
-msgid "malformed"
+#: src/nat/gnunet-service-nat.c:1803
+msgid "Connection reversal request failed\n"
 msgstr ""
 
-#: src/nat/nat.c:1600
+#: src/nat/gnunet-service-nat.c:1876
 msgid ""
 "UPnP enabled in configuration, but UPnP client `upnpc` command not found, "
-"disabling UPnP \n"
+"disabling UPnP\n"
 msgstr ""
 
-#: src/nat/nat.c:1726 src/nat/nat.c:1739
+#: src/nat/gnunet-service-nat_helper.c:186
 #, c-format
-msgid ""
-"Configuration requires `%s', but binary is not installed properly (SUID bit "
-"not set).  Option disabled.\n"
-msgstr ""
-
-#: src/nat/nat.c:1903
-msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n"
+msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/nat.c:1919
-#, c-format
-msgid "Running gnunet-helper-nat-client %s %s %u\n"
-msgstr ""
+#: src/nat/gnunet-service-nat_helper.c:260
+#, fuzzy, c-format
+msgid "Failed to start %s\n"
+msgstr "运行 %s失败:%s %d\n"
 
-#: src/nat/nat_mini.c:205
+#: src/nat/gnunet-service-nat_mini.c:196
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/nat_mini.c:611
+#: src/nat/gnunet-service-nat_mini.c:654
 msgid "`upnpc' command not found\n"
 msgstr ""
 
-#: src/nat/nat_test.c:518
-#, c-format
-msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n"
-msgstr ""
-
-#: src/nat/nat_test.c:568
-#, fuzzy
-msgid "NAT test failed to start NAT library\n"
-msgstr "初始化“%s”服务失败。\n"
-
 #: src/nse/gnunet-nse.c:122
 msgid "Show network size estimates from NSE service."
 msgstr ""
@@ -7115,179 +7212,156 @@ msgstr ""
 msgid "# validations succeeded"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:486
+#: src/transport/gnunet-transport.c:418
 #, c-format
 msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:496
+#: src/transport/gnunet-transport.c:428
 #, c-format
 msgid "Received %llu bytes/s (%llu bytes in %s)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:540
+#: src/transport/gnunet-transport.c:472
 #, fuzzy, c-format
 msgid "Failed to connect to `%s'\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/transport/gnunet-transport.c:553
+#: src/transport/gnunet-transport.c:485
 #, fuzzy, c-format
 msgid "Failed to resolve address for peer `%s'\n"
 msgstr "找不到接口“%s”的一个 IP 地址。\n"
 
-#: src/transport/gnunet-transport.c:565
+#: src/transport/gnunet-transport.c:499
 #, fuzzy
 msgid "Failed to list connections, timeout occured\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/transport/gnunet-transport.c:588
-#, c-format
-msgid "NAT plugin `%s' reports: %s\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:675
-msgid "No transport plugins configured, peer will never communicate\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:689
-#, c-format
-msgid "No port configured for plugin `%s', cannot test it\n"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:714
-#, fuzzy
-msgid "Failed to start resolver!\n"
-msgstr "运行 %s失败:%s %d\n"
-
-#: src/transport/gnunet-transport.c:750
+#: src/transport/gnunet-transport.c:532
 #, c-format
 msgid "Transmitting %u bytes\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:784
+#: src/transport/gnunet-transport.c:566
 #, c-format
 msgid ""
 "Successfully connected to `%s', starting to send benchmark data in %u Kb "
 "blocks\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:815
+#: src/transport/gnunet-transport.c:597
 #, fuzzy, c-format
 msgid "Disconnected from peer `%s' while benchmarking\n"
 msgstr "“%s”已连接到“%s”。\n"
 
-#: src/transport/gnunet-transport.c:839 src/transport/gnunet-transport.c:868
+#: src/transport/gnunet-transport.c:621 src/transport/gnunet-transport.c:650
 #, c-format
 msgid "%24s: %-17s %4s   (%u connections in total)\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:841
+#: src/transport/gnunet-transport.c:623
 #, fuzzy
 msgid "Connected to"
 msgstr "“%s”已连接到“%s”。\n"
 
-#: src/transport/gnunet-transport.c:870
+#: src/transport/gnunet-transport.c:652
 #, fuzzy
 msgid "Disconnected from"
 msgstr "“%s”已连接到“%s”。\n"
 
-#: src/transport/gnunet-transport.c:905
+#: src/transport/gnunet-transport.c:687
 #, c-format
 msgid "Received %u bytes\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:942
+#: src/transport/gnunet-transport.c:724
 #, c-format
 msgid "Peer `%s': %s %s in state `%s' until %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:954
+#: src/transport/gnunet-transport.c:736
 #, fuzzy, c-format
 msgid "Peer `%s': %s %s\n"
 msgstr "运行 %s失败:%s %d\n"
 
-#: src/transport/gnunet-transport.c:1366
+#: src/transport/gnunet-transport.c:1150
 #, fuzzy
 msgid "Monitor disconnected from transport service. Reconnecting.\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/transport/gnunet-transport.c:1488
+#: src/transport/gnunet-transport.c:1267
 #, c-format
 msgid ""
 "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, "
 "%s, %s %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1501
+#: src/transport/gnunet-transport.c:1280
 #, c-format
 msgid ""
 "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s, %s\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1529
+#: src/transport/gnunet-transport.c:1308
 #, fuzzy
 msgid "Failed to connect to transport service for disconnection\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/transport/gnunet-transport.c:1535
+#: src/transport/gnunet-transport.c:1314
 msgid "Blacklisting request in place, stop with CTRL-C\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1558 src/transport/gnunet-transport.c:1588
-#: src/transport/gnunet-transport.c:1641
+#: src/transport/gnunet-transport.c:1337 src/transport/gnunet-transport.c:1367
+#: src/transport/gnunet-transport.c:1420
 #, fuzzy
 msgid "Failed to connect to transport service\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/transport/gnunet-transport.c:1595
+#: src/transport/gnunet-transport.c:1374
 msgid "Starting to receive benchmark data\n"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1665
+#: src/transport/gnunet-transport.c:1444
 #, fuzzy
 msgid "print information for all peers (instead of only connected peers)"
 msgstr "无法获取有关用户“%s”的信息:%s\n"
 
-#: src/transport/gnunet-transport.c:1668
+#: src/transport/gnunet-transport.c:1447
 msgid "measure how fast we are receiving data from all peers (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1671
+#: src/transport/gnunet-transport.c:1450
 #, fuzzy
 msgid "disconnect from a peer"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/transport/gnunet-transport.c:1674
+#: src/transport/gnunet-transport.c:1453
 msgid "provide information about all current connections (once)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1680
+#: src/transport/gnunet-transport.c:1459
 msgid ""
 "provide information about all connects and disconnect events (continuously)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1683
+#: src/transport/gnunet-transport.c:1462
 msgid "do not resolve hostnames"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1686
+#: src/transport/gnunet-transport.c:1465
 #: src/transport/gnunet-transport-profiler.c:631
 msgid "peer identity"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1689
+#: src/transport/gnunet-transport.c:1468
 msgid "monitor plugin sessions"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1692
+#: src/transport/gnunet-transport.c:1471
 msgid "send data for benchmarking to the other peer (until CTRL-C)"
 msgstr ""
 
-#: src/transport/gnunet-transport.c:1695
-msgid "test transport configuration (involves external server)"
-msgstr ""
-
-#: src/transport/gnunet-transport.c:1706
+#: src/transport/gnunet-transport.c:1482
 #: src/transport/gnunet-transport-profiler.c:642
 #, fuzzy
 msgid "Direct access to transport service."
@@ -7322,9 +7396,9 @@ msgstr "消息尺寸"
 
 #: src/transport/plugin_transport_http_client.c:1477
 #: src/transport/plugin_transport_http_server.c:2248
-#: src/transport/plugin_transport_http_server.c:3457
-#: src/transport/plugin_transport_tcp.c:3365
-#: src/transport/plugin_transport_tcp.c:3372
+#: src/transport/plugin_transport_http_server.c:3462
+#: src/transport/plugin_transport_tcp.c:3375
+#: src/transport/plugin_transport_tcp.c:3382
 msgid "TCP_STEALTH not supported on this platform.\n"
 msgstr ""
 
@@ -7334,13 +7408,13 @@ msgid "Could not initialize curl multi handle, failed to start %s plugin!\n"
 msgstr ""
 
 #: src/transport/plugin_transport_http_client.c:2167
-#: src/transport/plugin_transport_http_server.c:3172
+#: src/transport/plugin_transport_http_server.c:3177
 #, fuzzy, c-format
 msgid "Shutting down plugin `%s'\n"
 msgstr "未知的命令“%s”。\n"
 
 #: src/transport/plugin_transport_http_client.c:2184
-#: src/transport/plugin_transport_http_server.c:3242
+#: src/transport/plugin_transport_http_server.c:3247
 #, c-format
 msgid "Shutdown for plugin `%s' complete\n"
 msgstr ""
@@ -7383,73 +7457,73 @@ msgstr ""
 msgid "Could not load or create server certificate! Loading plugin failed!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2583
+#: src/transport/plugin_transport_http_server.c:2586
 #, fuzzy
 msgid "Require valid port number for service in configuration!\n"
 msgstr "保存配置失败。"
 
-#: src/transport/plugin_transport_http_server.c:2748
+#: src/transport/plugin_transport_http_server.c:2751
 #, c-format
 msgid "Found %u addresses to report to NAT service\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2832
-#: src/transport/plugin_transport_udp.c:3600
+#: src/transport/plugin_transport_http_server.c:2837
+#: src/transport/plugin_transport_udp.c:3623
 msgid "Disabling IPv6 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2938
+#: src/transport/plugin_transport_http_server.c:2943
 #, c-format
 msgid "IPv4 support is %s\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2953
+#: src/transport/plugin_transport_http_server.c:2958
 #, c-format
 msgid "IPv6 support is %s\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2959
+#: src/transport/plugin_transport_http_server.c:2964
 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2970
+#: src/transport/plugin_transport_http_server.c:2975
 #, fuzzy
 msgid "Port is required! Fix in configuration\n"
 msgstr ""
 "\n"
 "结束配置。\n"
 
-#: src/transport/plugin_transport_http_server.c:2976
+#: src/transport/plugin_transport_http_server.c:2981
 #, c-format
 msgid "Using port %u\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:2995
+#: src/transport/plugin_transport_http_server.c:3000
 #, c-format
 msgid "Specific IPv4 address `%s' in configuration file is invalid!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3030
+#: src/transport/plugin_transport_http_server.c:3035
 #, c-format
 msgid "Specific IPv6 address `%s' in configuration file is invalid!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3105
+#: src/transport/plugin_transport_http_server.c:3110
 #, fuzzy, c-format
 msgid "Using external hostname `%s'\n"
 msgstr "卸载 GNUnet 服务"
 
-#: src/transport/plugin_transport_http_server.c:3126
+#: src/transport/plugin_transport_http_server.c:3131
 #, c-format
 msgid "Notifying transport only about hostname `%s'\n"
 msgstr ""
 
-#: src/transport/plugin_transport_http_server.c:3143
+#: src/transport/plugin_transport_http_server.c:3148
 #, fuzzy, c-format
 msgid "Maximum number of connections is %u\n"
 msgstr "增加 TCP/IP 的最大连接数"
 
-#: src/transport/plugin_transport_http_server.c:3469
+#: src/transport/plugin_transport_http_server.c:3474
 #, fuzzy
 msgid "Unable to compile URL regex\n"
 msgstr "无法初始化 SQLite:%s。\n"
@@ -7496,164 +7570,164 @@ msgstr ""
 msgid "# bytes dropped by SMTP (outgoing)"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1051
-#: src/transport/plugin_transport_tcp.c:2362
+#: src/transport/plugin_transport_tcp.c:1060
+#: src/transport/plugin_transport_tcp.c:2379
 #, c-format
 msgid "Unexpected address length: %u bytes\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1234
-#: src/transport/plugin_transport_tcp.c:1458
-#: src/transport/plugin_transport_tcp.c:2633
-#: src/transport/plugin_transport_tcp.c:3490
+#: src/transport/plugin_transport_tcp.c:1243
+#: src/transport/plugin_transport_tcp.c:1467
+#: src/transport/plugin_transport_tcp.c:2643
+#: src/transport/plugin_transport_tcp.c:3498
 msgid "# TCP sessions active"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1276
-#: src/transport/plugin_transport_tcp.c:1440
-#: src/transport/plugin_transport_tcp.c:1564
-#: src/transport/plugin_transport_tcp.c:1637
-#: src/transport/plugin_transport_tcp.c:1737
-#: src/transport/plugin_transport_tcp.c:1762
+#: src/transport/plugin_transport_tcp.c:1285
+#: src/transport/plugin_transport_tcp.c:1449
+#: src/transport/plugin_transport_tcp.c:1573
+#: src/transport/plugin_transport_tcp.c:1646
+#: src/transport/plugin_transport_tcp.c:1746
+#: src/transport/plugin_transport_tcp.c:1771
 msgid "# bytes currently in TCP buffers"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1279
+#: src/transport/plugin_transport_tcp.c:1288
 msgid "# bytes discarded by TCP (disconnect)"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1567
+#: src/transport/plugin_transport_tcp.c:1576
 msgid "# bytes discarded by TCP (timeout)"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:1641
+#: src/transport/plugin_transport_tcp.c:1650
 msgid "# bytes transmitted via TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2032
+#: src/transport/plugin_transport_tcp.c:2041
 msgid "# requests to create session with invalid address"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2200
+#: src/transport/plugin_transport_tcp.c:2217
 msgid "# transport-service disconnect requests for TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2692
+#: src/transport/plugin_transport_tcp.c:2702
 msgid "# TCP WELCOME messages received"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2883
+#: src/transport/plugin_transport_tcp.c:2893
 msgid "# bytes received via TCP"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2934
-#: src/transport/plugin_transport_tcp.c:2992
+#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:3002
 #, fuzzy
 msgid "# TCP server connections active"
 msgstr ""
 "\n"
 "按任意键继续\n"
 
-#: src/transport/plugin_transport_tcp.c:2938
+#: src/transport/plugin_transport_tcp.c:2948
 #, fuzzy
 msgid "# TCP server connect events"
 msgstr ""
 "\n"
 "按任意键继续\n"
 
-#: src/transport/plugin_transport_tcp.c:2944
+#: src/transport/plugin_transport_tcp.c:2954
 msgid "TCP connection limit reached, suspending server\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2946
+#: src/transport/plugin_transport_tcp.c:2956
 msgid "# TCP service suspended"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2986
+#: src/transport/plugin_transport_tcp.c:2996
 msgid "# TCP service resumed"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:2996
+#: src/transport/plugin_transport_tcp.c:3006
 msgid "# network-level TCP disconnect events"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3315
+#: src/transport/plugin_transport_tcp.c:3325
 #, fuzzy
 msgid "Failed to start service.\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/transport/plugin_transport_tcp.c:3478
+#: src/transport/plugin_transport_tcp.c:3486
 #, c-format
 msgid "TCP transport listening on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3482
+#: src/transport/plugin_transport_tcp.c:3490
 msgid "TCP transport not listening on any port (client only)\n"
 msgstr ""
 
-#: src/transport/plugin_transport_tcp.c:3486
+#: src/transport/plugin_transport_tcp.c:3494
 #, c-format
 msgid "TCP transport advertises itself as being on port %llu\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:170
+#: src/transport/plugin_transport_udp_broadcasting.c:169
 msgid "# Multicast HELLO beacons received via UDP"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:546
+#: src/transport/plugin_transport_udp_broadcasting.c:545
 msgid ""
 "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp_broadcasting.c:567
+#: src/transport/plugin_transport_udp_broadcasting.c:566
 #, c-format
 msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3344
+#: src/transport/plugin_transport_udp.c:3367
 #, c-format
 msgid ""
 "UDP could not transmit message to `%s': Network seems down, please check "
 "your network configuration\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3358
+#: src/transport/plugin_transport_udp.c:3381
 msgid ""
 "UDP could not transmit IPv6 message! Please check your network configuration "
 "and disable IPv6 if your connection does not have a global IPv6 address\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3676
-#: src/transport/plugin_transport_udp.c:3775
+#: src/transport/plugin_transport_udp.c:3699
+#: src/transport/plugin_transport_udp.c:3798
 #, fuzzy, c-format
 msgid "Failed to bind UDP socket to %s: %s\n"
 msgstr "打开日志文件“%s”失败:%s\n"
 
-#: src/transport/plugin_transport_udp.c:3694
+#: src/transport/plugin_transport_udp.c:3717
 msgid "Disabling IPv4 since it is not supported on this system!\n"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3785
+#: src/transport/plugin_transport_udp.c:3808
 #, fuzzy
 msgid "Failed to open UDP sockets\n"
 msgstr "打开日志文件“%s”失败:%s\n"
 
-#: src/transport/plugin_transport_udp.c:3857
-#: src/transport/plugin_transport_udp.c:3871
+#: src/transport/plugin_transport_udp.c:3879
+#: src/transport/plugin_transport_udp.c:3893
 msgid "must be in [0,65535]"
 msgstr ""
 
-#: src/transport/plugin_transport_udp.c:3903
+#: src/transport/plugin_transport_udp.c:3925
 #, fuzzy
 msgid "must be valid IPv4 address"
 msgstr "“%s”不可用。\n"
 
-#: src/transport/plugin_transport_udp.c:3930
+#: src/transport/plugin_transport_udp.c:3952
 #, fuzzy
 msgid "must be valid IPv6 address"
 msgstr "“%s”不可用。\n"
 
-#: src/transport/plugin_transport_udp.c:3996
+#: src/transport/plugin_transport_udp.c:4018
 #, fuzzy
 msgid "Failed to create UDP network sockets\n"
 msgstr "发送消息失败。\n"
@@ -7764,7 +7838,7 @@ msgstr ""
 msgid "Metadata `%s' failed to deserialize"
 msgstr ""
 
-#: src/util/client_new.c:864
+#: src/util/client.c:864
 #, c-format
 msgid "Need a non-empty hostname for service `%s'.\n"
 msgstr ""
@@ -8532,42 +8606,42 @@ msgstr ""
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "无效的进程优先级“%s”\n"
 
-#: src/util/strings.c:1475 src/util/strings.c:1491
+#: src/util/strings.c:1541 src/util/strings.c:1557
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1500
+#: src/util/strings.c:1566
 #, fuzzy, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/util/strings.c:1583 src/util/strings.c:1614 src/util/strings.c:1662
-#: src/util/strings.c:1683
+#: src/util/strings.c:1649 src/util/strings.c:1680 src/util/strings.c:1728
+#: src/util/strings.c:1749
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "IP 格式无效:“%s”\n"
 
-#: src/util/strings.c:1640
+#: src/util/strings.c:1706
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "网络表示法无效(“/%d” 在 IPv4 CIDR 中是非法的)。"
 
-#: src/util/strings.c:1692
+#: src/util/strings.c:1758
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "IP 格式无效:“%s”\n"
 
-#: src/util/strings.c:1744
+#: src/util/strings.c:1810
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "无效的网络表示法(没有以“;”结尾:“%s”)\n"
 
-#: src/util/strings.c:1794
+#: src/util/strings.c:1860
 #, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "网络掩码的格式“%s”错误\n"
 
-#: src/util/strings.c:1825
+#: src/util/strings.c:1891
 #, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "网络的格式“%s”错误\n"
@@ -8747,21 +8821,29 @@ msgid "Setup tunnels via VPN."
 msgstr ""
 
 #: src/include/gnunet_common.h:645 src/include/gnunet_common.h:652
-#: src/include/gnunet_common.h:660
+#: src/include/gnunet_common.h:662 src/include/gnunet_common.h:670
 #, c-format
 msgid "Assertion failed at %s:%d.\n"
 msgstr ""
 
-#: src/include/gnunet_common.h:672
+#: src/include/gnunet_common.h:682
 #, c-format
 msgid "External protocol violation detected at %s:%d.\n"
 msgstr ""
 
-#: src/include/gnunet_common.h:699 src/include/gnunet_common.h:708
+#: src/include/gnunet_common.h:709 src/include/gnunet_common.h:718
 #, c-format
 msgid "`%s' failed on file `%s' at %s:%d with error: %s\n"
 msgstr ""
 
+#, fuzzy
+#~ msgid "Failed to run upnp client for port %u\n"
+#~ msgstr "初始化“%s”服务失败。\n"
+
+#, fuzzy
+#~ msgid "Failed to start resolver!\n"
+#~ msgstr "运行 %s失败:%s %d\n"
+
 #, fuzzy
 #~ msgid "Unable to initialize Postgres: %s\n"
 #~ msgstr "无法初始化 SQLite:%s。\n"
@@ -9583,10 +9665,6 @@ msgstr ""
 #~ msgid "Setting d->dead on peer `%4s'\n"
 #~ msgstr "卸载 GNUnet 服务"
 
-#, fuzzy
-#~ msgid "Failed to write new configuration to disk."
-#~ msgstr "保存配置失败。"
-
 #, fuzzy
 #~ msgid "Failed to copy new configuration to remote machine."
 #~ msgstr "保存配置失败。"
@@ -9835,9 +9913,6 @@ msgstr ""
 #~ "量。如果您的网速很平稳,您可以将该限制设置为网速的最大值。您不应该使用超过"
 #~ "实际连接速度极限的值。"
 
-#~ msgid "Quota configuration"
-#~ msgstr "配额配置"
-
 #~ msgid "What is the maximum size of the datastore in MB?"
 #~ msgstr "数据仓库的最大尺寸是多少(MB)?"
 
@@ -9912,9 +9987,6 @@ msgstr ""
 #~ msgid "Save configuration?"
 #~ msgstr "保存配置?"
 
-#~ msgid "GNUnet Configuration"
-#~ msgstr "GNUnet 配置"
-
 #~ msgid "Back"
 #~ msgstr "后退"
 
@@ -9939,13 +10011,6 @@ msgstr ""
 #~ msgid "Do you wish to save your new configuration?"
 #~ msgstr "您想保存新配置吗?"
 
-#~ msgid ""
-#~ "\n"
-#~ "Your configuration changes were NOT saved.\n"
-#~ msgstr ""
-#~ "\n"
-#~ "您的配置更改没有保存。\n"
-
 #~ msgid "install GNUnet as Windows service"
 #~ msgstr "以 Windows 服务方式安装 GNUnet"
 
index 2877cab0b8e7168c05de1c243b145be134462b19..120d80a3fc81d2a114e86e113377407b92cbcdef 100644 (file)
@@ -8,6 +8,7 @@ if HAVE_TESTING
  TESTBED = testbed-logger testbed
  CONSENSUS = consensus
  SECRETSHARING = secretsharing
+ ATS_TESTS = ats-tests
 endif
 
 if HAVE_EXPERIMENTAL
@@ -59,6 +60,10 @@ if HAVE_JSON
 endif
 endif
 
+if HAVE_JSON
+  AUCTION_DIR = auction
+endif
+
 if TALER_ONLY
 SUBDIRS = \
  include \
@@ -85,13 +90,14 @@ SUBDIRS = \
   template \
   ats \
   nat \
+  nat-auto \
   fragmentation \
   transport \
   ats-tool \
   peerinfo-tool \
   core \
   $(TESTBED) \
-  ats-tests \
+  $(ATS_TESTS) \
   nse \
   dht \
   hostlist \
@@ -110,6 +116,7 @@ SUBDIRS = \
   vpn \
   gns \
        credential \
+  zonemaster \
   $(CONVERSATION_DIR) \
   fs \
   exit \
@@ -120,6 +127,7 @@ SUBDIRS = \
   psycstore \
   psyc \
   social \
+  $(AUCTION_DIR) \
   $(EXP_DIR) \
   $(PROVIDER_DIR)
 
index 0ea6853534f8f3cd3fadeda5acf00039dff51c0f..859c6e393e6302ecdd7fb61de2cbeeba83676f72 100644 (file)
@@ -1,3 +1,7 @@
 mockup-service
 gnunet-arm
 gnunet-service-arm
+test_arm_api
+test_exponential_backoff
+test_gnunet_arm.py
+test_gnunet_service_arm
index 2967e62b754fd68192b9c145cf8654e6985e164f..a613438334fad05bfbe480f98098b2d467362cac 100644 (file)
@@ -474,7 +474,7 @@ reconnect_arm (struct GNUNET_ARM_Handle *h)
   if (NULL != h->mq)
     return GNUNET_OK;
   GNUNET_assert (GNUNET_NO == h->currently_up);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "arm",
                                  handlers,
                                  &mq_error_handler,
index 471393c7e13274dc52be228ff137960c556a1efe..b4dc6cb6a717c69c2c45a5605a09e9499355958c 100644 (file)
@@ -209,7 +209,7 @@ reconnect_arm_monitor (struct GNUNET_ARM_MonitorHandle *h)
   struct GNUNET_MQ_Envelope *env;
 
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "arm",
                                  handlers,
                                  &mq_error_handler,
index 3b024ea93f183b41ebea20bb91df2f2ae6daece6..b6f4d99a802e194dc26ec31dcde5bbb88067fedd 100644 (file)
@@ -110,10 +110,14 @@ static unsigned int phase;
 
 /**
  * User defined timestamp for completing operations.
- * FIXME: to be implemented!
  */
 static struct GNUNET_TIME_Relative timeout;
 
+/**
+ * Task to be run on timeout.
+ */
+static struct GNUNET_SCHEDULER_Task *timeout_task;
+
 /**
  * Do we want to give our stdout to gnunet-service-arm?
  */
@@ -191,6 +195,11 @@ shutdown_task (void *cls)
     GNUNET_ARM_monitor_stop (m);
     m = NULL;
   }
+  if (NULL != timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (timeout_task);
+    timeout_task = NULL;
+  }
   if ((GNUNET_YES == end) && (GNUNET_YES == delete))
     delete_files ();
   GNUNET_CONFIGURATION_destroy (cfg);
@@ -682,6 +691,18 @@ srv_status (void *cls,
 }
 
 
+/**
+ * Task run on timeout (if -T is given).
+ */
+static void
+timeout_task_cb (void *cls)
+{
+  timeout_task = NULL;
+  ret = 2;
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
 /**
  * Main function that will be run by the scheduler.
  *
@@ -739,6 +760,10 @@ run (void *cls,
                                       NULL);
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
                                  NULL);
+  if (0 != timeout.rel_value_us)
+    timeout_task = GNUNET_SCHEDULER_add_delayed (timeout,
+                                                 &timeout_task_cb,
+                                                 NULL);
 }
 
 
@@ -747,7 +772,7 @@ run (void *cls,
  *
  * @param argc number of arguments from the command line
  * @param argv command line arguments
- * @return 0 ok, 1 on error
+ * @return 0 ok, 1 on error, 2 on timeout
  */
 int
 main (int argc, char *const *argv)
@@ -793,10 +818,10 @@ main (int argc, char *const *argv)
                          gettext_noop
                          ("Control services and the Automated Restart Manager (ARM)"),
                          options, &run, NULL))
-    {
-      GNUNET_free ((void *) argv);
-      return ret;
-    }
+  {
+    GNUNET_free ((void *) argv);
+    return ret;
+  }
   GNUNET_free ((void*) argv);
   return 1;
 }
index ab47ff6350b6143c1f1f50e364a1d664708e5cde..0905f145d593f44b018fe4c922ea7f549cb5386f 100644 (file)
@@ -151,7 +151,7 @@ kill_task (void *cbData)
     GNUNET_free (shutdown_ctx);
     return;
   }
-  shutdown_ctx->mq = GNUNET_CLIENT_connecT (cfg,
+  shutdown_ctx->mq = GNUNET_CLIENT_connect (cfg,
                                             SERVICE,
                                             handlers,
                                             &mq_error_handler,
index 9e4a44df5e41a6f29b858f4935dbe62723372f1e..800898bf9cb54c8d59fc6acbeb37f506f857a6fd 100644 (file)
@@ -1,2 +1,8 @@
 gnunet-solver-eval
 gnunet-ats-sim
+perf_ats_proportional_core_bandwidth
+perf_ats_proportional_core_latency
+perf_ats_proportional_core_none
+perf_ats_proportional_transport_bandwidth
+perf_ats_proportional_transport_latency
+perf_ats_proportional_transport_none
index eb30daa6b6af7bc3844fcc72b7cadb699e86e2b9..326d3bdd41884fe5e2fb9923043403860240d49e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  This file is part of GNUnet.
- Copyright (C) 2010-2013, 2016 GNUnet e.V.
+ Copyright (C) 2010-2013, 2016, 2017 GNUnet e.V.
 
  GNUnet is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published
@@ -88,11 +88,6 @@ do_shutdown (void *cls)
 
     for (c_op = 0; c_op < p->num_partners; c_op++)
     {
-      if (NULL != p->partners[c_op].cth)
-      {
-        GNUNET_CORE_notify_transmit_ready_cancel (p->partners[c_op].cth);
-        p->partners[c_op].cth = NULL;
-      }
       if ( (NULL != p->core_connect_ops) &&
            (NULL != p->core_connect_ops[c_op].connect_op) )
       {
@@ -128,15 +123,6 @@ do_shutdown (void *cls)
       GNUNET_TESTBED_operation_done (p->peer_id_op);
       p->peer_id_op = NULL;
     }
-
-    for (c_op = 0; c_op < p->num_partners; c_op++)
-    {
-      if (NULL != p->partners[c_op].cth)
-      {
-        GNUNET_CORE_notify_transmit_ready_cancel (p->partners[c_op].cth);
-        p->partners[c_op].cth = NULL;
-      }
-    }
     if (NULL != p->ats_perf_op)
     {
       GNUNET_TESTBED_operation_done (p->ats_perf_op);
@@ -314,11 +300,6 @@ comm_disconnect_cb (void *cls,
                "%s disconnected from %s while benchmarking\n",
                id,
                GNUNET_i2s (peer));
-    if (NULL != p->cth)
-    {
-      GNUNET_CORE_notify_transmit_ready_cancel (p->cth);
-      p->cth = NULL;
-    }
   }
   GNUNET_free(id);
 }
@@ -403,7 +384,7 @@ core_connect_adapter (void *cls,
     GNUNET_MQ_handler_end ()
   };
 
-  me->ch = GNUNET_CORE_connecT (cfg,
+  me->ch = GNUNET_CORE_connect (cfg,
                                me,
                                NULL,
                                &comm_connect_cb,
@@ -422,7 +403,7 @@ core_disconnect_adapter (void *cls,
 {
   struct BenchmarkPeer *me = cls;
 
-  GNUNET_CORE_disconnecT (me->ch);
+  GNUNET_CORE_disconnect (me->ch);
   me->ch = NULL;
 }
 
index de189953e36b94a7ba431ea07862e082bba7f1fb..32f0b02d884b927af17d752b9dde7aae2ef14dc9 100644 (file)
@@ -284,11 +284,6 @@ struct BenchmarkPartner
    */
   struct BenchmarkPeer *dest;
 
-  /**
-   * Core transmit handles
-   */
-  struct GNUNET_CORE_TransmitHandle *cth;
-
   /**
    * Message queue handle.
    */
@@ -335,27 +330,27 @@ struct BenchmarkPartner
   unsigned int bytes_received;
 
   /**
-   * Current ATS properties 
+   * Current ATS properties
    */
   struct GNUNET_ATS_Properties props;
 
   /**
-   * Bandwidth assigned inbound 
+   * Bandwidth assigned inbound
    */
   uint32_t bandwidth_in;
 
   /**
-   * Bandwidth assigned outbound 
+   * Bandwidth assigned outbound
    */
   uint32_t bandwidth_out;
 
   /**
-   * Current preference values for bandwidth 
+   * Current preference values for bandwidth
    */
   double pref_bandwidth;
 
   /**
-   * Current preference values for delay 
+   * Current preference values for delay
    */
   double pref_delay;
 
index 7b70f84a5a7887c39d166aaebc9006d9290a1085..983dc28432ad3c56fdb90360cd301faa02af61eb 100644 (file)
@@ -1 +1,3 @@
 gnunet-service-ats
+test_ats_api_proportional
+test_ats_reservation_api_proportional
index 241e5f93c29845a20f463f3133198f241b3ecfe0..d551aacd4ab6353f778d5e78a860cb27c250fefd 100644 (file)
@@ -195,7 +195,7 @@ reconnect (struct GNUNET_ATS_ConnectivityHandle *ch)
   struct ClientStartMessage *init;
 
   GNUNET_assert (NULL == ch->mq);
-  ch->mq = GNUNET_CLIENT_connecT (ch->cfg,
+  ch->mq = GNUNET_CLIENT_connect (ch->cfg,
                                   "ats",
                                   handlers,
                                   &error_handler,
index dd8666d4cc16af5bc350080d3464ed25af59bc4d..cd67583d15cee9340ede6bb4f2532df3b3efa889 100644 (file)
@@ -585,7 +585,7 @@ reconnect (struct GNUNET_ATS_PerformanceHandle *ph)
   struct ClientStartMessage *init;
 
   GNUNET_assert (NULL == ph->mq);
-  ph->mq = GNUNET_CLIENT_connecT (ph->cfg,
+  ph->mq = GNUNET_CLIENT_connect (ph->cfg,
                                   "ats",
                                   handlers,
                                   &mq_error_handler,
index 4a872b90a5b2a1362e5e45eedaaa0581e915a478..faeeb60817e05f9a373342aab8560faf21bd46c6 100644 (file)
@@ -532,7 +532,7 @@ reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
   struct GNUNET_ATS_AddressRecord *ar;
 
   GNUNET_assert (NULL == sh->mq);
-  sh->mq = GNUNET_CLIENT_connecT (sh->cfg,
+  sh->mq = GNUNET_CLIENT_connect (sh->cfg,
                                   "ats",
                                   handlers,
                                   &error_handler,
diff --git a/src/auction/.gitignore b/src/auction/.gitignore
new file mode 100644 (file)
index 0000000..5c3ec20
--- /dev/null
@@ -0,0 +1,5 @@
+gnunet-auction-create
+gnunet-auction-info
+gnunet-auction-join
+gnunet-service-auction
+test_auction_api
diff --git a/src/auction/Makefile.am b/src/auction/Makefile.am
new file mode 100644 (file)
index 0000000..87f9172
--- /dev/null
@@ -0,0 +1,74 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+
+pkgcfg_DATA = \
+  auction.conf
+
+if MINGW
+ WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+
+libexec_PROGRAMS = \
+ gnunet-service-auction
+
+gnunet_service_auction_SOURCES = \
+ gnunet-service-auction.c
+gnunet_service_auction_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  -ljansson \
+  $(GN_LIBINTL)
+
+
+bin_PROGRAMS = \
+ gnunet-auction-create \
+ gnunet-auction-info \
+ gnunet-auction-join
+
+gnunet_auction_create_SOURCES = \
+ gnunet-auction-create.c
+gnunet_auction_create_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  -ljansson \
+  $(GN_LIBINTL)
+
+gnunet_auction_info_SOURCES = \
+ gnunet-auction-info.c
+gnunet_auction_info_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  -ljansson \
+  $(GN_LIBINTL)
+
+gnunet_auction_join_SOURCES = \
+ gnunet-auction-join.c
+gnunet_auction_join_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  -ljansson \
+  $(GN_LIBINTL)
+
+
+check_PROGRAMS = \
+ test_auction_api
+
+test_auction_api_SOURCES = \
+ test_auction_api.c
+test_auction_api_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la
+
+
+check_SCRIPTS = \
+ test_auction_create.sh
+
+if ENABLE_TEST_RUN
+AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
+TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
+endif
diff --git a/src/auction/auction.conf b/src/auction/auction.conf
new file mode 100644 (file)
index 0000000..6ca3589
--- /dev/null
@@ -0,0 +1,4 @@
+[auction]
+AUTOSTART = NO
+BINARY = gnunet-service-auction
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-auction.sock
diff --git a/src/auction/auction.h b/src/auction/auction.h
new file mode 100644 (file)
index 0000000..758307a
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2011 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @author Markus Teich
+ * @file auction/auction.h
+ *
+ * @brief Common type definitions for the auction service and API.
+ */
+#ifndef AUCTION_H
+#define AUCTION_H
+
+#include "gnunet_common.h"
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Auction creation request sent from the client to the service
+ */
+struct GNUNET_AUCTION_ClientCreateMessage
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_CREATE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * When should the auction start
+   */
+  struct GNUNET_TIME_AbsoluteNBO time_start;
+
+  /**
+   * How long is each round allowed to be maximally
+   */
+  struct GNUNET_TIME_RelativeNBO time_round;
+
+  /**
+   * Auction parameter m.
+   * 0 for first price auctions.
+   * >0 for M+1st price auctions.
+   */
+  uint16_t m GNUNET_PACKED;
+
+  /**
+   * Should the auction outcome be public?
+   * 0 for private outcome auctions.
+   * 1 for public outcome auctions.
+   */
+  uint16_t outcome_public GNUNET_PACKED;
+
+  /**
+   * TODO: Price mapping.
+   */
+
+  /* DESCRIPTION text copied to end of this message */
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/auction/gnunet-auction-create.c b/src/auction/gnunet-auction-create.c
new file mode 100644 (file)
index 0000000..a4c0295
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+
+/**
+ * @file auction/gnunet-auction-create.c
+ * @brief tool to create a new auction
+ * @author Markus Teich
+ */
+#include "platform.h"
+
+#include <float.h>
+
+#include "gnunet_util_lib.h"
+#include "gnunet_json_lib.h"
+/* #include "gnunet_auction_service.h" */
+
+#define FIRST_PRICE 0
+#define OUTCOME_PRIVATE 0
+#define OUTCOME_PUBLIC 1
+
+static int ret; /** Final status code. */
+static char *fndesc; /** filename of the item description */
+static char *fnprices; /** filename of the price map */
+static struct GNUNET_TIME_Relative dround; /** max round duration */
+static struct GNUNET_TIME_Relative dstart; /** time until auction starts */
+static unsigned int m = FIRST_PRICE; /** auction parameter m */
+static int outcome = OUTCOME_PRIVATE; /** outcome */
+static int interactive; /** keep running in foreground */
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls,
+        char *const *args,
+        const char *cfgfile,
+        const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+       unsigned int i;
+       double cur, prev = DBL_MAX;
+       json_t *pmap;
+       json_t *parray;
+       json_t *pnode;
+       json_error_t jerr;
+
+       /* cmdline parsing */
+       if (GNUNET_TIME_UNIT_ZERO.rel_value_us == dstart.rel_value_us)
+       {
+               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                           "required argument --regtime missing or invalid (zero)\n");
+               goto fail;
+       }
+       if (GNUNET_TIME_UNIT_ZERO.rel_value_us == dround.rel_value_us)
+       {
+               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                           "required argument --roundtime missing or invalid (zero)\n");
+               goto fail;
+       }
+       if (!fndesc)
+       {
+               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                           "required argument --description missing\n");
+               goto fail;
+       }
+       if (!fnprices)
+       {
+               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                           "required argument --pricemap missing\n");
+               goto fail;
+       }
+
+       /* parse and check pricemap validity */
+       if (!(pmap = json_load_file (fnprices, JSON_DECODE_INT_AS_REAL, &jerr)))
+       {
+               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                           "parsing pricemap json at %d:%d: %s\n",
+                           jerr.line, jerr.column, jerr.text);
+               goto fail;
+       }
+       if (-1 == json_unpack_ex (pmap, &jerr, JSON_VALIDATE_ONLY,
+                                 "{s:s, s:[]}", "currency", "prices"))
+       {
+               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                           "validating pricemap: %s\n", jerr.text);
+               goto fail;
+       }
+       if (!(parray = json_object_get (pmap, "prices")) || !json_is_array (parray))
+       {
+               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                           "could not get `prices` array node from pricemap\n");
+               goto fail;
+       }
+       if (0 == json_array_size (parray))
+       {
+               GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "empty pricemap array\n");
+               goto fail;
+       }
+       json_array_foreach (parray, i, pnode)
+       {
+               if (-1 == json_unpack_ex (pnode, &jerr, 0, "F", &cur))
+               {
+                       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                   "validating pricearray index %d: %s\n", i, jerr.text);
+                       goto fail;
+               }
+               if (prev <= cur)
+               {
+                       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                   "validating pricearray index %d: "
+                                   "prices must be strictly monotonically decreasing\n",
+                                   i);
+                       goto fail;
+               }
+               prev = cur;
+       }
+
+       return;
+
+fail:
+       ret = 1;
+       return;
+}
+
+
+/**
+ * The main function.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+       static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+               {'d', "description", "FILE",
+                       gettext_noop ("description of the item to be sold"),
+                       1, &GNUNET_GETOPT_set_filename, &fndesc},
+               {'p', "pricemap", "FILE",
+                       gettext_noop ("mapping of possible prices"),
+                       1, &GNUNET_GETOPT_set_filename, &fnprices},
+               {'r', "roundtime", "DURATION",
+                       gettext_noop ("max duration per round"),
+                       1, &GNUNET_GETOPT_set_relative_time, &dround},
+               {'s', "regtime", "DURATION",
+                       gettext_noop ("duration until auction starts"),
+                       1, &GNUNET_GETOPT_set_relative_time, &dstart},
+               {'m', "m", "NUMBER",
+                       gettext_noop ("number of items to sell\n"
+                                     "0 for first price auction\n"
+                                     ">0 for vickrey/M+1st price auction"),
+                       1, &GNUNET_GETOPT_set_uint, &m},
+               {'u', "public", NULL,
+                       gettext_noop ("public auction outcome"),
+                       0, &GNUNET_GETOPT_set_one, &outcome},
+               {'i', "interactive", NULL,
+                       gettext_noop ("keep running in foreground until auction completes"),
+                       0, &GNUNET_GETOPT_set_one, &interactive},
+               GNUNET_GETOPT_OPTION_END
+       };
+       if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+               return 2;
+
+       ret = (GNUNET_OK ==
+                  GNUNET_PROGRAM_run (argc, argv,
+                                                          "gnunet-auction-create",
+                                                          gettext_noop ("create a new auction and "
+                                                                        "start listening for bidders"),
+                                                          options,
+                                                          &run,
+                                                          NULL)) ? ret : 1;
+       GNUNET_free ((void*) argv);
+       return ret;
+}
diff --git a/src/auction/gnunet-auction-info.c b/src/auction/gnunet-auction-info.c
new file mode 100644 (file)
index 0000000..a4af115
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file auction/gnunet-auction.c
+ * @brief auction for writing a tool
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+/* #include "gnunet_auction_service.h" */
+
+/**
+ * Final status code.
+ */
+static int ret;
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  /* main code here */
+}
+
+
+/**
+ * The main function.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    /* FIMXE: add options here */
+    GNUNET_GETOPT_OPTION_END
+  };
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_get_utf8_args (argc, argv,
+                                   &argc, &argv))
+    return 2;
+
+  ret = (GNUNET_OK ==
+        GNUNET_PROGRAM_run (argc, argv,
+                            "gnunet-auction",
+                            gettext_noop ("help text"),
+                            options,
+                            &run,
+                            NULL)) ? ret : 1;
+  GNUNET_free ((void*) argv);
+  return ret;
+}
+
+/* end of gnunet-auction.c */
diff --git a/src/auction/gnunet-auction-join.c b/src/auction/gnunet-auction-join.c
new file mode 100644 (file)
index 0000000..a4af115
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file auction/gnunet-auction.c
+ * @brief auction for writing a tool
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+/* #include "gnunet_auction_service.h" */
+
+/**
+ * Final status code.
+ */
+static int ret;
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  /* main code here */
+}
+
+
+/**
+ * The main function.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    /* FIMXE: add options here */
+    GNUNET_GETOPT_OPTION_END
+  };
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_get_utf8_args (argc, argv,
+                                   &argc, &argv))
+    return 2;
+
+  ret = (GNUNET_OK ==
+        GNUNET_PROGRAM_run (argc, argv,
+                            "gnunet-auction",
+                            gettext_noop ("help text"),
+                            options,
+                            &run,
+                            NULL)) ? ret : 1;
+  GNUNET_free ((void*) argv);
+  return ret;
+}
+
+/* end of gnunet-auction.c */
diff --git a/src/auction/gnunet-service-auction.c b/src/auction/gnunet-service-auction.c
new file mode 100644 (file)
index 0000000..dac3891
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2009 GNUnet e.V.
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+
+/**
+ * @file auction/gnunet-service-auction.c
+ * @brief service for executing auctions
+ * @author Markus Teich
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "auction.h"
+
+/**
+ * Check AUCTION CREATE messages from the client.
+ *
+ * @param cls the client we received this message from
+ * @param msg the actual message received
+ * @return #GNUNET_OK (always)
+ */
+static int
+check_create (void *cls, const struct GNUNET_AUCTION_ClientCreateMessage *msg)
+{
+       /* always well-formed due to arbitrary length description */
+       return GNUNET_OK;
+}
+
+
+/**
+ * Handler for CREATE messages.
+ *
+ * @param cls the client we received this message from
+ * @param msg the actual message received
+ */
+static void
+handle_create (void *cls, const struct GNUNET_AUCTION_ClientCreateMessage *msg)
+{
+       struct GNUNET_SERVICE_Client *client = cls;
+//     struct GNUNET_MQ_Handle *mq;
+//     struct GNUNET_MQ_Envelope *env;
+//     struct GNUNET_AUCTION_blabla em;
+       uint16_t size;
+
+       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                   "Received CREATE message from client\n");
+
+       size = ntohs (msg->header.size);
+
+       /**TODO: create auction and return auction object */
+//     mq = GNUNET_SERVICE_client_get_mq (client);
+//     setup_info_message (&em);
+//     env = GNUNET_MQ_msg_copy (&em.header);
+//     GNUNET_MQ_send (mq, env);
+
+       GNUNET_SERVICE_client_continue (client);
+}
+
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ */
+static void
+cleanup_task (void *cls)
+{
+       /* FIXME: do clean up here */
+}
+
+
+/**
+ * Callback called when a client connects to the service.
+ *
+ * @param cls closure for the service
+ * @param c the new client that connected to the service
+ * @param mq the message queue used to send messages to the client
+ * @return @a c
+ */
+static void *
+client_connect_cb (void *cls,
+                   struct GNUNET_SERVICE_Client *c,
+                   struct GNUNET_MQ_Handle *mq)
+{
+       return c;
+}
+
+
+/**
+ * Callback called when a client disconnected from the service
+ *
+ * @param cls closure for the service
+ * @param c the client that disconnected
+ * @param internal_cls should be equal to @a c
+ */
+static void
+client_disconnect_cb (void *cls,
+                      struct GNUNET_SERVICE_Client *c,
+                      void *internal_cls)
+{
+       GNUNET_assert (c == internal_cls);
+}
+
+
+/**
+ * Process auction requests.
+ *
+ * @param cls closure
+ * @param cfg configuration to use
+ * @param service the initialized service
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_SERVICE_Handle *service)
+{
+       /* FIXME: do setup here */
+       GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
+}
+
+
+/**
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN
+("auction",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_var_size (create,
+                        GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_CREATE,
+                        struct GNUNET_AUCTION_ClientCreateMessage,
+                        NULL),
+ GNUNET_MQ_handler_end ())
+
+
+/* end of gnunet-service-auction.c */
diff --git a/src/auction/test_auction_api.c b/src/auction/test_auction_api.c
new file mode 100644 (file)
index 0000000..38e93c6
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file auction/test_auction_api.c
+ * @brief testcase for auction.c
+ */
+#include "platform.h"
+
+static int
+check ()
+{
+  return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  ret = check ();
+
+  return ret;
+}
+
+/* end of test_auction_api.c */
diff --git a/src/auction/test_auction_create.sh b/src/auction/test_auction_create.sh
new file mode 100755 (executable)
index 0000000..b0f4de7
--- /dev/null
@@ -0,0 +1,80 @@
+#! /bin/sh
+
+trap 'rm -f test.json' EXIT
+
+
+# missing required cmdline args
+gnunet-auction-create      -r 1 -d foo -p test.json && exit 1
+gnunet-auction-create -s 1      -d foo -p test.json && exit 1
+gnunet-auction-create -s 1 -r 1        -p test.json && exit 1
+gnunet-auction-create -s 1 -r 1 -d foo              && exit 1
+
+
+# no pricemap
+rm -f test.json
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+
+# json errors
+cat <<DOG >test.json
+[,]
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+cat <<DOG >test.json
+bla
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+
+# unexpected structures
+cat <<DOG >test.json
+{"foo": "bar"}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+cat <<DOG >test.json
+{"currency": "foo"}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+cat <<DOG >test.json
+{"prices": []}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+cat <<DOG >test.json
+{"currency": "foo", "prices": "bar"}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+
+# wrong array content
+cat <<DOG >test.json
+{"currency": "foo", "prices": []}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+cat <<DOG >test.json
+{"currency": "foo", "prices": ["bar"]}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+cat <<DOG >test.json
+{"currency": "foo", "prices": [null]}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+cat <<DOG >test.json
+{"currency": "foo", "prices": [1, 2]}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
+
+
+# correct example
+cat <<DOG >test.json
+{"currency": "foo", "prices": [2, 1]}
+DOG
+gnunet-auction-create -s 1 -r 1 -d foo -p test.json || exit 1
+
+rm -f test.json
index d823b4872b7aaae3d98c9f9f059be9c1f425cfd2..53d17dd9c293a1c3f9c420ad5085758f97ffd093 100644 (file)
@@ -22,7 +22,9 @@ plugindir = $(libdir)/gnunet
 AM_CLFAGS = -g
 
 libexec_PROGRAMS = \
- gnunet-service-cadet $(EXP_LIBEXEC)
+ gnunet-service-cadet \
+ gnunet-service-cadet-new \
+ $(EXP_LIBEXEC)
 
 bin_PROGRAMS = \
  gnunet-cadet
@@ -46,6 +48,27 @@ gnunet_cadet_LDADD = \
   libgnunetcadet.la \
   $(top_builddir)/src/util/libgnunetutil.la
 
+gnunet_service_cadet_new_SOURCES = \
+ gnunet-service-cadet-new.c gnunet-service-cadet-new.h \
+ gnunet-service-cadet-new_channel.c gnunet-service-cadet-new_channel.h \
+ gnunet-service-cadet-new_connection.c gnunet-service-cadet-new_connection.h \
+ gnunet-service-cadet-new_core.c gnunet-service-cadet-new_core.h \
+ gnunet-service-cadet-new_dht.c gnunet-service-cadet-new_dht.h \
+ gnunet-service-cadet-new_hello.c gnunet-service-cadet-new_hello.h \
+ gnunet-service-cadet-new_tunnels.c gnunet-service-cadet-new_tunnels.h \
+ gnunet-service-cadet-new_paths.c gnunet-service-cadet-new_paths.h \
+ gnunet-service-cadet-new_peer.c gnunet-service-cadet-new_peer.h
+gnunet_service_cadet_new_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/ats/libgnunetats.la \
+  $(top_builddir)/src/core/libgnunetcore.la \
+  $(top_builddir)/src/dht/libgnunetdht.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/transport/libgnunettransport.la \
+  $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
+  $(top_builddir)/src/hello/libgnunethello.la \
+  $(top_builddir)/src/block/libgnunetblock.la
+
 gnunet_service_cadet_SOURCES = \
  gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \
  gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
@@ -87,6 +110,11 @@ libgnunetcadettest_a_LIBADD = \
 
 if HAVE_TESTING
 check_PROGRAMS = \
+  test_cadet_2_speed_reliable_backwards \
+  test_cadet_5_speed \
+  test_cadet_5_speed_ack \
+  test_cadet_5_speed_reliable \
+  test_cadet_5_speed_reliable_backwards \
   test_cadet_single \
   test_cadet_local \
   test_cadet_2_forward \
@@ -96,15 +124,10 @@ check_PROGRAMS = \
   test_cadet_2_speed_ack \
   test_cadet_2_speed_backwards \
   test_cadet_2_speed_reliable \
-  test_cadet_2_speed_reliable_backwards \
   test_cadet_5_forward \
   test_cadet_5_signal \
   test_cadet_5_keepalive \
-  test_cadet_5_speed \
-  test_cadet_5_speed_ack \
-  test_cadet_5_speed_backwards \
-  test_cadet_5_speed_reliable \
-  test_cadet_5_speed_reliable_backwards
+  test_cadet_5_speed_backwards
 endif
 
 ld_cadet_test_lib = \
index 049f3a85a729a1264ba537b4aa5dada0a9eba882..c16fb29174891c5c7ecbe9128924196f098a544a 100644 (file)
@@ -57,6 +57,7 @@ extern "C"
 #include "gnunet_util_lib.h"
 #include "gnunet_peer_lib.h"
 #include "gnunet_core_service.h"
+#include "gnunet_cadet_service.h"
 #include "gnunet_protocols.h"
 #include <gnunet_cadet_service.h>
 
@@ -64,13 +65,29 @@ extern "C"
 /**************************       CONSTANTS      ******************************/
 /******************************************************************************/
 
+/**
+ * Minimum value for channel IDs of local clients.
+ */
 #define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI        0x80000000
-#define GNUNET_CADET_LOCAL_CHANNEL_ID_SERV       0xB0000000
 
-#define HIGH_PID                                0xFFFF0000
-#define LOW_PID                                 0x0000FFFF
+/**
+ * FIXME.
+ */
+#define HIGH_PID                                0xFF000000
+
+/**
+ * FIXME.
+ */
+#define LOW_PID                                 0x00FFFFFF
 
-#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID)
+
+/**
+ * Test if the two PIDs (of type `uint32_t`) are in the range where we
+ * have to worry about overflows.  This is the case when @a pid is
+ * large and @a max is small, useful when comparing @a pid smaller
+ * than @a max.
+ */
+#define PID_OVERFLOW(pid, max) (((pid) > HIGH_PID) && ((max) < LOW_PID))
 
 /******************************************************************************/
 /**************************        MESSAGES      ******************************/
@@ -79,6 +96,22 @@ extern "C"
 GNUNET_NETWORK_STRUCT_BEGIN
 
 
+/**
+ * Number uniquely identifying a channel of a client.
+ */
+struct GNUNET_CADET_ClientChannelNumber
+{
+  /**
+   * Values for channel numbering.
+   * Local channel numbers given by the service (incoming) are
+   * smaller than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI.
+   * Local channel numbers given by the client (created) are
+   * larger than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI.
+   */
+  uint32_t channel_of_client GNUNET_PACKED;
+};
+
+
 /**
  * Message for a client to create and destroy channels.
  */
@@ -98,31 +131,23 @@ struct GNUNET_CADET_PortMessage
   struct GNUNET_HashCode port GNUNET_PACKED;
 };
 
-/**
- * Type for channel numbering.
- * - Local channel numbers given by the service (incoming) are >= 0xB0000000
- * - Local channel numbers given by the client (created) are >= 0x80000000
- * - Global channel numbers are < 0x80000000
- */
-typedef uint32_t CADET_ChannelNumber;
-
 
 /**
  * Message for a client to create channels.
  */
-struct GNUNET_CADET_ChannelCreateMessage
+struct GNUNET_CADET_ChannelOpenMessageMessage
 {
   /**
    * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_CREATE
    *
-   * Size: sizeof(struct GNUNET_CADET_ChannelCreateMessage)
+   * Size: sizeof(struct GNUNET_CADET_ChannelOpenMessageMessage)
    */
   struct GNUNET_MessageHeader header;
 
   /**
    * ID of a channel controlled by this client.
    */
-  CADET_ChannelNumber channel_id GNUNET_PACKED;
+  struct GNUNET_CADET_ClientChannelNumber channel_id;
 
   /**
    * Channel's peer
@@ -152,11 +177,11 @@ struct GNUNET_CADET_ChannelDestroyMessage
    * Size: sizeof(struct GNUNET_CADET_ChannelDestroyMessage)
    */
   struct GNUNET_MessageHeader header;
-  
+
   /**
    * ID of a channel controlled by this client.
    */
-  CADET_ChannelNumber channel_id GNUNET_PACKED;
+  struct GNUNET_CADET_ClientChannelNumber channel_id;
 };
 
 
@@ -173,7 +198,7 @@ struct GNUNET_CADET_LocalData
   /**
    * ID of the channel
    */
-  uint32_t id GNUNET_PACKED;
+  struct GNUNET_CADET_ClientChannelNumber id;
 
   /**
    * Payload follows
@@ -195,7 +220,7 @@ struct GNUNET_CADET_LocalAck
   /**
    * ID of the channel allowed to send more data.
    */
-  CADET_ChannelNumber channel_id GNUNET_PACKED;
+  struct GNUNET_CADET_ClientChannelNumber channel_id;
 
 };
 
@@ -214,7 +239,7 @@ struct GNUNET_CADET_LocalInfo
   /**
    * ID of the channel allowed to send more data.
    */
-  CADET_ChannelNumber channel_id GNUNET_PACKED;
+  struct GNUNET_CADET_ClientChannelNumber channel_id;
 
   /**
    * ID of the owner of the channel (can be local peer).
@@ -258,6 +283,7 @@ struct GNUNET_CADET_LocalInfoPeer
    * (each path ends in destination) */
 };
 
+
 /**
  * Message to inform the client about one of the tunnels in the service.
  */
@@ -294,7 +320,7 @@ struct GNUNET_CADET_LocalInfoTunnel
    */
   uint16_t cstate GNUNET_PACKED;
 
-  /* If TUNNEL (no 'S'): GNUNET_PeerIdentity connection_ids[connections] */
+  /* If TUNNEL (no 'S'): struct GNUNET_CADET_ConnectionTunnelIdentifier connection_ids[connections] */
   /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */
 };
 
@@ -349,25 +375,6 @@ uint32_t
 GC_min_pid (uint32_t a, uint32_t b);
 
 
-/**
- * Convert a 256 bit CadetHash into a 512 HashCode to use in GNUNET_h2s,
- * multihashmap, and other HashCode-based functions.
- *
- * @param id A 256 bit hash to expand.
- *
- * @return A HashCode containing the original 256 bit hash right-padded with 0.
- */
-const struct GNUNET_HashCode *
-GC_h2hc (const struct GNUNET_CADET_Hash *id);
-
-/**
- * Get a string from a Cadet Hash (256 bits).
- * WARNING: Not reentrant (based on GNUNET_h2s).
- */
-const char *
-GC_h2s (const struct GNUNET_CADET_Hash *id);
-
-
 /**
  * Allocate a string with a hexdump of any binary data.
  *
@@ -378,7 +385,10 @@ GC_h2s (const struct GNUNET_CADET_Hash *id);
  * @return The size of the output.
  */
 size_t
-GC_bin2s (void *bin, unsigned int len, char **output);
+GC_bin2s (void *bin,
+          unsigned int len,
+          char **output);
+
 
 /**
  * Convert a message type into a string to help debug
index d758155886c51312805bdd2dc636db01de2ecfbe..8f1274d6332fc7a9c6878782385ad83ce4f30042 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2011 GNUnet e.V.
+     Copyright (C) 2011, 2017 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -19,7 +19,7 @@
 */
 /**
  * @file cadet/cadet_api.c
- * @brief cadet api: client implementation of new cadet service
+ * @brief cadet api: client implementation of cadet service
  * @author Bartlomiej Polot
  */
 
  */
 struct GNUNET_CADET_TransmitHandle
 {
-    /**
-     * Double Linked list
-     */
+  /**
+   * Double Linked list
+   */
   struct GNUNET_CADET_TransmitHandle *next;
 
-    /**
-     * Double Linked list
-     */
+  /**
+   * Double Linked list
+   */
   struct GNUNET_CADET_TransmitHandle *prev;
 
-    /**
-     * Channel this message is sent on / for (may be NULL for control messages).
-     */
+  /**
+   * Channel this message is sent on / for (may be NULL for control messages).
+   */
   struct GNUNET_CADET_Channel *channel;
 
-    /**
-     * Request data task.
-     */
+  /**
+   * Request data task.
+   */
   struct GNUNET_SCHEDULER_Task *request_data_task;
 
-    /**
-     * Callback to obtain the message to transmit, or NULL if we
-     * got the message in 'data'.  Notice that messages built
-     * by 'notify' need to be encapsulated with information about
-     * the 'target'.
-     */
+  /**
+   * Callback to obtain the message to transmit, or NULL if we
+   * got the message in 'data'.  Notice that messages built
+   * by 'notify' need to be encapsulated with information about
+   * the 'target'.
+   */
   GNUNET_CONNECTION_TransmitReadyNotify notify;
 
-    /**
-     * Closure for 'notify'
-     */
+  /**
+   * Closure for 'notify'
+   */
   void *notify_cls;
 
-    /**
-     * Size of the payload.
-     */
+  /**
+   * Size of the payload.
+   */
   size_t size;
 };
 
-union CadetInfoCB {
+
+union CadetInfoCB
+{
 
   /**
    * Channel callback.
@@ -114,14 +116,14 @@ union CadetInfoCB {
  */
 struct GNUNET_CADET_Handle
 {
-    /**
-     * Message queue (if available).
-     */
+  /**
+   * Message queue (if available).
+   */
   struct GNUNET_MQ_Handle *mq;
 
-    /**
-     * Set of handlers used for processing incoming messages in the channels
-     */
+  /**
+   * Set of handlers used for processing incoming messages in the channels
+   */
   const struct GNUNET_CADET_MessageHandler *message_handlers;
 
   /**
@@ -134,40 +136,40 @@ struct GNUNET_CADET_Handle
    */
   struct GNUNET_CONTAINER_MultiHashMap *ports;
 
-    /**
-     * Double linked list of the channels this client is connected to, head.
-     */
+  /**
+   * Double linked list of the channels this client is connected to, head.
+   */
   struct GNUNET_CADET_Channel *channels_head;
 
-    /**
-     * Double linked list of the channels this client is connected to, tail.
-     */
+  /**
+   * Double linked list of the channels this client is connected to, tail.
+   */
   struct GNUNET_CADET_Channel *channels_tail;
 
-    /**
-     * Callback for inbound channel disconnection
-     */
+  /**
+   * Callback for inbound channel disconnection
+   */
   GNUNET_CADET_ChannelEndHandler *cleaner;
 
-    /**
-     * Closure for all the handlers given by the client
-     */
+  /**
+   * Closure for all the handlers given by the client
+   */
   void *cls;
 
-    /**
-     * Messages to send to the service, head.
-     */
+  /**
+   * Messages to send to the service, head.
+   */
   struct GNUNET_CADET_TransmitHandle *th_head;
 
-    /**
-     * Messages to send to the service, tail.
-     */
+  /**
+   * Messages to send to the service, tail.
+   */
   struct GNUNET_CADET_TransmitHandle *th_tail;
 
-    /**
-     * chid of the next channel to create (to avoid reusing IDs often)
-     */
-  CADET_ChannelNumber next_chid;
+  /**
+   * child of the next channel to create (to avoid reusing IDs often)
+   */
+  struct GNUNET_CADET_ClientChannelNumber next_chid;
 
   /**
    * Configuration given by the client, in case of reconnection
@@ -201,9 +203,9 @@ struct GNUNET_CADET_Handle
  */
 struct GNUNET_CADET_Peer
 {
-    /**
-     * ID of the peer in short form
-     */
+  /**
+   * ID of the peer in short form
+   */
   GNUNET_PEER_Id id;
 
   /**
@@ -218,34 +220,34 @@ struct GNUNET_CADET_Peer
  */
 struct GNUNET_CADET_Channel
 {
-    /**
-     * DLL next
-     */
+  /**
+   * DLL next
+   */
   struct GNUNET_CADET_Channel *next;
 
-    /**
-     * DLL prev
-     */
+  /**
+   * DLL prev
+   */
   struct GNUNET_CADET_Channel *prev;
 
-    /**
-     * Handle to the cadet this channel belongs to
-     */
+  /**
+   * Handle to the cadet this channel belongs to
+   */
   struct GNUNET_CADET_Handle *cadet;
 
-    /**
-     * Local ID of the channel
-     */
-  CADET_ChannelNumber chid;
+  /**
+   * Local ID of the channel
+   */
+  struct GNUNET_CADET_ClientChannelNumber chid;
 
-    /**
-     * Channel's port, if any.
-     */
+  /**
+   * Channel's port, if any.
+   */
   struct GNUNET_CADET_Port *port;
 
-    /**
-     * Other end of the channel.
-     */
+  /**
+   * Other end of the channel.
+   */
   GNUNET_PEER_Id peer;
 
   /**
@@ -253,46 +255,47 @@ struct GNUNET_CADET_Channel
    */
   void *ctx;
 
-    /**
-     * Size of packet queued in this channel
-     */
+  /**
+   * Size of packet queued in this channel
+   */
   unsigned int packet_size;
 
-    /**
-     * Channel options: reliability, etc.
-     */
+  /**
+   * Channel options: reliability, etc.
+   */
   enum GNUNET_CADET_ChannelOption options;
 
-    /**
-     * Are we allowed to send to the service?
-     */
+  /**
+   * Are we allowed to send to the service?
+   */
   int allow_send;
 
 };
 
+
 /**
  * Opaque handle to a port.
  */
 struct GNUNET_CADET_Port
 {
-    /**
-     * Handle to the CADET session this port belongs to.
-     */
+  /**
+   * Handle to the CADET session this port belongs to.
+   */
   struct GNUNET_CADET_Handle *cadet;
 
-    /**
-     * Port ID.
-     */
+  /**
+   * Port ID.
+   */
   struct GNUNET_HashCode *hash;
 
-    /**
-     * Callback handler for incoming channels on this port.
-     */
+  /**
+   * Callback handler for incoming channels on this port.
+   */
   GNUNET_CADET_InboundChannelNotificationHandler *handler;
 
-    /**
-     * Closure for @a handler.
-     */
+  /**
+   * Closure for @a handler.
+   */
   void *cls;
 };
 
@@ -356,22 +359,20 @@ find_port (const struct GNUNET_CADET_Handle *h,
 
 /**
  * Get the channel handler for the channel specified by id from the given handle
+ *
  * @param h Cadet handle
  * @param chid ID of the wanted channel
  * @return handle to the required channel or NULL if not found
  */
 static struct GNUNET_CADET_Channel *
-retrieve_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid)
+retrieve_channel (struct GNUNET_CADET_Handle *h,
+                  struct GNUNET_CADET_ClientChannelNumber chid)
 {
   struct GNUNET_CADET_Channel *ch;
 
-  ch = h->channels_head;
-  while (ch != NULL)
-  {
-    if (ch->chid == chid)
+  for (ch = h->channels_head; NULL != ch; ch = ch->next)
+    if (ch->chid.channel_of_client == chid.channel_of_client)
       return ch;
-    ch = ch->next;
-  }
   return NULL;
 }
 
@@ -385,21 +386,27 @@ retrieve_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid)
  * @return Handle to the created channel.
  */
 static struct GNUNET_CADET_Channel *
-create_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid)
+create_channel (struct GNUNET_CADET_Handle *h,
+                struct GNUNET_CADET_ClientChannelNumber chid)
 {
   struct GNUNET_CADET_Channel *ch;
 
   ch = GNUNET_new (struct GNUNET_CADET_Channel);
-  GNUNET_CONTAINER_DLL_insert (h->channels_head, h->channels_tail, ch);
+  GNUNET_CONTAINER_DLL_insert (h->channels_head,
+                               h->channels_tail,
+                               ch);
   ch->cadet = h;
-  if (0 == chid)
+  if (0 == chid.channel_of_client)
   {
     ch->chid = h->next_chid;
-    while (NULL != retrieve_channel (h, h->next_chid))
+    while (NULL != retrieve_channel (h,
+                                     h->next_chid))
     {
-      h->next_chid++;
-      h->next_chid &= ~GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
-      h->next_chid |= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
+      h->next_chid.channel_of_client
+        = htonl (1 + ntohl (h->next_chid.channel_of_client));
+      if (0 == ntohl (h->next_chid.channel_of_client))
+        h->next_chid.channel_of_client
+          = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
     }
   }
   else
@@ -440,7 +447,9 @@ destroy_channel (struct GNUNET_CADET_Channel *ch, int call_cleaner)
   }
   h = ch->cadet;
 
-  GNUNET_CONTAINER_DLL_remove (h->channels_head, h->channels_tail, ch);
+  GNUNET_CONTAINER_DLL_remove (h->channels_head,
+                               h->channels_tail,
+                               ch);
 
   /* signal channel destruction */
   if ( (NULL != h->cleaner) && (0 != ch->peer) && (GNUNET_YES == call_cleaner) )
@@ -466,7 +475,7 @@ destroy_channel (struct GNUNET_CADET_Channel *ch, int call_cleaner)
   if (0 != ch->peer)
     GNUNET_PEER_change_rc (ch->peer, -1);
   GNUNET_free (ch);
-  return;
+
 }
 
 
@@ -516,13 +525,15 @@ send_ack (struct GNUNET_CADET_Channel *ch)
   struct GNUNET_CADET_LocalAck *msg;
   struct GNUNET_MQ_Envelope *env;
 
-  env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on channel %X\n", ch->chid);
-  msg->channel_id = htonl (ch->chid);
-  GNUNET_MQ_send (ch->cadet->mq, env);
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
 
-  return;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Sending ACK on channel %X\n",
+       ch->chid.channel_of_client);
+  msg->channel_id = ch->chid;
+  GNUNET_MQ_send (ch->cadet->mq,
+                  env);
 }
 
 
@@ -555,13 +566,16 @@ request_data (void *cls)
   th->channel->packet_size = 0;
   remove_from_queue (th);
 
-  env = GNUNET_MQ_msg_extra (msg, th->size,
+  env = GNUNET_MQ_msg_extra (msg,
+                             th->size,
                              GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
-  msg->id = htonl (th->channel->chid);
-  osize = th->notify (th->notify_cls, th->size, &msg[1]);
+  msg->id = th->channel->chid;
+  osize = th->notify (th->notify_cls,
+                      th->size,
+                      &msg[1]);
   GNUNET_assert (osize == th->size);
-  GNUNET_MQ_send (th->channel->cadet->mq, env);
-
+  GNUNET_MQ_send (th->channel->cadet->mq,
+                  env);
   GNUNET_free (th);
 }
 
@@ -574,19 +588,21 @@ request_data (void *cls)
  */
 static void
 handle_channel_created (void *cls,
-                        const struct GNUNET_CADET_ChannelCreateMessage *msg)
+                        const struct GNUNET_CADET_ChannelOpenMessageMessage *msg)
 {
   struct GNUNET_CADET_Handle *h = cls;
   struct GNUNET_CADET_Channel *ch;
   struct GNUNET_CADET_Port *port;
   const struct GNUNET_HashCode *port_number;
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
 
-  chid = ntohl (msg->channel_id);
+  chid = msg->channel_id;
   port_number = &msg->port;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X [%s]\n",
-       chid, GNUNET_h2s (port_number));
-  if (chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Creating incoming channel %X [%s]\n",
+       ntohl (chid.channel_of_client),
+       GNUNET_h2s (port_number));
+  if (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
   {
     GNUNET_break (0);
     return;
@@ -636,18 +652,24 @@ handle_channel_destroy (void *cls,
 {
   struct GNUNET_CADET_Handle *h = cls;
   struct GNUNET_CADET_Channel *ch;
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
 
-  chid = ntohl (msg->channel_id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X Destroy from service\n", chid);
-  ch = retrieve_channel (h, chid);
+  chid = msg->channel_id;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Channel %X Destroy from service\n",
+       ntohl (chid.channel_of_client));
+  ch = retrieve_channel (h,
+                         chid);
 
   if (NULL == ch)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X unknown\n", chid);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "channel %X unknown\n",
+         ntohl (chid.channel_of_client));
     return;
   }
-  destroy_channel (ch, GNUNET_YES);
+  destroy_channel (ch,
+                   GNUNET_YES);
 }
 
 
@@ -674,7 +696,8 @@ check_local_data (void *cls,
     return GNUNET_SYSERR;
   }
 
-  ch = retrieve_channel (h, ntohl (message->id));
+  ch = retrieve_channel (h,
+                         message->id);
   if (NULL == ch)
   {
     GNUNET_break_op (0);
@@ -702,14 +725,17 @@ handle_local_data (void *cls,
   unsigned int i;
   uint16_t type;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
-  ch = retrieve_channel (h, ntohl (message->id));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got a data message!\n");
+  ch = retrieve_channel (h, message->id);
   GNUNET_assert (NULL != ch);
 
   payload = (struct GNUNET_MessageHeader *) &message[1];
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  %s data on channel %s [%X]\n",
-       GC_f2s (ch->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV),
-       GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), ntohl (message->id));
+       GC_f2s (ntohl (ch->chid.channel_of_client) >=
+               GNUNET_CADET_LOCAL_CHANNEL_ID_CLI),
+       GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)),
+       ntohl (message->id.channel_of_client));
 
   type = ntohs (payload->type);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  payload type %s\n", GC_m2s (type));
@@ -751,17 +777,21 @@ handle_local_ack (void *cls,
 {
   struct GNUNET_CADET_Handle *h = cls;
   struct GNUNET_CADET_Channel *ch;
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
-  chid = ntohl (message->channel_id);
+  chid = message->channel_id;
   ch = retrieve_channel (h, chid);
   if (NULL == ch)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK on unknown channel %X\n", chid);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "ACK on unknown channel %X\n",
+         ntohl (chid.channel_of_client));
     return;
   }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X!\n", ch->chid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "  on channel %X!\n",
+       ntohl (ch->chid.channel_of_client));
   ch->allow_send = GNUNET_YES;
   if (0 < ch->packet_size)
   {
@@ -1132,9 +1162,12 @@ handle_get_tunnels (void *cls,
 {
   struct GNUNET_CADET_Handle *h = cls;
 
-  h->info_cb.tunnels_cb (h->info_cls, &msg->destination,
-                         ntohl (msg->channels), ntohl (msg->connections),
-                         ntohs (msg->estate), ntohs (msg->cstate));
+  h->info_cb.tunnels_cb (h->info_cls,
+                         &msg->destination,
+                         ntohl (msg->channels),
+                         ntohl (msg->connections),
+                         ntohs (msg->estate),
+                         ntohs (msg->cstate));
 
 }
 
@@ -1170,13 +1203,14 @@ check_get_tunnel (void *cls,
   if (esize > msize)
   {
     GNUNET_break_op (0);
-    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
+    h->info_cb.tunnel_cb (h->info_cls,
+                          NULL, 0, 0, NULL, NULL, 0, 0);
     goto clean_cls;
   }
   ch_n = ntohl (msg->channels);
   c_n = ntohl (msg->connections);
-  esize += ch_n * sizeof (CADET_ChannelNumber);
-  esize += c_n * sizeof (struct GNUNET_CADET_Hash);
+  esize += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
+  esize += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
   if (msize != esize)
   {
     GNUNET_break_op (0);
@@ -1186,7 +1220,8 @@ check_get_tunnel (void *cls,
                 (unsigned int) esize,
                 ch_n,
                 c_n);
-    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
+    h->info_cb.tunnel_cb (h->info_cls,
+                          NULL, 0, 0, NULL, NULL, 0, 0);
     goto clean_cls;
   }
 
@@ -1212,18 +1247,23 @@ handle_get_tunnel (void *cls,
   struct GNUNET_CADET_Handle *h = cls;
   unsigned int ch_n;
   unsigned int c_n;
-  struct GNUNET_CADET_Hash *conns;
-  CADET_ChannelNumber *chns;
+  const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns;
+  const struct GNUNET_CADET_ChannelTunnelNumber *chns;
 
   ch_n = ntohl (msg->channels);
   c_n = ntohl (msg->connections);
 
   /* Call Callback with tunnel info. */
-  conns = (struct GNUNET_CADET_Hash *) &msg[1];
-  chns = (CADET_ChannelNumber *) &conns[c_n];
-  h->info_cb.tunnel_cb (h->info_cls, &msg->destination,
-                        ch_n, c_n, chns, conns,
-                        ntohs (msg->estate), ntohs (msg->cstate));
+  conns = (const struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
+  chns = (const struct GNUNET_CADET_ChannelTunnelNumber *) &conns[c_n];
+  h->info_cb.tunnel_cb (h->info_cls,
+                        &msg->destination,
+                        ch_n,
+                        c_n,
+                        chns,
+                        conns,
+                        ntohs (msg->estate),
+                        ntohs (msg->cstate));
 }
 
 
@@ -1241,8 +1281,8 @@ do_reconnect (struct GNUNET_CADET_Handle *h)
 {
   struct GNUNET_MQ_MessageHandler handlers[] = {
     GNUNET_MQ_hd_fixed_size (channel_created,
-                             GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE,
-                             struct GNUNET_CADET_ChannelCreateMessage,
+                             GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
+                             struct GNUNET_CADET_ChannelOpenMessageMessage,
                              h),
     GNUNET_MQ_hd_fixed_size (channel_destroy,
                              GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
@@ -1274,7 +1314,7 @@ do_reconnect (struct GNUNET_CADET_Handle *h)
                            h),
   // FIXME
 //   GNUNET_MQ_hd_fixed_Y       size (channel_destroyed,
-//                            GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK,
+//                            GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED,
 //                            struct GNUNET_CADET_ChannelDestroyMessage);
     GNUNET_MQ_handler_end ()
   };
@@ -1282,7 +1322,7 @@ do_reconnect (struct GNUNET_CADET_Handle *h)
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET\n");
 
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "cadet",
                                  handlers,
                                  &handle_mq_error,
@@ -1343,9 +1383,10 @@ reconnect (struct GNUNET_CADET_Handle *h)
 /******************************************************************************/
 
 struct GNUNET_CADET_Handle *
-GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
-                     GNUNET_CADET_ChannelEndHandler cleaner,
-                     const struct GNUNET_CADET_MessageHandler *handlers)
+GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                      void *cls,
+                      GNUNET_CADET_ChannelEndHandler cleaner,
+                      const struct GNUNET_CADET_MessageHandler *handlers)
 {
   struct GNUNET_CADET_Handle *h;
 
@@ -1364,7 +1405,7 @@ GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
   }
   h->cls = cls;
   h->message_handlers = handlers;
-  h->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
+  h->next_chid.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
   h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
   h->reconnect_task = NULL;
 
@@ -1384,21 +1425,24 @@ GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
   struct GNUNET_CADET_Channel *aux;
   struct GNUNET_CADET_TransmitHandle *th;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET DISCONNECT\n");
-
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "CADET DISCONNECT\n");
   ch = handle->channels_head;
   while (NULL != ch)
   {
     aux = ch->next;
-    if (ch->chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
+    if (ntohl (ch->chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
     {
       GNUNET_break (0);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X not destroyed\n", ch->chid);
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "channel %X not destroyed\n",
+           ntohl (ch->chid.channel_of_client));
     }
-    destroy_channel (ch, GNUNET_YES);
+    destroy_channel (ch,
+                     GNUNET_YES);
     ch = aux;
   }
-  while ( (th = handle->th_head) != NULL)
+  while (NULL != (th = handle->th_head))
   {
     struct GNUNET_MessageHeader *msg;
 
@@ -1409,7 +1453,7 @@ GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
     msg = (struct GNUNET_MessageHeader *) &th[1];
     switch (ntohs(msg->type))
     {
-      case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+      case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
       case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
       case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN:
       case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE:
@@ -1531,27 +1575,30 @@ GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
                             const struct GNUNET_HashCode *port,
                             enum GNUNET_CADET_ChannelOption options)
 {
-  struct GNUNET_CADET_ChannelCreateMessage *msg;
+  struct GNUNET_CADET_ChannelOpenMessageMessage *msg;
   struct GNUNET_MQ_Envelope *env;
   struct GNUNET_CADET_Channel *ch;
+  struct GNUNET_CADET_ClientChannelNumber chid;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Creating new channel to %s:%u\n",
        GNUNET_i2s (peer), port);
-  ch = create_channel (h, 0);
+  chid.channel_of_client = htonl (0);
+  ch = create_channel (h, chid);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", ch);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", ch->chid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n",
+       ntohl (ch->chid.channel_of_client));
   ch->ctx = channel_ctx;
   ch->peer = GNUNET_PEER_intern (peer);
 
-  env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
-  msg->channel_id = htonl (ch->chid);
+  env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
+  msg->channel_id = ch->chid;
   msg->port = *port;
   msg->peer = *peer;
   msg->opt = htonl (options);
   ch->allow_send = GNUNET_NO;
-  GNUNET_MQ_send (h->mq, env);
-
+  GNUNET_MQ_send (h->mq,
+                  env);
   return ch;
 }
 
@@ -1590,7 +1637,7 @@ GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
   }
 
   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
-  msg->channel_id = htonl (channel->chid);
+  msg->channel_id = channel->chid;
   GNUNET_MQ_send (h->mq, env);
 
   destroy_channel (channel, GNUNET_YES);
@@ -1617,7 +1664,7 @@ GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
   {
     case GNUNET_CADET_OPTION_NOBUFFER:
     case GNUNET_CADET_OPTION_RELIABLE:
-    case GNUNET_CADET_OPTION_OOORDER:
+    case GNUNET_CADET_OPTION_OUT_OF_ORDER:
       if (0 != (option & channel->options))
         bool_flag = GNUNET_YES;
       else
@@ -1651,7 +1698,8 @@ GNUNET_CADET_notify_transmit_ready (struct GNUNET_CADET_Channel *channel,
   LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY\n");
   LOG (GNUNET_ERROR_TYPE_DEBUG, "    on channel %X\n", channel->chid);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "    allow_send %d\n", channel->allow_send);
-  if (channel->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
+  if (ntohl (channel->chid.channel_of_client) >=
+      GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
     LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
   else
     LOG (GNUNET_ERROR_TYPE_DEBUG, "    to destination\n");
@@ -1946,7 +1994,7 @@ GNUNET_CADET_show_channel (struct GNUNET_CADET_Handle *h,
 
   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL);
   msg->peer = *initiator;
-  msg->channel_id = htonl (channel_number);
+  msg->channel_id.channel_of_client = htonl (channel_number);
   GNUNET_MQ_send (h->mq, env);
 
   h->info_cb.channel_cb = callback;
index a9d9a35be7dc40db20959bb257992dd9d5b98bde..95a3144e4dda0dc2fd2c431cf7a667ccd180fdf6 100644 (file)
@@ -51,11 +51,20 @@ GC_f2s (int fwd)
   }
 }
 
+
+/**
+ * Test if @a bigger is larger than @a smaller.
+ * Considers the case that @a bigger just overflowed
+ * and is thus tiny while @a smaller is still below
+ * `UINT32_MAX`.
+ */
 int
-GC_is_pid_bigger (uint32_t bigger, uint32_t smaller)
+GC_is_pid_bigger (uint32_t bigger,
+                 uint32_t smaller)
 {
-    return (GNUNET_YES == PID_OVERFLOW (smaller, bigger) ||
-            (bigger > smaller && GNUNET_NO == PID_OVERFLOW (bigger, smaller)));
+    return (PID_OVERFLOW (smaller, bigger) ||
+            ( (bigger > smaller) &&
+             (! PID_OVERFLOW (bigger, smaller))) );
 }
 
 
@@ -77,28 +86,6 @@ GC_min_pid (uint32_t a, uint32_t b)
 }
 
 
-const struct GNUNET_HashCode *
-GC_h2hc (const struct GNUNET_CADET_Hash *id)
-{
-  static struct GNUNET_HashCode hc;
-  GNUNET_memcpy (&hc, id, sizeof (*id));
-
-  return &hc;
-}
-
-
-const char *
-GC_h2s (const struct GNUNET_CADET_Hash *id)
-{
-  static char s[53];
-
-  GNUNET_memcpy (s, GNUNET_h2s_full (GC_h2hc (id)), 52);
-  s[52] = '\0';
-
-  return s;
-}
-
-
 /**
  * Allocate a string with a hexdump of any binary data.
  *
@@ -159,7 +146,7 @@ GC_m2s (uint16_t m)
       /**
        * Request the modification of an existing path
        */
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
       s = "CONN_ACK";
       break;
 
@@ -173,35 +160,35 @@ GC_m2s (uint16_t m)
       /**
        * At some point, the route will spontaneously change
        */
-    case GNUNET_MESSAGE_TYPE_CADET_PATH_CHANGED:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_PATH_CHANGED_UNIMPLEMENTED:
       s = "PATH_CHNGD";
       break;
 
       /**
        * Transport payload data.
        */
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
       s = "DATA";
       break;
 
     /**
      * Confirm receipt of payload data.
      */
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
       s = "DATA_ACK";
       break;
 
       /**
        * Key exchange message.
        */
-    case GNUNET_MESSAGE_TYPE_CADET_KX:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
       s = "KX";
       break;
 
       /**
        * Encrypted.
        */
-    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
       s = "ENCRYPTED";
       break;
 
@@ -215,21 +202,21 @@ GC_m2s (uint16_t m)
       /**
        * ACK for a data packet.
        */
-    case GNUNET_MESSAGE_TYPE_CADET_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
       s = "ACK";
       break;
 
       /**
        * POLL for ACK.
        */
-    case GNUNET_MESSAGE_TYPE_CADET_POLL:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
       s = "POLL";
       break;
 
       /**
        * Announce origin is still alive.
        */
-    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE:
       s = "KEEPALIVE";
       break;
 
@@ -250,7 +237,7 @@ GC_m2s (uint16_t m)
       /**
        * Ask the cadet service to create a new tunnel
        */
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
       s = "CHAN_CREAT";
       break;
 
@@ -264,14 +251,14 @@ GC_m2s (uint16_t m)
       /**
        * Confirm the creation of a channel.
        */
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
       s = "CHAN_ACK";
       break;
 
       /**
        * Confirm the creation of a channel.
        */
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
       s = "CHAN_NACK";
       break;
 
index d034c63b0529d16050b43ce0fa2b1e233000de3d..cf32e0d6d61f8458d7863afc3d8d80d97ceccb18 100644 (file)
@@ -56,12 +56,12 @@ GNUNET_NETWORK_STRUCT_BEGIN
 /**
  * Message for cadet connection creation.
  */
-struct GNUNET_CADET_ConnectionCreate
+struct GNUNET_CADET_ConnectionCreateMessage
 {
   /**
    * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
    *
-   * Size: sizeof (struct GNUNET_CADET_ConnectionCreate) +
+   * Size: sizeof (struct GNUNET_CADET_ConnectionCreateMessage) +
    *       path_length * sizeof (struct GNUNET_PeerIdentity)
    */
   struct GNUNET_MessageHeader header;
@@ -70,11 +70,11 @@ struct GNUNET_CADET_ConnectionCreate
    * For alignment.
    */
   uint32_t reserved GNUNET_PACKED;
-  
+
   /**
    * ID of the connection
    */
-  struct GNUNET_CADET_Hash cid;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
 
   /**
    * path_length structs defining the *whole* path from the origin [0] to the
@@ -87,10 +87,10 @@ struct GNUNET_CADET_ConnectionCreate
 /**
  * Message for ack'ing a connection
  */
-struct GNUNET_CADET_ConnectionACK
+struct GNUNET_CADET_ConnectionCreateMessageAckMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
    */
   struct GNUNET_MessageHeader header;
 
@@ -102,7 +102,7 @@ struct GNUNET_CADET_ConnectionACK
   /**
    * ID of the connection.
    */
-  struct GNUNET_CADET_Hash cid;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
 
 };
 
@@ -110,10 +110,10 @@ struct GNUNET_CADET_ConnectionACK
 /**
  * Message for notifying a disconnection in a path
  */
-struct GNUNET_CADET_ConnectionBroken
+struct GNUNET_CADET_ConnectionBrokenMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN.
    */
   struct GNUNET_MessageHeader header;
 
@@ -125,7 +125,7 @@ struct GNUNET_CADET_ConnectionBroken
   /**
    * ID of the connection.
    */
-  struct GNUNET_CADET_Hash cid;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
 
   /**
    * ID of the endpoint
@@ -142,7 +142,7 @@ struct GNUNET_CADET_ConnectionBroken
 /**
  * Message to destroy a connection.
  */
-struct GNUNET_CADET_ConnectionDestroy
+struct GNUNET_CADET_ConnectionDestroyMessage
 {
   /**
    * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
@@ -157,60 +157,31 @@ struct GNUNET_CADET_ConnectionDestroy
   /**
    * ID of the connection.
    */
-  struct GNUNET_CADET_Hash cid;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
 };
 
 
-/**
- * Message to acknowledge cadet encrypted traffic.
- */
-struct GNUNET_CADET_ACK
-{
-  /**
-   * Type: #GNUNET_MESSAGE_TYPE_CADET_ACK
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Maximum packet ID authorized.
-   */
-  uint32_t ack GNUNET_PACKED;
-
-  /**
-   * ID of the connection.
-   */
-  struct GNUNET_CADET_Hash cid;
-};
-
+/******************************************************************************/
+/*******************************   TUNNEL   ***********************************/
+/******************************************************************************/
 
 /**
- * Message to query a peer about its Flow Control status regarding a tunnel.
+ * Unique identifier (counter) for an encrypted message in a channel.
+ * Used to match #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
+ * and  #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL messages
+ * against the respective  #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED
+ * messages.
  */
-struct GNUNET_CADET_Poll
+struct CadetEncryptedMessageIdentifier
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_CADET_POLL
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Last packet sent.
+   * This number is incremented by one per message. It may wrap around.
+   * In network byte order.
    */
   uint32_t pid GNUNET_PACKED;
-
-  /**
-   * ID of the connection.
-   */
-  struct GNUNET_CADET_Hash cid;
-
 };
 
 
-
-/******************************************************************************/
-/*******************************   TUNNEL   ***********************************/
-/******************************************************************************/
-
 /**
  * Flags to be used in GNUNET_CADET_KX.
  */
@@ -231,10 +202,10 @@ enum GNUNET_CADET_KX_Flags {
 /**
  * Message for a Key eXchange for a tunnel.
  */
-struct GNUNET_CADET_KX
+struct GNUNET_CADET_TunnelKeyExchangeMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_CADET_KX.
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX.
    */
   struct GNUNET_MessageHeader header;
 
@@ -247,7 +218,7 @@ struct GNUNET_CADET_KX
   /**
    * ID of the connection.
    */
-  struct GNUNET_CADET_Hash cid;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
 
   /**
    * Sender's ephemeral public ECC key encoded in a
@@ -262,35 +233,42 @@ struct GNUNET_CADET_KX
    * using 'gcry_sexp_sprint'.
    */
   struct GNUNET_CRYPTO_EcdhePublicKey ratchet_key;
+
+#ifdef NEW_CADET
+  /**
+   * Proof that sender could compute the 3-DH, in lieu of a signature.
+   */
+  struct GNUNET_HashCode triple_dh_proof;
+#endif
 };
 
 
 /**
  * Axolotl tunnel message.
  */
-struct GNUNET_CADET_Encrypted
+struct GNUNET_CADET_TunnelEncryptedMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED
    */
   struct GNUNET_MessageHeader header;
 
   /**
    * ID of the packet (hop by hop).
    */
-  uint32_t pid GNUNET_PACKED;
+  struct CadetEncryptedMessageIdentifier cemi;
 
   /**
    * ID of the connection.
    */
-  struct GNUNET_CADET_Hash cid;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
 
   /**
    * MAC of the encrypted message, used to verify message integrity.
    * Everything after this value  will be encrypted with the header key
    * and authenticated.
    */
-  struct GNUNET_CADET_Hash hmac;
+  struct GNUNET_ShortHashCode hmac;
 
   /**************** AX_HEADER start ****************/
 
@@ -317,18 +295,69 @@ struct GNUNET_CADET_Encrypted
 };
 
 
+/**
+ * Message to query a peer about its Flow Control status regarding a tunnel.
+ *
+ * It is NOT yet clear if we need this.
+ */
+struct GNUNET_CADET_ConnectionHopByHopPollMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Last packet sent.
+   */
+  struct CadetEncryptedMessageIdentifier cemi;
+
+  /**
+   * ID of the connection.
+   */
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
+
+};
+
+
+/**
+ * Message to acknowledge cadet encrypted traffic, used for
+ * flow-control on a hop-by-hop basis on the connection-level. Note
+ * that we do use the @e cemi from the tunnel layer as the connection
+ * layer's header is included/shared with the tunnel layer messages,
+ * and we only do flow control for the payload.
+ */
+struct GNUNET_CADET_ConnectionEncryptedAckMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Maximum packet ID authorized.
+   */
+  struct CadetEncryptedMessageIdentifier cemi;
+
+  /**
+   * ID of the connection.
+   */
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
+};
+
 
 /******************************************************************************/
 /*******************************   CHANNEL  ***********************************/
 /******************************************************************************/
 
+
 /**
  * Message to create a Channel.
  */
-struct GNUNET_CADET_ChannelCreate
+struct GNUNET_CADET_ChannelOpenMessage
 {
   /**
-   * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN
    */
   struct GNUNET_MessageHeader header;
 
@@ -343,33 +372,42 @@ struct GNUNET_CADET_ChannelCreate
   struct GNUNET_HashCode port;
 
   /**
-   * ID of the channel
+   * ID of the channel within the tunnel.
    */
-  CADET_ChannelNumber chid GNUNET_PACKED;
+  struct GNUNET_CADET_ChannelTunnelNumber chid;
 };
 
 
 /**
  * Message to manage a Channel (ACK, NACK, Destroy).
  */
-struct GNUNET_CADET_ChannelManage
+struct GNUNET_CADET_ChannelManageMessage
 {
   /**
    * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_{ACK|NACK|DESTROY}
    */
   struct GNUNET_MessageHeader header;
 
+#ifdef NEW_CADET
+  /**
+   * For alignment.
+   */
+  uint32_t reserved GNUNET_PACKED;
+#endif
+
   /**
    * ID of the channel
    */
-  CADET_ChannelNumber chid GNUNET_PACKED;
+  struct GNUNET_CADET_ChannelTunnelNumber chid;
 };
 
 
+#ifndef NEW_CADET
+
 /**
  * Message for cadet data traffic.
  */
-struct GNUNET_CADET_Data
+struct GNUNET_CADET_ChannelAppDataMessage
 {
   /**
    * Type: #GNUNET_MESSAGE_TYPE_CADET_UNICAST,
@@ -380,12 +418,13 @@ struct GNUNET_CADET_Data
   /**
    * Unique ID of the payload message
    */
+  /* NEW: struct ChannelMessageIdentifier */
   uint32_t mid GNUNET_PACKED;
 
   /**
    * ID of the channel
    */
-  CADET_ChannelNumber chid GNUNET_PACKED;
+  struct GNUNET_CADET_ChannelTunnelNumber chid;
 
   /**
    * Payload follows
@@ -396,17 +435,17 @@ struct GNUNET_CADET_Data
 /**
  * Message to acknowledge end-to-end data.
  */
-struct GNUNET_CADET_DataACK
+struct GNUNET_CADET_ChannelDataAckMessage
 {
   /**
-   * Type: GNUNET_MESSAGE_TYPE_CADET_DATA_ACK
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK
    */
   struct GNUNET_MessageHeader header;
 
   /**
    * ID of the channel
    */
-  CADET_ChannelNumber chid GNUNET_PACKED;
+  struct GNUNET_CADET_ChannelTunnelNumber chid;
 
   /**
    * Bitfield of already-received newer messages
@@ -418,10 +457,82 @@ struct GNUNET_CADET_DataACK
   /**
    * Last message ID received.
    */
+  /* NEW: struct ChannelMessageIdentifier */
+  uint32_t mid GNUNET_PACKED;
+};
+
+#else
+
+
+/**
+ * Number used to uniquely identify messages in a CADET Channel.
+ */
+struct ChannelMessageIdentifier
+{
+  /**
+   * Unique ID of the message, cycles around, in NBO.
+   */
   uint32_t mid GNUNET_PACKED;
 };
 
 
+/**
+ * Message for cadet data traffic.
+ */
+struct GNUNET_CADET_ChannelAppDataMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_UNICAST,
+   *       #GNUNET_MESSAGE_TYPE_CADET_TO_ORIGIN
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique ID of the payload message.
+   */
+  struct ChannelMessageIdentifier mid;
+
+  /**
+   * ID of the channel
+   */
+  struct GNUNET_CADET_ChannelTunnelNumber gid;
+
+  /**
+   * Payload follows
+   */
+};
+
+
+/**
+ * Message to acknowledge end-to-end data.
+ */
+struct GNUNET_CADET_ChannelDataAckMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the channel
+   */
+  struct GNUNET_CADET_ChannelTunnelNumber gid;
+
+  /**
+   * Bitfield of already-received messages past @e mid.
+   * pid +  1 @ LSB
+   * pid + 64 @ MSB
+   */
+  uint64_t futures GNUNET_PACKED;
+
+  /**
+   * Last message ID received.
+   */
+  struct ChannelMessageIdentifier mid;
+};
+
+
+#endif
 
 GNUNET_NETWORK_STRUCT_END
 
index 5afb64e24e5b99a9e0694ea28f2b7b54fbdb43d8..80010ec54b3a47ddb0d3de5ed7477068fa997d6e 100644 (file)
@@ -727,8 +727,8 @@ tunnel_callback (void *cls,
                  const struct GNUNET_PeerIdentity *peer,
                  unsigned int n_channels,
                  unsigned int n_connections,
-                 uint32_t *channels,
-                 struct GNUNET_CADET_Hash *connections,
+                 const struct GNUNET_CADET_ChannelTunnelNumber *channels,
+                 const struct GNUNET_CADET_ConnectionTunnelIdentifier *connections,
                  unsigned int estate,
                  unsigned int cstate)
 {
@@ -739,10 +739,10 @@ tunnel_callback (void *cls,
     FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer));
     FPRINTF (stdout, "\t%u channels\n", n_channels);
     for (i = 0; i < n_channels; i++)
-      FPRINTF (stdout, "\t\t%X\n", ntohl (channels[i]));
+      FPRINTF (stdout, "\t\t%X\n", ntohl (channels[i].cn));
     FPRINTF (stdout, "\t%u connections\n", n_connections);
     for (i = 0; i < n_connections; i++)
-      FPRINTF (stdout, "\t\t%s\n", GC_h2s (&connections[i]));
+      FPRINTF (stdout, "\t\t%s\n", GNUNET_sh2s (&connections[i].connection_of_tunnel));
     FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate));
     FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate));
   }
@@ -827,7 +827,10 @@ show_tunnel (void *cls)
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  GNUNET_CADET_get_tunnel (mh, &pid, tunnel_callback, NULL);
+  GNUNET_CADET_get_tunnel (mh,
+                           &pid,
+                           &tunnel_callback,
+                           NULL);
 }
 
 
diff --git a/src/cadet/gnunet-service-cadet-new.c b/src/cadet/gnunet-service-cadet-new.c
new file mode 100644 (file)
index 0000000..2f6cc7b
--- /dev/null
@@ -0,0 +1,1350 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2013, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new.c
+ * @brief GNUnet CADET service with encryption
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * Dictionary:
+ * - peer: other cadet instance. If there is direct connection it's a neighbor.
+ * - path: series of directly connected peer from one peer to another.
+ * - connection: path which is being used in a tunnel.
+ * - tunnel: encrypted connection to a peer, neighbor or not.
+ * - channel: logical link between two clients, on the same or different peers.
+ *            have properties like reliability.
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "cadet.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet-service-cadet-new.h"
+#include "gnunet-service-cadet-new_channel.h"
+#include "gnunet-service-cadet-new_connection.h"
+#include "gnunet-service-cadet-new_core.h"
+#include "gnunet-service-cadet-new_dht.h"
+#include "gnunet-service-cadet-new_hello.h"
+#include "gnunet-service-cadet-new_tunnels.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "gnunet-service-cadet-new_paths.h"
+
+#define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
+
+
+/**
+ * Struct containing information about a client of the service
+ */
+struct CadetClient
+{
+  /**
+   * Linked list next
+   */
+  struct CadetClient *next;
+
+  /**
+   * Linked list prev
+   */
+  struct CadetClient *prev;
+
+  /**
+   * Tunnels that belong to this client, indexed by local id
+   */
+  struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
+
+  /**
+   * Tunnels this client has accepted, indexed by incoming local id
+   */
+  struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels;
+
+  /**
+   * Channel ID for the next incoming channel.
+   */
+  struct GNUNET_CADET_ClientChannelNumber next_chid;
+
+  /**
+   * Handle to communicate with the client
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Client handle.
+   */
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * Ports that this client has declared interest in.
+   * Indexed by port, contains *Client.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *ports;
+
+  /**
+   * Whether the client is active or shutting down (don't send confirmations
+   * to a client that is shutting down).
+   */
+  int shutting_down;
+
+  /**
+   * ID of the client, mainly for debug messages
+   */
+  unsigned int id;
+};
+
+/******************************************************************************/
+/***********************      GLOBAL VARIABLES     ****************************/
+/******************************************************************************/
+
+/****************************** Global variables ******************************/
+
+/**
+ * Handle to the statistics service.
+ */
+struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Handle to communicate with ATS.
+ */
+struct GNUNET_ATS_ConnectivityHandle *ats_ch;
+
+/**
+ * Local peer own ID.
+ */
+struct GNUNET_PeerIdentity my_full_id;
+
+/**
+ * Own private key.
+ */
+struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
+
+/**
+ * Signal that shutdown is happening: prevent recover measures.
+ */
+int shutting_down;
+
+/**
+ * DLL with all the clients, head.
+ */
+static struct CadetClient *clients_head;
+
+/**
+ * DLL with all the clients, tail.
+ */
+static struct CadetClient *clients_tail;
+
+/**
+ * Next ID to assign to a client.
+ */
+static unsigned int next_client_id;
+
+/**
+ * All ports clients of this peer have opened.
+ */
+struct GNUNET_CONTAINER_MultiHashMap *open_ports;
+
+/**
+ * Map from ports to channels where the ports were closed at the
+ * time we got the inbound connection.
+ * Indexed by port, contains `struct CadetChannel`.
+ */
+struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
+
+/**
+ * Map from PIDs to `struct CadetPeer` entries.
+ */
+struct GNUNET_CONTAINER_MultiPeerMap *peers;
+
+/**
+ * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
+ * hash codes to `struct CadetConnection` objects.
+ */
+struct GNUNET_CONTAINER_MultiShortmap *connections;
+
+/**
+ * How many messages are needed to trigger an AXOLOTL ratchet advance.
+ */
+unsigned long long ratchet_messages;
+
+/**
+ * How long until we trigger a ratched advance due to time.
+ */
+struct GNUNET_TIME_Relative ratchet_time;
+
+
+
+/**
+ * Send a message to a client.
+ *
+ * @param c client to get the message
+ * @param env envelope with the message
+ */
+void
+GSC_send_to_client (struct CadetClient *c,
+                    struct GNUNET_MQ_Envelope *env)
+{
+  GNUNET_MQ_send (c->mq,
+                  env);
+}
+
+
+/**
+ * Return identifier for a client as a string.
+ *
+ * @param c client to identify
+ * @return string for debugging
+ */
+const char *
+GSC_2s (struct CadetClient *c)
+{
+  static char buf[32];
+
+  if (NULL == c)
+    return "Client(NULL)";
+  GNUNET_snprintf (buf,
+                   sizeof (buf),
+                   "Client(%u)",
+                   c->id);
+  return buf;
+}
+
+
+/**
+ * Obtain the next LID to use for incoming connections to
+ * the given client.
+ *
+ * @param c client handle
+ */
+static struct GNUNET_CADET_ClientChannelNumber
+client_get_next_lid (struct CadetClient *c)
+{
+  struct GNUNET_CADET_ClientChannelNumber ccn = c->next_chid;
+
+  /* increment until we have a free one... */
+  while (NULL !=
+         GNUNET_CONTAINER_multihashmap32_get (c->incoming_channels,
+                                              ntohl (ccn.channel_of_client)))
+  {
+    ccn.channel_of_client
+      = htonl (1 + (ntohl (ccn.channel_of_client)));
+    if (ntohl (ccn.channel_of_client) >=
+        GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+      ccn.channel_of_client = htonl (0);
+  }
+  c->next_chid.channel_of_client
+    = htonl (1 + (ntohl (ccn.channel_of_client)));
+  return ccn;
+}
+
+
+/**
+ * Bind incoming channel to this client, and notify client
+ * about incoming connection.
+ *
+ * @param c client to bind to
+ * @param ch channel to be bound
+ * @param dest peer that establishes the connection
+ * @param port port number
+ * @param options options
+ * @return local channel number assigned to the new client
+ */
+struct GNUNET_CADET_ClientChannelNumber
+GSC_bind (struct CadetClient *c,
+          struct CadetChannel *ch,
+          struct CadetPeer *dest,
+          const struct GNUNET_HashCode *port,
+          uint32_t options)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_ChannelOpenMessageMessage *msg;
+  struct GNUNET_CADET_ClientChannelNumber lid;
+
+  lid = client_get_next_lid (c);
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap32_put (c->incoming_channels,
+                                                      ntohl (lid.channel_of_client),
+                                                      ch,
+                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+
+  /* notify local client about incoming connection! */
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
+  msg->channel_id = lid;
+  msg->port = *port;
+  msg->opt = htonl (options);
+  msg->peer = *GCP_get_id (dest);
+  GSC_send_to_client (c,
+                      env);
+  return lid;
+}
+
+
+/******************************************************************************/
+/************************      MAIN FUNCTIONS      ****************************/
+/******************************************************************************/
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ */
+static void
+shutdown_task (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "shutting down\n");
+  shutting_down = GNUNET_YES;
+  GCO_shutdown ();
+  if (NULL != stats)
+  {
+    GNUNET_STATISTICS_destroy (stats,
+                               GNUNET_NO);
+    stats = NULL;
+  }
+  if (NULL != open_ports)
+  {
+    GNUNET_CONTAINER_multihashmap_destroy (open_ports);
+    open_ports = NULL;
+  }
+  if (NULL != loose_channels)
+  {
+    GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
+    loose_channels = NULL;
+  }
+  /* All channels, connections and CORE must be down before this point. */
+  GCP_destroy_all_peers ();
+  if (NULL != peers)
+  {
+    GNUNET_CONTAINER_multipeermap_destroy (peers);
+    peers = NULL;
+  }
+  if (NULL != connections)
+  {
+    GNUNET_CONTAINER_multishortmap_destroy (connections);
+    connections = NULL;
+  }
+  if (NULL != ats_ch)
+  {
+    GNUNET_ATS_connectivity_done (ats_ch);
+    ats_ch = NULL;
+  }
+  GCD_shutdown ();
+  GCH_shutdown ();
+  GNUNET_free_non_null (my_private_key);
+  my_private_key = NULL;
+}
+
+
+/**
+ * We had a remote connection @a value to port @a port before
+ * client @a cls opened port @a port.  Bind them now.
+ *
+ * @param cls the `struct CadetClient`
+ * @param port the port
+ * @param value the `struct CadetChannel`
+ * @return #GNUNET_YES (iterate over all such channels)
+ */
+static int
+bind_loose_channel (void *cls,
+                    const struct GNUNET_HashCode *port,
+                    void *value)
+{
+  struct CadetClient *c = cls;
+  struct CadetChannel *ch = value;
+
+  GCCH_bind (ch,
+             c);
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
+                                                       port,
+                                                       value));
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handler for port open requests.
+ *
+ * @param cls Identification of the client.
+ * @param pmsg The actual message.
+ */
+static void
+handle_port_open (void *cls,
+                  const struct GNUNET_CADET_PortMessage *pmsg)
+{
+  struct CadetClient *c = cls;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Open port %s requested by client %u\n",
+       GNUNET_h2s (&pmsg->port),
+       c->id);
+  if (NULL == c->ports)
+    c->ports = GNUNET_CONTAINER_multihashmap_create (4,
+                                                     GNUNET_NO);
+  if (GNUNET_OK !=
+      GNUNET_CONTAINER_multihashmap_put (c->ports,
+                                         &pmsg->port,
+                                         c,
+                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+  /* store in global hashmap */
+  /* FIXME only allow one client to have the port open,
+   *       have a backup hashmap with waiting clients */
+  GNUNET_CONTAINER_multihashmap_put (open_ports,
+                                     &pmsg->port,
+                                     c,
+                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+  GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
+                                              &pmsg->port,
+                                              &bind_loose_channel,
+                                              c);
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Handler for port close requests.
+ *
+ * @param cls Identification of the client.
+ * @param pmsg The actual message.
+ */
+static void
+handle_port_close (void *cls,
+                   const struct GNUNET_CADET_PortMessage *pmsg)
+{
+  struct CadetClient *c = cls;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Open port %s requested by client %u\n",
+       GNUNET_h2s (&pmsg->port),
+       c->id);
+  if (GNUNET_YES !=
+      GNUNET_CONTAINER_multihashmap_remove (c->ports,
+                                            &pmsg->port,
+                                            c))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (open_ports,
+                                                       &pmsg->port,
+                                                       c));
+
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Handler for requests of new channels.
+ *
+ * @param cls Identification of the client.
+ * @param ccm The actual message.
+ */
+static void
+handle_channel_create (void *cls,
+                       const struct GNUNET_CADET_ChannelOpenMessageMessage *ccm)
+{
+  struct CadetClient *c = cls;
+  struct CadetChannel *ch;
+  struct GNUNET_CADET_ClientChannelNumber chid;
+  struct CadetPeer *dst;
+
+  chid = ccm->channel_id;
+  if (ntohl (chid.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+  {
+    /* Channel ID not in allowed range. */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+  ch = GNUNET_CONTAINER_multihashmap32_get (c->own_channels,
+                                            ntohl (chid.channel_of_client));
+  if (NULL != ch)
+  {
+    /* Channel ID already in use. Not allowed. */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+
+  dst = GCP_get (&ccm->peer,
+                 GNUNET_YES);
+
+  /* Create channel */
+  ch = GCCH_channel_local_new (c,
+                               chid,
+                               dst,
+                               &ccm->port,
+                               ntohl (ccm->opt));
+  if (NULL == ch)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap32_put (c->own_channels,
+                                                      ntohl (chid.channel_of_client),
+                                                      ch,
+                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "New channel %s to %s at port %s requested by client %u\n",
+       GCCH_2s (ch),
+       GNUNET_i2s (&ccm->peer),
+       GNUNET_h2s (&ccm->port),
+       c->id);
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Return the map which we use for client @a c for a channel ID of @a chid
+ *
+ * @param c client to find map for
+ * @param chid chid to find map for
+ * @return applicable map we use
+ */
+static struct GNUNET_CONTAINER_MultiHashMap32 *
+get_map_by_chid (struct CadetClient *c,
+                 struct GNUNET_CADET_ClientChannelNumber chid)
+{
+  return (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+    ? c->own_channels
+    : c->incoming_channels;
+}
+
+
+/**
+ * Handler for requests of deleting tunnels
+ *
+ * @param cls client identification of the client
+ * @param msg the actual message
+ */
+static void
+handle_channel_destroy (void *cls,
+                        const struct GNUNET_CADET_ChannelDestroyMessage *msg)
+{
+  struct CadetClient *c = cls;
+  struct GNUNET_CADET_ClientChannelNumber chid;
+  struct GNUNET_CONTAINER_MultiHashMap32 *map;
+  struct CadetChannel *ch;
+
+  /* Retrieve tunnel */
+  chid = msg->channel_id;
+  map = get_map_by_chid (c,
+                         chid);
+  ch = GNUNET_CONTAINER_multihashmap32_get (map,
+                                            ntohl (chid.channel_of_client));
+  if (NULL == ch)
+  {
+    /* Client attempted to destroy unknown channel */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Client %u is destroying channel %s\n",
+       c->id,
+       GCCH_2s (ch));
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap32_remove (map,
+                                                         ntohl (chid.channel_of_client),
+                                                         ch));
+  GCCH_channel_local_destroy (ch);
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Check for client traffic data message is well-formed
+ *
+ * @param cls identification of the client
+ * @param msg the actual message
+ * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not
+ */
+static int
+check_data (void *cls,
+            const struct GNUNET_CADET_LocalData *msg)
+{
+  const struct GNUNET_MessageHeader *payload;
+  size_t payload_size;
+  size_t payload_claimed_size;
+
+  /* Sanity check for message size */
+  payload_size = ntohs (msg->header.size) - sizeof (*msg);
+  if ( (payload_size < sizeof (struct GNUNET_MessageHeader)) ||
+       (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_size) )
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  payload = (struct GNUNET_MessageHeader *) &msg[1];
+  payload_claimed_size = ntohs (payload->size);
+  if (payload_size != payload_claimed_size)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handler for client traffic
+ *
+ * @param cls identification of the client
+ * @param msg the actual message
+ */
+static void
+handle_data (void *cls,
+             const struct GNUNET_CADET_LocalData *msg)
+{
+  struct CadetClient *c = cls;
+  struct GNUNET_CONTAINER_MultiHashMap32 *map;
+  struct GNUNET_CADET_ClientChannelNumber chid;
+  struct CadetChannel *ch;
+  const struct GNUNET_MessageHeader *payload;
+
+  chid = msg->id;
+  map = get_map_by_chid (c,
+                         chid);
+  ch = GNUNET_CONTAINER_multihashmap32_get (map,
+                                            ntohl (chid.channel_of_client));
+  if (NULL == ch)
+  {
+    /* Channel does not exist! */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+
+  payload = (const struct GNUNET_MessageHeader *) &msg[1];
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received %u bytes payload from client %u for channel %s\n",
+       ntohs (payload->size),
+       c->id,
+       GCCH_2s (ch));
+  if (GNUNET_OK !=
+      GCCH_handle_local_data (ch,
+                              payload))
+  {
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Handler for client's ACKs for payload traffic.
+ *
+ * @param cls identification of the client.
+ * @param msg The actual message.
+ */
+static void
+handle_ack (void *cls,
+            const struct GNUNET_CADET_LocalAck *msg)
+{
+  struct CadetClient *c = cls;
+  struct GNUNET_CONTAINER_MultiHashMap32 *map;
+  struct GNUNET_CADET_ClientChannelNumber chid;
+  struct CadetChannel *ch;
+
+  chid = msg->channel_id;
+  map = get_map_by_chid (c,
+                         chid);
+  ch = GNUNET_CONTAINER_multihashmap32_get (map,
+                                            ntohl (chid.channel_of_client));
+  if (NULL == ch)
+  {
+    /* Channel does not exist! */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (c->client);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got a local ACK from client %u for channel %s\n",
+       c->id,
+       GCCH_2s (ch));
+  GCCH_handle_local_ack (ch);
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Iterator over all peers to send a monitoring client info about each peer.
+ *
+ * @param cls Closure ().
+ * @param peer Peer ID (tunnel remote peer).
+ * @param value Peer info.
+ * @return #GNUNET_YES, to keep iterating.
+ */
+static int
+get_all_peers_iterator (void *cls,
+                        const struct GNUNET_PeerIdentity *peer,
+                        void *value)
+{
+  struct CadetClient *c = cls;
+  struct CadetPeer *p = value;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_LocalInfoPeer *msg;
+
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
+  msg->destination = *peer;
+  msg->paths = htons (GCP_count_paths (p));
+  msg->tunnel = htons (NULL != GCP_get_tunnel (p,
+                                               GNUNET_NO));
+  GNUNET_MQ_send (c->mq,
+                  env);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handler for client's INFO PEERS request.
+ *
+ * @param cls Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_get_peers (void *cls,
+                  const struct GNUNET_MessageHeader *message)
+{
+  struct CadetClient *c = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_MessageHeader *reply;
+
+  GCP_iterate_all (&get_all_peers_iterator,
+                   c);
+  env = GNUNET_MQ_msg (reply,
+                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
+  GNUNET_MQ_send (c->mq,
+                  env);
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Iterator over all paths of a peer to build an InfoPeer message.
+ * Message contains blocks of peers, first not included.
+ *
+ * @param cls message queue for transmission
+ * @param path Path itself
+ * @param off offset of the peer on @a path
+ * @return #GNUNET_YES if should keep iterating.
+ *         #GNUNET_NO otherwise.
+ */
+static int
+path_info_iterator (void *cls,
+                    struct CadetPeerPath *path,
+                    unsigned int off)
+{
+  struct GNUNET_MQ_Handle *mq = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_MessageHeader *resp;
+  struct GNUNET_PeerIdentity *id;
+  uint16_t path_size;
+  unsigned int i;
+  unsigned int path_length;
+
+  path_length = GCPP_get_length (path);
+  path_size = sizeof (struct GNUNET_PeerIdentity) * (path_length - 1);
+  if (sizeof (*resp) + path_size > UINT16_MAX)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Path of %u entries is too long for info message\n",
+         path_length);
+    return GNUNET_YES;
+  }
+  env = GNUNET_MQ_msg_extra (resp,
+                             path_size,
+                             GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
+  id = (struct GNUNET_PeerIdentity *) &resp[1];
+
+  /* Don't copy first peer.  First peer is always the local one.  Last
+   * peer is always the destination (leave as 0, EOL).
+   */
+  for (i = 0; i < off; i++)
+    id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path,
+                                                  i + 1));
+  GNUNET_MQ_send (mq,
+                  env);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handler for client's SHOW_PEER request.
+ *
+ * @param cls Identification of the client.
+ * @param msg The actual message.
+ */
+static void
+handle_show_peer (void *cls,
+                  const struct GNUNET_CADET_LocalInfo *msg)
+{
+  struct CadetClient *c = cls;
+  struct CadetPeer *p;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_MessageHeader *resp;
+
+  p = GCP_get (&msg->peer,
+               GNUNET_NO);
+  if (NULL != p)
+    GCP_iterate_paths (p,
+                       &path_info_iterator,
+                       c->mq);
+  /* Send message with 0/0 to indicate the end */
+  env = GNUNET_MQ_msg (resp,
+                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END);
+  GNUNET_MQ_send (c->mq,
+                  env);
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Iterator over all tunnels to send a monitoring client info about each tunnel.
+ *
+ * @param cls Closure ().
+ * @param peer Peer ID (tunnel remote peer).
+ * @param value a `struct CadetPeer`
+ * @return #GNUNET_YES, to keep iterating.
+ */
+static int
+get_all_tunnels_iterator (void *cls,
+                          const struct GNUNET_PeerIdentity *peer,
+                          void *value)
+{
+  struct CadetClient *c = cls;
+  struct CadetPeer *p = value;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_LocalInfoTunnel *msg;
+  struct CadetTunnel *t;
+
+  t = GCP_get_tunnel (p,
+                      GNUNET_NO);
+  if (NULL == t)
+    return GNUNET_YES;
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
+  msg->destination = *peer;
+  msg->channels = htonl (GCT_count_channels (t));
+  msg->connections = htonl (GCT_count_any_connections (t));
+  msg->cstate = htons ((uint16_t) GCT_get_cstate (t));
+  msg->estate = htons ((uint16_t) GCT_get_estate (t));
+  GNUNET_MQ_send (c->mq,
+                  env);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handler for client's INFO TUNNELS request.
+ *
+ * @param cls client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_get_tunnels (void *cls,
+                    const struct GNUNET_MessageHeader *message)
+{
+  struct CadetClient *c = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_MessageHeader *reply;
+
+  GCP_iterate_all (&get_all_tunnels_iterator,
+                   c);
+  env = GNUNET_MQ_msg (reply,
+                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
+  GNUNET_MQ_send (c->mq,
+                  env);
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * FIXME.
+ */
+static void
+iter_connection (void *cls,
+                 struct CadetConnection *c)
+{
+  struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
+
+  h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
+  h[msg->connections++] = *(GCC_get_id (c));
+}
+
+
+/**
+ * FIXME.
+ */
+static void
+iter_channel (void *cls,
+              struct CadetChannel *ch)
+{
+  struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
+  struct GNUNET_CADET_ChannelTunnelNumber *chn
+    = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections];
+
+  chn[msg->channels++] = GCCH_get_id (ch);
+}
+
+
+/**
+ * Handler for client's SHOW_TUNNEL request.
+ *
+ * @param cls Identification of the client.
+ * @param msg The actual message.
+ */
+static void
+handle_show_tunnel (void *cls,
+                    const struct GNUNET_CADET_LocalInfo *msg)
+{
+  struct CadetClient *c = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_LocalInfoTunnel *resp;
+  struct CadetTunnel *t;
+  struct CadetPeer *p;
+  unsigned int ch_n;
+  unsigned int c_n;
+
+  p = GCP_get (&msg->peer,
+               GNUNET_NO);
+  t = GCP_get_tunnel (p,
+                      GNUNET_NO);
+  if (NULL == t)
+  {
+    /* We don't know the tunnel */
+    struct GNUNET_MQ_Envelope *env;
+    struct GNUNET_CADET_LocalInfoTunnel *warn;
+
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         "Tunnel to %s unknown\n",
+         GNUNET_i2s_full (&msg->peer));
+    env = GNUNET_MQ_msg (warn,
+                         GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
+    warn->destination = msg->peer;
+    GNUNET_MQ_send (c->mq,
+                    env);
+    GNUNET_SERVICE_client_continue (c->client);
+    return;
+  }
+
+  /* Initialize context */
+  ch_n = GCT_count_channels (t);
+  c_n = GCT_count_any_connections (t);
+  env = GNUNET_MQ_msg_extra (resp,
+                             c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier) +
+                             ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber),
+                             GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
+  resp->destination = msg->peer;
+  /* Do not reorder! #iter_channel needs counters in HBO! */
+  GCT_iterate_connections (t,
+                           &iter_connection,
+                           resp);
+  GCT_iterate_channels (t,
+                        &iter_channel,
+                        resp);
+  resp->connections = htonl (resp->connections);
+  resp->channels = htonl (resp->channels);
+  resp->cstate = htons (GCT_get_cstate (t));
+  resp->estate = htons (GCT_get_estate (t));
+  GNUNET_MQ_send (c->mq,
+                  env);
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+/**
+ * Iterator over all peers to dump info for each peer.
+ *
+ * @param cls Closure (unused).
+ * @param peer Peer ID (tunnel remote peer).
+ * @param value Peer info.
+ *
+ * @return #GNUNET_YES, to keep iterating.
+ */
+static int
+show_peer_iterator (void *cls,
+                    const struct GNUNET_PeerIdentity *peer,
+                    void *value)
+{
+  struct CadetPeer *p = value;
+  struct CadetTunnel *t;
+
+  t = GCP_get_tunnel (p,
+                      GNUNET_NO);
+  if (NULL != t)
+    GCT_debug (t,
+               GNUNET_ERROR_TYPE_ERROR);
+  LOG (GNUNET_ERROR_TYPE_ERROR, "\n");
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handler for client's INFO_DUMP request.
+ *
+ * @param cls Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_info_dump (void *cls,
+                  const struct GNUNET_MessageHeader *message)
+{
+  struct CadetClient *c = cls;
+
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Received dump info request from client %u\n",
+       c->id);
+
+  LOG (GNUNET_ERROR_TYPE_ERROR,
+       "*************************** DUMP START ***************************\n");
+  for (struct CadetClient *ci = clients_head; NULL != ci; ci = ci->next)
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Client %u (%p), handle: %p, ports: %u, own channels: %u, incoming channels: %u\n",
+         ci->id,
+         ci,
+         ci->client,
+         (NULL != c->ports)
+         ? GNUNET_CONTAINER_multihashmap_size (ci->ports)
+         : 0,
+         GNUNET_CONTAINER_multihashmap32_size (ci->own_channels),
+         GNUNET_CONTAINER_multihashmap32_size (ci->incoming_channels));
+  }
+  LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n");
+  GCP_iterate_all (&show_peer_iterator,
+                   NULL);
+
+  LOG (GNUNET_ERROR_TYPE_ERROR,
+       "**************************** DUMP END ****************************\n");
+
+  GNUNET_SERVICE_client_continue (c->client);
+}
+
+
+
+/**
+ * Callback called when a client connects to the service.
+ *
+ * @param cls closure for the service
+ * @param client the new client that connected to the service
+ * @param mq the message queue used to send messages to the client
+ * @return @a c
+ */
+static void *
+client_connect_cb (void *cls,
+                  struct GNUNET_SERVICE_Client *client,
+                  struct GNUNET_MQ_Handle *mq)
+{
+  struct CadetClient *c;
+
+  c = GNUNET_new (struct CadetClient);
+  c->client = client;
+  c->mq = mq;
+  c->id = next_client_id++; /* overflow not important: just for debug */
+  c->own_channels
+    = GNUNET_CONTAINER_multihashmap32_create (32);
+  c->incoming_channels
+    = GNUNET_CONTAINER_multihashmap32_create (32);
+  GNUNET_CONTAINER_DLL_insert (clients_head,
+                               clients_tail,
+                               c);
+  GNUNET_STATISTICS_update (stats,
+                            "# clients",
+                            +1,
+                            GNUNET_NO);
+  return c;
+}
+
+
+/**
+ * Iterator for deleting each channel whose client endpoint disconnected.
+ *
+ * @param cls Closure (client that has disconnected).
+ * @param key The local channel id (used to access the hashmap).
+ * @param value The value stored at the key (channel to destroy).
+ * @return #GNUNET_OK, keep iterating.
+ */
+static int
+own_channel_destroy_iterator (void *cls,
+                              uint32_t key,
+                              void *value)
+{
+  struct CadetClient *c = cls;
+  struct CadetChannel *ch = value;
+
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
+                                                         key,
+                                                         ch));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Destroying own channel %s, due to client %u shutdown.\n",
+       GCCH_2s (ch),
+       c->id);
+  GCCH_channel_local_destroy (ch);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Iterator for deleting each channel whose client endpoint disconnected.
+ *
+ * @param cls Closure (client that has disconnected).
+ * @param key The local channel id (used to access the hashmap).
+ * @param value The value stored at the key (channel to destroy).
+ * @return #GNUNET_OK, keep iterating.
+ */
+static int
+incoming_channel_destroy_iterator (void *cls,
+                                   uint32_t key,
+                                   void *value)
+{
+  struct CadetChannel *ch = value;
+  struct CadetClient *c = cls;
+
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
+                                                         key,
+                                                         ch));
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Destroying incoming channel %s due to client %u shutdown.\n",
+       GCCH_2s (ch),
+       c->id);
+  GCCH_channel_incoming_destroy (ch);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Remove client's ports from the global hashmap on disconnect.
+ *
+ * @param cls Closure (unused).
+ * @param key Port.
+ * @param value the `struct CadetClient` to remove
+ * @return #GNUNET_OK, keep iterating.
+ */
+static int
+client_release_ports (void *cls,
+                      const struct GNUNET_HashCode *key,
+                      void *value)
+{
+  struct CadetClient *c = value;
+
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (open_ports,
+                                                       key,
+                                                       value));
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (c->ports,
+                                                       key,
+                                                       value));
+  return GNUNET_OK;
+}
+
+
+/**
+ * Callback called when a client disconnected from the service
+ *
+ * @param cls closure for the service
+ * @param client the client that disconnected
+ * @param internal_cls should be equal to @a c
+ */
+static void
+client_disconnect_cb (void *cls,
+                     struct GNUNET_SERVICE_Client *client,
+                     void *internal_cls)
+{
+  struct CadetClient *c = internal_cls;
+
+  GNUNET_assert (c->client == client);
+  c->shutting_down = GNUNET_YES;
+  if (NULL != c->own_channels)
+  {
+    GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
+                                             &own_channel_destroy_iterator,
+                                             c);
+    GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
+  }
+  if (NULL != c->incoming_channels)
+  {
+    GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
+                                             &incoming_channel_destroy_iterator,
+                                             c);
+    GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
+  }
+  if (NULL != c->ports)
+  {
+    GNUNET_CONTAINER_multihashmap_iterate (c->ports,
+                                           &client_release_ports,
+                                           c);
+    GNUNET_CONTAINER_multihashmap_destroy (c->ports);
+  }
+  GNUNET_CONTAINER_DLL_remove (clients_head,
+                               clients_tail,
+                               c);
+  GNUNET_STATISTICS_update (stats,
+                            "# clients",
+                            -1,
+                            GNUNET_NO);
+  GNUNET_free (c);
+}
+
+
+/**
+ * Setup CADET internals.
+ *
+ * @param cls closure
+ * @param server the initialized server
+ * @param c configuration to use
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *c,
+     struct GNUNET_SERVICE_Handle *service)
+{
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c,
+                                             "CADET",
+                                             "RATCHET_MESSAGES",
+                                             &ratchet_messages))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+                               "CADET",
+                               "RATCHET_MESSAGES",
+                               "needs to be a number");
+    ratchet_messages = 64;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (c,
+                                           "CADET",
+                                           "RATCHET_TIME",
+                                           &ratchet_time))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+                               "CADET",
+                               "RATCHET_TIME",
+                               "need delay value");
+    ratchet_time = GNUNET_TIME_UNIT_HOURS;
+  }
+
+  my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
+  if (NULL == my_private_key)
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
+                                      &my_full_id.public_key);
+  stats = GNUNET_STATISTICS_create ("cadet",
+                                    c);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                NULL);
+  ats_ch = GNUNET_ATS_connectivity_init (c);
+  /* FIXME: optimize code to allow GNUNET_YES here! */
+  open_ports = GNUNET_CONTAINER_multihashmap_create (16,
+                                                     GNUNET_NO);
+  loose_channels = GNUNET_CONTAINER_multihashmap_create (16,
+                                                         GNUNET_NO);
+  peers = GNUNET_CONTAINER_multipeermap_create (16,
+                                                GNUNET_YES);
+  connections = GNUNET_CONTAINER_multishortmap_create (256,
+                                                       GNUNET_YES);
+  GCH_init (c);
+  GCD_init (c);
+  GCO_init (c);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "CADET starting at peer %s\n",
+              GNUNET_i2s (&my_full_id));
+
+}
+
+
+/**
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN
+("cadet",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_fixed_size (port_open,
+                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
+                          struct GNUNET_CADET_PortMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (port_close,
+                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
+                          struct GNUNET_CADET_PortMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (channel_create,
+                          GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
+                          struct GNUNET_CADET_ChannelOpenMessageMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (channel_destroy,
+                          GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
+                          struct GNUNET_CADET_ChannelDestroyMessage,
+                          NULL),
+ GNUNET_MQ_hd_var_size (data,
+                        GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
+                        struct GNUNET_CADET_LocalData,
+                        NULL),
+ GNUNET_MQ_hd_fixed_size (ack,
+                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
+                          struct GNUNET_CADET_LocalAck,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (get_peers,
+                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
+                          struct GNUNET_MessageHeader,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (show_peer,
+                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
+                          struct GNUNET_CADET_LocalInfo,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (get_tunnels,
+                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
+                          struct GNUNET_MessageHeader,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (show_tunnel,
+                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
+                          struct GNUNET_CADET_LocalInfo,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (info_dump,
+                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP,
+                          struct GNUNET_MessageHeader,
+                          NULL),
+ GNUNET_MQ_handler_end ());
+
+/* end of gnunet-service-cadet-new.c */
diff --git a/src/cadet/gnunet-service-cadet-new.h b/src/cadet/gnunet-service-cadet-new.h
new file mode 100644 (file)
index 0000000..9f4667e
--- /dev/null
@@ -0,0 +1,264 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new.h
+ * @brief Information we track per peer.
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SERVICE_CADET_H
+#define GNUNET_SERVICE_CADET_H
+
+#include "gnunet_util_lib.h"
+#define NEW_CADET 1
+
+/**
+ * A client to the CADET service.  Each client gets a unique handle.
+ */
+struct CadetClient;
+
+/**
+ * A peer in the GNUnet network.  Each peer we care about must have one globally
+ * unique such handle within this process.
+ */
+struct CadetPeer;
+
+/**
+ * Tunnel from us to another peer.  There can only be at most one
+ * tunnel per peer.
+ */
+struct CadetTunnel;
+
+/**
+ * Entry in the message queue of a `struct CadetTunnel`.
+ */
+struct CadetTunnelQueueEntry;
+
+/**
+ * A path of peer in the GNUnet network.  There must only be at most
+ * once such path.  Paths may share disjoint prefixes, but must all
+ * end at a unique suffix.  Paths must also not be proper subsets of
+ * other existing paths.
+ */
+struct CadetPeerPath;
+
+/**
+ * Entry in a peer path.
+ */
+struct CadetPeerPathEntry
+{
+  /**
+   * DLL of paths where the same @e peer is at the same offset.
+   */
+  struct CadetPeerPathEntry *next;
+
+  /**
+   * DLL of paths where the same @e peer is at the same offset.
+   */
+  struct CadetPeerPathEntry *prev;
+
+  /**
+   * The peer at this offset of the path.
+   */
+  struct CadetPeer *peer;
+
+  /**
+   * Path this entry belongs to.
+   */
+  struct CadetPeerPath *path;
+
+  /**
+   * Connection using this path, or NULL for none.
+   */
+  struct CadetConnection *cc;
+
+  /**
+   * Path's historic score up to this point.  Basically, how often did
+   * we succeed or fail to use the path up to this entry in a
+   * connection.  Positive values indicate good experiences, negative
+   * values bad experiences.  Code updating the score must guard
+   * against overflows.
+   */
+  int score;
+
+};
+
+/**
+ * Entry in list of connections used by tunnel, with metadata.
+ */
+struct CadetTConnection
+{
+  /**
+   * Next in DLL.
+   */
+  struct CadetTConnection *next;
+
+  /**
+   * Prev in DLL.
+   */
+  struct CadetTConnection *prev;
+
+  /**
+   * Connection handle.
+   */
+  struct CadetConnection *cc;
+
+  /**
+   * Tunnel this connection belongs to.
+   */
+  struct CadetTunnel *t;
+
+  /**
+   * Creation time, to keep oldest connection alive.
+   */
+  struct GNUNET_TIME_Absolute created;
+
+  /**
+   * Connection throughput, to keep fastest connection alive.
+   */
+  uint32_t throughput;
+
+  /**
+   * Is the connection currently ready for transmission?
+   */
+  int is_ready;
+};
+
+
+/**
+ * Active path through the network (used by a tunnel).  There may
+ * be at most one connection per path.
+ */
+struct CadetConnection;
+
+/**
+ * Description of a segment of a `struct CadetConnection` at the
+ * intermediate peers.  Routes are basically entries in a peer's
+ * routing table for forwarding traffic.  At both endpoints, the
+ * routes are terminated by a `struct CadetConnection`, which knows
+ * the complete `struct CadetPath` that is formed by the individual
+ * routes.
+ */
+struct CadetRoute;
+
+/**
+ * Logical end-to-end conenction between clients.  There can be
+ * any number of channels between clients.
+ */
+struct CadetChannel;
+
+/**
+ * Handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Handle to communicate with ATS.
+ */
+extern struct GNUNET_ATS_ConnectivityHandle *ats_ch;
+
+/**
+ * Local peer own ID.
+ */
+extern struct GNUNET_PeerIdentity my_full_id;
+
+/**
+ * Own private key.
+ */
+extern struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
+
+/**
+ * All ports clients of this peer have opened.
+ */
+extern struct GNUNET_CONTAINER_MultiHashMap *open_ports;
+
+/**
+ * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
+ * hash codes to `struct CadetConnection` objects.
+ */
+extern struct GNUNET_CONTAINER_MultiShortmap *connections;
+
+/**
+ * Map from ports to channels where the ports were closed at the
+ * time we got the inbound connection.
+ * Indexed by port, contains `struct CadetChannel`.
+ */
+extern struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
+
+/**
+ * Map from PIDs to `struct CadetPeer` entries.
+ */
+extern struct GNUNET_CONTAINER_MultiPeerMap *peers;
+
+/**
+ * How many messages are needed to trigger an AXOLOTL ratchet advance.
+ */
+extern unsigned long long ratchet_messages;
+
+/**
+ * How long until we trigger a ratched advance due to time.
+ */
+extern struct GNUNET_TIME_Relative ratchet_time;
+
+
+
+/**
+ * Send a message to a client.
+ *
+ * @param c client to get the message
+ * @param env envelope with the message
+ */
+void
+GSC_send_to_client (struct CadetClient *c,
+                    struct GNUNET_MQ_Envelope *env);
+
+
+/**
+ * Bind incoming channel to this client, and notify client
+ * about incoming connection.
+ *
+ * @param c client to bind to
+ * @param ch channel to be bound
+ * @param dest peer that establishes the connection
+ * @param port port number
+ * @param options options
+ * @return local channel number assigned to the new client
+ */
+struct GNUNET_CADET_ClientChannelNumber
+GSC_bind (struct CadetClient *c,
+          struct CadetChannel *ch,
+          struct CadetPeer *dest,
+          const struct GNUNET_HashCode *port,
+          uint32_t options);
+
+
+/**
+ * Return identifier for a client as a string.
+ *
+ * @param c client to identify
+ * @return string for debugging
+ */
+const char *
+GSC_2s (struct CadetClient *c);
+
+
+#endif
diff --git a/src/cadet/gnunet-service-cadet-new_channel.c b/src/cadet/gnunet-service-cadet-new_channel.c
new file mode 100644 (file)
index 0000000..5acd098
--- /dev/null
@@ -0,0 +1,1077 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_channel.c
+ * @brief logical links between CADET clients
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - estimate max bandwidth using bursts and use to optimize
+ *   transmission rate(s)
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "cadet.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet-service-cadet-new.h"
+#include "gnunet-service-cadet-new_channel.h"
+#include "gnunet-service-cadet-new_connection.h"
+#include "gnunet-service-cadet-new_tunnels.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "gnunet-service-cadet-new_paths.h"
+
+#define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
+
+/**
+ * How long do we initially wait before retransmitting?
+ */
+#define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250)
+
+/**
+ * How long do we wait before dropping state about incoming
+ * connection to closed port?
+ */
+#define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
+
+
+/**
+ * All the states a connection can be in.
+ */
+enum CadetChannelState
+{
+  /**
+   * Uninitialized status, should never appear in operation.
+   */
+  CADET_CHANNEL_NEW,
+
+  /**
+   * Connection create message sent, waiting for ACK.
+   */
+  CADET_CHANNEL_CREATE_SENT,
+
+  /**
+   * Connection confirmed, ready to carry traffic.
+   */
+  CADET_CHANNEL_READY
+};
+
+
+/**
+ * Info needed to retry a message in case it gets lost.
+ * Note that we DO use this structure also for unreliable
+ * messages.
+ */
+struct CadetReliableMessage
+{
+  /**
+   * Double linked list, FIFO style
+   */
+  struct CadetReliableMessage *next;
+
+  /**
+   * Double linked list, FIFO style
+   */
+  struct CadetReliableMessage *prev;
+
+  /**
+   * Which channel is this message in?
+   */
+  struct CadetChannel *ch;
+
+  /**
+   * Entry in the tunnels queue for this message, NULL if it has left
+   * the tunnel.  Used to cancel transmission in case we receive an
+   * ACK in time.
+   */
+  struct CadetTunnelQueueEntry *qe;
+
+  /**
+   * How soon should we retry if we fail to get an ACK?
+   * Messages in the queue are sorted by this value.
+   */
+  struct GNUNET_TIME_Absolute next_retry;
+
+  /**
+   * How long do we wait for an ACK after transmission?
+   * Use for the back-off calculation.
+   */
+  struct GNUNET_TIME_Relative retry_delay;
+
+  /**
+   * Data message we are trying to send.
+   */
+  struct GNUNET_CADET_ChannelAppDataMessage data_message;
+
+  /* followed by variable-size payload */
+};
+
+
+/**
+ * List of received out-of-order data messages.
+ */
+struct CadetOutOfOrderMessage
+{
+  /**
+   * Double linked list, FIFO style
+   */
+  struct CadetOutOfOrderMessage *next;
+
+  /**
+   * Double linked list, FIFO style
+   */
+  struct CadetOutOfOrderMessage *prev;
+
+  /**
+   * ID of the message (ACK needed to free)
+   */
+  struct ChannelMessageIdentifier mid;
+
+  /**
+   * The envelope with the payload of the out-of-order message
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+};
+
+
+/**
+ * Struct containing all information regarding a channel to a remote client.
+ */
+struct CadetChannel
+{
+  /**
+   * Tunnel this channel is in.
+   */
+  struct CadetTunnel *t;
+
+  /**
+   * Last entry in the tunnel's queue relating to control messages
+   * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
+   * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK).  Used to cancel
+   * transmission in case we receive updated information.
+   */
+  struct CadetTunnelQueueEntry *last_control_qe;
+
+  /**
+   * Client owner of the tunnel, if any.
+   * (Used if this channel represends the initiating end of the tunnel.)
+   */
+  struct CadetClient *owner;
+
+  /**
+   * Client destination of the tunnel, if any.
+   * (Used if this channel represents the listening end of the tunnel.)
+   */
+  struct CadetClient *dest;
+
+  /**
+   * Head of DLL of messages sent and not yet ACK'd.
+   */
+  struct CadetReliableMessage *head_sent;
+
+  /**
+   * Tail of DLL of messages sent and not yet ACK'd.
+   */
+  struct CadetReliableMessage *tail_sent;
+
+  /**
+   * Head of DLL of messages received out of order or while client was unready.
+   */
+  struct CadetOutOfOrderMessage *head_recv;
+
+  /**
+   * Tail DLL of messages received out of order or while client was unready.
+   */
+  struct CadetOutOfOrderMessage *tail_recv;
+
+  /**
+   * Task to resend/poll in case no ACK is received.
+   */
+  struct GNUNET_SCHEDULER_Task *retry_task;
+
+  /**
+   * Last time the channel was used
+   */
+  struct GNUNET_TIME_Absolute timestamp;
+
+  /**
+   * Destination port of the channel.
+   */
+  struct GNUNET_HashCode port;
+
+  /**
+   * Counter for exponential backoff.
+   */
+  struct GNUNET_TIME_Relative retry_time;
+
+  /**
+   * How long does it usually take to get an ACK.
+   */
+  struct GNUNET_TIME_Relative expected_delay;
+
+  /**
+   * Bitfield of already-received messages past @e mid_recv.
+   */
+  uint64_t mid_futures;
+
+  /**
+   * Next MID expected for incoming traffic.
+   */
+  struct ChannelMessageIdentifier mid_recv;
+
+  /**
+   * Next MID to use for outgoing traffic.
+   */
+  struct ChannelMessageIdentifier mid_send;
+
+  /**
+   * Total (reliable) messages pending ACK for this channel.
+   */
+  unsigned int pending_messages;
+
+  /**
+   * Maximum (reliable) messages pending ACK for this channel
+   * before we throttle the client.
+   */
+  unsigned int max_pending_messages;
+
+  /**
+   * Number identifying this channel in its tunnel.
+   */
+  struct GNUNET_CADET_ChannelTunnelNumber gid;
+
+  /**
+   * Local tunnel number for local client owning the channel.
+   * ( >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
+   */
+  struct GNUNET_CADET_ClientChannelNumber lid;
+
+  /**
+   * Channel state.
+   */
+  enum CadetChannelState state;
+
+  /**
+   * Can we send data to the client?
+   */
+  int client_ready;
+
+  /**
+   * Can the client send data to us?
+   */
+  int client_allowed;
+
+  /**
+   * Is the tunnel bufferless (minimum latency)?
+   */
+  int nobuffer;
+
+  /**
+   * Is the tunnel reliable?
+   */
+  int reliable;
+
+  /**
+   * Is the tunnel out-of-order?
+   */
+  int out_of_order;
+
+  /**
+   * Flag to signal the destruction of the channel.  If this is set to
+   * #GNUNET_YES the channel will be destroyed once the queue is
+   * empty.
+   */
+  int destroy;
+
+};
+
+
+
+/**
+ * Get the static string for identification of the channel.
+ *
+ * @param ch Channel.
+ *
+ * @return Static string with the channel IDs.
+ */
+const char *
+GCCH_2s (const struct CadetChannel *ch)
+{
+  static char buf[128];
+
+  if (NULL == ch)
+    return "(NULL Channel)";
+  GNUNET_snprintf (buf,
+                   sizeof (buf),
+                   "%s:%s gid:%X (%X)",
+                   GCT_2s (ch->t),
+                   GNUNET_h2s (&ch->port),
+                   ch->gid,
+                   ntohl (ch->lid.channel_of_client));
+  return buf;
+}
+
+
+/**
+ * Get the channel's public ID.
+ *
+ * @param ch Channel.
+ *
+ * @return ID used to identify the channel with the remote peer.
+ */
+struct GNUNET_CADET_ChannelTunnelNumber
+GCCH_get_id (const struct CadetChannel *ch)
+{
+  return ch->gid;
+}
+
+
+/**
+ * Destroy the given channel.
+ *
+ * @param ch channel to destroy
+ */
+static void
+channel_destroy (struct CadetChannel *ch)
+{
+  struct CadetReliableMessage *crm;
+  struct CadetOutOfOrderMessage *com;
+
+  while (NULL != (crm = ch->head_sent))
+  {
+    GNUNET_assert (ch == crm->ch);
+    if (NULL != crm->qe)
+    {
+      GCT_send_cancel (crm->qe);
+      crm->qe = NULL;
+    }
+    GNUNET_CONTAINER_DLL_remove (ch->head_sent,
+                                 ch->tail_sent,
+                                 crm);
+    GNUNET_free (crm);
+  }
+  while (NULL != (com = ch->head_recv))
+  {
+    GNUNET_CONTAINER_DLL_remove (ch->head_recv,
+                                 ch->tail_recv,
+                                 com);
+    GNUNET_MQ_discard (com->env);
+    GNUNET_free (com);
+  }
+  if (NULL != ch->last_control_qe)
+  {
+    GCT_send_cancel (ch->last_control_qe);
+    ch->last_control_qe = NULL;
+  }
+  if (NULL != ch->retry_task)
+  {
+    GNUNET_SCHEDULER_cancel (ch->retry_task);
+    ch->retry_task = NULL;
+  }
+  GCT_remove_channel (ch->t,
+                      ch,
+                      ch->gid);
+  GNUNET_free (ch);
+}
+
+
+/**
+ * Send a channel create message.
+ *
+ * @param cls Channel for which to send.
+ */
+static void
+send_create (void *cls);
+
+
+/**
+ * Function called once the tunnel confirms that we sent the
+ * create message.  Delays for a bit until we retry.
+ *
+ * @param cls our `struct CadetChannel`.
+ */
+static void
+create_sent_cb (void *cls)
+{
+  struct CadetChannel *ch = cls;
+
+  ch->last_control_qe = NULL;
+  ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
+  ch->retry_task = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
+                                                 &send_create,
+                                                 ch);
+}
+
+
+/**
+ * Send a channel create message.
+ *
+ * @param cls Channel for which to send.
+ */
+static void
+send_create (void *cls)
+{
+  struct CadetChannel *ch = cls;
+  struct GNUNET_CADET_ChannelOpenMessage msgcc;
+  uint32_t options;
+
+  options = 0;
+  if (ch->nobuffer)
+    options |= GNUNET_CADET_OPTION_NOBUFFER;
+  if (ch->reliable)
+    options |= GNUNET_CADET_OPTION_RELIABLE;
+  if (ch->out_of_order)
+    options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
+  msgcc.header.size = htons (sizeof (msgcc));
+  msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
+  msgcc.opt = htonl (options);
+  msgcc.port = ch->port;
+  msgcc.chid = ch->gid;
+  ch->state = CADET_CHANNEL_CREATE_SENT;
+  ch->last_control_qe = GCT_send (ch->t,
+                                  &msgcc.header,
+                                  &create_sent_cb,
+                                  ch);
+}
+
+
+/**
+ * Create a new channel.
+ *
+ * @param owner local client owning the channel
+ * @param owner_id local chid of this channel at the @a owner
+ * @param destination peer to which we should build the channel
+ * @param port desired port at @a destination
+ * @param options options for the channel
+ * @return handle to the new channel
+ */
+struct CadetChannel *
+GCCH_channel_local_new (struct CadetClient *owner,
+                        struct GNUNET_CADET_ClientChannelNumber owner_id,
+                        struct CadetPeer *destination,
+                        const struct GNUNET_HashCode *port,
+                        uint32_t options)
+{
+  struct CadetChannel *ch;
+
+  ch = GNUNET_new (struct CadetChannel);
+  ch->max_pending_messages = 32; /* FIXME: allow control via options
+                                    or adjust dynamically... */
+  ch->owner = owner;
+  ch->lid = owner_id;
+  ch->port = *port;
+  ch->t = GCP_get_tunnel (destination,
+                          GNUNET_YES);
+  ch->gid = GCT_add_channel (ch->t,
+                             ch);
+  ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
+  ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
+  ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
+  ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
+  ch->retry_task = GNUNET_SCHEDULER_add_now (&send_create,
+                                             ch);
+  GNUNET_STATISTICS_update (stats,
+                            "# channels",
+                            1,
+                            GNUNET_NO);
+  return ch;
+}
+
+
+/**
+ * We had an incoming channel to a port that is closed.
+ * It has not been opened for a while, drop it.
+ *
+ * @param cls the channel to drop
+ */
+static void
+timeout_closed_cb (void *cls)
+{
+  struct CadetChannel *ch = cls;
+
+  ch->retry_task = NULL;
+  channel_destroy (ch);
+}
+
+
+/**
+ * Create a new channel.
+ *
+ * @param t tunnel to the remote peer
+ * @param gid identifier of this channel in the tunnel
+ * @param port desired local port
+ * @param options options for the channel
+ * @return handle to the new channel
+ */
+struct CadetChannel *
+GCCH_channel_incoming_new (struct CadetTunnel *t,
+                           struct GNUNET_CADET_ChannelTunnelNumber gid,
+                           const struct GNUNET_HashCode *port,
+                           uint32_t options)
+{
+  struct CadetChannel *ch;
+  struct CadetClient *c;
+
+  ch = GNUNET_new (struct CadetChannel);
+  ch->max_pending_messages = 32; /* FIXME: allow control via options
+                                    or adjust dynamically... */
+  ch->port = *port;
+  ch->t = t;
+  ch->gid = gid;
+  ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
+  ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
+  ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
+  ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
+  GNUNET_STATISTICS_update (stats,
+                            "# channels",
+                            1,
+                            GNUNET_NO);
+
+  c = GNUNET_CONTAINER_multihashmap_get (open_ports,
+                                         port);
+  if (NULL == c)
+  {
+    /* port closed, wait for it to possibly open */
+    (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
+                                              port,
+                                              ch,
+                                              GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+    ch->retry_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
+                                                   &timeout_closed_cb,
+                                                   ch);
+  }
+  else
+  {
+    GCCH_bind (ch,
+               c);
+  }
+  GNUNET_STATISTICS_update (stats,
+                            "# channels",
+                            1,
+                            GNUNET_NO);
+  return ch;
+}
+
+
+/**
+ * Function called once the tunnel confirms that we sent the
+ * ACK message.  Just remembers it was sent, we do not expect
+ * ACKs for ACKs ;-).
+ *
+ * @param cls our `struct CadetChannel`.
+ */
+static void
+send_ack_cb (void *cls)
+{
+  struct CadetChannel *ch = cls;
+
+  ch->last_control_qe = NULL;
+}
+
+
+/**
+ * Compute and send the current ACK to the other peer.
+ *
+ * @param ch channel to send the ACK for
+ */
+static void
+send_channel_ack (struct CadetChannel *ch)
+{
+  struct GNUNET_CADET_ChannelDataAckMessage msg;
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
+  msg.header.size = htons (sizeof (msg));
+  msg.gid = ch->gid;
+  msg.mid.mid = htonl (ntohl (ch->mid_recv.mid) - 1);
+  msg.futures = GNUNET_htonll (ch->mid_futures);
+  if (NULL != ch->last_control_qe)
+    GCT_send_cancel (ch->last_control_qe);
+  ch->last_control_qe = GCT_send (ch->t,
+                                  &msg.header,
+                                  &send_ack_cb,
+                                  ch);
+}
+
+
+/**
+ * Send our initial ACK to the client confirming that the
+ * connection is up.
+ *
+ * @param cls the `struct CadetChannel`
+ */
+static void
+send_connect_ack (void *cls)
+{
+  struct CadetChannel *ch = cls;
+
+  ch->retry_task = NULL;
+  send_channel_ack (ch);
+}
+
+
+/**
+ * A client is bound to the port that we have a channel
+ * open to.  Send the acknowledgement for the connection
+ * request and establish the link with the client.
+ *
+ * @param ch open incoming channel
+ * @param c client listening on the respective port
+ */
+void
+GCCH_bind (struct CadetChannel *ch,
+           struct CadetClient *c)
+{
+  uint32_t options;
+
+  if (NULL != ch->retry_task)
+  {
+    /* there might be a timeout task here */
+    GNUNET_SCHEDULER_cancel (ch->retry_task);
+    ch->retry_task = NULL;
+  }
+  options = 0;
+  if (ch->nobuffer)
+    options |= GNUNET_CADET_OPTION_NOBUFFER;
+  if (ch->reliable)
+    options |= GNUNET_CADET_OPTION_RELIABLE;
+  if (ch->out_of_order)
+    options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
+  ch->dest = c;
+  ch->lid = GSC_bind (c,
+                      ch,
+                      GCT_get_destination (ch->t),
+                      &ch->port,
+                      options);
+  ch->mid_recv.mid = htonl (1); /* The CONNECT counts as message 0! */
+
+  /* notify other peer that we accepted the connection */
+  ch->retry_task = GNUNET_SCHEDULER_add_now (&send_connect_ack,
+                                             ch);
+}
+
+
+/**
+ * Destroy locally created channel.  Called by the
+ * local client, so no need to tell the client.
+ *
+ * @param ch channel to destroy
+ */
+void
+GCCH_channel_local_destroy (struct CadetChannel *ch)
+{
+  if (GNUNET_YES == ch->destroy)
+  {
+    /* other end already destroyed, with the local client gone, no need
+       to finish transmissions, just destroy immediately. */
+    channel_destroy (ch);
+    return;
+  }
+  if (NULL != ch->head_sent)
+  {
+    /* allow send queue to train first */
+    ch->destroy = GNUNET_YES;
+    return;
+  }
+  /* Nothing left to do, just finish destruction */
+  channel_destroy (ch);
+}
+
+
+/**
+ * Destroy channel that was incoming.  Called by the
+ * local client, so no need to tell the client.
+ *
+ * @param ch channel to destroy
+ */
+void
+GCCH_channel_incoming_destroy (struct CadetChannel *ch)
+{
+  if (GNUNET_YES == ch->destroy)
+  {
+    /* other end already destroyed, with the remote client gone, no need
+       to finish transmissions, just destroy immediately. */
+    channel_destroy (ch);
+    return;
+  }
+  if (NULL != ch->head_recv)
+  {
+    /* allow local client to see all data first */
+    ch->destroy = GNUNET_YES;
+    return;
+  }
+  /* Nothing left to do, just finish destruction */
+  channel_destroy (ch);
+}
+
+
+/**
+ * Destroy channel, based on the other peer closing the
+ * connection.  Also needs to remove this channel from
+ * the tunnel.
+ *
+ * FIXME: need to make it possible to defer destruction until we have
+ * received all messages up to the destroy, and right now the destroy
+ * message (and this API) fails to give is the information we need!
+ *
+ * FIXME: also need to know if the other peer got a destroy from
+ * us before!
+ *
+ * @param ch channel to destroy
+ */
+void
+GCCH_channel_remote_destroy (struct CadetChannel *ch)
+{
+  GNUNET_break (0); // FIXME!
+}
+
+
+/**
+ * Function called once the tunnel has sent one of our messages.
+ * If the message is unreliable, simply frees the `crm`. If the
+ * message was reliable, calculate retransmission time and
+ * wait for ACK (or retransmit).
+ *
+ * @param cls the `struct CadetReliableMessage` that was sent
+ */
+static void
+data_sent_cb (void *cls);
+
+
+/**
+ * We need to retry a transmission, the last one took too long to
+ * be acknowledged.
+ *
+ * @param cls the `struct CadetChannel` where we need to retransmit
+ */
+static void
+retry_transmission (void *cls)
+{
+  struct CadetChannel *ch = cls;
+  struct CadetReliableMessage *crm = ch->head_sent;
+
+  GNUNET_assert (NULL == crm->qe);
+  crm->qe = GCT_send (ch->t,
+                      &crm->data_message.header,
+                      &data_sent_cb,
+                      crm);
+}
+
+
+/**
+ * Check if we can now allow the client to transmit, and if so,
+ * let the client know about it.
+ *
+ * @param ch channel to check
+ */
+static void
+GCCH_check_allow_client (struct CadetChannel *ch)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_LocalAck *msg;
+
+  if (GNUNET_YES == ch->client_allowed)
+    return; /* client already allowed! */
+  if (CADET_CHANNEL_READY != ch->state)
+  {
+    /* destination did not yet ACK our CREATE! */
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Channel %s not yet ready, throttling client until ACK.\n",
+         GCCH_2s (ch));
+    return;
+  }
+  if (ch->pending_messages > ch->max_pending_messages)
+  {
+    /* Too many messages in queue. */
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Message queue still too long on channel %s, throttling client until ACK.\n",
+         GCCH_2s (ch));
+    return;
+  }
+  if ( (NULL != ch->head_sent) &&
+       (64 <= ntohl (ch->mid_send.mid) - ntohl (ch->head_sent->data_message.mid.mid)) )
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Gap in ACKs too big on channel %s, throttling client until ACK.\n",
+         GCCH_2s (ch));
+    return;
+  }
+  ch->client_allowed = GNUNET_YES;
+
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Sending local ack to channel %s client\n",
+       GCCH_2s (ch));
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
+  msg->channel_id = ch->lid;
+  GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
+                      env);
+}
+
+
+/**
+ * Function called once the tunnel has sent one of our messages.
+ * If the message is unreliable, simply frees the `crm`. If the
+ * message was reliable, calculate retransmission time and
+ * wait for ACK (or retransmit).
+ *
+ * @param cls the `struct CadetReliableMessage` that was sent
+ */
+static void
+data_sent_cb (void *cls)
+{
+  struct CadetReliableMessage *crm = cls;
+  struct CadetChannel *ch = crm->ch;
+  struct CadetReliableMessage *off;
+
+  crm->qe = NULL;
+  GNUNET_CONTAINER_DLL_remove (ch->head_sent,
+                               ch->tail_sent,
+                               crm);
+  if (GNUNET_NO == ch->reliable)
+  {
+    GNUNET_free (crm);
+    ch->pending_messages--;
+    GCCH_check_allow_client (ch);
+    return;
+  }
+  if (0 == crm->retry_delay.rel_value_us)
+    crm->retry_delay = ch->expected_delay;
+  crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
+
+  /* find position for re-insertion into the DLL */
+  if ( (NULL == ch->head_sent) ||
+       (crm->next_retry.abs_value_us < ch->head_sent->next_retry.abs_value_us) )
+  {
+    /* insert at HEAD, also (re)schedule retry task! */
+    GNUNET_CONTAINER_DLL_insert (ch->head_sent,
+                                 ch->tail_sent,
+                                 crm);
+    if (NULL != ch->retry_task)
+      GNUNET_SCHEDULER_cancel (ch->retry_task);
+    ch->retry_task = GNUNET_SCHEDULER_add_delayed (crm->retry_delay,
+                                                   &retry_transmission,
+                                                   ch);
+    return;
+  }
+  for (off = ch->head_sent; NULL != off; off = off->next)
+    if (crm->next_retry.abs_value_us < off->next_retry.abs_value_us)
+      break;
+  if (NULL == off)
+  {
+    /* insert at tail */
+    GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent,
+                                      ch->tail_sent,
+                                      crm);
+  }
+  else
+  {
+    /* insert before off */
+    GNUNET_CONTAINER_DLL_insert_after (ch->head_sent,
+                                       ch->tail_sent,
+                                       off->prev,
+                                       crm);
+  }
+}
+
+
+/**
+ * Handle data given by a client.
+ *
+ * Check whether the client is allowed to send in this tunnel, save if
+ * channel is reliable and send an ACK to the client if there is still
+ * buffer space in the tunnel.
+ *
+ * @param ch Channel.
+ * @param message payload to transmit.
+ * @return #GNUNET_OK if everything goes well,
+ *         #GNUNET_SYSERR in case of an error.
+ */
+int
+GCCH_handle_local_data (struct CadetChannel *ch,
+                        const struct GNUNET_MessageHeader *message)
+{
+  uint16_t payload_size = ntohs (message->size);
+  struct CadetReliableMessage *crm;
+
+  if (GNUNET_NO == ch->client_allowed)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  ch->client_allowed = GNUNET_NO;
+  ch->pending_messages++;
+
+  /* Everything is correct, send the message. */
+  crm = GNUNET_malloc (sizeof (*crm) + payload_size);
+  crm->ch = ch;
+  crm->data_message.header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + payload_size);
+  crm->data_message.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
+  ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
+  crm->data_message.mid = ch->mid_send;
+  crm->data_message.gid = ch->gid;
+  GNUNET_memcpy (&crm[1],
+                 message,
+                 payload_size);
+  GNUNET_CONTAINER_DLL_insert (ch->head_sent,
+                               ch->tail_sent,
+                               crm);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Sending %u bytes from local client to channel %s\n",
+       payload_size,
+       GCCH_2s (ch));
+  crm->qe = GCT_send (ch->t,
+                      &crm->data_message.header,
+                      &data_sent_cb,
+                      crm);
+  GCCH_check_allow_client (ch);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Try to deliver messages to the local client, if it is ready for more.
+ *
+ * @param ch channel to process
+ */
+static void
+send_client_buffered_data (struct CadetChannel *ch)
+{
+  struct CadetOutOfOrderMessage *com;
+
+  if (GNUNET_NO == ch->client_ready)
+    return; /* client not ready */
+  com = ch->head_recv;
+  if (NULL == com)
+    return; /* none pending */
+  if ( (com->mid.mid != ch->mid_recv.mid) &&
+       (GNUNET_NO == ch->out_of_order) )
+    return; /* missing next one in-order */
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Passing payload message to client on channel %s\n",
+              GCCH_2s (ch));
+
+  /* all good, pass next message to client */
+  GNUNET_CONTAINER_DLL_remove (ch->head_recv,
+                               ch->tail_recv,
+                               com);
+  ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
+  ch->mid_futures >>= 1; /* equivalent to division by 2 */
+  GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
+                      com->env);
+  GNUNET_free (com);
+  if ( (0xFFULL == (ch->mid_futures & 0xFFULL)) &&
+       (GNUNET_YES == ch->reliable) )
+  {
+    /* The next 15 messages were also already received (0xFF), this
+       suggests that the sender may be blocked on flow control
+       urgently waiting for an ACK from us. (As we have an inherent
+       maximum of 64 bits, and 15 is getting too close for comfort.)
+       So we should send one now. */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sender on channel %s likely blocked on flow-control, sending ACK now.\n",
+                GCCH_2s (ch));
+    if (GNUNET_YES == ch->reliable)
+      send_channel_ack (ch);
+  }
+
+  if (NULL != ch->head_recv)
+    return;
+  if (GNUNET_NO == ch->destroy)
+    return;
+  channel_destroy (ch);
+}
+
+
+/**
+ * Handle ACK from client on local channel.
+ *
+ * @param ch channel to destroy
+ */
+void
+GCCH_handle_local_ack (struct CadetChannel *ch)
+{
+  ch->client_ready = GNUNET_YES;
+  send_client_buffered_data (ch);
+}
+
+
+#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
+
+
+/**
+ * Log channel info.
+ *
+ * @param ch Channel.
+ * @param level Debug level to use.
+ */
+void
+GCCH_debug (struct CadetChannel *ch,
+            enum GNUNET_ErrorType level)
+{
+  int do_log;
+
+  do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
+                                       "cadet-chn",
+                                       __FILE__, __FUNCTION__, __LINE__);
+  if (0 == do_log)
+    return;
+
+  if (NULL == ch)
+  {
+    LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
+    return;
+  }
+  LOG2 (level,
+        "CHN Channel %s:%X (%p)\n",
+        GCT_2s (ch->t),
+        ch->gid,
+        ch);
+  if (NULL != ch->owner)
+  {
+    LOG2 (level,
+          "CHN origin %s ready %s local-id: %u\n",
+          GSC_2s (ch->owner),
+          ch->client_ready ? "YES" : "NO",
+          ntohl (ch->lid.channel_of_client));
+  }
+  if (NULL != ch->dest)
+  {
+    LOG2 (level,
+          "CHN destination %s ready %s local-id: %u\n",
+          GSC_2s (ch->dest),
+          ch->client_ready ? "YES" : "NO",
+          ntohl (ch->lid.channel_of_client));
+  }
+  LOG2 (level,
+        "CHN  Message IDs recv: %d (%LLX), send: %d\n",
+        ntohl (ch->mid_recv.mid),
+        (unsigned long long) ch->mid_futures,
+        ntohl (ch->mid_send.mid));
+}
+
+
+
+/* end of gnunet-service-cadet-new_channel.c */
diff --git a/src/cadet/gnunet-service-cadet-new_channel.h b/src/cadet/gnunet-service-cadet-new_channel.h
new file mode 100644 (file)
index 0000000..8caa254
--- /dev/null
@@ -0,0 +1,191 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_channel.h
+ * @brief GNUnet CADET service with encryption
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SERVICE_CADET_CHANNEL_H
+#define GNUNET_SERVICE_CADET_CHANNEL_H
+
+#include "gnunet-service-cadet-new.h"
+#include "gnunet-service-cadet-new_peer.h"
+
+
+/**
+ * A channel is a bidirectional connection between two CADET
+ * clients.  Communiation can be reliable, unreliable, in-order
+ * or out-of-order.  One client is the "local" client, this
+ * one initiated the connection.   The other client is the
+ * "incoming" client, this one listened on a port to accept
+ * the connection from the "local" client.
+ */
+struct CadetChannel;
+
+
+/**
+ * Get the static string for identification of the channel.
+ *
+ * @param ch Channel.
+ *
+ * @return Static string with the channel IDs.
+ */
+const char *
+GCCH_2s (const struct CadetChannel *ch);
+
+
+/**
+ * Log channel info.
+ *
+ * @param ch Channel.
+ * @param level Debug level to use.
+ */
+void
+GCCH_debug (struct CadetChannel *ch,
+            enum GNUNET_ErrorType level);
+
+
+/**
+ * Get the channel's public ID.
+ *
+ * @param ch Channel.
+ *
+ * @return ID used to identify the channel with the remote peer.
+ */
+struct GNUNET_CADET_ChannelTunnelNumber
+GCCH_get_id (const struct CadetChannel *ch);
+
+
+/**
+ * Create a new channel.
+ *
+ * @param owner local client owning the channel
+ * @param owner_id local chid of this channel at the @a owner
+ * @param destination peer to which we should build the channel
+ * @param port desired port at @a destination
+ * @param options options for the channel
+ * @return handle to the new channel
+ */
+struct CadetChannel *
+GCCH_channel_local_new (struct CadetClient *owner,
+                        struct GNUNET_CADET_ClientChannelNumber owner_id,
+                        struct CadetPeer *destination,
+                        const struct GNUNET_HashCode *port,
+                        uint32_t options);
+
+
+/**
+ * A client is bound to the port that we have a channel
+ * open to.  Send the acknowledgement for the connection
+ * request and establish the link with the client.
+ *
+ * @param ch open incoming channel
+ * @param c client listening on the respective port
+ */
+void
+GCCH_bind (struct CadetChannel *ch,
+           struct CadetClient *c);
+
+
+
+/**
+ * Destroy locally created channel.  Called by the
+ * local client, so no need to tell the client.
+ *
+ * @param ch channel to destroy
+ */
+void
+GCCH_channel_local_destroy (struct CadetChannel *ch);
+
+
+/**
+ * Create a new channel.
+ *
+ * @param t tunnel to the remote peer
+ * @param gid identifier of this channel in the tunnel
+ * @param origin peer to who initiated the channel
+ * @param port desired local port
+ * @param options options for the channel
+ * @return handle to the new channel
+ */
+struct CadetChannel *
+GCCH_channel_incoming_new (struct CadetTunnel *t,
+                           struct GNUNET_CADET_ChannelTunnelNumber gid,
+                           const struct GNUNET_HashCode *port,
+                           uint32_t options);
+
+
+/**
+ * Destroy channel that was incoming.  Called by the
+ * local client, so no need to tell the client.
+ *
+ * @param ch channel to destroy
+ */
+void
+GCCH_channel_incoming_destroy (struct CadetChannel *ch);
+
+
+/**
+ * Destroy channel, based on the other peer closing the
+ * connection.  Also needs to remove this channel from
+ * the tunnel.
+ *
+ * FIXME: need to make it possible to defer destruction until we have
+ * received all messages up to the destroy, and right now the destroy
+ * message (and this API) fails to give is the information we need!
+ *
+ * FIXME: also need to know if the other peer got a destroy from
+ * us before!
+ *
+ * @param ch channel to destroy
+ */
+void
+GCCH_channel_remote_destroy (struct CadetChannel *ch);
+
+
+/**
+ * Handle data given by a client.
+ *
+ * Check whether the client is allowed to send in this tunnel, save if
+ * channel is reliable and send an ACK to the client if there is still
+ * buffer space in the tunnel.
+ *
+ * @param ch Channel.
+ * @param message payload to transmit.
+ * @return #GNUNET_OK if everything goes well,
+ *         #GNUNET_SYSERR in case of an error.
+ */
+int
+GCCH_handle_local_data (struct CadetChannel *ch,
+                        const struct GNUNET_MessageHeader *message);
+
+
+/**
+ * Handle ACK from client on local channel.
+ *
+ * @param ch channel to destroy
+ */
+void
+GCCH_handle_local_ack (struct CadetChannel *ch);
+
+#endif
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c
new file mode 100644 (file)
index 0000000..bf88d78
--- /dev/null
@@ -0,0 +1,665 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_connection.c
+ * @brief management of CORE-level end-to-end connections; establishes
+ *        end-to-end routes and transmits messages along the route
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - keepalive messages
+ * - keep performance metrics (?)
+ */
+#include "platform.h"
+#include "gnunet-service-cadet-new_channel.h"
+#include "gnunet-service-cadet-new_connection.h"
+#include "gnunet-service-cadet-new_paths.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "gnunet-service-cadet-new_tunnels.h"
+#include "gnunet_cadet_service.h"
+#include "cadet_protocol.h"
+
+
+/**
+ * All the states a connection can be in.
+ */
+enum CadetConnectionState
+{
+  /**
+   * Uninitialized status, we have not yet even gotten the message queue.
+   */
+  CADET_CONNECTION_NEW,
+
+  /**
+   * Connection create message in queue, awaiting transmission by CORE.
+   */
+  CADET_CONNECTION_SENDING_CREATE,
+
+  /**
+   * Connection create message sent, waiting for ACK.
+   */
+  CADET_CONNECTION_SENT,
+
+  /**
+   * We are an inbound connection, and received a CREATE. Need to
+   * send an CREATE_ACK back.
+   */
+  CADET_CONNECTION_CREATE_RECEIVED,
+
+  /**
+   * Connection confirmed, ready to carry traffic.
+   */
+  CADET_CONNECTION_READY
+
+};
+
+
+/**
+ * Low-level connection to a destination.
+ */
+struct CadetConnection
+{
+
+  /**
+   * ID of the connection.
+   */
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
+
+  /**
+   * To which peer does this connection go?
+   */
+  struct CadetPeer *destination;
+
+  /**
+   * Which tunnel is using this connection?
+   */
+  struct CadetTConnection *ct;
+
+  /**
+   * Path we are using to our destination.
+   */
+  struct CadetPeerPath *path;
+
+  /**
+   * Pending message, NULL if we are ready to transmit.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * Handle for calling #GCP_request_mq_cancel() once we are finished.
+   */
+  struct GCP_MessageQueueManager *mq_man;
+
+  /**
+   * Task for connection maintenance.
+   */
+  struct GNUNET_SCHEDULER_Task *task;
+
+  /**
+   * Function to call once we are ready to transmit.
+   */
+  GCC_ReadyCallback ready_cb;
+
+  /**
+   * Closure for @e ready_cb.
+   */
+  void *ready_cb_cls;
+
+  /**
+   * How long do we wait before we try again with a CREATE message?
+   */
+  struct GNUNET_TIME_Relative retry_delay;
+
+  /**
+   * State of the connection.
+   */
+  enum CadetConnectionState state;
+
+  /**
+   * Offset of our @e destination in @e path.
+   */
+  unsigned int off;
+
+  /**
+   * Are we ready to transmit via @e mq_man right now?
+   */
+  int mqm_ready;
+
+};
+
+
+/**
+ * Destroy a connection.
+ *
+ * @param cc connection to destroy
+ */
+void
+GCC_destroy (struct CadetConnection *cc)
+{
+  struct GNUNET_MQ_Envelope *env = NULL;
+
+  if (CADET_CONNECTION_SENDING_CREATE != cc->state)
+  {
+    struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
+
+    /* Need to notify next hop that we are down. */
+    env = GNUNET_MQ_msg (destroy_msg,
+                         GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
+    destroy_msg->cid = cc->cid;
+  }
+  GCP_request_mq_cancel (cc->mq_man,
+                         env);
+  cc->mq_man = NULL;
+  GCPP_del_connection (cc->path,
+                       cc->off,
+                       cc);
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multishortmap_remove (connections,
+                                                        &GCC_get_id (cc)->connection_of_tunnel,
+                                                        cc));
+  GNUNET_free (cc);
+}
+
+
+/**
+ * Return the tunnel associated with this connection.
+ *
+ * @param cc connection to query
+ * @return corresponding entry in the tunnel's connection list
+ */
+struct CadetTConnection *
+GCC_get_ct (struct CadetConnection *cc)
+{
+  return cc->ct;
+}
+
+
+/**
+ * A connection ACK was received for this connection, implying
+ * that the end-to-end connection is up.  Process it.
+ *
+ * @param cc the connection that got the ACK.
+ */
+void
+GCC_handle_connection_ack (struct CadetConnection *cc)
+{
+  if (NULL != cc->task)
+  {
+    GNUNET_SCHEDULER_cancel (cc->task);
+    cc->task = NULL;
+  }
+#if FIXME_KEEPALIVE
+  cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period,
+                                           &send_keepalive,
+                                           cc);
+#endif
+  cc->state = CADET_CONNECTION_READY;
+  if (GNUNET_YES == cc->mqm_ready)
+    cc->ready_cb (cc->ready_cb_cls,
+                  GNUNET_YES);
+}
+
+
+/**
+ * Handle KX message.
+ *
+ * @param cc connection that received encrypted message
+ * @param msg the key exchange message
+ */
+void
+GCC_handle_kx (struct CadetConnection *cc,
+               const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
+{
+  if (CADET_CONNECTION_SENT == cc->state)
+  {
+    /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
+       clearly something is working, so pretend we got an ACK. */
+    GCC_handle_connection_ack (cc);
+  }
+  GCT_handle_kx (cc->ct,
+                 msg);
+}
+
+
+/**
+ * Handle encrypted message.
+ *
+ * @param cc connection that received encrypted message
+ * @param msg the encrypted message to decrypt
+ */
+void
+GCC_handle_encrypted (struct CadetConnection *cc,
+                      const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
+{
+  if (CADET_CONNECTION_SENT == cc->state)
+  {
+    /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
+       clearly something is working, so pretend we got an ACK. */
+    GCC_handle_connection_ack (cc);
+  }
+  GCT_handle_encrypted (cc->ct,
+                        msg);
+}
+
+
+/**
+ * Send a CREATE message to the first hop.
+ *
+ * @param cls the `struct CadetConnection` to initiate
+ */
+static void
+send_create (void *cls)
+{
+  struct CadetConnection *cc = cls;
+  struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
+  struct GNUNET_PeerIdentity *pids;
+  struct GNUNET_MQ_Envelope *env;
+  unsigned int path_length;
+
+  cc->task = NULL;
+  GNUNET_assert (GNUNET_YES == cc->mqm_ready);
+  path_length = GCPP_get_length (cc->path);
+  env = GNUNET_MQ_msg_extra (create_msg,
+                             path_length * sizeof (struct GNUNET_PeerIdentity),
+                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
+  create_msg->cid = cc->cid;
+  pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
+  for (unsigned int i=0;i<path_length;i++)
+    pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
+                                                    i));
+  cc->env = env;
+  cc->mqm_ready = GNUNET_NO;
+  cc->state = CADET_CONNECTION_SENT;
+  GCP_send (cc->mq_man,
+            env);
+}
+
+
+/**
+ * Send a CREATE_ACK message towards the origin.
+ *
+ * @param cls the `struct CadetConnection` to initiate
+ */
+static void
+send_create_ack (void *cls)
+{
+  struct CadetConnection *cc = cls;
+  struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
+  struct GNUNET_PeerIdentity *pids;
+  struct GNUNET_MQ_Envelope *env;
+  unsigned int path_length;
+
+  cc->task = NULL;
+  GNUNET_assert (GNUNET_YES == cc->mqm_ready);
+  path_length = GCPP_get_length (cc->path);
+  env = GNUNET_MQ_msg_extra (create_msg,
+                             path_length * sizeof (struct GNUNET_PeerIdentity),
+                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
+  create_msg->cid = cc->cid;
+  pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
+  for (unsigned int i=0;i<path_length;i++)
+    pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
+                                                    i));
+  cc->env = env;
+  cc->mqm_ready = GNUNET_NO;
+  cc->state = CADET_CONNECTION_READY;
+  GCP_send (cc->mq_man,
+            env);
+}
+
+
+/**
+ * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
+ * connection that we already have.  Either our ACK got lost
+ * or something is fishy.  Consider retransmitting the ACK.
+ *
+ * @param cc connection that got the duplicate CREATE
+ */
+void
+GCC_handle_duplicate_create (struct CadetConnection *cc)
+{
+  if (GNUNET_YES == cc->mqm_ready)
+  {
+    /* Tell tunnel that we are not ready for transmission anymore
+       (until CREATE_ACK is done) */
+    cc->ready_cb (cc->ready_cb_cls,
+                  GNUNET_NO);
+
+    /* Revert back to the state of having only received the 'CREATE',
+       and immediately proceed to send the CREATE_ACK. */
+    cc->state = CADET_CONNECTION_CREATE_RECEIVED;
+    cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
+                                         cc);
+  }
+  else
+  {
+    /* We are currently sending something else back, which
+       can only be an ACK or payload, either of which would
+       do. So actually no need to do anything. */
+  }
+}
+
+
+/**
+ * There has been a change in the message queue existence for our
+ * peer at the first hop.  Adjust accordingly.
+ *
+ * @param cls the `struct CadetConnection`
+ * @param available #GNUNET_YES if sending is now possible,
+ *                  #GNUNET_NO if sending is no longer possible
+ *                  #GNUNET_SYSERR if sending is no longer possible
+ *                                 and the last envelope was discarded
+ */
+static void
+manage_first_hop_mq (void *cls,
+                     int available)
+{
+  struct CadetConnection *cc = cls;
+
+  if (GNUNET_YES != available)
+  {
+    /* Connection is down, for now... */
+    cc->mqm_ready = GNUNET_NO;
+    cc->state = CADET_CONNECTION_NEW;
+    cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
+    if (NULL != cc->task)
+    {
+      GNUNET_SCHEDULER_cancel (cc->task);
+      cc->task = NULL;
+    }
+    cc->ready_cb (cc->ready_cb_cls,
+                  GNUNET_NO);
+    return;
+  }
+
+  cc->mqm_ready = GNUNET_YES;
+  switch (cc->state)
+  {
+  case CADET_CONNECTION_NEW:
+    /* Transmit immediately */
+    cc->task = GNUNET_SCHEDULER_add_now (&send_create,
+                                         cc);
+    break;
+  case CADET_CONNECTION_SENDING_CREATE:
+    /* Should not be possible to be called in this state. */
+    GNUNET_assert (0);
+    break;
+  case CADET_CONNECTION_SENT:
+    /* Retry a bit later... */
+    cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
+    cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
+                                             &send_create,
+                                             cc);
+    break;
+  case CADET_CONNECTION_CREATE_RECEIVED:
+    /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
+    cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
+                                         cc);
+    break;
+  case CADET_CONNECTION_READY:
+    cc->ready_cb (cc->ready_cb_cls,
+                  GNUNET_YES);
+    break;
+  }
+}
+
+
+/**
+ * Create a connection to @a destination via @a path and notify @a cb
+ * whenever we are ready for more data.  Shared logic independent of
+ * who is initiating the connection.
+ *
+ * @param destination where to go
+ * @param path which path to take (may not be the full path)
+ * @param ct which tunnel uses this connection
+ * @param init_state initial state for the connection
+ * @param ready_cb function to call when ready to transmit
+ * @param ready_cb_cls closure for @a cb
+ * @return handle to the connection
+ */
+static struct CadetConnection *
+connection_create (struct CadetPeer *destination,
+                   struct CadetPeerPath *path,
+                   struct CadetTConnection *ct,
+                   const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
+                   enum CadetConnectionState init_state,
+                   GCC_ReadyCallback ready_cb,
+                   void *ready_cb_cls)
+{
+  struct CadetConnection *cc;
+  struct CadetPeer *first_hop;
+  unsigned int off;
+
+  off = GCPP_find_peer (path,
+                        destination);
+  GNUNET_assert (UINT_MAX > off);
+  cc = GNUNET_new (struct CadetConnection);
+  cc->state = init_state;
+  cc->ct = ct;
+  cc->cid = *cid;
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multishortmap_put (connections,
+                                                     &GCC_get_id (cc)->connection_of_tunnel,
+                                                     cc,
+                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  cc->ready_cb = ready_cb;
+  cc->ready_cb_cls = ready_cb_cls;
+  cc->path = path;
+  cc->off = off;
+  GCPP_add_connection (path,
+                       off,
+                       cc);
+  for (unsigned int i=0;i<off;i++)
+    GCP_add_connection (GCPP_get_peer_at_offset (path,
+                                                 off),
+                        cc);
+
+  first_hop = GCPP_get_peer_at_offset (path,
+                                       0);
+  cc->mq_man = GCP_request_mq (first_hop,
+                               &manage_first_hop_mq,
+                               cc);
+  return cc;
+}
+
+
+/**
+ * Create a connection to @a destination via @a path and
+ * notify @a cb whenever we are ready for more data.  This
+ * is an inbound tunnel, so we must use the existing @a cid
+ *
+ * @param destination where to go
+ * @param path which path to take (may not be the full path)
+ * @param ct which tunnel uses this connection
+ * @param ready_cb function to call when ready to transmit
+ * @param ready_cb_cls closure for @a cb
+ * @return handle to the connection
+ */
+struct CadetConnection *
+GCC_create_inbound (struct CadetPeer *destination,
+                    struct CadetPeerPath *path,
+                    struct CadetTConnection *ct,
+                    const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
+                    GCC_ReadyCallback ready_cb,
+                    void *ready_cb_cls)
+{
+  return connection_create (destination,
+                            path,
+                            ct,
+                            cid,
+                            CADET_CONNECTION_CREATE_RECEIVED,
+                            ready_cb,
+                            ready_cb_cls);
+}
+
+
+/**
+ * Create a connection to @a destination via @a path and
+ * notify @a cb whenever we are ready for more data.
+ *
+ * @param destination where to go
+ * @param path which path to take (may not be the full path)
+ * @param ct tunnel that uses the connection
+ * @param ready_cb function to call when ready to transmit
+ * @param ready_cb_cls closure for @a cb
+ * @return handle to the connection
+ */
+struct CadetConnection *
+GCC_create (struct CadetPeer *destination,
+            struct CadetPeerPath *path,
+            struct CadetTConnection *ct,
+            GCC_ReadyCallback ready_cb,
+            void *ready_cb_cls)
+{
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
+
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+                              &cid,
+                              sizeof (cid));
+  return connection_create (destination,
+                            path,
+                            ct,
+                            &cid,
+                            CADET_CONNECTION_NEW,
+                            ready_cb,
+                            ready_cb_cls);
+}
+
+
+/**
+ * Transmit message @a msg via connection @a cc.  Must only be called
+ * (once) after the connection has signalled that it is ready via the
+ * `ready_cb`.  Clients can also use #GCC_is_ready() to check if the
+ * connection is right now ready for transmission.
+ *
+ * @param cc connection identification
+ * @param env envelope with message to transmit; must NOT
+ *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
+ */
+void
+GCC_transmit (struct CadetConnection *cc,
+              struct GNUNET_MQ_Envelope *env)
+{
+  GNUNET_assert (GNUNET_YES == cc->mqm_ready);
+  GNUNET_assert (CADET_CONNECTION_READY == cc->state);
+  cc->mqm_ready = GNUNET_NO;
+  GCP_send (cc->mq_man,
+            env);
+}
+
+
+/**
+ * Obtain the path used by this connection.
+ *
+ * @param cc connection
+ * @return path to @a cc
+ */
+struct CadetPeerPath *
+GCC_get_path (struct CadetConnection *cc)
+{
+  return cc->path;
+}
+
+
+/**
+ * Obtain unique ID for the connection.
+ *
+ * @param cc connection.
+ * @return unique number of the connection
+ */
+const struct GNUNET_CADET_ConnectionTunnelIdentifier *
+GCC_get_id (struct CadetConnection *cc)
+{
+  return &cc->cid;
+}
+
+
+/**
+ * Get a (static) string for a connection.
+ *
+ * @param cc Connection.
+ */
+const char *
+GCC_2s (const struct CadetConnection *cc)
+{
+  static char buf[128];
+
+  if (NULL == cc)
+    return "Connection(NULL)";
+
+  if (NULL != cc->ct)
+  {
+    GNUNET_snprintf (buf,
+                     sizeof (buf),
+                     "Connection(%s(Tunnel(%s)))",
+                     GNUNET_sh2s (&cc->cid.connection_of_tunnel),
+                     GCT_2s (cc->ct->t));
+    return buf;
+  }
+  GNUNET_snprintf (buf,
+                   sizeof (buf),
+                   "Connection(%s(Tunnel(NULL)))",
+                   GNUNET_sh2s (&cc->cid.connection_of_tunnel));
+  return buf;
+}
+
+
+#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
+
+
+/**
+ * Log connection info.
+ *
+ * @param cc connection
+ * @param level Debug level to use.
+ */
+void
+GCC_debug (struct CadetConnection *cc,
+           enum GNUNET_ErrorType level)
+{
+  int do_log;
+  char *s;
+
+  do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
+                                       "cadet-con",
+                                       __FILE__, __FUNCTION__, __LINE__);
+  if (0 == do_log)
+    return;
+  if (NULL == cc)
+  {
+    LOG2 (level,
+          "Connection (NULL)\n");
+    return;
+  }
+  s = GCPP_2s (cc->path);
+  LOG2 (level,
+        "Connection %s to %s via path %s in state %d is %s\n",
+        GCC_2s (cc),
+        GCP_2s (cc->destination),
+        s,
+        cc->state,
+        (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
+  GNUNET_free (s);
+}
+
+/* end of gnunet-service-cadet-new_connection.c */
diff --git a/src/cadet/gnunet-service-cadet-new_connection.h b/src/cadet/gnunet-service-cadet-new_connection.h
new file mode 100644 (file)
index 0000000..9942677
--- /dev/null
@@ -0,0 +1,196 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_connection.h
+ * @brief
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SERVICE_CADET_CONNECTION_H
+#define GNUNET_SERVICE_CADET_CONNECTION_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet-service-cadet-new.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "cadet_protocol.h"
+
+
+/**
+ * Function called to notify tunnel about change in our readyness.
+ *
+ * @param cls closure
+ * @param is_ready #GNUNET_YES if the connection is now ready for transmission,
+ *                 #GNUNET_NO if the connection is no longer ready for transmission
+ */
+typedef void
+(*GCC_ReadyCallback)(void *cls,
+                     int is_ready);
+
+
+/**
+ * Destroy a connection.
+ *
+ * @param cc connection to destroy
+ */
+void
+GCC_destroy (struct CadetConnection *cc);
+
+
+/**
+ * Create a connection to @a destination via @a path and
+ * notify @a cb whenever we are ready for more data.
+ *
+ * @param destination where to go
+ * @param path which path to take (may not be the full path)
+ * @param ct which tunnel uses this connection
+ * @param ready_cb function to call when ready to transmit
+ * @param ready_cb_cls closure for @a cb
+ * @return handle to the connection
+ */
+struct CadetConnection *
+GCC_create (struct CadetPeer *destination,
+            struct CadetPeerPath *path,
+            struct CadetTConnection *ct,
+            GCC_ReadyCallback ready_cb,
+            void *ready_cb_cls);
+
+
+/**
+ * Create a connection to @a destination via @a path and
+ * notify @a cb whenever we are ready for more data.  This
+ * is an inbound tunnel, so we must use the existing @a cid
+ *
+ * @param destination where to go
+ * @param path which path to take (may not be the full path)
+ * @param ct which tunnel uses this connection
+ * @param ready_cb function to call when ready to transmit
+ * @param ready_cb_cls closure for @a cb
+ * @return handle to the connection
+ */
+struct CadetConnection *
+GCC_create_inbound (struct CadetPeer *destination,
+                    struct CadetPeerPath *path,
+                    struct CadetTConnection *ct,
+                    const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
+                    GCC_ReadyCallback ready_cb,
+                    void *ready_cb_cls);
+
+
+/**
+ * Transmit message @a msg via connection @a cc.  Must only be called
+ * (once) after the connection has signalled that it is ready via the
+ * `ready_cb`.  Clients can also use #GCC_is_ready() to check if the
+ * connection is right now ready for transmission.
+ *
+ * @param cc connection identification
+ * @param env envelope with message to transmit;
+ *            the #GNUNET_MQ_notify_send() must not have yet been used
+ *            for the envelope.  Also, the message better match the
+ *            connection identifier of this connection...
+ */
+void
+GCC_transmit (struct CadetConnection *cc,
+              struct GNUNET_MQ_Envelope *env);
+
+
+/**
+ * An ACK was received for this connection, process it.
+ *
+ * @param cc the connection that got the ACK.
+ */
+void
+GCC_handle_connection_ack (struct CadetConnection *cc);
+
+
+/**
+ * Handle KX message.
+ *
+ * @param cc connection that received encrypted message
+ * @param msg the key exchange message
+ */
+void
+GCC_handle_kx (struct CadetConnection *cc,
+               const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
+
+
+/**
+ * Handle encrypted message.
+ *
+ * @param cc connection that received encrypted message
+ * @param msg the encrypted message to decrypt
+ */
+void
+GCC_handle_encrypted (struct CadetConnection *cc,
+                      const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
+
+
+/**
+ * Return the tunnel associated with this connection.
+ *
+ * @param cc connection to query
+ * @return corresponding entry in the tunnel's connection list
+ */
+struct CadetTConnection *
+GCC_get_ct (struct CadetConnection *cc);
+
+
+/**
+ * Obtain the path used by this connection.
+ *
+ * @param cc connection
+ * @return path to @a cc
+ */
+struct CadetPeerPath *
+GCC_get_path (struct CadetConnection *cc);
+
+
+/**
+ * Obtain unique ID for the connection.
+ *
+ * @param cc connection.
+ * @return unique number of the connection
+ */
+const struct GNUNET_CADET_ConnectionTunnelIdentifier *
+GCC_get_id (struct CadetConnection *cc);
+
+
+/**
+ * Get a (static) string for a connection.
+ *
+ * @param cc Connection.
+ */
+const char *
+GCC_2s (const struct CadetConnection *cc);
+
+
+/**
+ * Log connection info.
+ *
+ * @param cc connection
+ * @param level Debug level to use.
+ */
+void
+GCC_debug (struct CadetConnection *cc,
+           enum GNUNET_ErrorType level);
+
+
+#endif
diff --git a/src/cadet/gnunet-service-cadet-new_core.c b/src/cadet/gnunet-service-cadet-new_core.c
new file mode 100644 (file)
index 0000000..9ce4418
--- /dev/null
@@ -0,0 +1,903 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_core.c
+ * @brief cadet service; interaction with CORE service
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
+ *
+ * TODO:
+ * - pass encrypted ACK to connection (!)
+ * - given BROKEN messages, destroy paths (?)
+ * -
+ * - handle POLL (if needed)
+ */
+#include "platform.h"
+#include "gnunet-service-cadet-new_core.h"
+#include "gnunet-service-cadet-new_paths.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "gnunet-service-cadet-new_connection.h"
+#include "gnunet-service-cadet-new_tunnels.h"
+#include "gnunet_core_service.h"
+#include "cadet_protocol.h"
+
+/**
+ * Number of messages we are willing to buffer per route.
+ */
+#define ROUTE_BUFFER_SIZE 8
+
+
+/**
+ * Information we keep per direction for a route.
+ */
+struct RouteDirection
+{
+  /**
+   * Target peer.
+   */
+  struct CadetPeer *hop;
+
+  /**
+   * Route this direction is part of.
+   */
+  struct CadetRoute *my_route;
+
+  /**
+   * Message queue manager for @e hop.
+   */
+  struct GCP_MessageQueueManager *mqm;
+
+  /**
+   * Cyclic message buffer to @e hop.
+   */
+  struct GNUNET_MQ_Envelope *out_buffer[ROUTE_BUFFER_SIZE];
+
+  /**
+   * Next write offset to use to append messages to @e out_buffer.
+   */
+  unsigned int out_wpos;
+
+  /**
+   * Next read offset to use to retrieve messages from @e out_buffer.
+   */
+  unsigned int out_rpos;
+
+  /**
+   * Is @e mqm currently ready for transmission?
+   */
+  int is_ready;
+
+};
+
+
+/**
+ * Description of a segment of a `struct CadetConnection` at the
+ * intermediate peers.  Routes are basically entries in a peer's
+ * routing table for forwarding traffic.  At both endpoints, the
+ * routes are terminated by a `struct CadetConnection`, which knows
+ * the complete `struct CadetPath` that is formed by the individual
+ * routes.
+ */
+struct CadetRoute
+{
+
+  /**
+   * Information about the next hop on this route.
+   */
+  struct RouteDirection next;
+
+  /**
+   * Information about the previous hop on this route.
+   */
+  struct RouteDirection prev;
+
+  /**
+   * Unique identifier for the connection that uses this route.
+   */
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
+
+  /**
+   * When was this route last in use?
+   */
+  struct GNUNET_TIME_Absolute last_use;
+
+};
+
+
+/**
+ * Handle to the CORE service.
+ */
+static struct GNUNET_CORE_Handle *core;
+
+/**
+ * Routes on which this peer is an intermediate.
+ */
+static struct GNUNET_CONTAINER_MultiShortmap *routes;
+
+
+/**
+ * Get the route corresponding to a hash.
+ *
+ * @param cid hash generated from the connection identifier
+ */
+static struct CadetRoute *
+get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
+{
+  return GNUNET_CONTAINER_multishortmap_get (routes,
+                                             &cid->connection_of_tunnel);
+}
+
+
+/**
+ * We message @a msg from @a prev.  Find its route by @a cid and
+ * forward to the next hop.  Drop and signal broken route if we do not
+ * have a route.
+ *
+ * @param prev previous hop (sender)
+ * @param cid connection identifier, tells us which route to use
+ * @param msg the message to forward
+ */
+static void
+route_message (struct CadetPeer *prev,
+               const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
+               const struct GNUNET_MessageHeader *msg)
+{
+  struct CadetRoute *route;
+  struct RouteDirection *dir;
+  struct GNUNET_MQ_Envelope *env;
+
+  route = get_route (cid);
+  if (NULL == route)
+  {
+    struct GNUNET_MQ_Envelope *env;
+    struct GNUNET_CADET_ConnectionBrokenMessage *bm;
+
+    env = GNUNET_MQ_msg (bm,
+                         GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
+    bm->cid = *cid;
+    bm->peer1 = my_full_id;
+    GCP_send_ooo (prev,
+                  env);
+    return;
+  }
+  dir = (prev == route->prev.hop) ? &route->next : &route->prev;
+  if (GNUNET_YES == dir->is_ready)
+  {
+    dir->is_ready = GNUNET_NO;
+    GCP_send (dir->mqm,
+              GNUNET_MQ_msg_copy (msg));
+    return;
+  }
+  env = dir->out_buffer[dir->out_wpos];
+  if (NULL != env)
+  {
+    /* Queue full, drop earliest message in queue */
+    GNUNET_assert (dir->out_rpos == dir->out_wpos);
+    GNUNET_MQ_discard (env);
+    dir->out_rpos++;
+    if (ROUTE_BUFFER_SIZE == dir->out_rpos)
+      dir->out_rpos = 0;
+  }
+  env = GNUNET_MQ_msg_copy (msg);
+  dir->out_buffer[dir->out_wpos] = env;
+  dir->out_wpos++;
+  if (ROUTE_BUFFER_SIZE == dir->out_wpos)
+    dir->out_wpos = 0;
+}
+
+
+/**
+ * Check if the create_connection message has the appropriate size.
+ *
+ * @param cls Closure (unused).
+ * @param msg Message to check.
+ *
+ * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
+ */
+static int
+check_connection_create (void *cls,
+                         const struct GNUNET_CADET_ConnectionCreateMessage *msg)
+{
+  uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
+
+  if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_NO;
+  }
+  return GNUNET_YES;
+}
+
+
+/**
+ * Free internal data of a route direction.
+ *
+ * @param dir direction to destroy (do NOT free memory of 'dir' itself)
+ */
+static void
+destroy_direction (struct RouteDirection *dir)
+{
+  for (unsigned int i=0;i<ROUTE_BUFFER_SIZE;i++)
+    if (NULL != dir->out_buffer[i])
+    {
+      GNUNET_MQ_discard (dir->out_buffer[i]);
+      dir->out_buffer[i] = NULL;
+    }
+  if (NULL != dir->mqm)
+  {
+    GCP_request_mq_cancel (dir->mqm,
+                           NULL);
+    dir->mqm = NULL;
+  }
+}
+
+
+/**
+ * Destroy our state for @a route.
+ *
+ * @param route route to destroy
+ */
+static void
+destroy_route (struct CadetRoute *route)
+{
+  destroy_direction (&route->prev);
+  destroy_direction (&route->next);
+  GNUNET_free (route);
+}
+
+
+/**
+ * Send message that a route is broken between @a peer1 and @a peer2.
+ *
+ * @param target where to send the message
+ * @param cid connection identifier to use
+ * @param peer1 one of the peers where a link is broken
+ * @param peer2 another one of the peers where a link is broken
+ */
+static void
+send_broken (struct RouteDirection *target,
+             const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
+             const struct GNUNET_PeerIdentity *peer1,
+             const struct GNUNET_PeerIdentity *peer2)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_ConnectionBrokenMessage *bm;
+
+  env = GNUNET_MQ_msg (bm,
+                       GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
+  bm->cid = *cid;
+  if (NULL != peer1)
+    bm->peer1 = *peer1;
+  if (NULL != peer2)
+    bm->peer2 = *peer2;
+  GCP_request_mq_cancel (target->mqm,
+                         env);
+  target->mqm = NULL;
+}
+
+
+/**
+ * Function called when the message queue to the previous hop
+ * becomes available/unavailable.  We expect this function to
+ * be called immediately when we register, and then again
+ * later if the connection ever goes down.
+ *
+ * @param cls the `struct RouteDirection`
+ * @param available #GNUNET_YES if sending is now possible,
+ *                  #GNUNET_NO if sending is no longer possible
+ *                  #GNUNET_SYSERR if sending is no longer possible
+ *                                 and the last envelope was discarded
+ */
+static void
+dir_ready_cb (void *cls,
+              int ready)
+{
+  struct RouteDirection *dir = cls;
+  struct CadetRoute *route = dir->my_route;
+  struct RouteDirection *odir;
+
+  if (GNUNET_YES == ready)
+  {
+    struct GNUNET_MQ_Envelope *env;
+
+    dir->is_ready = GNUNET_YES;
+    if (NULL != (env = dir->out_buffer[dir->out_rpos]))
+    {
+      dir->out_buffer[dir->out_rpos] = NULL;
+      dir->out_rpos++;
+      if (ROUTE_BUFFER_SIZE == dir->out_rpos)
+        dir->out_rpos = 0;
+      dir->is_ready = GNUNET_NO;
+      GCP_send (dir->mqm,
+                env);
+    }
+    return;
+  }
+  odir = (dir == &route->next) ? &route->prev : &route->next;
+  send_broken (&route->next,
+               &route->cid,
+               GCP_get_id (odir->hop),
+               &my_full_id);
+  destroy_route (route);
+}
+
+
+/**
+ * Initialize one of the directions of a route.
+ *
+ * @param route route the direction belongs to
+ * @param dir direction to initialize
+ * @param hop next hop on in the @a dir
+ */
+static void
+dir_init (struct RouteDirection *dir,
+          struct CadetRoute *route,
+          struct CadetPeer *hop)
+{
+  dir->hop = hop;
+  dir->my_route = route;
+  dir->mqm = GCP_request_mq (hop,
+                             &dir_ready_cb,
+                             dir);
+  GNUNET_assert (GNUNET_YES == dir->is_ready);
+}
+
+
+/**
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
+ *
+ * @param cls Closure (CadetPeer for neighbor that sent the message).
+ * @param msg Message itself.
+ */
+static void
+handle_connection_create (void *cls,
+                          const struct GNUNET_CADET_ConnectionCreateMessage *msg)
+{
+  struct CadetPeer *sender = cls;
+  struct CadetPeer *next;
+  const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
+  struct CadetRoute *route;
+  uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
+  unsigned int path_length;
+  unsigned int off;
+
+  path_length = size / sizeof (struct GNUNET_PeerIdentity);
+  /* Initiator is at offset 0. */
+  for (off=1;off<path_length;off++)
+    if (0 == memcmp (&my_full_id,
+                     &pids[off],
+                     sizeof (struct GNUNET_PeerIdentity)))
+      break;
+  if (off == path_length)
+  {
+    /* We are not on the path, bogus request */
+    GNUNET_break_op (0);
+    return;
+  }
+  /* Check previous hop */
+  if (sender != GCP_get (&pids[off - 1],
+                         GNUNET_NO))
+  {
+    /* sender is not on the path, not allowed */
+    GNUNET_break_op (0);
+    return;
+  }
+  if (NULL !=
+      get_route (&msg->cid))
+  {
+    /* Duplicate CREATE, pass it on, previous one might have been lost! */
+    route_message (sender,
+                   &msg->cid,
+                   &msg->header);
+    return;
+  }
+  if (off == path_length - 1)
+  {
+    /* We are the destination, create connection */
+    struct CadetConnection *cc;
+    struct CadetPeerPath *path;
+    struct CadetPeer *origin;
+
+    cc = GNUNET_CONTAINER_multishortmap_get (connections,
+                                             &msg->cid.connection_of_tunnel);
+    if (NULL != cc)
+    {
+      /* Duplicate CREATE, likely our ACK got lost, retransmit the ACK! */
+      GNUNET_break (0); // FIXME: not implemented!
+      return;
+    }
+
+    path = GCPP_get_path_from_route (path_length,
+                                     pids);
+    origin = GCP_get (&pids[0],
+                      GNUNET_YES);
+    GCT_add_inbound_connection (GCT_create_tunnel (origin),
+                                &msg->cid,
+                                path);
+    return;
+  }
+  /* We are merely a hop on the way, check if we can support the route */
+  next = GCP_get (&pids[off + 1],
+                  GNUNET_NO);
+  if ( (NULL == next) ||
+       (GNUNET_NO == GCP_has_core_connection (next)) )
+  {
+    /* unworkable, send back BROKEN notification */
+    struct GNUNET_MQ_Envelope *env;
+    struct GNUNET_CADET_ConnectionBrokenMessage *bm;
+
+    env = GNUNET_MQ_msg (bm,
+                         GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
+    bm->cid = msg->cid;
+    bm->peer1 = pids[off + 1];
+    bm->peer2 = my_full_id;
+    GCP_send_ooo (sender,
+                  env);
+    return;
+  }
+
+  /* Workable route, create routing entry */
+  route = GNUNET_new (struct CadetRoute);
+  route->cid = msg->cid;
+  dir_init (&route->prev,
+            route,
+            sender);
+  dir_init (&route->next,
+            route,
+            next);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multishortmap_put (routes,
+                                                     &route->cid.connection_of_tunnel,
+                                                     route,
+                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+}
+
+
+/**
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
+ *
+ * @param cls Closure (CadetPeer for neighbor that sent the message).
+ * @param msg Message itself.
+ */
+static void
+handle_connection_create_ack (void *cls,
+                              const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetConnection *cc;
+
+  /* First, check if ACK belongs to a connection that ends here. */
+  cc = GNUNET_CONTAINER_multishortmap_get (connections,
+                                           &msg->cid.connection_of_tunnel);
+  if (NULL != cc)
+  {
+    /* verify ACK came from the right direction */
+    struct CadetPeerPath *path = GCC_get_path (cc);
+
+    if (peer !=
+        GCPP_get_peer_at_offset (path,
+                                 0))
+    {
+      /* received ACK from unexpected direction, ignore! */
+      GNUNET_break_op (0);
+      return;
+    }
+    GCC_handle_connection_ack (cc);
+    return;
+  }
+
+  /* We're just an intermediary peer, route the message along its path */
+  route_message (peer,
+                 &msg->cid,
+                 &msg->header);
+}
+
+
+/**
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
+ *
+ * @param cls Closure (CadetPeer for neighbor that sent the message).
+ * @param msg Message itself.
+ * @deprecated duplicate logic with #handle_destroy(); dedup!
+ */
+static void
+handle_connection_broken (void *cls,
+                          const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetConnection *cc;
+  struct CadetRoute *route;
+
+  /* First, check if message belongs to a connection that ends here. */
+  cc = GNUNET_CONTAINER_multishortmap_get (connections,
+                                           &msg->cid.connection_of_tunnel);
+  if (NULL != cc)
+  {
+    /* verify message came from the right direction */
+    struct CadetPeerPath *path = GCC_get_path (cc);
+
+    if (peer !=
+        GCPP_get_peer_at_offset (path,
+                                 0))
+    {
+      /* received message from unexpected direction, ignore! */
+      GNUNET_break_op (0);
+      return;
+    }
+    GCC_destroy (cc);
+
+    /* FIXME: also destroy the path up to the specified link! */
+    return;
+  }
+
+  /* We're just an intermediary peer, route the message along its path */
+  route = get_route (&msg->cid);
+  route_message (peer,
+                 &msg->cid,
+                 &msg->header);
+  destroy_route (route);
+  /* FIXME: also destroy paths we MAY have up to the specified link! */
+}
+
+
+/**
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
+ *
+ * @param cls Closure (CadetPeer for neighbor that sent the message).
+ * @param msg Message itself.
+ */
+static void
+handle_connection_destroy (void *cls,
+                           const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetConnection *cc;
+  struct CadetRoute *route;
+
+  /* First, check if message belongs to a connection that ends here. */
+  cc = GNUNET_CONTAINER_multishortmap_get (connections,
+                                           &msg->cid.connection_of_tunnel);
+  if (NULL != cc)
+  {
+    /* verify message came from the right direction */
+    struct CadetPeerPath *path = GCC_get_path (cc);
+
+    if (peer !=
+        GCPP_get_peer_at_offset (path,
+                                 0))
+    {
+      /* received message from unexpected direction, ignore! */
+      GNUNET_break_op (0);
+      return;
+    }
+    GCC_destroy (cc);
+    return;
+  }
+
+  /* We're just an intermediary peer, route the message along its path */
+  route = get_route (&msg->cid);
+  route_message (peer,
+                 &msg->cid,
+                 &msg->header);
+  destroy_route (route);
+}
+
+
+/**
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_HOP_BY_HOP_ENCRYPTED_ACK.
+ *
+ * @param cls Closure (CadetPeer for neighbor that sent the message).
+ * @param msg Message itself.
+ */
+static void
+handle_hop_by_hop_encrypted_ack (void *cls,
+                                 const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetConnection *cc;
+
+  /* First, check if message belongs to a connection that ends here. */
+  cc = GNUNET_CONTAINER_multishortmap_get (connections,
+                                           &msg->cid.connection_of_tunnel);
+  if (NULL != cc)
+  {
+    /* verify message came from the right direction */
+    struct CadetPeerPath *path = GCC_get_path (cc);
+
+    if (peer !=
+        GCPP_get_peer_at_offset (path,
+                                 0))
+    {
+      /* received message from unexpected direction, ignore! */
+      GNUNET_break_op (0);
+      return;
+    }
+#if FIXME
+    GCC_handle_ack (peer,
+                    msg);
+#endif
+    return;
+  }
+
+  /* We're just an intermediary peer, route the message along its path */
+  route_message (peer,
+                 &msg->cid,
+                 &msg->header);
+}
+
+
+/**
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
+ *
+ * @param cls Closure (CadetPeer for neighbor that sent the message).
+ * @param msg Message itself.
+ */
+static void
+handle_poll (void *cls,
+             const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
+{
+  struct CadetPeer *peer = cls;
+
+#if FIXME
+  GCC_handle_poll (peer,
+                   msg);
+#endif
+}
+
+
+/**
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
+ *
+ * @param cls Closure (CadetPeer for neighbor that sent the message).
+ * @param msg Message itself.
+ */
+static void
+handle_tunnel_kx (void *cls,
+                  const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetConnection *cc;
+
+  /* First, check if message belongs to a connection that ends here. */
+  cc = GNUNET_CONTAINER_multishortmap_get (connections,
+                                           &msg->cid.connection_of_tunnel);
+  if (NULL != cc)
+  {
+    /* verify message came from the right direction */
+    struct CadetPeerPath *path = GCC_get_path (cc);
+
+    if (peer !=
+        GCPP_get_peer_at_offset (path,
+                                 0))
+    {
+      /* received message from unexpected direction, ignore! */
+      GNUNET_break_op (0);
+      return;
+    }
+    GCC_handle_kx (cc,
+                   msg);
+    return;
+  }
+
+  /* We're just an intermediary peer, route the message along its path */
+  route_message (peer,
+                 &msg->cid,
+                 &msg->header);
+}
+
+
+/**
+ * Check if the encrypted message has the appropriate size.
+ *
+ * @param cls Closure (unused).
+ * @param msg Message to check.
+ *
+ * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
+ */
+static int
+check_tunnel_encrypted (void *cls,
+                        const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
+{
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
+ *
+ * @param cls Closure (CadetPeer for neighbor that sent the message).
+ * @param msg Message itself.
+ */
+static void
+handle_tunnel_encrypted (void *cls,
+                         const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetConnection *cc;
+
+  /* First, check if message belongs to a connection that ends here. */
+  cc = GNUNET_CONTAINER_multishortmap_get (connections,
+                                           &msg->cid.connection_of_tunnel);
+  if (NULL != cc)
+  {
+    /* verify message came from the right direction */
+    struct CadetPeerPath *path = GCC_get_path (cc);
+
+    if (peer !=
+        GCPP_get_peer_at_offset (path,
+                                 0))
+    {
+      /* received message from unexpected direction, ignore! */
+      GNUNET_break_op (0);
+      return;
+    }
+    GCC_handle_encrypted (cc,
+                          msg);
+    return;
+  }
+
+  /* We're just an intermediary peer, route the message along its path */
+  route_message (peer,
+                 &msg->cid,
+                 &msg->header);
+}
+
+
+/**
+ * Function called after #GNUNET_CORE_connect has succeeded (or failed
+ * for good).  Note that the private key of the peer is intentionally
+ * not exposed here; if you need it, your process should try to read
+ * the private key file directly (which should work if you are
+ * authorized...).  Implementations of this function must not call
+ * #GNUNET_CORE_disconnect (other than by scheduling a new task to
+ * do this later).
+ *
+ * @param cls closure
+ * @param my_identity ID of this peer, NULL if we failed
+ */
+static void
+core_init_cb (void *cls,
+              const struct GNUNET_PeerIdentity *my_identity)
+{
+  if (NULL == my_identity)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  GNUNET_break (0 ==
+                memcmp (my_identity,
+                        &my_full_id,
+                        sizeof (struct GNUNET_PeerIdentity)));
+}
+
+
+/**
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void *
+core_connect_cb (void *cls,
+                 const struct GNUNET_PeerIdentity *peer,
+                 struct GNUNET_MQ_Handle *mq)
+{
+  struct CadetPeer *cp;
+
+  cp = GCP_get (peer,
+                GNUNET_YES);
+  GCP_set_mq (cp,
+              mq);
+  return cp;
+}
+
+
+/**
+ * Method called whenever a peer disconnects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+core_disconnect_cb (void *cls,
+                    const struct GNUNET_PeerIdentity *peer,
+                    void *peer_cls)
+{
+  struct CadetPeer *cp = peer_cls;
+
+  GCP_set_mq (cp,
+              NULL);
+}
+
+
+/**
+ * Initialize the CORE subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_var_size (connection_create,
+                           GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
+                           struct GNUNET_CADET_ConnectionCreateMessage,
+                           NULL),
+    GNUNET_MQ_hd_fixed_size (connection_create_ack,
+                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
+                             struct GNUNET_CADET_ConnectionCreateMessageAckMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (connection_broken,
+                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
+                             struct GNUNET_CADET_ConnectionBrokenMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (connection_destroy,
+                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
+                             struct GNUNET_CADET_ConnectionDestroyMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (hop_by_hop_encrypted_ack,
+                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
+                             struct GNUNET_CADET_ConnectionEncryptedAckMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (poll,
+                             GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
+                             struct GNUNET_CADET_ConnectionHopByHopPollMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (tunnel_kx,
+                             GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
+                             struct GNUNET_CADET_TunnelKeyExchangeMessage,
+                             NULL),
+    GNUNET_MQ_hd_var_size (tunnel_encrypted,
+                           GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
+                           struct GNUNET_CADET_TunnelEncryptedMessage,
+                           NULL),
+    GNUNET_MQ_handler_end ()
+  };
+
+  routes = GNUNET_CONTAINER_multishortmap_create (1024,
+                                                  GNUNET_NO);
+  core = GNUNET_CORE_connect (c,
+                              NULL,
+                              &core_init_cb,
+                              &core_connect_cb,
+                              &core_disconnect_cb,
+                              handlers);
+}
+
+
+/**
+ * Shut down the CORE subsystem.
+ */
+void
+GCO_shutdown ()
+{
+  if (NULL != core)
+  {
+    GNUNET_CORE_disconnect (core);
+    core = NULL;
+  }
+  GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
+  GNUNET_CONTAINER_multishortmap_destroy (routes);
+}
+
+/* end of gnunet-cadet-service_core.c */
diff --git a/src/cadet/gnunet-service-cadet-new_core.h b/src/cadet/gnunet-service-cadet-new_core.h
new file mode 100644 (file)
index 0000000..65b0a6b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_core.h
+ * @brief cadet service; interaction with CORE service
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
+ */
+
+#ifndef GNUNET_SERVICE_CADET_CORE_H
+#define GNUNET_SERVICE_CADET_CORE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_util_lib.h"
+
+
+/**
+ * Initialize the CORE subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GCO_init (const struct GNUNET_CONFIGURATION_Handle *c);
+
+
+/**
+ * Shut down the CORE subsystem.
+ */
+void
+GCO_shutdown (void);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_CADET_SERVICE_CORE_H */
+#endif
+/* end of gnunet-cadet-service_core.h */
diff --git a/src/cadet/gnunet-service-cadet-new_dht.c b/src/cadet/gnunet-service-cadet-new_dht.c
new file mode 100644 (file)
index 0000000..3cf3f03
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2013, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file cadet/gnunet-service-cadet-new_dht.c
+ * @brief Information we track per peer.
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_dht_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet-service-cadet-new.h"
+#include "gnunet-service-cadet-new_dht.h"
+#include "gnunet-service-cadet-new_hello.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "gnunet-service-cadet-new_paths.h"
+
+#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
+
+
+/**
+ * Handle for DHT searches.
+ */
+struct GCD_search_handle
+{
+  /**
+   * DHT_GET handle.
+   */
+  struct GNUNET_DHT_GetHandle *dhtget;
+
+};
+
+
+/**
+ * Handle to use DHT.
+ */
+static struct GNUNET_DHT_Handle *dht_handle;
+
+/**
+ * How often to PUT own ID in the DHT.
+ */
+static struct GNUNET_TIME_Relative id_announce_time;
+
+/**
+ * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
+ */
+static unsigned long long dht_replication_level;
+
+/**
+ * Task to periodically announce itself in the network.
+ */
+static struct GNUNET_SCHEDULER_Task *announce_id_task;
+
+/**
+ * Delay for the next ID announce.
+ */
+static struct GNUNET_TIME_Relative announce_delay;
+
+
+/**
+ * Function to process paths received for a new peer addition. The recorded
+ * paths form the initial tunnel, which can be optimized later.
+ * Called on each result obtained for the DHT search.
+ *
+ * @param cls closure
+ * @param exp when will this value expire
+ * @param key key of the result
+ * @param get_path path of the get request
+ * @param get_path_length lenght of @a get_path
+ * @param put_path path of the put request
+ * @param put_path_length length of the @a put_path
+ * @param type type of the result
+ * @param size number of bytes in data
+ * @param data pointer to the result data
+ */
+static void
+dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
+                    const struct GNUNET_HashCode *key,
+                    const struct GNUNET_PeerIdentity *get_path,
+                    unsigned int get_path_length,
+                    const struct GNUNET_PeerIdentity *put_path,
+                    unsigned int put_path_length,
+                    enum GNUNET_BLOCK_Type type,
+                    size_t size,
+                    const void *data)
+{
+  const struct GNUNET_HELLO_Message *hello = data;
+  struct CadetPeer *peer;
+
+  GCPP_try_path_from_dht (get_path,
+                          get_path_length,
+                          put_path,
+                          put_path_length);
+  if ( (size >= sizeof (struct GNUNET_HELLO_Message)) &&
+       (ntohs (hello->header.size) == size) &&
+       (size == GNUNET_HELLO_size (hello)) )
+  {
+    peer = GCP_get (&put_path[0],
+                    GNUNET_YES);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Got HELLO for %s\n",
+         GCP_2s (peer));
+    GCP_set_hello (peer,
+                   hello);
+  }
+}
+
+
+/**
+ * Periodically announce self id in the DHT
+ *
+ * @param cls closure
+ */
+static void
+announce_id (void *cls)
+{
+  struct GNUNET_HashCode phash;
+  const struct GNUNET_HELLO_Message *hello;
+  size_t size;
+  struct GNUNET_TIME_Absolute expiration;
+  struct GNUNET_TIME_Relative next_put;
+
+  hello = GCH_get_mine ();
+  size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
+  if (0 == size)
+  {
+    expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                                           announce_delay);
+    announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
+  }
+  else
+  {
+    expiration = GNUNET_HELLO_get_last_expiration (hello);
+    announce_delay = GNUNET_TIME_UNIT_SECONDS;
+  }
+
+  /* Call again in id_announce_time, unless HELLO expires first,
+   * but wait at least 1s. */
+  next_put
+    = GNUNET_TIME_absolute_get_remaining (expiration);
+  next_put
+    = GNUNET_TIME_relative_min (next_put,
+                                id_announce_time);
+  next_put
+    = GNUNET_TIME_relative_max (next_put,
+                                GNUNET_TIME_UNIT_SECONDS);
+  announce_id_task
+    = GNUNET_SCHEDULER_add_delayed (next_put,
+                                    &announce_id,
+                                    cls);
+  GNUNET_STATISTICS_update (stats,
+                            "# DHT announce",
+                            1,
+                            GNUNET_NO);
+  memset (&phash,
+          0,
+          sizeof (phash));
+  GNUNET_memcpy (&phash,
+                 &my_full_id,
+                 sizeof (my_full_id));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Announcing my HELLO (%u bytes) in the DHT\n",
+       size);
+  GNUNET_DHT_put (dht_handle,   /* DHT handle */
+                  &phash,       /* Key to use */
+                  dht_replication_level,     /* Replication level */
+                  GNUNET_DHT_RO_RECORD_ROUTE
+                  | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
+                  GNUNET_BLOCK_TYPE_DHT_HELLO,       /* Block type */
+                  size,  /* Size of the data */
+                  (const char *) hello, /* Data itself */
+                  expiration,  /* Data expiration */
+                  NULL,         /* Continuation */
+                  NULL);        /* Continuation closure */
+}
+
+
+/**
+ * Initialize the DHT subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "init\n");
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c,
+                                             "CADET",
+                                             "DHT_REPLICATION_LEVEL",
+                                             &dht_replication_level))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+                               "CADET",
+                               "DHT_REPLICATION_LEVEL",
+                               "USING DEFAULT");
+    dht_replication_level = 3;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (c,
+                                           "CADET",
+                                           "ID_ANNOUNCE_TIME",
+                                           &id_announce_time))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               "CADET",
+                               "ID_ANNOUNCE_TIME",
+                               "MISSING");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  dht_handle = GNUNET_DHT_connect (c,
+                                   64);
+  GNUNET_break (NULL != dht_handle);
+  announce_delay = GNUNET_TIME_UNIT_SECONDS;
+  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id,
+                                               NULL);
+}
+
+
+/**
+ * Shut down the DHT subsystem.
+ */
+void
+GCD_shutdown (void)
+{
+  if (NULL != dht_handle)
+  {
+    GNUNET_DHT_disconnect (dht_handle);
+    dht_handle = NULL;
+  }
+  if (NULL != announce_id_task)
+  {
+    GNUNET_SCHEDULER_cancel (announce_id_task);
+    announce_id_task = NULL;
+  }
+}
+
+
+/**
+ * Search DHT for paths to @a peeR_id
+ *
+ * @param peer_id peer to search for
+ * @return handle to abort search
+ */
+struct GCD_search_handle *
+GCD_search (const struct GNUNET_PeerIdentity *peer_id)
+{
+  struct GNUNET_HashCode phash;
+  struct GCD_search_handle *h;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Starting DHT GET for peer %s\n",
+       GNUNET_i2s (peer_id));
+  GNUNET_STATISTICS_update (stats,
+                            "# DHT search",
+                            1,
+                            GNUNET_NO);
+  memset (&phash,
+          0,
+          sizeof (phash));
+  GNUNET_memcpy (&phash,
+                 peer_id,
+                 sizeof (*peer_id));
+
+  h = GNUNET_new (struct GCD_search_handle);
+  h->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
+                                    GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
+                                    &phash,     /* key to search */
+                                    dht_replication_level, /* replication level */
+                                    GNUNET_DHT_RO_RECORD_ROUTE |
+                                    GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
+                                    NULL,       /* xquery */
+                                    0,     /* xquery bits */
+                                    &dht_get_id_handler,
+                                   h);
+  return h;
+}
+
+
+/**
+ * Stop DHT search started with #GCD_search().
+ *
+ * @param h handle to search to stop
+ */
+void
+GCD_search_stop (struct GCD_search_handle *h)
+{
+  GNUNET_DHT_get_stop (h->dhtget);
+  GNUNET_free (h);
+}
+
+/* end of gnunet-service-cadet_dht.c */
diff --git a/src/cadet/gnunet-service-cadet-new_dht.h b/src/cadet/gnunet-service-cadet-new_dht.h
new file mode 100644 (file)
index 0000000..81f16ae
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2013, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_dht.h
+ * @brief cadet service; dealing with DHT requests and results
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * All functions in this file should use the prefix GCD (Gnunet Cadet Dht)
+ */
+#ifndef GNUNET_SERVICE_CADET_DHT_H
+#define GNUNET_SERVICE_CADET_DHT_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+/**
+ * Handle for DHT search operation.
+ */
+struct GCD_search_handle;
+
+
+/**
+ * Initialize the DHT subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GCD_init (const struct GNUNET_CONFIGURATION_Handle *c);
+
+
+/**
+ * Shut down the DHT subsystem.
+ */
+void
+GCD_shutdown (void);
+
+
+/**
+ * Search DHT for paths to @a peeR_id
+ *
+ * @param peer_id peer to search for
+ * @return handle to abort search
+ */
+struct GCD_search_handle *
+GCD_search (const struct GNUNET_PeerIdentity *peer_id);
+
+
+/**
+ * Stop DHT search started with #GCD_search().
+ *
+ * @param h handle to search to stop
+ */
+void
+GCD_search_stop (struct GCD_search_handle *h);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_CADET_SERVICE_DHT_H */
+#endif
+/* end of gnunet-service-cadet_dht.h */
diff --git a/src/cadet/gnunet-service-cadet-new_hello.c b/src/cadet/gnunet-service-cadet-new_hello.c
new file mode 100644 (file)
index 0000000..9d46350
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2014, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet_statistics_service.h"
+#include "gnunet_peerinfo_service.h"
+#include "cadet_protocol.h"
+#include "gnunet-service-cadet-new.h"
+#include "gnunet-service-cadet-new_hello.h"
+#include "gnunet-service-cadet-new_peer.h"
+
+#define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__)
+
+/**
+ * Hello message of local peer.
+ */
+static struct GNUNET_HELLO_Message *mine;
+
+/**
+ * Handle to peerinfo service.
+ */
+static struct GNUNET_PEERINFO_Handle *peerinfo;
+
+/**
+ * Iterator context.
+ */
+static struct GNUNET_PEERINFO_NotifyContext* nc;
+
+
+/**
+ * Process each hello message received from peerinfo.
+ *
+ * @param cls Closure (unused).
+ * @param peer Identity of the peer.
+ * @param hello Hello of the peer.
+ * @param err_msg Error message.
+ */
+static void
+got_hello (void *cls,
+           const struct GNUNET_PeerIdentity *id,
+           const struct GNUNET_HELLO_Message *hello,
+           const char *err_msg)
+{
+  struct CadetPeer *peer;
+
+  if ( (NULL == id) ||
+       (NULL == hello) )
+    return;
+  if (0 == memcmp (id,
+                   &my_full_id,
+                   sizeof (struct GNUNET_PeerIdentity)))
+  {
+    GNUNET_free_non_null (mine);
+    mine = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (&hello->header);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Hello for %s (%d bytes), expires on %s\n",
+       GNUNET_i2s (id),
+       GNUNET_HELLO_size (hello),
+       GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration (hello)));
+  peer = GCP_get (id,
+                  GNUNET_YES);
+  GCP_set_hello (peer,
+                 hello);
+
+}
+
+
+/**
+ * Initialize the hello subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GCH_init (const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  GNUNET_assert (NULL == nc);
+  peerinfo = GNUNET_PEERINFO_connect (c);
+  nc = GNUNET_PEERINFO_notify (c,
+                               GNUNET_NO,
+                               &got_hello,
+                               NULL);
+}
+
+
+/**
+ * Shut down the hello subsystem.
+ */
+void
+GCH_shutdown ()
+{
+  if (NULL != nc)
+  {
+    GNUNET_PEERINFO_notify_cancel (nc);
+    nc = NULL;
+  }
+  if (NULL != peerinfo)
+  {
+    GNUNET_PEERINFO_disconnect (peerinfo);
+    peerinfo = NULL;
+  }
+  if (NULL != mine)
+  {
+    GNUNET_free (mine);
+    mine = NULL;
+  }
+}
+
+
+/**
+ * Get own hello message.
+ *
+ * @return Own hello message.
+ */
+const struct GNUNET_HELLO_Message *
+GCH_get_mine (void)
+{
+  return mine;
+}
+
+/* end of gnunet-service-cadet-new_hello.c */
diff --git a/src/cadet/gnunet-service-cadet-new_hello.h b/src/cadet/gnunet-service-cadet-new_hello.h
new file mode 100644 (file)
index 0000000..4291ae9
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2014, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_hello.h
+ * @brief cadet service; dealing with hello messages
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * All functions in this file should use the prefix GCH (Gnunet Cadet Hello)
+ */
+
+#ifndef GNUNET_SERVICE_CADET_HELLO_H
+#define GNUNET_SERVICE_CADET_HELLO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_hello_lib.h"
+
+
+/**
+ * Initialize the hello subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GCH_init (const struct GNUNET_CONFIGURATION_Handle *c);
+
+
+/**
+ * Shut down the hello subsystem.
+ */
+void
+GCH_shutdown (void);
+
+
+/**
+ * Get own hello message.
+ *
+ * @return Own hello message.
+ */
+const struct GNUNET_HELLO_Message *
+GCH_get_mine (void);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_CADET_SERVICE_HELLO_H */
+#endif
+/* end of gnunet-cadet-service_hello.h */
diff --git a/src/cadet/gnunet-service-cadet-new_paths.c b/src/cadet/gnunet-service-cadet-new_paths.c
new file mode 100644 (file)
index 0000000..3cfce33
--- /dev/null
@@ -0,0 +1,557 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_paths.c
+ * @brief Information we track per path.
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - path desirability score calculations are not done
+ *   (and will be tricky to have during path changes)
+ */
+#include "platform.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "gnunet-service-cadet-new_paths.h"
+
+
+/**
+ * Information regarding a possible path to reach a peer.
+ */
+struct CadetPeerPath
+{
+
+  /**
+   * Array of all the peers on the path.  If @e hn is non-NULL, the
+   * last one is our owner.
+   */
+  struct CadetPeerPathEntry *entries;
+
+  /**
+   * Node of this path in the owner's heap.  Used to update our position
+   * in the heap whenever our @e desirability changes.
+   */
+  struct GNUNET_CONTAINER_HeapNode *hn;
+
+  /**
+   * Connections using this path, by destination peer
+   * (each hop of the path could correspond to an
+   * active connection).
+   */
+  struct GNUNET_CONTAINER_MultiPeerMap *connections;
+
+  /**
+   * Desirability of the path. How unique is it for the various peers
+   * on it?
+   */
+  GNUNET_CONTAINER_HeapCostType desirability;
+
+  /**
+   * Length of the @e entries array.
+   */
+  unsigned int entries_length;
+
+};
+
+
+/**
+ * Return how much we like keeping the path.  This is an aggregate
+ * score based on various factors, including the age of the path
+ * (older == better), and the value of this path to all of its ajacent
+ * peers.  For example, long paths that end at a peer that we have no
+ * shorter way to reach are very desirable, while long paths that end
+ * at a peer for which we have a shorter way as well are much less
+ * desirable.  Higher values indicate more valuable paths.  The
+ * returned value should be used to decide which paths to remember.
+ *
+ * @param path path to return the length for
+ * @return desirability of the path, larger is more desirable
+ */
+GNUNET_CONTAINER_HeapCostType
+GCPP_get_desirability (const struct CadetPeerPath *path)
+{
+  return path->desirability;
+}
+
+
+/**
+ * Return connection to @a destination using @a path, or return
+ * NULL if no such connection exists.
+ *
+ * @param path path to traverse
+ * @param destination destination node to get to, must be on path
+ * @param off offset of @a destination on @a path
+ * @return NULL if we have no existing connection
+ *         otherwise connection from us to @a destination via @a path
+ */
+struct CadetConnection *
+GCPP_get_connection (struct CadetPeerPath *path,
+                     struct CadetPeer *destination,
+                     unsigned int off)
+{
+  struct CadetPeerPathEntry *entry;
+
+  GNUNET_assert (off < path->entries_length);
+  entry = &path->entries[off];
+  GNUNET_assert (entry->peer == destination);
+  return entry->cc;
+}
+
+
+/**
+ * Notify @a path that it is used for connection @a cc
+ * which ends at the path's offset @a off.
+ *
+ * @param path the path to remember the @a cc
+ * @param off the offset where the @a cc ends
+ * @param cc the connection to remember
+ */
+void
+GCPP_add_connection (struct CadetPeerPath *path,
+                     unsigned int off,
+                     struct CadetConnection *cc)
+{
+  struct CadetPeerPathEntry *entry;
+
+  GNUNET_assert (off < path->entries_length);
+  entry = &path->entries[off];
+  GNUNET_assert (NULL == entry->cc);
+  entry->cc = cc;
+}
+
+
+
+/**
+ * Notify @a path that it is no longer used for connection @a cc which
+ * ended at the path's offset @a off.
+ *
+ * @param path the path to forget the @a cc
+ * @param off the offset where the @a cc ended
+ * @param cc the connection to forget
+ */
+void
+GCPP_del_connection (struct CadetPeerPath *path,
+                     unsigned int off,
+                     struct CadetConnection *cc)
+{
+  struct CadetPeerPathEntry *entry;
+
+  GNUNET_assert (off < path->entries_length);
+  entry = &path->entries[off];
+  GNUNET_assert (cc == entry->cc);
+  entry->cc = NULL;
+}
+
+
+/**
+ * This path is no longer needed, free resources.
+ *
+ * @param path path resources to free
+ */
+static void
+path_destroy (struct CadetPeerPath *path)
+{
+  GNUNET_assert (0 ==
+                 GNUNET_CONTAINER_multipeermap_size (path->connections));
+  GNUNET_CONTAINER_multipeermap_destroy (path->connections);
+  GNUNET_free (path->entries);
+  GNUNET_free (path);
+}
+
+
+/**
+ * The owning peer of this path is no longer interested in maintaining
+ * it, so the path should be discarded or shortened (in case a
+ * previous peer on the path finds the path desirable).
+ *
+ * @param path the path that is being released
+ */
+void
+GCPP_release (struct CadetPeerPath *path)
+{
+  struct CadetPeerPathEntry *entry;
+
+  path->hn = NULL;
+  entry = &path->entries[path->entries_length - 1];
+  while (1)
+  {
+    /* cut 'off' end of path, verifying it is not in use */
+    GNUNET_assert (NULL ==
+                   GNUNET_CONTAINER_multipeermap_get (path->connections,
+                                                      GCP_get_id (entry->peer)));
+    GCP_path_entry_remove (entry->peer,
+                           entry,
+                           path->entries_length - 1);
+    path->entries_length--; /* We don't bother shrinking the 'entries' array,
+                               as it's probably not worth it. */
+    if (0 == path->entries_length)
+      break; /* the end */
+
+    /* see if new peer at the end likes this path any better */
+    entry = &path->entries[path->entries_length - 1];
+    path->hn = GCP_attach_path (entry->peer,
+                                path,
+                                path->entries_length);
+    if (NULL != path->hn)
+      return; /* yep, got attached, we are done. */
+  }
+
+  /* nobody wants us, discard the path */
+  path_destroy (path);
+}
+
+
+/**
+ * Updates the score for an entry on the path based
+ * on our experiences with using @a path.
+ *
+ * @param path the path to update
+ * @param off offset of the entry to update
+ * @param delta change in the score to apply
+ */
+void
+GCPP_update_score (struct CadetPeerPath *path,
+                   unsigned int off,
+                   int delta)
+{
+  struct CadetPeerPathEntry *entry;
+
+  GNUNET_assert (off < path->entries_length);
+  entry = &path->entries[off];
+
+  /* Add delta, with checks for overflows */
+  if (delta >= 0)
+  {
+    if (delta + entry->score < entry->score)
+      entry->score = INT_MAX;
+    else
+      entry->score += delta;
+  }
+  else
+  {
+    if (delta + entry->score > entry->score)
+      entry->score = INT_MIN;
+    else
+      entry->score += delta;
+  }
+
+  /* FIXME: update path desirability! */
+}
+
+
+/**
+ * Closure for #find_peer_at() and #check_match().
+ */
+struct CheckMatchContext
+{
+
+  /**
+   * Set to a matching path, if any.
+   */
+  struct CadetPeerPath *match;
+
+  /**
+   * Array the combined paths.
+   */
+  struct CadetPeer **cpath;
+
+};
+
+
+/**
+ * Check if the given path is identical on all of the
+ * hops until @a off, and not longer than @a off.  If the
+ * @a path matches, store it in `match`.
+ *
+ * @param cls the `struct CheckMatchContext` to check against
+ * @param path the path to check
+ * @param off offset to check at
+ * @return #GNUNET_YES (continue to iterate), or if found #GNUNET_NO
+ */
+static int
+check_match (void *cls,
+             struct CadetPeerPath *path,
+             unsigned int off)
+{
+  struct CheckMatchContext *cm_ctx = cls;
+
+  if (path->entries_length > off)
+    return GNUNET_YES; /* too long, cannot be useful */
+  for (unsigned int i=0;i<off;i++)
+    if (cm_ctx->cpath[i] !=
+        GCPP_get_peer_at_offset (path,
+                                 i))
+      return GNUNET_YES; /* missmatch, ignore */
+  cm_ctx->match = path;
+  return GNUNET_NO; /* match, we are done! */
+}
+
+
+/**
+ * Extend path @a path by the @a num_peers from the @a peers
+ * array, assuming the owners past the current owner want it.
+ *
+ * @param path path to extend
+ * @param peers list of peers beyond the end of @a path
+ * @param num_peers length of the @a peers array
+ */
+static void
+extend_path (struct CadetPeerPath *path,
+             struct CadetPeer **peers,
+             unsigned int num_peers)
+{
+  unsigned int old_len = path->entries_length;
+  struct GNUNET_CONTAINER_HeapNode *hn;
+  int i;
+
+  /* If we extend an existing path, detach it from the
+     old owner and re-attach to the new one */
+  hn = NULL;
+  for (i=num_peers-1;i>=0;i--)
+  {
+    /* FIXME: note that path->desirability is used, but not yet updated here! */
+    hn = GCP_attach_path (peers[i],
+                          path,
+                          old_len + (unsigned int) i);
+    if (NULL != hn)
+      break;
+  }
+  if (NULL == hn)
+    return; /* none of the peers is interested in this path */
+  GCP_detach_path (path->entries[old_len-1].peer,
+                   path,
+                   path->hn);
+  path->hn = hn;
+  GNUNET_array_grow (path->entries,
+                     path->entries_length,
+                     old_len + i);
+  for (;i >= 0;i--)
+  {
+    struct CadetPeerPathEntry *entry = &path->entries[old_len + i];
+
+    entry->peer = peers[i];
+    entry->path = path;
+    GCP_path_entry_add (entry->peer,
+                        entry,
+                        old_len + i);
+  }
+}
+
+
+/**
+ * Create a peer path based on the result of a DHT lookup.  If we
+ * already know this path, or one that is longer, simply return NULL.
+ * Otherwise, we try to extend an existing path, or create a new one
+ * if applicable.
+ *
+ * @param get_path path of the get request
+ * @param get_path_length lenght of @a get_path
+ * @param put_path path of the put request
+ * @param put_path_length length of the @a put_path
+ * @return a path through the network
+ */
+void
+GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
+                        unsigned int get_path_length,
+                        const struct GNUNET_PeerIdentity *put_path,
+                        unsigned int put_path_length)
+{
+  struct CheckMatchContext cm_ctx;
+  struct CadetPeer *cpath[get_path_length + put_path_length];
+  struct CadetPeerPath *path;
+  struct GNUNET_CONTAINER_HeapNode *hn;
+  int i;
+
+  /* precompute 'cpath' so we can avoid doing the lookups lots of times */
+  for (unsigned int off=0;off<get_path_length + put_path_length;off++)
+  {
+    const struct GNUNET_PeerIdentity *pid;
+
+    pid = (off < get_path_length)
+      ? &get_path[get_path_length - off]
+      : &put_path[get_path_length + put_path_length - off];
+    cpath[off] = GCP_get (pid,
+                          GNUNET_YES);
+  }
+
+  /* First figure out if this path is a subset of an existing path, an
+     extension of an existing path, or a new path. */
+  cm_ctx.cpath = cpath;
+  cm_ctx.match = NULL;
+  for (i=get_path_length + put_path_length-1;i>=0;i--)
+  {
+    GCP_iterate_paths_at (cpath[i],
+                          (unsigned int) i,
+                          &check_match,
+                          &cm_ctx);
+    if (NULL != cm_ctx.match)
+    {
+      if (i == get_path_length + put_path_length - 1)
+      {
+        /* Existing path includes this one, nothing to do! */
+        return;
+      }
+      if (cm_ctx.match->entries_length == i + 1)
+      {
+        /* Existing path ends in the middle of new path, extend it! */
+        extend_path (cm_ctx.match,
+                     &cpath[i],
+                     get_path_length + put_path_length - i);
+        return;
+      }
+    }
+  }
+
+  /* No match at all, create completely new path */
+  path = GNUNET_new (struct CadetPeerPath);
+
+  /* First, try to attach it */
+  hn = NULL;
+  for (i=get_path_length + put_path_length-1;i>=0;i--)
+  {
+    path->entries_length = i;
+    /* FIXME: note that path->desirability is used, but not yet initialized here! */
+    hn = GCP_attach_path (cpath[i],
+                          path,
+                          (unsigned int) i);
+    if (NULL != hn)
+      break;
+  }
+  if (NULL == hn)
+  {
+    /* None of the peers on the path care about it. */
+    GNUNET_free (path);
+    return;
+  }
+  path->hn = hn;
+  path->entries_length = i;
+  path->entries = GNUNET_new_array (path->entries_length,
+                                    struct CadetPeerPathEntry);
+  for (;i>=0;i--)
+  {
+    struct CadetPeerPathEntry *entry = &path->entries[i];
+
+    entry->peer = cpath[i];
+    entry->path = path;
+    GCP_path_entry_add (entry->peer,
+                        entry,
+                        i);
+  }
+}
+
+
+/**
+ * We got an incoming connection, obtain the corresponding path.
+ *
+ * @param path_length number of segments on the @a path
+ * @param path through the network, in reverse order (we are at the end!)
+ * @return corresponding path object
+ */
+struct CadetPeerPath *
+GCPP_get_path_from_route (unsigned int path_length,
+                          const struct GNUNET_PeerIdentity *pids)
+{
+  GNUNET_assert (0); // FIXME!
+  return NULL;
+}
+
+
+/**
+ * Return the length of the path.  Excludes one end of the
+ * path, so the loopback path has length 0.
+ *
+ * @param path path to return the length for
+ * @return number of peers on the path
+ */
+unsigned int
+GCPP_get_length (struct CadetPeerPath *path)
+{
+  return path->entries_length;
+}
+
+
+/**
+ * Find peer's offset on path.
+ *
+ * @param path path to search
+ * @param cp peer to look for
+ * @return offset of @a cp on @a path, or UINT_MAX if not found
+ */
+unsigned int
+GCPP_find_peer (struct CadetPeerPath *path,
+                struct CadetPeer *cp)
+{
+  for (unsigned int off = 0;
+       off < path->entries_length;
+       off++)
+    if (cp == GCPP_get_peer_at_offset (path,
+                                       off))
+      return off;
+  return UINT_MAX;
+}
+
+
+/**
+ * Obtain the peer at offset @a off in @a path.
+ *
+ * @param path peer path to inspect
+ * @param off offset to return, must be smaller than path length
+ * @return the peer at offset @a off
+ */
+struct CadetPeer *
+GCPP_get_peer_at_offset (struct CadetPeerPath *path,
+                         unsigned int off)
+{
+  return path->entries[off].peer;
+}
+
+
+/**
+ * Convert a path to a human-readable string.
+ *
+ * @param path path to convert
+ * @return string, to be freed by caller (unlike other *_2s APIs!)
+ */
+char *
+GCPP_2s (struct CadetPeerPath *path)
+{
+  char *s;
+  char *old;
+
+  old = GNUNET_strdup ("");
+  for (unsigned int i = 0;
+       i < path->entries_length;
+       i++)
+  {
+    GNUNET_asprintf (&s,
+                     "%s %s",
+                     old,
+                     GCP_2s (GCPP_get_peer_at_offset (path,
+                                                      i)));
+    GNUNET_free_non_null (old);
+    old = s;
+  }
+  return old;
+}
+
+
+/* end of gnunet-service-cadet-new_paths.c */
diff --git a/src/cadet/gnunet-service-cadet-new_paths.h b/src/cadet/gnunet-service-cadet-new_paths.h
new file mode 100644 (file)
index 0000000..5714368
--- /dev/null
@@ -0,0 +1,182 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_paths.h
+ * @brief Information we track per path.
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SERVICE_CADET_PATHS_H
+#define GNUNET_SERVICE_CADET_PATHS_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet-service-cadet-new.h"
+
+/**
+ * Create a peer path based on the result of a DHT lookup.  If we
+ * already know this path, or one that is longer, simply return NULL.
+ * Otherwise, we try to extend an existing path, or create a new one
+ * if applicable.
+ *
+ * @param get_path path of the get request
+ * @param get_path_length lenght of @a get_path
+ * @param put_path path of the put request
+ * @param put_path_length length of the @a put_path
+ */
+void
+GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
+                        unsigned int get_path_length,
+                        const struct GNUNET_PeerIdentity *put_path,
+                        unsigned int put_path_length);
+
+
+/**
+ * We got an incoming connection, obtain the corresponding path.
+ *
+ * @param path_length number of segments on the @a path
+ * @param path through the network, in reverse order (we are at the end!)
+ * @return corresponding path object
+ */
+struct CadetPeerPath *
+GCPP_get_path_from_route (unsigned int path_length,
+                          const struct GNUNET_PeerIdentity *pids);
+
+
+/**
+ * Return the length of the path.  Excludes one end of the
+ * path, so the loopback path has length 0.
+ *
+ * @param path path to return the length for
+ * @return number of peers on the path
+ */
+unsigned int
+GCPP_get_length (struct CadetPeerPath *path);
+
+
+/**
+ * Return connection to @a destination using @a path, or return
+ * NULL if no such connection exists.
+ *
+ * @param path path to traverse
+ * @param destination destination node to get to, must be on path
+ * @param off offset of @a destination on @a path
+ * @return NULL if we have no existing connection
+ *         otherwise connection from us to @a destination via @a path
+ */
+struct CadetConnection *
+GCPP_get_connection (struct CadetPeerPath *path,
+                     struct CadetPeer *destination,
+                     unsigned int off);
+
+
+/**
+ * Notify @a path that it is used for connection @a cc
+ * which ends at the path's offset @a off.
+ *
+ * @param path the path to remember the @a cc
+ * @param off the offset where the @a cc ends
+ * @param cc the connection to remember
+ */
+void
+GCPP_add_connection (struct CadetPeerPath *path,
+                     unsigned int off,
+                     struct CadetConnection *cc);
+
+
+/**
+ * Notify @a path that it is no longer used for connection @a cc which
+ * ended at the path's offset @a off.
+ *
+ * @param path the path to forget the @a cc
+ * @param off the offset where the @a cc ended
+ * @param cc the connection to forget
+ */
+void
+GCPP_del_connection (struct CadetPeerPath *path,
+                     unsigned int off,
+                     struct CadetConnection *cc);
+
+
+/**
+ * Find peer's offset on path.
+ *
+ * @param path path to search
+ * @param cp peer to look for
+ * @return offset of @a cp on @a path, or UINT_MAX if not found
+ */
+unsigned int
+GCPP_find_peer (struct CadetPeerPath *path,
+                struct CadetPeer *cp);
+
+
+/**
+ * Return how much we like keeping the path.  This is an aggregate
+ * score based on various factors, including the age of the path
+ * (older == better), and the value of this path to all of its ajacent
+ * peers.  For example, long paths that end at a peer that we have no
+ * shorter way to reach are very desirable, while long paths that end
+ * at a peer for which we have a shorter way as well are much less
+ * desirable.  Higher values indicate more valuable paths.  The
+ * returned value should be used to decide which paths to remember.
+ *
+ * @param path path to return the length for
+ * @return desirability of the path, larger is more desirable
+ */
+GNUNET_CONTAINER_HeapCostType
+GCPP_get_desirability (const struct CadetPeerPath *path);
+
+
+/**
+ * The given peer @a cp used to own this @a path.  However, it is no
+ * longer interested in maintaining it, so the path should be
+ * discarded or shortened (in case a previous peer on the path finds
+ * the path desirable).
+ *
+ * @param path the path that is being released
+ */
+void
+GCPP_release (struct CadetPeerPath *path);
+
+
+/**
+ * Obtain the peer at offset @a off in @a path.
+ *
+ * @param path peer path to inspect
+ * @param off offset to return, must be smaller than path length
+ * @return peer at offset @a off
+ */
+struct CadetPeer *
+GCPP_get_peer_at_offset (struct CadetPeerPath *path,
+                         unsigned int off);
+
+
+/**
+ * Convert a path to a human-readable string.
+ *
+ * @param path path to convert
+ * @return string, to be freed by caller (unlike other *_2s APIs!)
+ */
+char *
+GCPP_2s (struct CadetPeerPath *p);
+
+
+#endif
diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c
new file mode 100644 (file)
index 0000000..47f725e
--- /dev/null
@@ -0,0 +1,1056 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_peer.c
+ * @brief Information we track per peer.
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - implement GCP_set_hello() / do HELLO advertising properly
+ * - optimize stopping/restarting DHT search to situations
+ *   where we actually need it (i.e. not if we have a direct connection,
+ *   or if we already have plenty of good short ones, or maybe even
+ *   to take a break if we have some connections and have searched a lot (?))
+ * - optimize MQM ready scans (O(n) -> O(1))
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_ats_service.h"
+#include "gnunet_core_service.h"
+#include "gnunet_statistics_service.h"
+#include "cadet_protocol.h"
+#include "cadet_path.h"
+#include "gnunet-service-cadet-new.h"
+#include "gnunet-service-cadet-new_connection.h"
+#include "gnunet-service-cadet-new_dht.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "gnunet-service-cadet-new_paths.h"
+#include "gnunet-service-cadet-new_tunnels.h"
+
+/**
+ * How long do we wait until tearing down an idle peer?
+ */
+#define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
+
+/**
+ * How long do we keep paths around if we no longer care about the peer?
+ */
+#define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
+
+
+
+
+/**
+ * Data structure used to track whom we have to notify about changes
+ * to our message queue.
+ */
+struct GCP_MessageQueueManager
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GCP_MessageQueueManager *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GCP_MessageQueueManager *prev;
+
+  /**
+   * Function to call with updated message queue object.
+   */
+  GCP_MessageQueueNotificationCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * The peer this is for.
+   */
+  struct CadetPeer *cp;
+
+  /**
+   * Envelope this manager would like to transmit once it is its turn.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+};
+
+
+/**
+ * Struct containing all information regarding a given peer
+ */
+struct CadetPeer
+{
+  /**
+   * ID of the peer
+   */
+  struct GNUNET_PeerIdentity pid;
+
+  /**
+   * Last time we heard from this peer
+   */
+  struct GNUNET_TIME_Absolute last_contact;
+
+  /**
+   * Array of DLLs of paths traversing the peer, organized by the
+   * offset of the peer on the larger path.
+   */
+  struct CadetPeerPathEntry **path_heads;
+
+  /**
+   * Array of DLL of paths traversing the peer, organized by the
+   * offset of the peer on the larger path.
+   */
+  struct CadetPeerPathEntry **path_tails;
+
+  /**
+   * Notifications to call when @e core_mq changes.
+   */
+  struct GCP_MessageQueueManager *mqm_head;
+
+  /**
+   * Notifications to call when @e core_mq changes.
+   */
+  struct GCP_MessageQueueManager *mqm_tail;
+
+  /**
+   * MIN-heap of paths owned by this peer (they also end at this
+   * peer).  Ordered by desirability.
+   */
+  struct GNUNET_CONTAINER_Heap *path_heap;
+
+  /**
+   * Handle to stop the DHT search for paths to this peer
+   */
+  struct GCD_search_handle *search_h;
+
+  /**
+   * Task to stop the DHT search for paths to this peer
+   */
+  struct GNUNET_SCHEDULER_Task *search_delayedXXX;
+
+  /**
+   * Task to destroy this entry.
+   */
+  struct GNUNET_SCHEDULER_Task *destroy_task;
+
+  /**
+   * Tunnel to this peer, if any.
+   */
+  struct CadetTunnel *t;
+
+  /**
+   * Connections that go through this peer; indexed by tid.
+   */
+  struct GNUNET_CONTAINER_MultiShortmap *connections;
+
+  /**
+   * Handle for core transmissions.
+   */
+  struct GNUNET_MQ_Handle *core_mq;
+
+  /**
+   * Hello message of the peer.
+   */
+  struct GNUNET_HELLO_Message *hello;
+
+  /**
+   * Handle to us offering the HELLO to the transport.
+   */
+  struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
+
+  /**
+   * Handle to our ATS request asking ATS to suggest an address
+   * to TRANSPORT for this peer (to establish a direct link).
+   */
+  struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
+
+  /**
+   * How many messages are in the queue to this peer.
+   */
+  unsigned int queue_n;
+
+  /**
+   * How many paths do we have to this peer (in all @e path_heads DLLs combined).
+   */
+  unsigned int num_paths;
+
+  /**
+   * Number of message queue managers of this peer that have a message in waiting.
+   *
+   * Used to quickly see if we need to bother scanning the @e msm_head DLL.
+   * TODO: could be replaced by another DLL that would then allow us to avoid
+   * the O(n)-scan of the DLL for ready entries!
+   */
+  unsigned int mqm_ready_counter;
+
+  /**
+   * Current length of the @e path_heads and @path_tails arrays.
+   * The arrays should be grown as needed.
+   */
+  unsigned int path_dll_length;
+
+};
+
+
+/**
+ * Get the static string for a peer ID.
+ *
+ * @param peer Peer.
+ *
+ * @return Static string for it's ID.
+ */
+const char *
+GCP_2s (const struct CadetPeer *peer)
+{
+  if (NULL == peer)
+    return "PEER(NULL)";
+  return GNUNET_i2s (&peer->pid);
+}
+
+
+/**
+ * This peer is no longer be needed, clean it up now.
+ *
+ * @param cls peer to clean up
+ */
+static void
+destroy_peer (void *cls)
+{
+  struct CadetPeer *cp = cls;
+
+  cp->destroy_task = NULL;
+  GNUNET_assert (NULL == cp->t);
+  GNUNET_assert (NULL == cp->core_mq);
+  GNUNET_assert (0 == cp->path_dll_length);
+  GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multipeermap_remove (peers,
+                                                       &cp->pid,
+                                                       cp));
+  GNUNET_free_non_null (cp->path_heads);
+  GNUNET_free_non_null (cp->path_tails);
+  cp->path_dll_length = 0;
+  if (NULL != cp->search_h)
+  {
+    GCD_search_stop (cp->search_h);
+    cp->search_h = NULL;
+  }
+  /* FIXME: clean up search_delayedXXX! */
+
+  if (NULL != cp->hello_offer)
+  {
+    GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
+    cp->hello_offer = NULL;
+  }
+  if (NULL != cp->connectivity_suggestion)
+  {
+    GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
+    cp->connectivity_suggestion = NULL;
+  }
+  GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
+  GNUNET_CONTAINER_heap_destroy (cp->path_heap);
+  GNUNET_free_non_null (cp->hello);
+  /* Peer should not be freed if paths exist; if there are no paths,
+     there ought to be no connections, and without connections, no
+     notifications. Thus we can assert that mqm_head is empty at this
+     point. */
+  GNUNET_assert (NULL == cp->mqm_head);
+  GNUNET_free (cp);
+}
+
+
+/**
+ * Set the message queue to @a mq for peer @a cp and notify watchers.
+ *
+ * @param cp peer to modify
+ * @param mq message queue to set (can be NULL)
+ */
+void
+GCP_set_mq (struct CadetPeer *cp,
+            struct GNUNET_MQ_Handle *mq)
+{
+  cp->core_mq = mq;
+
+  for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
+       NULL != mqm;
+       mqm = mqm->next)
+  {
+    if (NULL == mq)
+    {
+      if (NULL != mqm->env)
+      {
+        GNUNET_MQ_discard (mqm->env);
+        mqm->env = NULL;
+        mqm->cb (mqm->cb_cls,
+                 GNUNET_SYSERR);
+      }
+      else
+      {
+        mqm->cb (mqm->cb_cls,
+                 GNUNET_NO);
+      }
+    }
+    else
+    {
+      GNUNET_assert (NULL == mqm->env);
+      mqm->cb (mqm->cb_cls,
+               GNUNET_YES);
+    }
+  }
+}
+
+
+/**
+ * Transmit current envelope from this @a mqm.
+ *
+ * @param mqm mqm to transmit message for now
+ */
+static void
+mqm_execute (struct GCP_MessageQueueManager *mqm)
+{
+  struct CadetPeer *cp = mqm->cp;
+
+  /* Move entry to the end of the DLL, to be fair. */
+  if (mqm != cp->mqm_tail)
+  {
+    GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
+                                 cp->mqm_tail,
+                                 mqm);
+    GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
+                                      cp->mqm_tail,
+                                      mqm);
+  }
+  GNUNET_MQ_send (cp->core_mq,
+                  mqm->env);
+  mqm->env = NULL;
+  cp->mqm_ready_counter--;
+}
+
+
+/**
+ * Function called when CORE took one of the messages from
+ * a message queue manager and transmitted it.
+ *
+ * @param cls the `struct CadetPeeer` where we made progress
+ */
+static void
+mqm_send_done (void *cls)
+{
+  struct CadetPeer *cp = cls;
+
+  if (0 == cp->mqm_ready_counter)
+    return; /* nothing to do */
+  for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
+       NULL != mqm;
+       mqm = mqm->next)
+  {
+    if (NULL == mqm->env)
+      continue;
+    mqm_execute (mqm);
+    return;
+  }
+}
+
+
+/**
+ * Send the message in @a env to @a cp.
+ *
+ * @param mqm the message queue manager to use for transmission
+ * @param env envelope with the message to send; must NOT
+ *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
+ */
+void
+GCP_send (struct GCP_MessageQueueManager *mqm,
+          struct GNUNET_MQ_Envelope *env)
+{
+  struct CadetPeer *cp = mqm->cp;
+
+  GNUNET_assert (NULL != cp->core_mq);
+  GNUNET_assert (NULL == mqm->env);
+  GNUNET_MQ_notify_sent (env,
+                         &mqm_send_done,
+                         cp);
+  mqm->env = env;
+  cp->mqm_ready_counter++;
+  if (0 != GNUNET_MQ_get_length (cp->core_mq))
+    return;
+  mqm_execute (mqm);
+}
+
+
+/**
+ * Function called to destroy a peer now.
+ *
+ * @param cls NULL
+ * @param pid identity of the peer (unused)
+ * @param value the `struct CadetPeer` to clean up
+ * @return #GNUNET_OK (continue to iterate)
+ */
+static int
+destroy_iterator_cb (void *cls,
+                     const struct GNUNET_PeerIdentity *pid,
+                     void *value)
+{
+  struct CadetPeer *cp = value;
+
+  if (NULL != cp->destroy_task)
+  {
+    GNUNET_SCHEDULER_cancel (cp->destroy_task);
+    cp->destroy_task = NULL;
+  }
+  destroy_peer (cp);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Clean up all entries about all peers.
+ * Must only be called after all tunnels, CORE-connections and
+ * connections are down.
+ */
+void
+GCP_destroy_all_peers ()
+{
+  GNUNET_CONTAINER_multipeermap_iterate (peers,
+                                         &destroy_iterator_cb,
+                                         NULL);
+}
+
+
+/**
+ * This peer may no longer be needed, consider cleaning it up.
+ *
+ * @param cp peer to clean up
+ */
+static void
+consider_peer_destroy (struct CadetPeer *cp);
+
+
+/**
+ * We really no longere care about a peer, stop hogging memory with paths to it.
+ * Afterwards, see if there is more to be cleaned up about this peer.
+ *
+ * @param cls a `struct CadetPeer`.
+ */
+static void
+drop_paths (void *cls)
+{
+  struct CadetPeer *cp = cls;
+  struct CadetPeerPath *path;
+
+  cp->destroy_task = NULL;
+  while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
+    GCPP_release (path);
+  consider_peer_destroy (cp);
+}
+
+
+/**
+ * This peer may no longer be needed, consider cleaning it up.
+ *
+ * @param cp peer to clean up
+ */
+static void
+consider_peer_destroy (struct CadetPeer *cp)
+{
+  struct GNUNET_TIME_Relative exp;
+
+  if (NULL != cp->destroy_task)
+  {
+    GNUNET_SCHEDULER_cancel (cp->destroy_task);
+    cp->destroy_task = NULL;
+  }
+  if (NULL != cp->t)
+    return; /* still relevant! */
+  if (NULL != cp->core_mq)
+    return; /* still relevant! */
+  if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
+    return; /* still relevant! */
+  if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
+  {
+    cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
+                                                     &drop_paths,
+                                                     cp);
+    return;
+  }
+  if (0 < cp->path_dll_length)
+    return; /* still relevant! */
+  if (NULL != cp->hello)
+  {
+    /* relevant only until HELLO expires */
+    exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
+    cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
+                                                     &destroy_peer,
+                                                     cp);
+    return;
+  }
+  cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
+                                                   &destroy_peer,
+                                                   cp);
+}
+
+
+/**
+ * Add an entry to the DLL of all of the paths that this peer is on.
+ *
+ * @param cp peer to modify
+ * @param entry an entry on a path
+ * @param off offset of this peer on the path
+ */
+void
+GCP_path_entry_add (struct CadetPeer *cp,
+                    struct CadetPeerPathEntry *entry,
+                    unsigned int off)
+{
+  if (off >= cp->path_dll_length)
+  {
+    unsigned int len = cp->path_dll_length;
+
+    GNUNET_array_grow (cp->path_heads,
+                       len,
+                       off + 4);
+    GNUNET_array_grow (cp->path_tails,
+                       cp->path_dll_length,
+                       off + 4);
+  }
+  GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
+                               cp->path_tails[off],
+                               entry);
+  cp->num_paths++;
+
+  /* If we have a tunnel to this peer, tell the tunnel that there is a
+     new path available. */
+  if (NULL != cp->t)
+    GCT_consider_path (cp->t,
+                       entry->path,
+                       off);
+}
+
+
+/**
+ * Remove an entry from the DLL of all of the paths that this peer is on.
+ *
+ * @param cp peer to modify
+ * @param entry an entry on a path
+ * @param off offset of this peer on the path
+ */
+void
+GCP_path_entry_remove (struct CadetPeer *cp,
+                       struct CadetPeerPathEntry *entry,
+                       unsigned int off)
+{
+  GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
+                               cp->path_tails[off],
+                               entry);
+  GNUNET_assert (0 < cp->num_paths);
+  cp->num_paths--;
+}
+
+
+/**
+ * Try adding a @a path to this @a peer.  If the peer already
+ * has plenty of paths, return NULL.
+ *
+ * @param cp peer to which the @a path leads to
+ * @param path a path looking for an owner; may not be fully initialized yet!
+ * @param off offset of @a cp in @a path
+ * @return NULL if this peer does not care to become a new owner,
+ *         otherwise the node in the peer's path heap for the @a path.
+ */
+struct GNUNET_CONTAINER_HeapNode *
+GCP_attach_path (struct CadetPeer *cp,
+                 struct CadetPeerPath *path,
+                 unsigned int off)
+{
+  GNUNET_CONTAINER_HeapCostType desirability;
+  struct CadetPeerPath *root;
+  GNUNET_CONTAINER_HeapCostType root_desirability;
+  struct GNUNET_CONTAINER_HeapNode *hn;
+
+  /* FIXME: desirability is not yet initialized; tricky! */
+  desirability = GCPP_get_desirability (path);
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
+                                   (void **) &root,
+                                   &root_desirability))
+  {
+    root = NULL;
+    root_desirability = 0;
+  }
+
+  if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
+       (desirability < root_desirability) )
+    return NULL;
+
+  /* Yes, we'd like to add this path, add to our heap */
+  hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
+                                     (void *) cp,
+                                     desirability);
+
+  /* Consider maybe dropping other paths because of the new one */
+  if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
+      2 * DESIRED_CONNECTIONS_PER_TUNNEL)
+  {
+    /* Now we have way too many, drop least desirable UNLESS it is in use!
+       (Note that this intentionally keeps highly desireable, but currently
+       unused paths around in the hope that we might be able to switch, even
+       if the number of paths exceeds the threshold.) */
+    root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
+    if (NULL ==
+        GCPP_get_connection (root,
+                             cp,
+                             GCPP_get_length (root) - 1))
+    {
+      /* Got plenty of paths to this destination, and this is a low-quality
+         one that we don't care, allow it to die. */
+      GNUNET_assert (root ==
+                     GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
+      GCPP_release (root);
+    }
+  }
+  return hn;
+}
+
+
+/**
+ * This peer can no longer own @a path as the path
+ * has been extended and a peer further down the line
+ * is now the new owner.
+ *
+ * @param cp old owner of the @a path
+ * @param path path where the ownership is lost
+ * @param hn note in @a cp's path heap that must be deleted
+ */
+void
+GCP_detach_path (struct CadetPeer *cp,
+                 struct CadetPeerPath *path,
+                 struct GNUNET_CONTAINER_HeapNode *hn)
+{
+  GNUNET_assert (path ==
+                 GNUNET_CONTAINER_heap_remove_node (hn));
+}
+
+
+/**
+ * Add a @a connection to this @a cp.
+ *
+ * @param cp peer via which the @a connection goes
+ * @param cc the connection to add
+ */
+void
+GCP_add_connection (struct CadetPeer *cp,
+                    struct CadetConnection *cc)
+{
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multishortmap_put (cp->connections,
+                                                     &GCC_get_id (cc)->connection_of_tunnel,
+                                                     cc,
+                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+}
+
+
+/**
+ * Remove a @a connection that went via this @a cp.
+ *
+ * @param cp peer via which the @a connection went
+ * @param cc the connection to remove
+ */
+void
+GCP_remove_connection (struct CadetPeer *cp,
+                       struct CadetConnection *cc)
+{
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
+                                                        &GCC_get_id (cc)->connection_of_tunnel,
+                                                        cc));
+}
+
+
+/**
+ * This peer is now on more "active" duty, activate processes related to it.
+ *
+ * @param cp the more-active peer
+ */
+static void
+consider_peer_activate (struct CadetPeer *cp)
+{
+  uint32_t strength;
+
+  if (NULL != cp->destroy_task)
+  {
+    /* It's active, do not destory! */
+    GNUNET_SCHEDULER_cancel (cp->destroy_task);
+    cp->destroy_task = NULL;
+  }
+  if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
+       (NULL == cp->t) )
+  {
+    /* We're just on a path or directly connected; don't bother too much */
+    if (NULL != cp->connectivity_suggestion)
+    {
+      GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
+      cp->connectivity_suggestion = NULL;
+    }
+    if (NULL != cp->search_h)
+    {
+      GCD_search_stop (cp->search_h);
+      cp->search_h = NULL;
+    }
+    return;
+  }
+  if (NULL == cp->core_mq)
+  {
+    /* Lacks direct connection, try to create one by querying the DHT */
+    if ( (NULL == cp->search_h) &&
+         (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
+      cp->search_h
+        = GCD_search (&cp->pid);
+  }
+  else
+  {
+    /* Have direct connection, stop DHT search if active */
+    if (NULL != cp->search_h)
+    {
+      GCD_search_stop (cp->search_h);
+      cp->search_h = NULL;
+    }
+  }
+
+  /* If we have a tunnel, our urge for connections is much bigger */
+  strength = (NULL != cp->t) ? 32 : 1;
+  if (NULL != cp->connectivity_suggestion)
+    GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
+  cp->connectivity_suggestion
+    = GNUNET_ATS_connectivity_suggest (ats_ch,
+                                       &cp->pid,
+                                       strength);
+}
+
+
+/**
+ * Retrieve the CadetPeer stucture associated with the
+ * peer. Optionally create one and insert it in the appropriate
+ * structures if the peer is not known yet.
+ *
+ * @param peer_id Full identity of the peer.
+ * @param create #GNUNET_YES if a new peer should be created if unknown.
+ *               #GNUNET_NO to return NULL if peer is unknown.
+ * @return Existing or newly created peer structure.
+ *         NULL if unknown and not requested @a create
+ */
+struct CadetPeer *
+GCP_get (const struct GNUNET_PeerIdentity *peer_id,
+         int create)
+{
+  struct CadetPeer *cp;
+
+  cp = GNUNET_CONTAINER_multipeermap_get (peers,
+                                          peer_id);
+  if (NULL != cp)
+    return cp;
+  if (GNUNET_NO == create)
+    return NULL;
+  cp = GNUNET_new (struct CadetPeer);
+  cp->pid = *peer_id;
+  cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
+                                                           GNUNET_YES);
+  cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multipeermap_put (peers,
+                                                    &cp->pid,
+                                                    cp,
+                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  return cp;
+}
+
+
+/**
+ * Obtain the peer identity for a `struct CadetPeer`.
+ *
+ * @param cp our peer handle
+ * @return the peer identity
+ */
+const struct GNUNET_PeerIdentity *
+GCP_get_id (struct CadetPeer *cp)
+{
+  return &cp->pid;
+}
+
+
+/**
+ * Iterate over all known peers.
+ *
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
+                 void *cls)
+{
+  GNUNET_CONTAINER_multipeermap_iterate (peers,
+                                         iter,
+                                         cls);
+}
+
+
+/**
+ * Count the number of known paths toward the peer.
+ *
+ * @param peer Peer to get path info.
+ * @return Number of known paths.
+ */
+unsigned int
+GCP_count_paths (const struct CadetPeer *peer)
+{
+  return peer->num_paths;
+}
+
+
+/**
+ * Iterate over the paths to a peer.
+ *
+ * @param peer Peer to get path info.
+ * @param callback Function to call for every path.
+ * @param callback_cls Closure for @a callback.
+ * @return Number of iterated paths.
+ */
+unsigned int
+GCP_iterate_paths (struct CadetPeer *peer,
+                   GCP_PathIterator callback,
+                   void *callback_cls)
+{
+  unsigned int ret = 0;
+
+  for (unsigned int i=0;i<peer->path_dll_length;i++)
+  {
+    for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
+         NULL != pe;
+         pe = pe->next)
+    {
+      if (GNUNET_NO ==
+          callback (callback_cls,
+                    pe->path,
+                    i))
+        return ret;
+      ret++;
+    }
+  }
+  return ret;
+}
+
+
+/**
+ * Iterate over the paths to @a peer where
+ * @a peer is at distance @a dist from us.
+ *
+ * @param peer Peer to get path info.
+ * @param dist desired distance of @a peer to us on the path
+ * @param callback Function to call for every path.
+ * @param callback_cls Closure for @a callback.
+ * @return Number of iterated paths.
+ */
+unsigned int
+GCP_iterate_paths_at (struct CadetPeer *peer,
+                      unsigned int dist,
+                      GCP_PathIterator callback,
+                      void *callback_cls)
+{
+  unsigned int ret = 0;
+
+  if (dist<peer->path_dll_length)
+    return 0;
+  for (struct CadetPeerPathEntry *pe = peer->path_heads[dist];
+       NULL != pe;
+       pe = pe->next)
+  {
+    if (GNUNET_NO ==
+        callback (callback_cls,
+                  pe->path,
+                  dist))
+      return ret;
+    ret++;
+  }
+  return ret;
+}
+
+
+/**
+ * Get the tunnel towards a peer.
+ *
+ * @param peer Peer to get from.
+ * @param create #GNUNET_YES to create a tunnel if we do not have one
+ * @return Tunnel towards peer.
+ */
+struct CadetTunnel *
+GCP_get_tunnel (struct CadetPeer *peer,
+                int create)
+{
+  if (NULL == peer)
+    return NULL;
+  if ( (NULL != peer->t) ||
+       (GNUNET_NO == create) )
+    return peer->t;
+  peer->t = GCT_create_tunnel (peer);
+  consider_peer_activate (peer);
+  return peer->t;
+}
+
+
+/**
+ * We got a HELLO for a @a peer, remember it, and possibly
+ * trigger adequate actions (like trying to connect).
+ *
+ * @param peer the peer we got a HELLO for
+ * @param hello the HELLO to remember
+ */
+void
+GCP_set_hello (struct CadetPeer *peer,
+               const struct GNUNET_HELLO_Message *hello)
+{
+  /* FIXME: keep HELLO, possibly offer to TRANSPORT... */
+
+  consider_peer_destroy (peer);
+}
+
+
+/**
+ * The tunnel to the given peer no longer exists, remove it from our
+ * data structures, and possibly clean up the peer itself.
+ *
+ * @param peer the peer affected
+ * @param t the dead tunnel
+ */
+void
+GCP_drop_tunnel (struct CadetPeer *peer,
+                 struct CadetTunnel *t)
+{
+  GNUNET_assert (peer->t == t);
+  peer->t = NULL;
+  consider_peer_destroy (peer);
+}
+
+
+/**
+ * Test if @a cp has a core-level connection
+ *
+ * @param cp peer to test
+ * @return #GNUNET_YES if @a cp has a core-level connection
+ */
+int
+GCP_has_core_connection (struct CadetPeer *cp)
+{
+  return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
+ * Start message queue change notifications.
+ *
+ * @param cp peer to notify for
+ * @param cb function to call if mq becomes available or unavailable
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel request
+ */
+struct GCP_MessageQueueManager *
+GCP_request_mq (struct CadetPeer *cp,
+                GCP_MessageQueueNotificationCallback cb,
+                void *cb_cls)
+{
+  struct GCP_MessageQueueManager *mqm;
+
+  mqm = GNUNET_new (struct GCP_MessageQueueManager);
+  mqm->cb = cb;
+  mqm->cb_cls = cb_cls;
+  mqm->cp = cp;
+  GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
+                               cp->mqm_tail,
+                               mqm);
+  if (NULL != cp->core_mq)
+    cb (cb_cls,
+        GNUNET_YES);
+  return mqm;
+}
+
+
+/**
+ * Stops message queue change notifications.
+ *
+ * @param mqm handle matching request to cancel
+ * @param last_env final message to transmit, or NULL
+ */
+void
+GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
+                       struct GNUNET_MQ_Envelope *last_env)
+{
+  struct CadetPeer *cp = mqm->cp;
+
+  if (NULL != mqm->env)
+    GNUNET_MQ_discard (mqm->env);
+  if (NULL != last_env)
+  {
+    if (NULL != cp->core_mq)
+      GNUNET_MQ_send (cp->core_mq,
+                      last_env);
+    else
+      GNUNET_MQ_discard (last_env);
+  }
+  GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
+                               cp->mqm_tail,
+                               mqm);
+  GNUNET_free (mqm);
+}
+
+
+/**
+ * Send the message in @a env to @a cp, overriding queueing logic.
+ * This function should only be used to send error messages outside
+ * of flow and congestion control, similar to ICMP.  Note that
+ * the envelope may be silently discarded as well.
+ *
+ * @param cp peer to send the message to
+ * @param env envelope with the message to send
+ */
+void
+GCP_send_ooo (struct CadetPeer *cp,
+              struct GNUNET_MQ_Envelope *env)
+{
+  if (NULL == cp->core_mq)
+  {
+    GNUNET_MQ_discard (env);
+    return;
+  }
+  GNUNET_MQ_send (cp->core_mq,
+                  env);
+}
+
+
+
+
+/* end of gnunet-service-cadet-new_peer.c */
diff --git a/src/cadet/gnunet-service-cadet-new_peer.h b/src/cadet/gnunet-service-cadet-new_peer.h
new file mode 100644 (file)
index 0000000..c633f47
--- /dev/null
@@ -0,0 +1,368 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_peer.h
+ * @brief Information we track per peer.
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SERVICE_CADET_PEER_H
+#define GNUNET_SERVICE_CADET_PEER_H
+
+#include "gnunet-service-cadet-new.h"
+#include "gnunet_hello_lib.h"
+
+
+/**
+ * Get the static string for a peer ID.
+ *
+ * @param peer Peer.
+ *
+ * @return Static string for it's ID.
+ */
+const char *
+GCP_2s (const struct CadetPeer *peer);
+
+
+/**
+ * Retrieve the CadetPeer stucture associated with the
+ * peer. Optionally create one and insert it in the appropriate
+ * structures if the peer is not known yet.
+ *
+ * @param peer_id Full identity of the peer.
+ * @param create #GNUNET_YES if a new peer should be created if unknown.
+ *               #GNUNET_NO to return NULL if peer is unknown.
+ * @return Existing or newly created peer structure.
+ *         NULL if unknown and not requested @a create
+ */
+struct CadetPeer *
+GCP_get (const struct GNUNET_PeerIdentity *peer_id,
+         int create);
+
+
+/**
+ * Obtain the peer identity for a `struct CadetPeer`.
+ *
+ * @param cp our peer handle
+ * @return the peer identity
+ */
+const struct GNUNET_PeerIdentity *
+GCP_get_id (struct CadetPeer *cp);
+
+
+/**
+ * Iterate over all known peers.
+ *
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
+                 void *cls);
+
+
+/**
+ * Count the number of known paths toward the peer.
+ *
+ * @param cp Peer to get path info.
+ * @return Number of known paths.
+ */
+unsigned int
+GCP_count_paths (const struct CadetPeer *cp);
+
+
+/**
+ * Peer path iterator.
+ *
+ * @param cls Closure.
+ * @param path Path itself
+ * @param off offset of the target peer in @a path
+ * @return #GNUNET_YES if should keep iterating.
+ *         #GNUNET_NO otherwise.
+ */
+typedef int
+(*GCP_PathIterator) (void *cls,
+                     struct CadetPeerPath *path,
+                     unsigned int off);
+
+
+/**
+ * Iterate over the paths to a peer.
+ *
+ * @param cp Peer to get path info.
+ * @param callback Function to call for every path.
+ * @param callback_cls Closure for @a callback.
+ * @return Number of iterated paths.
+ */
+unsigned int
+GCP_iterate_paths (struct CadetPeer *cp,
+                   GCP_PathIterator callback,
+                   void *callback_cls);
+
+
+/**
+ * Iterate over the paths to @a peer where
+ * @a peer is at distance @a dist from us.
+ *
+ * @param peer Peer to get path info.
+ * @param dist desired distance of @a peer to us on the path
+ * @param callback Function to call for every path.
+ * @param callback_cls Closure for @a callback.
+ * @return Number of iterated paths.
+ */
+unsigned int
+GCP_iterate_paths_at (struct CadetPeer *peer,
+                      unsigned int dist,
+                      GCP_PathIterator callback,
+                      void *callback_cls);
+
+
+/**
+ * Remove an entry from the DLL of all of the paths that this peer is on.
+ *
+ * @param cp peer to modify
+ * @param entry an entry on a path
+ * @param off offset of this peer on the path
+ */
+void
+GCP_path_entry_remove (struct CadetPeer *cp,
+                       struct CadetPeerPathEntry *entry,
+                       unsigned int off);
+
+
+/**
+ * Add an entry to the DLL of all of the paths that this peer is on.
+ *
+ * @param cp peer to modify
+ * @param entry an entry on a path
+ * @param off offset of this peer on the path
+ */
+void
+GCP_path_entry_add (struct CadetPeer *cp,
+                    struct CadetPeerPathEntry *entry,
+                    unsigned int off);
+
+
+/**
+ * Get the tunnel towards a peer.
+ *
+ * @param cp Peer to get from.
+ * @param create #GNUNET_YES to create a tunnel if we do not have one
+ * @return Tunnel towards peer.
+ */
+struct CadetTunnel *
+GCP_get_tunnel (struct CadetPeer *cp,
+                int create);
+
+
+/**
+ * The tunnel to the given peer no longer exists, remove it from our
+ * data structures, and possibly clean up the peer itself.
+ *
+ * @param cp the peer affected
+ * @param t the dead tunnel
+ */
+void
+GCP_drop_tunnel (struct CadetPeer *cp,
+                 struct CadetTunnel *t);
+
+
+/**
+ * Try adding a @a path to this @a cp.  If the peer already
+ * has plenty of paths, return NULL.
+ *
+ * @param cp peer to which the @a path leads to
+ * @param path a path looking for an owner; may not be fully initialized yet!
+ * @param off offset of @a cp in @a path
+ * @return NULL if this peer does not care to become a new owner,
+ *         otherwise the node in the peer's path heap for the @a path.
+ */
+struct GNUNET_CONTAINER_HeapNode *
+GCP_attach_path (struct CadetPeer *cp,
+                 struct CadetPeerPath *path,
+                 unsigned int off);
+
+
+/**
+ * This peer can no longer own @a path as the path
+ * has been extended and a peer further down the line
+ * is now the new owner.
+ *
+ * @param cp old owner of the @a path
+ * @param path path where the ownership is lost
+ * @param hn note in @a cp's path heap that must be deleted
+ */
+void
+GCP_detach_path (struct CadetPeer *cp,
+                 struct CadetPeerPath *path,
+                 struct GNUNET_CONTAINER_HeapNode *hn);
+
+
+/**
+ * Add a @a connection to this @a cp.
+ *
+ * @param cp peer via which the @a connection goes
+ * @param cc the connection to add
+ */
+void
+GCP_add_connection (struct CadetPeer *cp,
+                    struct CadetConnection *cc);
+
+
+/**
+ * Remove a @a connection that went via this @a cp.
+ *
+ * @param cp peer via which the @a connection went
+ * @param cc the connection to remove
+ */
+void
+GCP_remove_connection (struct CadetPeer *cp,
+                       struct CadetConnection *cc);
+
+
+/**
+ * We got a HELLO for a @a cp, remember it, and possibly
+ * trigger adequate actions (like trying to connect).
+ *
+ * @param cp the peer we got a HELLO for
+ * @param hello the HELLO to remember
+ */
+void
+GCP_set_hello (struct CadetPeer *cp,
+               const struct GNUNET_HELLO_Message *hello);
+
+
+/**
+ * Clean up all entries about all peers.
+ * Must only be called after all tunnels, CORE-connections and
+ * connections are down.
+ */
+void
+GCP_destroy_all_peers (void);
+
+
+/**
+ * Data structure used to track whom we have to notify about changes
+ * in our ability to transmit to a given peer.
+ *
+ * All queue managers will be given equal chance for sending messages
+ * to @a cp.  This construct this guarantees fairness for access to @a
+ * cp among the different message queues.  Each connection or route
+ * will have its respective message queue managers for each direction.
+ */
+struct GCP_MessageQueueManager;
+
+
+/**
+ * Function to call with updated message queue object.
+ *
+ * @param cls closure
+ * @param available #GNUNET_YES if sending is now possible,
+ *                  #GNUNET_NO if sending is no longer possible
+ *                  #GNUNET_SYSERR if sending is no longer possible
+ *                                 and the last envelope was discarded
+ */
+typedef void
+(*GCP_MessageQueueNotificationCallback)(void *cls,
+                                        int available);
+
+
+/**
+ * Start message queue change notifications.  Will create a new slot
+ * to manage the message queue to the given @a cp.
+ *
+ * @param cp peer to notify for
+ * @param cb function to call if mq becomes available or unavailable
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel request
+ */
+struct GCP_MessageQueueManager *
+GCP_request_mq (struct CadetPeer *cp,
+                GCP_MessageQueueNotificationCallback cb,
+                void *cb_cls);
+
+
+/**
+ * Test if @a cp has a core-level connection
+ *
+ * @param cp peer to test
+ * @return #GNUNET_YES if @a cp has a core-level connection
+ */
+int
+GCP_has_core_connection (struct CadetPeer *cp);
+
+
+/**
+ * Send the message in @a env via a @a mqm.  Must only be called at
+ * most once after the respective
+ * #GCP_MessageQueueNotificationCallback was called with `available`
+ * set to #GNUNET_YES, and not after the callback was called with
+ * `available` set to #GNUNET_NO or #GNUNET_SYSERR.
+ *
+ * @param mqm message queue manager for the transmission
+ * @param env envelope with the message to send; must NOT
+ *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
+ */
+void
+GCP_send (struct GCP_MessageQueueManager *mqm,
+          struct GNUNET_MQ_Envelope *env);
+
+
+/**
+ * Send the message in @a env to @a cp, overriding queueing logic.
+ * This function should only be used to send error messages outside
+ * of flow and congestion control, similar to ICMP.  Note that
+ * the envelope may be silently discarded as well.
+ *
+ * @param cp peer to send the message to
+ * @param env envelope with the message to send
+ */
+void
+GCP_send_ooo (struct CadetPeer *cp,
+              struct GNUNET_MQ_Envelope *env);
+
+
+/**
+ * Stops message queue change notifications and sends a last message.
+ * In practice, this is implemented by sending that @a last_env
+ * message immediately (if any), ignoring queue order.
+ *
+ * @param mqm handle matching request to cancel
+ * @param last_env final message to transmit, or NULL
+ */
+void
+GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
+                       struct GNUNET_MQ_Envelope *last_env);
+
+
+/**
+ * Set the message queue to @a mq for peer @a cp and notify watchers.
+ *
+ * @param cp peer to modify
+ * @param mq message queue to set (can be NULL)
+ */
+void
+GCP_set_mq (struct CadetPeer *cp,
+            struct GNUNET_MQ_Handle *mq);
+
+
+#endif
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c b/src/cadet/gnunet-service-cadet-new_tunnels.c
new file mode 100644 (file)
index 0000000..23b270b
--- /dev/null
@@ -0,0 +1,2249 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2013, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_tunnels.c
+ * @brief Information we track per tunnel.
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ *
+ * FIXME:
+ * - when managing connections, distinguish those that
+ *   have (recently) had traffic from those that were
+ *   never ready (or not recently)
+ * - implement sending and receiving KX messages
+ * - implement processing of incoming decrypted plaintext messages
+ * - clean up KX logic!
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_signatures.h"
+#include "cadet_protocol.h"
+#include "cadet_path.h"
+#include "gnunet-service-cadet-new.h"
+#include "gnunet-service-cadet-new_channel.h"
+#include "gnunet-service-cadet-new_connection.h"
+#include "gnunet-service-cadet-new_tunnels.h"
+#include "gnunet-service-cadet-new_peer.h"
+#include "gnunet-service-cadet-new_paths.h"
+
+
+#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__)
+
+
+/**
+ * How long do we wait until tearing down an idle tunnel?
+ */
+#define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90)
+
+/**
+ * Yuck, replace by 'offsetof' expression?
+ * FIXME.
+ */
+#define AX_HEADER_SIZE (sizeof (uint32_t) * 2\
+                        + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey))
+
+
+/**
+ * Maximum number of skipped keys we keep in memory per tunnel.
+ */
+#define MAX_SKIPPED_KEYS 64
+
+/**
+ * Maximum number of keys (and thus ratchet steps) we are willing to
+ * skip before we decide this is either a bogus packet or a DoS-attempt.
+ */
+#define MAX_KEY_GAP 256
+
+
+/**
+ * Struct to old keys for skipped messages while advancing the Axolotl ratchet.
+ */
+struct CadetTunnelSkippedKey
+{
+  /**
+   * DLL next.
+   */
+  struct CadetTunnelSkippedKey *next;
+
+  /**
+   * DLL prev.
+   */
+  struct CadetTunnelSkippedKey *prev;
+
+  /**
+   * When was this key stored (for timeout).
+   */
+  struct GNUNET_TIME_Absolute timestamp;
+
+  /**
+   * Header key.
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey HK;
+
+  /**
+   * Message key.
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey MK;
+
+  /**
+   * Key number for a given HK.
+   */
+  unsigned int Kn;
+};
+
+
+/**
+ * Axolotl data, according to https://github.com/trevp/axolotl/wiki .
+ */
+struct CadetTunnelAxolotl
+{
+  /**
+   * A (double linked) list of stored message keys and associated header keys
+   * for "skipped" messages, i.e. messages that have not been
+   * received despite the reception of more recent messages, (head).
+   */
+  struct CadetTunnelSkippedKey *skipped_head;
+
+  /**
+   * Skipped messages' keys DLL, tail.
+   */
+  struct CadetTunnelSkippedKey *skipped_tail;
+
+  /**
+   * 32-byte root key which gets updated by DH ratchet.
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey RK;
+
+  /**
+   * 32-byte header key (send).
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey HKs;
+
+  /**
+   * 32-byte header key (recv)
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey HKr;
+
+  /**
+   * 32-byte next header key (send).
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey NHKs;
+
+  /**
+   * 32-byte next header key (recv).
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey NHKr;
+
+  /**
+   * 32-byte chain keys (used for forward-secrecy updating, send).
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey CKs;
+
+  /**
+   * 32-byte chain keys (used for forward-secrecy updating, recv).
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey CKr;
+
+  /**
+   * ECDH for key exchange (A0 / B0).
+   */
+  struct GNUNET_CRYPTO_EcdhePrivateKey *kx_0;
+
+  /**
+   * ECDH Ratchet key (send).
+   */
+  struct GNUNET_CRYPTO_EcdhePrivateKey *DHRs;
+
+  /**
+   * ECDH Ratchet key (recv).
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey DHRr;
+
+  /**
+   * When does this ratchet expire and a new one is triggered.
+   */
+  struct GNUNET_TIME_Absolute ratchet_expiration;
+
+  /**
+   * Number of elements in @a skipped_head <-> @a skipped_tail.
+   */
+  unsigned int skipped;
+
+  /**
+   * Message number (reset to 0 with each new ratchet, next message to send).
+   */
+  uint32_t Ns;
+
+  /**
+   * Message number (reset to 0 with each new ratchet, next message to recv).
+   */
+  uint32_t Nr;
+
+  /**
+   * Previous message numbers (# of msgs sent under prev ratchet)
+   */
+  uint32_t PNs;
+
+  /**
+   * True (#GNUNET_YES) if we have to send a new ratchet key in next msg.
+   */
+  int ratchet_flag;
+
+  /**
+   * Number of messages recieved since our last ratchet advance.
+   * - If this counter = 0, we cannot send a new ratchet key in next msg.
+   * - If this counter > 0, we can (but don't yet have to) send a new key.
+   */
+  unsigned int ratchet_allowed;
+
+  /**
+   * Number of messages recieved since our last ratchet advance.
+   * - If this counter = 0, we cannot send a new ratchet key in next msg.
+   * - If this counter > 0, we can (but don't yet have to) send a new key.
+   */
+  unsigned int ratchet_counter;
+
+};
+
+
+/**
+ * Struct used to save messages in a non-ready tunnel to send once connected.
+ */
+struct CadetTunnelQueueEntry
+{
+  /**
+   * We are entries in a DLL
+   */
+  struct CadetTunnelQueueEntry *next;
+
+  /**
+   * We are entries in a DLL
+   */
+  struct CadetTunnelQueueEntry *prev;
+
+  /**
+   * Tunnel these messages belong in.
+   */
+  struct CadetTunnel *t;
+
+  /**
+   * Continuation to call once sent (on the channel layer).
+   */
+  GNUNET_SCHEDULER_TaskCallback cont;
+
+  /**
+   * Closure for @c cont.
+   */
+  void *cont_cls;
+
+  /**
+   * Envelope of message to send follows.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * Where to put the connection identifier into the payload
+   * of the message in @e env once we have it?
+   */
+  struct GNUNET_CADET_ConnectionTunnelIdentifier *cid;
+};
+
+
+/**
+ * Struct containing all information regarding a tunnel to a peer.
+ */
+struct CadetTunnel
+{
+  /**
+   * Destination of the tunnel.
+   */
+  struct CadetPeer *destination;
+
+  /**
+   * Peer's ephemeral key, to recreate @c e_key and @c d_key when own
+   * ephemeral key changes.
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey peers_ephemeral_key;
+
+  /**
+   * Encryption ("our") key. It is only "confirmed" if kx_ctx is NULL.
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
+
+  /**
+   * Decryption ("their") key. It is only "confirmed" if kx_ctx is NULL.
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
+
+  /**
+   * Axolotl info.
+   */
+  struct CadetTunnelAxolotl ax;
+
+  /**
+   * State of the tunnel connectivity.
+   */
+  enum CadetTunnelCState cstate;
+
+  /**
+   * State of the tunnel encryption.
+   */
+  enum CadetTunnelEState estate;
+
+  /**
+   * Task to start the rekey process.
+   */
+  struct GNUNET_SCHEDULER_Task *rekey_task;
+
+  /**
+   * Tokenizer for decrypted messages.
+   */
+  struct GNUNET_MessageStreamTokenizer *mst;
+
+  /**
+   * Dispatcher for decrypted messages only (do NOT use for sending!).
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * DLL of connections that are actively used to reach the destination peer.
+   */
+  struct CadetTConnection *connection_head;
+
+  /**
+   * DLL of connections that are actively used to reach the destination peer.
+   */
+  struct CadetTConnection *connection_tail;
+
+  /**
+   * Channels inside this tunnel. Maps
+   * `struct GNUNET_CADET_ChannelTunnelNumber` to a `struct CadetChannel`.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap32 *channels;
+
+  /**
+   * Channel ID for the next created channel in this tunnel.
+   */
+  struct GNUNET_CADET_ChannelTunnelNumber next_chid;
+
+  /**
+   * Queued messages, to transmit once tunnel gets connected.
+   */
+  struct CadetTunnelQueueEntry *tq_head;
+
+  /**
+   * Queued messages, to transmit once tunnel gets connected.
+   */
+  struct CadetTunnelQueueEntry *tq_tail;
+
+  /**
+   * Task scheduled if there are no more channels using the tunnel.
+   */
+  struct GNUNET_SCHEDULER_Task *destroy_task;
+
+  /**
+   * Task to trim connections if too many are present.
+   */
+  struct GNUNET_SCHEDULER_Task *maintain_connections_task;
+
+  /**
+   * Ephemeral message in the queue (to avoid queueing more than one).
+   */
+  struct CadetConnectionQueue *ephm_hKILL;
+
+  /**
+   * Pong message in the queue.
+   */
+  struct CadetConnectionQueue *pong_hKILL;
+
+  /**
+   * Number of connections in the @e connection_head DLL.
+   */
+  unsigned int num_connections;
+
+  /**
+   * Number of entries in the @e tq_head DLL.
+   */
+  unsigned int tq_len;
+};
+
+
+/**
+ * Get the static string for the peer this tunnel is directed.
+ *
+ * @param t Tunnel.
+ *
+ * @return Static string the destination peer's ID.
+ */
+const char *
+GCT_2s (const struct CadetTunnel *t)
+{
+  static char buf[64];
+
+  if (NULL == t)
+    return "T(NULL)";
+
+  GNUNET_snprintf (buf,
+                   sizeof (buf),
+                   "T(%s)",
+                   GCP_2s (t->destination));
+  return buf;
+}
+
+
+/**
+ * Return the peer to which this tunnel goes.
+ *
+ * @param t a tunnel
+ * @return the destination of the tunnel
+ */
+struct CadetPeer *
+GCT_get_destination (struct CadetTunnel *t)
+{
+  return t->destination;
+}
+
+
+/**
+ * Count channels of a tunnel.
+ *
+ * @param t Tunnel on which to count.
+ *
+ * @return Number of channels.
+ */
+unsigned int
+GCT_count_channels (struct CadetTunnel *t)
+{
+  return GNUNET_CONTAINER_multihashmap32_size (t->channels);
+}
+
+
+/**
+ * Lookup a channel by its @a chid.
+ *
+ * @param t tunnel to look in
+ * @param chid number of channel to find
+ * @return NULL if channel does not exist
+ */
+struct CadetChannel *
+lookup_channel (struct CadetTunnel *t,
+                struct GNUNET_CADET_ChannelTunnelNumber chid)
+{
+  return GNUNET_CONTAINER_multihashmap32_get (t->channels,
+                                              ntohl (chid.cn));
+}
+
+
+/**
+ * Count all created connections of a tunnel. Not necessarily ready connections!
+ *
+ * @param t Tunnel on which to count.
+ *
+ * @return Number of connections created, either being established or ready.
+ */
+unsigned int
+GCT_count_any_connections (struct CadetTunnel *t)
+{
+  return t->num_connections;
+}
+
+
+/**
+ * Get the connectivity state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's connectivity state.
+ */
+enum CadetTunnelCState
+GCT_get_cstate (struct CadetTunnel *t)
+{
+  return t->cstate;
+}
+
+
+/**
+ * Get the encryption state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's encryption state.
+ */
+enum CadetTunnelEState
+GCT_get_estate (struct CadetTunnel *t)
+{
+  return t->estate;
+}
+
+
+/**
+ * Create a new Axolotl ephemeral (ratchet) key.
+ *
+ * @param t Tunnel.
+ */
+static void
+new_ephemeral (struct CadetTunnel *t)
+{
+  GNUNET_free_non_null (t->ax.DHRs);
+  t->ax.DHRs = GNUNET_CRYPTO_ecdhe_key_create ();
+}
+
+
+/* ************************************** start core crypto ***************************** */
+
+
+/**
+ * Calculate HMAC.
+ *
+ * @param plaintext Content to HMAC.
+ * @param size Size of @c plaintext.
+ * @param iv Initialization vector for the message.
+ * @param key Key to use.
+ * @param hmac[out] Destination to store the HMAC.
+ */
+static void
+t_hmac (const void *plaintext,
+        size_t size,
+        uint32_t iv,
+        const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+        struct GNUNET_ShortHashCode *hmac)
+{
+  static const char ctx[] = "cadet authentication key";
+  struct GNUNET_CRYPTO_AuthKey auth_key;
+  struct GNUNET_HashCode hash;
+
+  GNUNET_CRYPTO_hmac_derive_key (&auth_key,
+                                 key,
+                                 &iv, sizeof (iv),
+                                 key, sizeof (*key),
+                                 ctx, sizeof (ctx),
+                                 NULL);
+  /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */
+  GNUNET_CRYPTO_hmac (&auth_key,
+                      plaintext,
+                      size,
+                      &hash);
+  GNUNET_memcpy (hmac,
+                 &hash,
+                 sizeof (*hmac));
+}
+
+
+/**
+ * Perform a HMAC.
+ *
+ * @param key Key to use.
+ * @param hash[out] Resulting HMAC.
+ * @param source Source key material (data to HMAC).
+ * @param len Length of @a source.
+ */
+static void
+t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+                struct GNUNET_HashCode *hash,
+                const void *source,
+                unsigned int len)
+{
+  static const char ctx[] = "axolotl HMAC-HASH";
+  struct GNUNET_CRYPTO_AuthKey auth_key;
+
+  GNUNET_CRYPTO_hmac_derive_key (&auth_key,
+                                 key,
+                                 ctx, sizeof (ctx),
+                                 NULL);
+  GNUNET_CRYPTO_hmac (&auth_key,
+                      source,
+                      len,
+                      hash);
+}
+
+
+/**
+ * Derive a symmetric encryption key from an HMAC-HASH.
+ *
+ * @param key Key to use for the HMAC.
+ * @param[out] out Key to generate.
+ * @param source Source key material (data to HMAC).
+ * @param len Length of @a source.
+ */
+static void
+t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+                   struct GNUNET_CRYPTO_SymmetricSessionKey *out,
+                   const void *source,
+                   unsigned int len)
+{
+  static const char ctx[] = "axolotl derive key";
+  struct GNUNET_HashCode h;
+
+  t_ax_hmac_hash (key,
+                  &h,
+                  source,
+                  len);
+  GNUNET_CRYPTO_kdf (out, sizeof (*out),
+                     ctx, sizeof (ctx),
+                     &h, sizeof (h),
+                     NULL);
+}
+
+
+/**
+ * Encrypt data with the axolotl tunnel key.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination with @a size bytes for the encrypted data.
+ * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes
+ * @param size Size of the buffers at @a src and @a dst
+ */
+static void
+t_ax_encrypt (struct CadetTunnel *t,
+              void *dst,
+              const void *src,
+              size_t size)
+{
+  struct GNUNET_CRYPTO_SymmetricSessionKey MK;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct CadetTunnelAxolotl *ax;
+  size_t out_size;
+
+  ax = &t->ax;
+  ax->ratchet_counter++;
+  if ( (GNUNET_YES == ax->ratchet_allowed) &&
+       ( (ratchet_messages <= ax->ratchet_counter) ||
+         (0 == GNUNET_TIME_absolute_get_remaining (ax->ratchet_expiration).rel_value_us)) )
+  {
+    ax->ratchet_flag = GNUNET_YES;
+  }
+  if (GNUNET_YES == ax->ratchet_flag)
+  {
+    /* Advance ratchet */
+    struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
+    struct GNUNET_HashCode dh;
+    struct GNUNET_HashCode hmac;
+    static const char ctx[] = "axolotl ratchet";
+
+    new_ephemeral (t);
+    ax->HKs = ax->NHKs;
+
+    /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
+    GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
+                            &ax->DHRr,
+                            &dh);
+    t_ax_hmac_hash (&ax->RK,
+                    &hmac,
+                    &dh,
+                    sizeof (dh));
+    GNUNET_CRYPTO_kdf (keys, sizeof (keys),
+                       ctx, sizeof (ctx),
+                       &hmac, sizeof (hmac),
+                       NULL);
+    ax->RK = keys[0];
+    ax->NHKs = keys[1];
+    ax->CKs = keys[2];
+
+    ax->PNs = ax->Ns;
+    ax->Ns = 0;
+    ax->ratchet_flag = GNUNET_NO;
+    ax->ratchet_allowed = GNUNET_NO;
+    ax->ratchet_counter = 0;
+    ax->ratchet_expiration
+      = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
+                                  ratchet_time);
+  }
+
+  t_hmac_derive_key (&ax->CKs,
+                     &MK,
+                     "0",
+                     1);
+  GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+                                     &MK,
+                                     NULL, 0,
+                                     NULL);
+
+  out_size = GNUNET_CRYPTO_symmetric_encrypt (src,
+                                              size,
+                                              &MK,
+                                              &iv,
+                                              dst);
+  GNUNET_assert (size == out_size);
+  t_hmac_derive_key (&ax->CKs,
+                     &ax->CKs,
+                     "1",
+                     1);
+}
+
+
+/**
+ * Decrypt data with the axolotl tunnel key.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination for the decrypted data, must contain @a size bytes.
+ * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes.
+ * @param size Size of the @a src and @a dst buffers
+ */
+static void
+t_ax_decrypt (struct CadetTunnel *t,
+              void *dst,
+              const void *src,
+              size_t size)
+{
+  struct GNUNET_CRYPTO_SymmetricSessionKey MK;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct CadetTunnelAxolotl *ax;
+  size_t out_size;
+
+  ax = &t->ax;
+  t_hmac_derive_key (&ax->CKr,
+                     &MK,
+                     "0",
+                     1);
+  GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+                                     &MK,
+                                     NULL, 0,
+                                     NULL);
+  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
+  out_size = GNUNET_CRYPTO_symmetric_decrypt (src,
+                                              size,
+                                              &MK,
+                                              &iv,
+                                              dst);
+  GNUNET_assert (out_size == size);
+  t_hmac_derive_key (&ax->CKr,
+                     &ax->CKr,
+                     "1",
+                     1);
+}
+
+
+/**
+ * Encrypt header with the axolotl header key.
+ *
+ * @param t Tunnel whose key to use.
+ * @param msg Message whose header to encrypt.
+ */
+static void
+t_h_encrypt (struct CadetTunnel *t,
+             struct GNUNET_CADET_TunnelEncryptedMessage *msg)
+{
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct CadetTunnelAxolotl *ax;
+  size_t out_size;
+
+  ax = &t->ax;
+  GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+                                     &ax->HKs,
+                                     NULL, 0,
+                                     NULL);
+  out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns,
+                                              AX_HEADER_SIZE,
+                                              &ax->HKs,
+                                              &iv,
+                                              &msg->Ns);
+  GNUNET_assert (AX_HEADER_SIZE == out_size);
+}
+
+
+/**
+ * Decrypt header with the current axolotl header key.
+ *
+ * @param t Tunnel whose current ax HK to use.
+ * @param src Message whose header to decrypt.
+ * @param dst Where to decrypt header to.
+ */
+static void
+t_h_decrypt (struct CadetTunnel *t,
+             const struct GNUNET_CADET_TunnelEncryptedMessage *src,
+             struct GNUNET_CADET_TunnelEncryptedMessage *dst)
+{
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct CadetTunnelAxolotl *ax;
+  size_t out_size;
+
+  ax = &t->ax;
+  GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+                                     &ax->HKr,
+                                     NULL, 0,
+                                     NULL);
+  out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns,
+                                              AX_HEADER_SIZE,
+                                              &ax->HKr,
+                                              &iv,
+                                              &dst->Ns);
+  GNUNET_assert (AX_HEADER_SIZE == out_size);
+}
+
+
+/**
+ * Delete a key from the list of skipped keys.
+ *
+ * @param t Tunnel to delete from.
+ * @param key Key to delete.
+ */
+static void
+delete_skipped_key (struct CadetTunnel *t,
+                    struct CadetTunnelSkippedKey *key)
+{
+  GNUNET_CONTAINER_DLL_remove (t->ax.skipped_head,
+                               t->ax.skipped_tail,
+                               key);
+  GNUNET_free (key);
+  t->ax.skipped--;
+}
+
+
+/**
+ * Decrypt and verify data with the appropriate tunnel key and verify that the
+ * data has not been altered since it was sent by the remote peer.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination for the plaintext.
+ * @param src Source of the message. Can overlap with @c dst.
+ * @param size Size of the message.
+ * @return Size of the decrypted data, -1 if an error was encountered.
+ */
+static ssize_t
+try_old_ax_keys (struct CadetTunnel *t,
+                 void *dst,
+                 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
+                 size_t size)
+{
+  struct CadetTunnelSkippedKey *key;
+  struct GNUNET_ShortHashCode *hmac;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
+  struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
+  size_t esize;
+  size_t res;
+  size_t len;
+  unsigned int N;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Trying skipped keys\n");
+  hmac = &plaintext_header.hmac;
+  esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
+
+  /* Find a correct Header Key */
+  valid_HK = NULL;
+  for (key = t->ax.skipped_head; NULL != key; key = key->next)
+  {
+    t_hmac (&src->Ns,
+            AX_HEADER_SIZE + esize,
+            0,
+            &key->HK,
+            hmac);
+    if (0 == memcmp (hmac,
+                     &src->hmac,
+                     sizeof (*hmac)))
+    {
+      valid_HK = &key->HK;
+      break;
+    }
+  }
+  if (NULL == key)
+    return -1;
+
+  /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
+  GNUNET_assert (size > sizeof (struct GNUNET_CADET_TunnelEncryptedMessage));
+  len = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
+  GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader));
+
+  /* Decrypt header */
+  GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+                                     &key->HK,
+                                     NULL, 0,
+                                     NULL);
+  res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns,
+                                         AX_HEADER_SIZE,
+                                         &key->HK,
+                                         &iv,
+                                         &plaintext_header.Ns);
+  GNUNET_assert (AX_HEADER_SIZE == res);
+
+  /* Find the correct message key */
+  N = ntohl (plaintext_header.Ns);
+  while ( (NULL != key) &&
+          (N != key->Kn) )
+    key = key->next;
+  if ( (NULL == key) ||
+       (0 != memcmp (&key->HK,
+                     valid_HK,
+                     sizeof (*valid_HK))) )
+    return -1;
+
+  /* Decrypt payload */
+  GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+                                     &key->MK,
+                                     NULL,
+                                     0,
+                                     NULL);
+  res = GNUNET_CRYPTO_symmetric_decrypt (&src[1],
+                                         len,
+                                         &key->MK,
+                                         &iv,
+                                         dst);
+  delete_skipped_key (t,
+                      key);
+  return res;
+}
+
+
+/**
+ * Delete a key from the list of skipped keys.
+ *
+ * @param t Tunnel to delete from.
+ * @param HKr Header Key to use.
+ */
+static void
+store_skipped_key (struct CadetTunnel *t,
+                   const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr)
+{
+  struct CadetTunnelSkippedKey *key;
+
+  key = GNUNET_new (struct CadetTunnelSkippedKey);
+  key->timestamp = GNUNET_TIME_absolute_get ();
+  key->Kn = t->ax.Nr;
+  key->HK = t->ax.HKr;
+  t_hmac_derive_key (&t->ax.CKr,
+                     &key->MK,
+                     "0",
+                     1);
+  t_hmac_derive_key (&t->ax.CKr,
+                     &t->ax.CKr,
+                     "1",
+                     1);
+  GNUNET_CONTAINER_DLL_insert (t->ax.skipped_head,
+                               t->ax.skipped_tail,
+                               key);
+  t->ax.skipped++;
+  t->ax.Nr++;
+}
+
+
+/**
+ * Stage skipped AX keys and calculate the message key.
+ * Stores each HK and MK for skipped messages.
+ *
+ * @param t Tunnel where to stage the keys.
+ * @param HKr Header key.
+ * @param Np Received meesage number.
+ * @return #GNUNET_OK if keys were stored.
+ *         #GNUNET_SYSERR if an error ocurred (Np not expected).
+ */
+static int
+store_ax_keys (struct CadetTunnel *t,
+               const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr,
+               uint32_t Np)
+{
+  int gap;
+
+  gap = Np - t->ax.Nr;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Storing skipped keys [%u, %u)\n",
+       t->ax.Nr,
+       Np);
+  if (MAX_KEY_GAP < gap)
+  {
+    /* Avoid DoS (forcing peer to do 2^33 chain HMAC operations) */
+    /* TODO: start new key exchange on return */
+    GNUNET_break_op (0);
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Got message %u, expected %u+\n",
+         Np,
+         t->ax.Nr);
+    return GNUNET_SYSERR;
+  }
+  if (0 > gap)
+  {
+    /* Delayed message: don't store keys, flag to try old keys. */
+    return GNUNET_SYSERR;
+  }
+
+  while (t->ax.Nr < Np)
+    store_skipped_key (t,
+                       HKr);
+
+  while (t->ax.skipped > MAX_SKIPPED_KEYS)
+    delete_skipped_key (t,
+                        t->ax.skipped_tail);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Decrypt and verify data with the appropriate tunnel key and verify that the
+ * data has not been altered since it was sent by the remote peer.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination for the plaintext.
+ * @param src Source of the message. Can overlap with @c dst.
+ * @param size Size of the message.
+ * @return Size of the decrypted data, -1 if an error was encountered.
+ */
+static ssize_t
+t_ax_decrypt_and_validate (struct CadetTunnel *t,
+                           void *dst,
+                           const struct GNUNET_CADET_TunnelEncryptedMessage *src,
+                           size_t size)
+{
+  struct CadetTunnelAxolotl *ax;
+  struct GNUNET_ShortHashCode msg_hmac;
+  struct GNUNET_HashCode hmac;
+  struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
+  uint32_t Np;
+  uint32_t PNp;
+  size_t esize; /* Size of encryped payload */
+
+  esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
+  ax = &t->ax;
+
+  /* Try current HK */
+  t_hmac (&src->Ns,
+          AX_HEADER_SIZE + esize,
+          0, &ax->HKr,
+          &msg_hmac);
+  if (0 != memcmp (&msg_hmac,
+                   &src->hmac,
+                   sizeof (msg_hmac)))
+  {
+    static const char ctx[] = "axolotl ratchet";
+    struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
+    struct GNUNET_CRYPTO_SymmetricSessionKey HK;
+    struct GNUNET_HashCode dh;
+    struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
+
+    /* Try Next HK */
+    t_hmac (&src->Ns,
+            AX_HEADER_SIZE + esize,
+            0,
+            &ax->NHKr,
+            &msg_hmac);
+    if (0 != memcmp (&msg_hmac,
+                     &src->hmac,
+                     sizeof (msg_hmac)))
+    {
+      /* Try the skipped keys, if that fails, we're out of luck. */
+      return try_old_ax_keys (t,
+                              dst,
+                              src,
+                              size);
+    }
+    HK = ax->HKr;
+    ax->HKr = ax->NHKr;
+    t_h_decrypt (t,
+                 src,
+                 &plaintext_header);
+    Np = ntohl (plaintext_header.Ns);
+    PNp = ntohl (plaintext_header.PNs);
+    DHRp = &plaintext_header.DHRs;
+    store_ax_keys (t,
+                   &HK,
+                   PNp);
+
+    /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
+    GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
+                            DHRp,
+                            &dh);
+    t_ax_hmac_hash (&ax->RK,
+                    &hmac,
+                    &dh, sizeof (dh));
+    GNUNET_CRYPTO_kdf (keys, sizeof (keys),
+                       ctx, sizeof (ctx),
+                       &hmac, sizeof (hmac),
+                       NULL);
+
+    /* Commit "purported" keys */
+    ax->RK = keys[0];
+    ax->NHKr = keys[1];
+    ax->CKr = keys[2];
+    ax->DHRr = *DHRp;
+    ax->Nr = 0;
+    ax->ratchet_allowed = GNUNET_YES;
+  }
+  else
+  {
+    t_h_decrypt (t,
+                 src,
+                 &plaintext_header);
+    Np = ntohl (plaintext_header.Ns);
+    PNp = ntohl (plaintext_header.PNs);
+  }
+  if ( (Np != ax->Nr) &&
+       (GNUNET_OK != store_ax_keys (t,
+                                    &ax->HKr,
+                                    Np)) )
+  {
+    /* Try the skipped keys, if that fails, we're out of luck. */
+    return try_old_ax_keys (t,
+                            dst,
+                            src,
+                            size);
+  }
+
+  t_ax_decrypt (t,
+                dst,
+                &src[1],
+                esize);
+  ax->Nr = Np + 1;
+  return esize;
+}
+
+
+/**
+ * Send a KX message.
+ *
+ * FIXME: does not take care of sender-authentication yet!
+ *
+ * @param t Tunnel on which to send it.
+ * @param force_reply Force the other peer to reply with a KX message.
+ */
+static void
+send_kx (struct CadetTunnel *t,
+         int force_reply)
+{
+  struct CadetTunnelAxolotl *ax = &t->ax;
+  struct CadetConnection *c;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
+  enum GNUNET_CADET_KX_Flags flags;
+
+#if FIXME
+  if (NULL != t->ephm_h)
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         "     already queued, nop\n");
+    return;
+  }
+#endif
+  c = NULL; // FIXME: figure out where to transmit...
+
+  // GNUNET_assert (GNUNET_NO == GCT_is_loopback (t));
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
+  flags = GNUNET_CADET_KX_FLAG_NONE;
+  if (GNUNET_YES == force_reply)
+    flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
+  msg->flags = htonl (flags);
+  msg->cid = *GCC_get_id (c);
+  GNUNET_CRYPTO_ecdhe_key_get_public (ax->kx_0,
+                                      &msg->ephemeral_key);
+  GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs,
+                                      &msg->ratchet_key);
+
+  // FIXME: send 'env'.
+#if FIXME
+  t->ephm_h = GCC_send_prebuilt_message (&msg.header,
+                                         UINT16_MAX,
+                                         zero,
+                                         c,
+                                         GCC_is_origin (c, GNUNET_YES),
+                                         GNUNET_YES, &ephm_sent, t);
+  if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
+    GCT_change_estate (t, CADET_TUNNEL_KEY_SENT);
+#endif
+}
+
+
+/**
+ * Handle KX message.
+ *
+ * FIXME: sender-authentication in KX is missing!
+ *
+ * @param ct connection/tunnel combo that received encrypted message
+ * @param msg the key exchange message
+ */
+void
+GCT_handle_kx (struct CadetTConnection *ct,
+               const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
+{
+  struct CadetTunnel *t = ct->t;
+  struct CadetTunnelAxolotl *ax = &t->ax;
+  struct GNUNET_HashCode key_material[3];
+  struct GNUNET_CRYPTO_SymmetricSessionKey keys[5];
+  const char salt[] = "CADET Axolotl salt";
+  const struct GNUNET_PeerIdentity *pid;
+  int am_I_alice;
+
+  pid = GCP_get_id (t->destination);
+  if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id,
+                                           pid))
+    am_I_alice = GNUNET_YES;
+  else if (0 < GNUNET_CRYPTO_cmp_peer_identity (&my_full_id,
+                                                pid))
+    am_I_alice = GNUNET_NO;
+  else
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+
+  if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->flags)))
+  {
+    if (NULL != t->rekey_task)
+    {
+      GNUNET_SCHEDULER_cancel (t->rekey_task);
+      t->rekey_task = NULL;
+    }
+    send_kx (t,
+             GNUNET_NO);
+  }
+
+  if (0 == memcmp (&ax->DHRr,
+                   &msg->ratchet_key,
+                   sizeof (msg->ratchet_key)))
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         " known ratchet key, exit\n");
+    return;
+  }
+
+  ax->DHRr = msg->ratchet_key;
+
+  /* ECDH A B0 */
+  if (GNUNET_YES == am_I_alice)
+  {
+    GNUNET_CRYPTO_eddsa_ecdh (my_private_key,      /* A */
+                              &msg->ephemeral_key, /* B0 */
+                              &key_material[0]);
+  }
+  else
+  {
+    GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0,            /* B0 */
+                              &pid->public_key,    /* A */
+                              &key_material[0]);
+  }
+
+  /* ECDH A0 B */
+  if (GNUNET_YES == am_I_alice)
+  {
+    GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0,            /* A0 */
+                              &pid->public_key,    /* B */
+                              &key_material[1]);
+  }
+  else
+  {
+    GNUNET_CRYPTO_eddsa_ecdh (my_private_key,      /* A */
+                              &msg->ephemeral_key, /* B0 */
+                              &key_material[1]);
+
+
+  }
+
+  /* ECDH A0 B0 */
+  /* (This is the triple-DH, we could probably safely skip this,
+     as A0/B0 are already in the key material.) */
+  GNUNET_CRYPTO_ecc_ecdh (ax->kx_0,             /* A0 or B0 */
+                          &msg->ephemeral_key,  /* B0 or A0 */
+                          &key_material[2]);
+
+  /* KDF */
+  GNUNET_CRYPTO_kdf (keys, sizeof (keys),
+                     salt, sizeof (salt),
+                     &key_material, sizeof (key_material),
+                     NULL);
+
+  if (0 == memcmp (&ax->RK,
+                   &keys[0],
+                   sizeof (ax->RK)))
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         " known handshake key, exit\n");
+    return;
+  }
+  ax->RK = keys[0];
+  if (GNUNET_YES == am_I_alice)
+  {
+    ax->HKr = keys[1];
+    ax->NHKs = keys[2];
+    ax->NHKr = keys[3];
+    ax->CKr = keys[4];
+    ax->ratchet_flag = GNUNET_YES;
+  }
+  else
+  {
+    ax->HKs = keys[1];
+    ax->NHKr = keys[2];
+    ax->NHKs = keys[3];
+    ax->CKs = keys[4];
+    ax->ratchet_flag = GNUNET_NO;
+    ax->ratchet_allowed = GNUNET_NO;
+    ax->ratchet_counter = 0;
+    ax->ratchet_expiration
+      = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
+                                  ratchet_time);
+  }
+  ax->PNs = 0;
+  ax->Nr = 0;
+  ax->Ns = 0;
+
+#if FIXME
+  /* After KX is done, update state machine and begin transmissions... */
+  GCT_change_estate (t,
+                     CADET_TUNNEL_KEY_PING);
+  send_queued_data (t);
+#endif
+}
+
+
+/* ************************************** end core crypto ***************************** */
+
+
+/**
+ * Add a channel to a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel
+ * @return unique number identifying @a ch within @a t
+ */
+struct GNUNET_CADET_ChannelTunnelNumber
+GCT_add_channel (struct CadetTunnel *t,
+                 struct CadetChannel *ch)
+{
+  struct GNUNET_CADET_ChannelTunnelNumber ret;
+  uint32_t chid;
+
+  chid = ntohl (t->next_chid.cn);
+  while (NULL !=
+         GNUNET_CONTAINER_multihashmap32_get (t->channels,
+                                              chid))
+    chid++;
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap32_put (t->channels,
+                                                      chid,
+                                                      ch,
+                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  t->next_chid.cn = htonl (chid + 1);
+  ret.cn = htonl (chid);
+  return ret;
+}
+
+
+/**
+ * This tunnel is no longer used, destroy it.
+ *
+ * @param cls the idle tunnel
+ */
+static void
+destroy_tunnel (void *cls)
+{
+  struct CadetTunnel *t = cls;
+  struct CadetTConnection *ct;
+  struct CadetTunnelQueueEntry *tqe;
+
+  t->destroy_task = NULL;
+  GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (t->channels));
+  while (NULL != (ct = t->connection_head))
+  {
+    GNUNET_assert (ct->t == t);
+    GNUNET_CONTAINER_DLL_remove (t->connection_head,
+                                 t->connection_tail,
+                                 ct);
+    GCC_destroy (ct->cc);
+    GNUNET_free (ct);
+  }
+  while (NULL != (tqe = t->tq_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (t->tq_head,
+                                 t->tq_tail,
+                                 tqe);
+    GNUNET_MQ_discard (tqe->env);
+    GNUNET_free (tqe);
+  }
+  GCP_drop_tunnel (t->destination,
+                   t);
+  GNUNET_CONTAINER_multihashmap32_destroy (t->channels);
+  if (NULL != t->maintain_connections_task)
+  {
+    GNUNET_SCHEDULER_cancel (t->maintain_connections_task);
+    t->maintain_connections_task = NULL;
+  }
+  GNUNET_MST_destroy (t->mst);
+  GNUNET_MQ_destroy (t->mq);
+  GNUNET_free (t);
+}
+
+
+/**
+ * A connection is @a is_ready for transmission.  Looks at our message
+ * queue and if there is a message, sends it out via the connection.
+ *
+ * @param cls the `struct CadetTConnection` that is @a is_ready
+ * @param is_ready #GNUNET_YES if connection are now ready,
+ *                 #GNUNET_NO if connection are no longer ready
+ */
+static void
+connection_ready_cb (void *cls,
+                     int is_ready)
+{
+  struct CadetTConnection *ct = cls;
+  struct CadetTunnel *t = ct->t;
+  struct CadetTunnelQueueEntry *tq = t->tq_head;
+
+  if (GNUNET_NO == ct->is_ready)
+  {
+    ct->is_ready = GNUNET_NO;
+    return;
+  }
+  ct->is_ready = GNUNET_YES;
+  if (NULL == tq)
+    return; /* no messages pending right now */
+
+  /* ready to send message 'tq' on tunnel 'ct' */
+  GNUNET_assert (t == tq->t);
+  GNUNET_CONTAINER_DLL_remove (t->tq_head,
+                               t->tq_tail,
+                               tq);
+  if (NULL != tq->cid)
+    *tq->cid = *GCC_get_id (ct->cc);
+  ct->is_ready = GNUNET_NO;
+  GCC_transmit (ct->cc,
+                tq->env);
+  tq->cont (tq->cont_cls);
+  GNUNET_free (tq);
+}
+
+
+/**
+ * Called when either we have a new connection, or a new message in the
+ * queue, or some existing connection has transmission capacity.  Looks
+ * at our message queue and if there is a message, picks a connection
+ * to send it on.
+ *
+ * FIXME: yuck... Need better selection logic!
+ *
+ * @param t tunnel to process messages on
+ */
+static void
+trigger_transmissions (struct CadetTunnel *t)
+{
+  struct CadetTConnection *ct;
+
+  if (NULL == t->tq_head)
+    return; /* no messages pending right now */
+  for (ct = t->connection_head;
+       NULL != ct;
+       ct = ct->next)
+    if (GNUNET_YES == ct->is_ready)
+      break;
+  if (NULL == ct)
+    return; /* no connections ready */
+
+  /* FIXME: a bit hackish to do it like this... */
+  connection_ready_cb (ct,
+                       GNUNET_YES);
+}
+
+
+/**
+ * Function called to maintain the connections underlying our tunnel.
+ * Tries to maintain (incl. tear down) connections for the tunnel, and
+ * if there is a significant change, may trigger transmissions.
+ *
+ * Basically, needs to check if there are connections that perform
+ * badly, and if so eventually kill them and trigger a replacement.
+ * The strategy is to open one more connection than
+ * #DESIRED_CONNECTIONS_PER_TUNNEL, and then periodically kick out the
+ * least-performing one, and then inquire for new ones.
+ *
+ * @param cls the `struct CadetTunnel`
+ */
+static void
+maintain_connections_cb (void *cls)
+{
+  struct CadetTunnel *t = cls;
+
+  GNUNET_break (0); // FIXME: implement!
+}
+
+
+/**
+ * Consider using the path @a p for the tunnel @a t.
+ * The tunnel destination is at offset @a off in path @a p.
+ *
+ * @param cls our tunnel
+ * @param path a path to our destination
+ * @param off offset of the destination on path @a path
+ * @return #GNUNET_YES (should keep iterating)
+ */
+static int
+consider_path_cb (void *cls,
+                  struct CadetPeerPath *path,
+                  unsigned int off)
+{
+  struct CadetTunnel *t = cls;
+  unsigned int min_length = UINT_MAX;
+  GNUNET_CONTAINER_HeapCostType max_desire = 0;
+  struct CadetTConnection *ct;
+
+  /* Check if we care about the new path. */
+  for (ct = t->connection_head;
+       NULL != ct;
+       ct = ct->next)
+  {
+    struct CadetPeerPath *ps;
+
+    ps = GCC_get_path (ct->cc);
+    if (ps == path)
+      return GNUNET_YES; /* duplicate */
+    min_length = GNUNET_MIN (min_length,
+                             GCPP_get_length (ps));
+    max_desire = GNUNET_MAX (max_desire,
+                             GCPP_get_desirability (ps));
+  }
+
+  /* FIXME: not sure we should really just count
+     'num_connections' here, as they may all have
+     consistently failed to connect. */
+
+  /* We iterate by increasing path length; if we have enough paths and
+     this one is more than twice as long than what we are currently
+     using, then ignore all of these super-long ones! */
+  if ( (t->num_connections > DESIRED_CONNECTIONS_PER_TUNNEL) &&
+       (min_length * 2 < off) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Ignoring paths of length %u, they are way too long.\n",
+                min_length * 2);
+    return GNUNET_NO;
+  }
+  /* If we have enough paths and this one looks no better, ignore it. */
+  if ( (t->num_connections >= DESIRED_CONNECTIONS_PER_TUNNEL) &&
+       (min_length < GCPP_get_length (path)) &&
+       (max_desire > GCPP_get_desirability (path)) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Ignoring path (%u/%llu) to %s, got something better already.\n",
+                GCPP_get_length (path),
+                (unsigned long long) GCPP_get_desirability (path),
+                GCP_2s (t->destination));
+    return GNUNET_YES;
+  }
+
+  /* Path is interesting (better by some metric, or we don't have
+     enough paths yet). */
+  ct = GNUNET_new (struct CadetTConnection);
+  ct->created = GNUNET_TIME_absolute_get ();
+  ct->t = t;
+  ct->cc = GCC_create (t->destination,
+                       path,
+                       ct,
+                       &connection_ready_cb,
+                       ct);
+  /* FIXME: schedule job to kill connection (and path?)  if it takes
+     too long to get ready! (And track performance data on how long
+     other connections took with the tunnel!)
+     => Note: to be done within 'connection'-logic! */
+  GNUNET_CONTAINER_DLL_insert (t->connection_head,
+                               t->connection_tail,
+                               ct);
+  t->num_connections++;
+  return GNUNET_YES;
+}
+
+
+/**
+ * Consider using the path @a p for the tunnel @a t.
+ * The tunnel destination is at offset @a off in path @a p.
+ *
+ * @param cls our tunnel
+ * @param path a path to our destination
+ * @param off offset of the destination on path @a path
+ */
+void
+GCT_consider_path (struct CadetTunnel *t,
+                   struct CadetPeerPath *p,
+                   unsigned int off)
+{
+  (void) consider_path_cb (t,
+                           p,
+                           off);
+}
+
+
+/**
+ *
+ *
+ * @param cls the `struct CadetTunnel` for which we decrypted the message
+ * @param msg  the message we received on the tunnel
+ */
+static void
+handle_plaintext_keepalive (void *cls,
+                            const struct GNUNET_MessageHeader *msg)
+{
+  struct CadetTunnel *t = cls;
+  GNUNET_break (0); // FIXME
+}
+
+
+/**
+ * Check that @a msg is well-formed.
+ *
+ * @param cls the `struct CadetTunnel` for which we decrypted the message
+ * @param msg  the message we received on the tunnel
+ * @return #GNUNET_OK (any variable-size payload goes)
+ */
+static int
+check_plaintext_data (void *cls,
+                      const struct GNUNET_CADET_ChannelAppDataMessage *msg)
+{
+  return GNUNET_OK;
+}
+
+
+/**
+ *
+ *
+ * @param cls the `struct CadetTunnel` for which we decrypted the message
+ * @param msg the message we received on the tunnel
+ */
+static void
+handle_plaintext_data (void *cls,
+                       const struct GNUNET_CADET_ChannelAppDataMessage *msg)
+{
+  struct CadetTunnel *t = cls;
+  GNUNET_break (0); // FIXME!
+}
+
+
+/**
+ *
+ *
+ * @param cls the `struct CadetTunnel` for which we decrypted the message
+ * @param ack the message we received on the tunnel
+ */
+static void
+handle_plaintext_data_ack (void *cls,
+                           const struct GNUNET_CADET_ChannelDataAckMessage *ack)
+{
+  struct CadetTunnel *t = cls;
+  GNUNET_break (0); // FIXME!
+}
+
+
+/**
+ *
+ *
+ * @param cls the `struct CadetTunnel` for which we decrypted the message
+ * @param cc the message we received on the tunnel
+ */
+static void
+handle_plaintext_channel_create (void *cls,
+                                 const struct GNUNET_CADET_ChannelOpenMessage *cc)
+{
+  struct CadetTunnel *t = cls;
+  GNUNET_break (0); // FIXME!
+}
+
+
+/**
+ *
+ *
+ * @param cls the `struct CadetTunnel` for which we decrypted the message
+ * @param cm the message we received on the tunnel
+ */
+static void
+handle_plaintext_channel_nack (void *cls,
+                               const struct GNUNET_CADET_ChannelManageMessage *cm)
+{
+  struct CadetTunnel *t = cls;
+  GNUNET_break (0); // FIXME!
+}
+
+
+/**
+ *
+ *
+ * @param cls the `struct CadetTunnel` for which we decrypted the message
+ * @param cm the message we received on the tunnel
+ */
+static void
+handle_plaintext_channel_ack (void *cls,
+                              const struct GNUNET_CADET_ChannelManageMessage *cm)
+{
+  struct CadetTunnel *t = cls;
+  GNUNET_break (0); // FIXME!
+}
+
+
+/**
+ * We received a message saying that a channel should be destroyed.
+ * Pass it on to the correct channel.
+ *
+ * @param cls the `struct CadetTunnel` for which we decrypted the message
+ * @param cm the message we received on the tunnel
+ */
+static void
+handle_plaintext_channel_destroy (void *cls,
+                                  const struct GNUNET_CADET_ChannelManageMessage *cm)
+{
+  struct CadetTunnel *t = cls;
+  struct CadetChannel *cc = lookup_channel (t,
+                                            cm->chid);
+
+  GCCH_channel_remote_destroy (cc);
+}
+
+
+/**
+ * Handles a message we decrypted, by injecting it into
+ * our message queue (which will do the dispatching).
+ *
+ * @param cls the `struct CadetTunnel` that got the message
+ * @param msg the message
+ * @return #GNUNET_OK (continue to process)
+ */
+static int
+handle_decrypted (void *cls,
+                  const struct GNUNET_MessageHeader *msg)
+{
+  struct CadetTunnel *t = cls;
+
+  GNUNET_MQ_inject_message (t->mq,
+                            msg);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function called if we had an error processing
+ * an incoming decrypted message.
+ *
+ * @param cls the `struct CadetTunnel`
+ * @param error error code
+ */
+static void
+decrypted_error_cb (void *cls,
+                    enum GNUNET_MQ_Error error)
+{
+  GNUNET_break_op (0);
+}
+
+
+/**
+ * Create a tunnel to @a destionation.  Must only be called
+ * from within #GCP_get_tunnel().
+ *
+ * @param destination where to create the tunnel to
+ * @return new tunnel to @a destination
+ */
+struct CadetTunnel *
+GCT_create_tunnel (struct CadetPeer *destination)
+{
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_fixed_size (plaintext_keepalive,
+                             GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE,
+                             struct GNUNET_MessageHeader,
+                             NULL),
+    GNUNET_MQ_hd_var_size (plaintext_data,
+                           GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA,
+                           struct GNUNET_CADET_ChannelAppDataMessage,
+                           NULL),
+    GNUNET_MQ_hd_fixed_size (plaintext_data_ack,
+                             GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK,
+                             struct GNUNET_CADET_ChannelDataAckMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (plaintext_channel_create,
+                             GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
+                             struct GNUNET_CADET_ChannelOpenMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (plaintext_channel_nack,
+                             GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED,
+                             struct GNUNET_CADET_ChannelManageMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (plaintext_channel_ack,
+                             GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK,
+                             struct GNUNET_CADET_ChannelManageMessage,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy,
+                             GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
+                             struct GNUNET_CADET_ChannelManageMessage,
+                             NULL),
+    GNUNET_MQ_handler_end ()
+  };
+  struct CadetTunnel *t;
+
+  t = GNUNET_new (struct CadetTunnel);
+  t->destination = destination;
+  t->channels = GNUNET_CONTAINER_multihashmap32_create (8);
+  (void) GCP_iterate_paths (destination,
+                            &consider_path_cb,
+                            t);
+  t->maintain_connections_task
+    = GNUNET_SCHEDULER_add_now (&maintain_connections_cb,
+                                t);
+  t->mq = GNUNET_MQ_queue_for_callbacks (NULL,
+                                         NULL,
+                                         NULL,
+                                         NULL,
+                                         handlers,
+                                         &decrypted_error_cb,
+                                         t);
+  t->mst = GNUNET_MST_create (&handle_decrypted,
+                              t);
+  return t;
+}
+
+
+/**
+ * Remove a channel from a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel
+ * @param gid unique number identifying @a ch within @a t
+ */
+void
+GCT_remove_channel (struct CadetTunnel *t,
+                    struct CadetChannel *ch,
+                    struct GNUNET_CADET_ChannelTunnelNumber gid)
+{
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap32_remove (t->channels,
+                                                         ntohl (gid.cn),
+                                                         ch));
+  if (0 ==
+      GNUNET_CONTAINER_multihashmap32_size (t->channels))
+  {
+    t->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY,
+                                                    &destroy_tunnel,
+                                                    t);
+  }
+}
+
+
+/**
+ * Change the tunnel encryption state.
+ * If the encryption state changes to OK, stop the rekey task.
+ *
+ * @param t Tunnel whose encryption state to change, or NULL.
+ * @param state New encryption state.
+ */
+void
+GCT_change_estate (struct CadetTunnel *t,
+                   enum CadetTunnelEState state)
+{
+  enum CadetTunnelEState old = t->estate;
+
+  t->estate = state;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Tunnel %s estate changed from %d to %d\n",
+       GCT_2s (t),
+       old,
+       state);
+
+  if ( (CADET_TUNNEL_KEY_OK != old) &&
+       (CADET_TUNNEL_KEY_OK == t->estate) )
+  {
+    if (NULL != t->rekey_task)
+    {
+      GNUNET_SCHEDULER_cancel (t->rekey_task);
+      t->rekey_task = NULL;
+    }
+#if FIXME
+    /* Send queued data if tunnel is not loopback */
+    if (myid != GCP_get_short_id (t->peer))
+      send_queued_data (t);
+#endif
+  }
+}
+
+
+/**
+ * Add a @a connection to the @a tunnel.
+ *
+ * @param t a tunnel
+ * @param cid connection identifer to use for the connection
+ * @param path path to use for the connection
+ */
+void
+GCT_add_inbound_connection (struct CadetTunnel *t,
+                            const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
+                            struct CadetPeerPath *path)
+{
+  struct CadetConnection *cc;
+  struct CadetTConnection *ct;
+
+  ct = GNUNET_new (struct CadetTConnection);
+  ct->created = GNUNET_TIME_absolute_get ();
+  ct->t = t;
+  ct->cc = GCC_create_inbound (t->destination,
+                               path,
+                               ct,
+                               cid,
+                               &connection_ready_cb,
+                               t);
+  /* FIXME: schedule job to kill connection (and path?)  if it takes
+     too long to get ready! (And track performance data on how long
+     other connections took with the tunnel!)
+     => Note: to be done within 'connection'-logic! */
+  GNUNET_CONTAINER_DLL_insert (t->connection_head,
+                               t->connection_tail,
+                               ct);
+  t->num_connections++;
+}
+
+
+/**
+ * Handle encrypted message.
+ *
+ * @param ct connection/tunnel combo that received encrypted message
+ * @param msg the encrypted message to decrypt
+ */
+void
+GCT_handle_encrypted (struct CadetTConnection *ct,
+                      const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
+{
+  struct CadetTunnel *t = ct->t;
+  uint16_t size = ntohs (msg->header.size);
+  char cbuf [size] GNUNET_ALIGN;
+  ssize_t decrypted_size;
+
+  GNUNET_STATISTICS_update (stats,
+                            "# received encrypted",
+                            1,
+                            GNUNET_NO);
+
+  decrypted_size = t_ax_decrypt_and_validate (t,
+                                              cbuf,
+                                              msg,
+                                              size);
+
+  if (-1 == decrypted_size)
+  {
+    GNUNET_STATISTICS_update (stats,
+                              "# unable to decrypt",
+                              1,
+                              GNUNET_NO);
+    if (CADET_TUNNEL_KEY_PING <= t->estate)
+    {
+      GNUNET_break_op (0);
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+           "Wrong crypto, tunnel %s\n",
+           GCT_2s (t));
+      GCT_debug (t,
+                 GNUNET_ERROR_TYPE_WARNING);
+    }
+    return;
+  }
+
+  GCT_change_estate (t,
+                     CADET_TUNNEL_KEY_OK);
+  /* The MST will ultimately call #handle_decrypted() on each message. */
+  GNUNET_break_op (GNUNET_OK ==
+                   GNUNET_MST_from_buffer (t->mst,
+                                           cbuf,
+                                           decrypted_size,
+                                           GNUNET_YES,
+                                           GNUNET_NO));
+}
+
+
+/**
+ * Sends an already built message on a tunnel, encrypting it and
+ * choosing the best connection if not provided.
+ *
+ * @param message Message to send. Function modifies it.
+ * @param t Tunnel on which this message is transmitted.
+ * @param cont Continuation to call once message is really sent.
+ * @param cont_cls Closure for @c cont.
+ * @return Handle to cancel message. NULL if @c cont is NULL.
+ */
+struct CadetTunnelQueueEntry *
+GCT_send (struct CadetTunnel *t,
+          const struct GNUNET_MessageHeader *message,
+          GNUNET_SCHEDULER_TaskCallback cont,
+          void *cont_cls)
+{
+  struct CadetTunnelQueueEntry *tq;
+  uint16_t payload_size;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
+
+  /* FIXME: what about KX not yet being ready? (see "is_ready()" check in old code!) */
+
+  payload_size = ntohs (message->size);
+  env = GNUNET_MQ_msg_extra (ax_msg,
+                             payload_size,
+                             GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
+  t_ax_encrypt (t,
+                &ax_msg[1],
+                message,
+                payload_size);
+  ax_msg->Ns = htonl (t->ax.Ns++);
+  ax_msg->PNs = htonl (t->ax.PNs);
+  GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs,
+                                      &ax_msg->DHRs);
+  t_h_encrypt (t,
+               ax_msg);
+  t_hmac (&ax_msg->Ns,
+          AX_HEADER_SIZE + payload_size,
+          0,
+          &t->ax.HKs,
+          &ax_msg->hmac);
+  // ax_msg->pid = htonl (GCC_get_pid (c, fwd));  // FIXME: connection flow-control not (re)implemented yet!
+
+  tq = GNUNET_malloc (sizeof (*tq));
+  tq->t = t;
+  tq->env = env;
+  tq->cid = &ax_msg->cid;
+  tq->cont = cont;
+  tq->cont_cls = cont_cls;
+  GNUNET_CONTAINER_DLL_insert_tail (t->tq_head,
+                                    t->tq_tail,
+                                    tq);
+  trigger_transmissions (t);
+  return tq;
+}
+
+
+/**
+ * Cancel a previously sent message while it's in the queue.
+ *
+ * ONLY can be called before the continuation given to the send
+ * function is called. Once the continuation is called, the message is
+ * no longer in the queue!
+ *
+ * @param q Handle to the queue entry to cancel.
+ */
+void
+GCT_send_cancel (struct CadetTunnelQueueEntry *q)
+{
+  struct CadetTunnel *t = q->t;
+
+  GNUNET_CONTAINER_DLL_remove (t->tq_head,
+                               t->tq_tail,
+                               q);
+  GNUNET_free (q);
+}
+
+
+/**
+ * Iterate over all connections of a tunnel.
+ *
+ * @param t Tunnel whose connections to iterate.
+ * @param iter Iterator.
+ * @param iter_cls Closure for @c iter.
+ */
+void
+GCT_iterate_connections (struct CadetTunnel *t,
+                         GCT_ConnectionIterator iter,
+                         void *iter_cls)
+{
+  for (struct CadetTConnection *ct = t->connection_head;
+       NULL != ct;
+       ct = ct->next)
+    iter (iter_cls,
+          ct->cc);
+}
+
+
+/**
+ * Closure for #iterate_channels_cb.
+ */
+struct ChanIterCls
+{
+  /**
+   * Function to call.
+   */
+  GCT_ChannelIterator iter;
+
+  /**
+   * Closure for @e iter.
+   */
+  void *iter_cls;
+};
+
+
+/**
+ * Helper function for #GCT_iterate_channels.
+ *
+ * @param cls the `struct ChanIterCls`
+ * @param key unused
+ * @param value a `struct CadetChannel`
+ * @return #GNUNET_OK
+ */
+static int
+iterate_channels_cb (void *cls,
+                     uint32_t key,
+                     void *value)
+{
+  struct ChanIterCls *ctx = cls;
+  struct CadetChannel *ch = value;
+
+  ctx->iter (ctx->iter_cls,
+             ch);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Iterate over all channels of a tunnel.
+ *
+ * @param t Tunnel whose channels to iterate.
+ * @param iter Iterator.
+ * @param iter_cls Closure for @c iter.
+ */
+void
+GCT_iterate_channels (struct CadetTunnel *t,
+                      GCT_ChannelIterator iter,
+                      void *iter_cls)
+{
+  struct ChanIterCls ctx;
+
+  ctx.iter = iter;
+  ctx.iter_cls = iter_cls;
+  GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
+                                           &iterate_channels_cb,
+                                           &ctx);
+
+}
+
+
+/**
+ * Call #GCCH_debug() on a channel.
+ *
+ * @param cls points to the log level to use
+ * @param key unused
+ * @param value the `struct CadetChannel` to dump
+ * @return #GNUNET_OK (continue iteration)
+ */
+static int
+debug_channel (void *cls,
+               uint32_t key,
+               void *value)
+{
+  const enum GNUNET_ErrorType *level = cls;
+  struct CadetChannel *ch = value;
+
+  GCCH_debug (ch, *level);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Get string description for tunnel connectivity state.
+ *
+ * @param cs Tunnel state.
+ *
+ * @return String representation.
+ */
+static const char *
+cstate2s (enum CadetTunnelCState cs)
+{
+  static char buf[32];
+
+  switch (cs)
+  {
+    case CADET_TUNNEL_NEW:
+      return "CADET_TUNNEL_NEW";
+    case CADET_TUNNEL_SEARCHING:
+      return "CADET_TUNNEL_SEARCHING";
+    case CADET_TUNNEL_WAITING:
+      return "CADET_TUNNEL_WAITING";
+    case CADET_TUNNEL_READY:
+      return "CADET_TUNNEL_READY";
+    case CADET_TUNNEL_SHUTDOWN:
+      return "CADET_TUNNEL_SHUTDOWN";
+    default:
+      SPRINTF (buf, "%u (UNKNOWN STATE)", cs);
+      return buf;
+  }
+}
+
+
+/**
+ * Get string description for tunnel encryption state.
+ *
+ * @param es Tunnel state.
+ *
+ * @return String representation.
+ */
+static const char *
+estate2s (enum CadetTunnelEState es)
+{
+  static char buf[32];
+
+  switch (es)
+  {
+    case CADET_TUNNEL_KEY_UNINITIALIZED:
+      return "CADET_TUNNEL_KEY_UNINITIALIZED";
+    case CADET_TUNNEL_KEY_SENT:
+      return "CADET_TUNNEL_KEY_SENT";
+    case CADET_TUNNEL_KEY_PING:
+      return "CADET_TUNNEL_KEY_PING";
+    case CADET_TUNNEL_KEY_OK:
+      return "CADET_TUNNEL_KEY_OK";
+    case CADET_TUNNEL_KEY_REKEY:
+      return "CADET_TUNNEL_KEY_REKEY";
+    default:
+      SPRINTF (buf, "%u (UNKNOWN STATE)", es);
+      return buf;
+  }
+}
+
+
+#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-tun",__VA_ARGS__)
+
+
+/**
+ * Log all possible info about the tunnel state.
+ *
+ * @param t Tunnel to debug.
+ * @param level Debug level to use.
+ */
+void
+GCT_debug (const struct CadetTunnel *t,
+           enum GNUNET_ErrorType level)
+{
+  struct CadetTConnection *iter_c;
+  int do_log;
+
+  do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
+                                       "cadet-tun",
+                                       __FILE__, __FUNCTION__, __LINE__);
+  if (0 == do_log)
+    return;
+
+  LOG2 (level,
+        "TTT TUNNEL TOWARDS %s in cstate %s, estate %s tq_len: %u #cons: %u\n",
+        GCT_2s (t),
+        cstate2s (t->cstate),
+        estate2s (t->estate),
+        t->tq_len,
+        t->num_connections);
+#if DUMP_KEYS_TO_STDERR
+  ax_debug (t->ax, level);
+#endif
+  LOG2 (level,
+        "TTT channels:\n");
+  GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
+                                           &debug_channel,
+                                           &level);
+  LOG2 (level,
+        "TTT connections:\n");
+  for (iter_c = t->connection_head; NULL != iter_c; iter_c = iter_c->next)
+    GCC_debug (iter_c->cc,
+               level);
+
+  LOG2 (level,
+        "TTT TUNNEL END\n");
+}
+
+
+/* end of gnunet-service-cadet-new_tunnels.c */
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.h b/src/cadet/gnunet-service-cadet-new_tunnels.h
new file mode 100644 (file)
index 0000000..82e4b0d
--- /dev/null
@@ -0,0 +1,357 @@
+
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet-new_tunnels.h
+ * @brief Information we track per tunnel.
+ * @author Bartlomiej Polot
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SERVICE_CADET_TUNNELS_H
+#define GNUNET_SERVICE_CADET_TUNNELS_H
+
+#include "gnunet-service-cadet-new.h"
+#include "cadet_protocol.h"
+
+
+/**
+ * How many connections would we like to have per tunnel?
+ */
+#define DESIRED_CONNECTIONS_PER_TUNNEL 3
+
+
+/**
+ * All the connectivity states a tunnel can be in.
+ */
+enum CadetTunnelCState
+{
+  /**
+   * Uninitialized status, should never appear in operation.
+   */
+  CADET_TUNNEL_NEW,
+
+  /**
+   * No path to the peer known yet.
+   */
+  CADET_TUNNEL_SEARCHING,
+
+  /**
+   * Request sent, not yet answered.
+   */
+  CADET_TUNNEL_WAITING,
+
+  /**
+   * Peer connected and ready to accept data.
+   */
+  CADET_TUNNEL_READY,
+
+  /**
+   * Tunnel being shut down, don't try to keep it alive.
+   */
+  CADET_TUNNEL_SHUTDOWN
+};
+
+
+
+/**
+ * All the encryption states a tunnel can be in.
+ */
+enum CadetTunnelEState
+{
+  /**
+   * Uninitialized status, should never appear in operation.
+   */
+  CADET_TUNNEL_KEY_UNINITIALIZED,
+
+  /**
+   * Ephemeral key sent, waiting for peer's key.
+   */
+  CADET_TUNNEL_KEY_SENT,
+
+  /**
+   * In OTR: New ephemeral key and ping sent, waiting for pong.
+   *
+   * This means that we DO have the peer's ephemeral key, otherwise the
+   * state would be KEY_SENT. We DO NOT have a valid session key (either no
+   * previous key or previous key expired).
+   *
+   *
+   * In Axolotl: Key sent and received but no deciphered traffic yet.
+   *
+   * This means that we can send traffic (otherwise we would never complete
+   * the handshake), but we don't have complete confirmation. Since the first
+   * traffic MUST be a complete channel creation 3-way handshake, no payload
+   * will be sent before confirmation.
+   */
+  CADET_TUNNEL_KEY_PING,
+
+  /**
+   * Handshake completed: session key available.
+   */
+  CADET_TUNNEL_KEY_OK,
+
+  /**
+   * New ephemeral key and ping sent, waiting for pong. Unlike KEY_PING,
+   * we still have a valid session key and therefore we *can* still send
+   * traffic on the tunnel.
+   */
+  CADET_TUNNEL_KEY_REKEY
+};
+
+
+/**
+ * Get the static string for the peer this tunnel is directed.
+ *
+ * @param t Tunnel.
+ *
+ * @return Static string the destination peer's ID.
+ */
+const char *
+GCT_2s (const struct CadetTunnel *t);
+
+
+/**
+ * Create a tunnel to @a destionation.  Must only be called
+ * from within #GCP_get_tunnel().
+ *
+ * @param destination where to create the tunnel to
+ * @return new tunnel to @a destination
+ */
+struct CadetTunnel *
+GCT_create_tunnel (struct CadetPeer *destination);
+
+
+/**
+ * Add a @a connection to the @a tunnel.
+ *
+ * @param t a tunnel
+ * @param cid connection identifer to use for the connection
+ * @param path path to use for the connection
+ */
+void
+GCT_add_inbound_connection (struct CadetTunnel *t,
+                            const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
+                            struct CadetPeerPath *path);
+
+
+/**
+ * Return the peer to which this tunnel goes.
+ *
+ * @param t a tunnel
+ * @return the destination of the tunnel
+ */
+struct CadetPeer *
+GCT_get_destination (struct CadetTunnel *t);
+
+
+/**
+ * Consider using the path @a p for the tunnel @a t.
+ * The tunnel destination is at offset @a off in path @a p.
+ *
+ * @param cls our tunnel
+ * @param path a path to our destination
+ * @param off offset of the destination on path @a path
+ */
+void
+GCT_consider_path (struct CadetTunnel *t,
+                   struct CadetPeerPath *p,
+                   unsigned int off);
+
+
+/**
+ * Add a channel to a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel
+ * @return unique number identifying @a ch within @a t
+ */
+struct GNUNET_CADET_ChannelTunnelNumber
+GCT_add_channel (struct CadetTunnel *t,
+                 struct CadetChannel *ch);
+
+
+/**
+ * Remove a channel from a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel
+ * @param gid unique number identifying @a ch within @a t
+ */
+void
+GCT_remove_channel (struct CadetTunnel *t,
+                    struct CadetChannel *ch,
+                    struct GNUNET_CADET_ChannelTunnelNumber gid);
+
+
+/**
+ * Sends an already built message on a tunnel, encrypting it and
+ * choosing the best connection if not provided.
+ *
+ * @param message Message to send. Function modifies it.
+ * @param t Tunnel on which this message is transmitted.
+ * @param cont Continuation to call once message is really sent.
+ * @param cont_cls Closure for @c cont.
+ * @return Handle to cancel message. NULL if @c cont is NULL.
+ */
+struct CadetTunnelQueueEntry *
+GCT_send (struct CadetTunnel *t,
+          const struct GNUNET_MessageHeader *message,
+          GNUNET_SCHEDULER_TaskCallback cont,
+          void *cont_cls);
+
+
+/**
+ * Cancel a previously sent message while it's in the queue.
+ *
+ * ONLY can be called before the continuation given to the send
+ * function is called. Once the continuation is called, the message is
+ * no longer in the queue!
+ *
+ * @param q Handle to the queue entry to cancel.
+ */
+void
+GCT_send_cancel (struct CadetTunnelQueueEntry *q);
+
+
+/**
+ * Return the number of channels using a tunnel.
+ *
+ * @param t tunnel to count obtain the number of channels for
+ * @return number of channels using the tunnel
+ */
+unsigned int
+GCT_count_channels (struct CadetTunnel *t);
+
+
+/**
+ * Return the number of connections available for a tunnel.
+ *
+ * @param t tunnel to count obtain the number of connections for
+ * @return number of connections available for the tunnel
+ */
+unsigned int
+GCT_count_any_connections (struct CadetTunnel *t);
+
+
+/**
+ * Iterator over connections.
+ *
+ * @param cls closure
+ * @param c one of the connections
+ */
+typedef void
+(*GCT_ConnectionIterator) (void *cls,
+                           struct CadetConnection *c);
+
+
+/**
+ * Iterate over all connections of a tunnel.
+ *
+ * @param t Tunnel whose connections to iterate.
+ * @param iter Iterator.
+ * @param iter_cls Closure for @c iter.
+ */
+void
+GCT_iterate_connections (struct CadetTunnel *t,
+                         GCT_ConnectionIterator iter,
+                         void *iter_cls);
+
+
+/**
+ * Iterator over channels.
+ *
+ * @param cls closure
+ * @param ch one of the channels
+ */
+typedef void
+(*GCT_ChannelIterator) (void *cls,
+                        struct CadetChannel *ch);
+
+
+/**
+ * Iterate over all channels of a tunnel.
+ *
+ * @param t Tunnel whose channels to iterate.
+ * @param iter Iterator.
+ * @param iter_cls Closure for @c iter.
+ */
+void
+GCT_iterate_channels (struct CadetTunnel *t,
+                      GCT_ChannelIterator iter,
+                      void *iter_cls);
+
+
+/**
+ * Get the connectivity state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's connectivity state.
+ */
+enum CadetTunnelCState
+GCT_get_cstate (struct CadetTunnel *t);
+
+
+/**
+ * Get the encryption state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's encryption state.
+ */
+enum CadetTunnelEState
+GCT_get_estate (struct CadetTunnel *t);
+
+
+/**
+ * Handle KX message.
+ *
+ * @param ct connection/tunnel combo that received encrypted message
+ * @param msg the key exchange message
+ */
+void
+GCT_handle_kx (struct CadetTConnection *ct,
+               const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
+
+
+/**
+ * Handle encrypted message.
+ *
+ * @param ct connection/tunnel combo that received encrypted message
+ * @param msg the encrypted message to decrypt
+ */
+void
+GCT_handle_encrypted (struct CadetTConnection *ct,
+                      const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
+
+
+/**
+ * Log all possible info about the tunnel state.
+ *
+ * @param t Tunnel to debug.
+ * @param level Debug level to use.
+ */
+void
+GCT_debug (const struct CadetTunnel *t,
+           enum GNUNET_ErrorType level);
+
+
+#endif
index 22349aa80c5cf26acb979750eb58ca680be54e77..dee0c37d7390fe211fbf2d2f4c0bf5d34ccb09d1 100644 (file)
@@ -58,7 +58,7 @@ enum CadetChannelState
   /**
    * Connection confirmed, ready to carry traffic.
    */
-  CADET_CHANNEL_READY,
+  CADET_CHANNEL_READY
 };
 
 
@@ -125,7 +125,7 @@ struct CadetReliableMessage
    */
   struct GNUNET_TIME_Absolute   timestamp;
 
-  /* struct GNUNET_CADET_Data with payload */
+  /* struct GNUNET_CADET_ChannelAppDataMessage with payload */
 };
 
 
@@ -216,19 +216,19 @@ struct CadetChannel
   /**
    * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
    */
-  CADET_ChannelNumber gid;
+  struct GNUNET_CADET_ChannelTunnelNumber gid;
 
   /**
    * Local tunnel number for root (owner) client.
    * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
    */
-  CADET_ChannelNumber lid_root;
-  
+  struct GNUNET_CADET_ClientChannelNumber lid_root;
+
   /**
    * Local tunnel number for local destination clients (incoming number)
    * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0).
    */
-  CADET_ChannelNumber lid_dest;
+  struct GNUNET_CADET_ClientChannelNumber lid_dest;
 
   /**
    * Channel state.
@@ -368,7 +368,7 @@ is_loopback (const struct CadetChannel *ch)
  * @param rel Reliability data for retransmission.
  */
 static struct CadetReliableMessage *
-copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid,
+copy_message (const struct GNUNET_CADET_ChannelAppDataMessage *msg, uint32_t mid,
               struct CadetChannelReliability *rel)
 {
   struct CadetReliableMessage *copy;
@@ -378,7 +378,7 @@ copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid,
   copy = GNUNET_malloc (sizeof (*copy) + size);
   copy->mid = mid;
   copy->rel = rel;
-  copy->type = GNUNET_MESSAGE_TYPE_CADET_DATA;
+  copy->type = GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA;
   GNUNET_memcpy (&copy[1], msg, size);
 
   return copy;
@@ -393,7 +393,7 @@ copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid,
  * @param rel Reliability data to the corresponding direction.
  */
 static void
-add_buffered_data (const struct GNUNET_CADET_Data *msg,
+add_buffered_data (const struct GNUNET_CADET_ChannelAppDataMessage *msg,
                    struct CadetChannelReliability *rel)
 {
   struct CadetReliableMessage *copy;
@@ -513,11 +513,11 @@ channel_get_options (struct CadetChannel *ch)
 static void
 send_destroy (struct CadetChannel *ch, int local_only)
 {
-  struct GNUNET_CADET_ChannelManage msg;
+  struct GNUNET_CADET_ChannelManageMessage msg;
 
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
   msg.header.size = htons (sizeof (msg));
-  msg.chid = htonl (ch->gid);
+  msg.chid = ch->gid;
 
   /* If root is not NULL, notify.
    * If it's NULL, check lid_root. When a local destroy comes in, root
@@ -526,12 +526,12 @@ send_destroy (struct CadetChannel *ch, int local_only)
    */
   if (NULL != ch->root)
     GML_send_channel_destroy (ch->root, ch->lid_root);
-  else if (0 == ch->lid_root && GNUNET_NO == local_only)
+  else if (0 == ch->lid_root.channel_of_client && GNUNET_NO == local_only)
     GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
 
   if (NULL != ch->dest)
     GML_send_channel_destroy (ch->dest, ch->lid_dest);
-  else if (0 == ch->lid_dest && GNUNET_NO == local_only)
+  else if (0 == ch->lid_dest.channel_of_client && GNUNET_NO == local_only)
     GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL);
 }
 
@@ -552,7 +552,10 @@ send_client_create (struct CadetChannel *ch)
   opt = 0;
   opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0;
   opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0;
-  GML_send_channel_create (ch->dest, ch->lid_dest, &ch->port, opt,
+  GML_send_channel_create (ch->dest,
+                           ch->lid_dest,
+                           &ch->port,
+                           opt,
                            GCT_get_destination (ch->t));
 
 }
@@ -570,7 +573,7 @@ send_client_create (struct CadetChannel *ch)
  */
 static void
 send_client_data (struct CadetChannel *ch,
-                  const struct GNUNET_CADET_Data *msg,
+                  const struct GNUNET_CADET_ChannelAppDataMessage *msg,
                   int fwd)
 {
   if (fwd)
@@ -628,7 +631,7 @@ send_client_buffered_data (struct CadetChannel *ch,
   {
     if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable)
     {
-      struct GNUNET_CADET_Data *msg = (struct GNUNET_CADET_Data *) &copy[1];
+      struct GNUNET_CADET_ChannelAppDataMessage *msg = (struct GNUNET_CADET_ChannelAppDataMessage *) &copy[1];
 
       LOG (GNUNET_ERROR_TYPE_DEBUG, " have %u! now expecting %u\n",
            copy->mid, rel->mid_recv + 1);
@@ -728,7 +731,7 @@ channel_retransmit_message (void *cls)
   struct CadetChannelReliability *rel = cls;
   struct CadetReliableMessage *copy;
   struct CadetChannel *ch;
-  struct GNUNET_CADET_Data *payload;
+  struct GNUNET_CADET_ChannelAppDataMessage *payload;
   int fwd;
 
   rel->retry_task = NULL;
@@ -740,7 +743,7 @@ channel_retransmit_message (void *cls)
     return;
   }
 
-  payload = (struct GNUNET_CADET_Data *) &copy[1];
+  payload = (struct GNUNET_CADET_ChannelAppDataMessage *) &copy[1];
   fwd = (rel == ch->root_rel);
 
   /* Message not found in the queue that we are going to use. */
@@ -805,7 +808,7 @@ ch_message_sent (void *cls,
 
   switch (chq->type)
   {
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
       LOG (GNUNET_ERROR_TYPE_DEBUG, "data MID %u sent\n", copy->mid);
       GNUNET_assert (chq == copy->chq);
       copy->timestamp = GNUNET_TIME_absolute_get ();
@@ -841,16 +844,16 @@ ch_message_sent (void *cls,
       break;
 
 
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
       LOG (GNUNET_ERROR_TYPE_DEBUG, "sent %s\n", GC_m2s (chq->type));
       rel = chq->rel;
       GNUNET_assert (rel->uniq == chq);
       rel->uniq = NULL;
 
       if (CADET_CHANNEL_READY != rel->ch->state
-          && GNUNET_MESSAGE_TYPE_CADET_DATA_ACK != type
+          && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK != type
           && GNUNET_NO == rel->ch->destroy)
       {
         GNUNET_assert (NULL == rel->retry_task);
@@ -879,11 +882,11 @@ ch_message_sent (void *cls,
 static void
 send_create (struct CadetChannel *ch)
 {
-  struct GNUNET_CADET_ChannelCreate msgcc;
+  struct GNUNET_CADET_ChannelOpenMessage msgcc;
 
   msgcc.header.size = htons (sizeof (msgcc));
-  msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
-  msgcc.chid = htonl (ch->gid);
+  msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
+  msgcc.chid = ch->gid;
   msgcc.port = ch->port;
   msgcc.opt = htonl (channel_get_options (ch));
 
@@ -900,14 +903,15 @@ send_create (struct CadetChannel *ch)
 static void
 send_ack (struct CadetChannel *ch, int fwd)
 {
-  struct GNUNET_CADET_ChannelManage msg;
+  struct GNUNET_CADET_ChannelManageMessage msg;
 
   msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending channel %s ack for channel %s\n",
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "  sending channel %s ack for channel %s\n",
        GC_f2s (fwd), GCCH_2s (ch));
 
-  msg.chid = htonl (ch->gid);
+  msg.chid =ch->gid;
   GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL);
 }
 
@@ -925,8 +929,9 @@ fire_and_forget (const struct GNUNET_MessageHeader *msg,
                  struct CadetChannel *ch,
                  int force)
 {
-  GNUNET_break (NULL == GCT_send_prebuilt_message (msg, ch->t, NULL,
-                                                   force, NULL, NULL));
+  GNUNET_break (NULL ==
+                GCT_send_prebuilt_message (msg, ch->t, NULL,
+                                           force, NULL, NULL));
 }
 
 
@@ -938,15 +943,15 @@ fire_and_forget (const struct GNUNET_MessageHeader *msg,
 static void
 send_nack (struct CadetChannel *ch)
 {
-  struct GNUNET_CADET_ChannelManage msg;
+  struct GNUNET_CADET_ChannelManageMessage msg;
 
   msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "  sending channel NACK for channel %s\n",
        GCCH_2s (ch));
 
-  msg.chid = htonl (ch->gid);
+  msg.chid = ch->gid;
   GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
 }
 
@@ -1019,7 +1024,7 @@ channel_rel_free_all (struct CadetChannelReliability *rel)
  */
 static unsigned int
 channel_rel_free_sent (struct CadetChannelReliability *rel,
-                       const struct GNUNET_CADET_DataACK *msg)
+                       const struct GNUNET_CADET_ChannelDataAckMessage *msg)
 {
   struct CadetReliableMessage *copy;
   struct CadetReliableMessage *next;
@@ -1252,7 +1257,7 @@ channel_save_copy (struct CadetChannel *ch,
 static struct CadetChannel *
 channel_new (struct CadetTunnel *t,
              struct CadetClient *owner,
-             CADET_ChannelNumber lid_root)
+             struct GNUNET_CADET_ClientChannelNumber lid_root)
 {
   struct CadetChannel *ch;
 
@@ -1295,35 +1300,35 @@ handle_loopback (struct CadetChannel *ch,
 
   switch (type)
   {
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
       /* Don't send hop ACK, wait for client to ACK */
       LOG (GNUNET_ERROR_TYPE_DEBUG, "SEND loopback %u (%u)\n",
-           ntohl (((struct GNUNET_CADET_Data *) msgh)->mid), ntohs (msgh->size));
-      GCCH_handle_data (ch, (struct GNUNET_CADET_Data *) msgh, fwd);
+           ntohl (((struct GNUNET_CADET_ChannelAppDataMessage *) msgh)->mid), ntohs (msgh->size));
+      GCCH_handle_data (ch, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-      GCCH_handle_data_ack (ch, (struct GNUNET_CADET_DataACK *) msgh, fwd);
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
+      GCCH_handle_data_ack (ch, (struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
       GCCH_handle_create (ch->t,
-                          (struct GNUNET_CADET_ChannelCreate *) msgh);
+                          (struct GNUNET_CADET_ChannelOpenMessage *) msgh);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
       GCCH_handle_ack (ch,
-                       (struct GNUNET_CADET_ChannelManage *) msgh,
+                       (struct GNUNET_CADET_ChannelManageMessage *) msgh,
                        fwd);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
       GCCH_handle_nack (ch);
       break;
 
     case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
       GCCH_handle_destroy (ch,
-                           (struct GNUNET_CADET_ChannelManage *) msgh,
+                           (struct GNUNET_CADET_ChannelManageMessage *) msgh,
                            fwd);
       break;
 
@@ -1393,7 +1398,7 @@ GCCH_destroy (struct CadetChannel *ch)
  *
  * @return ID used to identify the channel with the remote peer.
  */
-CADET_ChannelNumber
+struct GNUNET_CADET_ChannelTunnelNumber
 GCCH_get_id (const struct CadetChannel *ch)
 {
   return ch->gid;
@@ -1518,7 +1523,7 @@ GCCH_is_terminal (struct CadetChannel *ch, int fwd)
 void
 GCCH_send_data_ack (struct CadetChannel *ch, int fwd)
 {
-  struct GNUNET_CADET_DataACK msg;
+  struct GNUNET_CADET_ChannelDataAckMessage msg;
   struct CadetChannelReliability *rel;
   struct CadetReliableMessage *copy;
   unsigned int delta;
@@ -1531,15 +1536,15 @@ GCCH_send_data_ack (struct CadetChannel *ch, int fwd)
   rel = fwd ? ch->dest_rel : ch->root_rel;
   ack = rel->mid_recv - 1;
 
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA_ACK);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
   msg.header.size = htons (sizeof (msg));
-  msg.chid = htonl (ch->gid);
+  msg.chid = ch->gid;
   msg.mid = htonl (ack);
 
   msg.futures = 0LL;
   for (copy = rel->head_recv; NULL != copy; copy = copy->next)
   {
-    if (copy->type != GNUNET_MESSAGE_TYPE_CADET_DATA)
+    if (copy->type != GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA)
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG, " Type %s, expected DATA\n",
            GC_m2s (copy->type));
@@ -1657,7 +1662,7 @@ GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
   {
     LOG2 (level, "CHN   cli %s\n", GML_2s (ch->root));
     LOG2 (level, "CHN   ready %s\n", ch->root_rel->client_ready ? "YES" : "NO");
-    LOG2 (level, "CHN   id %X\n", ch->lid_root);
+    LOG2 (level, "CHN   id %X\n", ch->lid_root.channel_of_client);
     LOG2 (level, "CHN   recv %d\n", ch->root_rel->n_recv);
     LOG2 (level, "CHN   MID r: %d, s: %d\n",
           ch->root_rel->mid_recv, ch->root_rel->mid_send);
@@ -1733,17 +1738,18 @@ GCCH_handle_local_ack (struct CadetChannel *ch, int fwd)
  * @param message Data message.
  * @param size Size of data.
  *
- * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error.
+ * @return #GNUNET_OK if everything goes well, #GNUNET_SYSERR in case of en error.
  */
 int
 GCCH_handle_local_data (struct CadetChannel *ch,
-                        struct CadetClient *c, int fwd,
+                        struct CadetClient *c,
+                        int fwd,
                         const struct GNUNET_MessageHeader *message,
                         size_t size)
 {
   struct CadetChannelReliability *rel;
-  struct GNUNET_CADET_Data *payload;
-  uint16_t p2p_size = sizeof(struct GNUNET_CADET_Data) + size;
+  struct GNUNET_CADET_ChannelAppDataMessage *payload;
+  uint16_t p2p_size = sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + size;
   unsigned char cbuf[p2p_size];
   unsigned char buffer;
 
@@ -1769,13 +1775,13 @@ GCCH_handle_local_data (struct CadetChannel *ch,
   rel->client_allowed = GNUNET_NO;
 
   /* Ok, everything is correct, send the message. */
-  payload = (struct GNUNET_CADET_Data *) cbuf;
+  payload = (struct GNUNET_CADET_ChannelAppDataMessage *) cbuf;
   payload->mid = htonl (rel->mid_send);
   rel->mid_send++;
   GNUNET_memcpy (&payload[1], message, size);
   payload->header.size = htons (p2p_size);
-  payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA);
-  payload->chid = htonl (ch->gid);
+  payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
+  payload->chid = ch->gid;
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
   GCCH_send_prebuilt_message (&payload->header, ch, fwd, NULL);
 
@@ -1840,16 +1846,16 @@ GCCH_handle_local_destroy (struct CadetChannel *ch,
  */
 int
 GCCH_handle_local_create (struct CadetClient *c,
-                          struct GNUNET_CADET_ChannelCreateMessage *msg)
+                          struct GNUNET_CADET_ChannelOpenMessageMessage *msg)
 {
   struct CadetChannel *ch;
   struct CadetTunnel *t;
   struct CadetPeer *peer;
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  towards %s:%u\n",
        GNUNET_i2s (&msg->peer), GNUNET_h2s (&msg->port));
-  chid = ntohl (msg->channel_id);
+  chid = msg->channel_id;
 
   /* Sanity check for duplicate channel IDs */
   if (NULL != GML_channel_get (c, chid))
@@ -1908,7 +1914,7 @@ GCCH_handle_local_create (struct CadetClient *c,
  */
 void
 GCCH_handle_data (struct CadetChannel *ch,
-                  const struct GNUNET_CADET_Data *msg,
+                  const struct GNUNET_CADET_ChannelAppDataMessage *msg,
                   int fwd)
 {
   struct CadetChannelReliability *rel;
@@ -1966,24 +1972,26 @@ GCCH_handle_data (struct CadetChannel *ch,
 
   mid = ntohl (msg->mid);
   LOG (GNUNET_ERROR_TYPE_INFO, "<== %s (%s %4u) on chan %s (%p) %s [%5u]\n",
-       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_DATA), GC_m2s (payload_type), mid,
+       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA), GC_m2s (payload_type), mid,
        GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
 
-  if (GNUNET_NO == ch->reliable ||
-      ( !GC_is_pid_bigger (rel->mid_recv, mid) &&
-        GC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
+  if ( (GNUNET_NO == ch->reliable) ||
+       ( (! GC_is_pid_bigger (rel->mid_recv, mid)) &&
+        GC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
   {
     if (GNUNET_YES == ch->reliable)
     {
       /* Is this the exact next expected messasge? */
       if (mid == rel->mid_recv)
       {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected, sending to client\n");
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+            "as expected, sending to client\n");
         send_client_data (ch, msg, fwd);
       }
       else
       {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n");
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+            "save for later\n");
         add_buffered_data (msg, rel);
       }
     }
@@ -2001,7 +2009,7 @@ GCCH_handle_data (struct CadetChannel *ch,
     if (GC_is_pid_bigger (rel->mid_recv, mid))
     {
       GNUNET_break_op (0);
-      LOG (GNUNET_ERROR_TYPE_INFO,
+      LOG (GNUNET_ERROR_TYPE_WARNING,
            "MID %u on channel %s not expected (window: %u - %u). Dropping!\n",
            mid, GCCH_2s (ch), rel->mid_recv, rel->mid_recv + 63);
     }
@@ -2036,7 +2044,7 @@ GCCH_handle_data (struct CadetChannel *ch,
  */
 void
 GCCH_handle_data_ack (struct CadetChannel *ch,
-                      const struct GNUNET_CADET_DataACK *msg,
+                      const struct GNUNET_CADET_ChannelDataAckMessage *msg,
                       int fwd)
 {
   struct CadetChannelReliability *rel;
@@ -2061,7 +2069,7 @@ GCCH_handle_data_ack (struct CadetChannel *ch,
   ack = ntohl (msg->mid);
   LOG (GNUNET_ERROR_TYPE_INFO,
        "<== %s (0x%010lX %4u) on chan %s (%p) %s [%5u]\n",
-       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_DATA_ACK), msg->futures, ack,
+       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK), msg->futures, ack,
        GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
 
   if (GNUNET_YES == fwd)
@@ -2143,22 +2151,23 @@ GCCH_handle_data_ack (struct CadetChannel *ch,
  */
 struct CadetChannel *
 GCCH_handle_create (struct CadetTunnel *t,
-                    const struct GNUNET_CADET_ChannelCreate *msg)
+                    const struct GNUNET_CADET_ChannelOpenMessage *msg)
 {
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
+  struct GNUNET_CADET_ChannelTunnelNumber gid;
   struct CadetChannel *ch;
   struct CadetClient *c;
   int new_channel;
   const struct GNUNET_HashCode *port;
 
-  chid = ntohl (msg->chid);
-
-  ch = GCT_get_channel (t, chid);
+  gid = msg->chid;
+  ch = GCT_get_channel (t, gid);
   if (NULL == ch)
   {
     /* Create channel */
-    ch = channel_new (t, NULL, 0);
-    ch->gid = chid;
+    chid.channel_of_client = htonl (0);
+    ch = channel_new (t, NULL, chid);
+    ch->gid = gid;
     channel_set_options (ch, ntohl (msg->opt));
     new_channel = GNUNET_YES;
   }
@@ -2170,7 +2179,7 @@ GCCH_handle_create (struct CadetTunnel *t,
 
   LOG (GNUNET_ERROR_TYPE_INFO,
        "<== %s (  0x%08X %4u) on chan %s (%p) %s [%5u]\n",
-       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE), chid, port,
+       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN), chid, port,
        GCCH_2s (ch), ch, GC_f2s (GNUNET_YES), ntohs (msg->header.size));
 
   if (GNUNET_YES == new_channel || GCT_is_loopback (t))
@@ -2243,7 +2252,7 @@ GCCH_handle_nack (struct CadetChannel *ch)
 {
   LOG (GNUNET_ERROR_TYPE_INFO,
        "<== %s (  0x%08X %4u) on chan %s (%p) %s [%5u]\n",
-       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK), ch->gid, 0,
+       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED), ch->gid, 0,
        GCCH_2s (ch), ch, "---", 0);
 
   send_client_nack (ch);
@@ -2263,12 +2272,12 @@ GCCH_handle_nack (struct CadetChannel *ch)
  */
 void
 GCCH_handle_ack (struct CadetChannel *ch,
-                 const struct GNUNET_CADET_ChannelManage *msg,
+                 const struct GNUNET_CADET_ChannelManageMessage *msg,
                  int fwd)
 {
   LOG (GNUNET_ERROR_TYPE_INFO,
        "<== %s (  0x%08X %4u) on chan %s (%p) %s [%5u]\n",
-       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK), ch->gid, 0,
+       GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK), ch->gid, 0,
        GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
 
   /* If this is a remote (non-loopback) channel, find 'fwd'. */
@@ -2299,7 +2308,7 @@ GCCH_handle_ack (struct CadetChannel *ch,
  */
 void
 GCCH_handle_destroy (struct CadetChannel *ch,
-                     const struct GNUNET_CADET_ChannelManage *msg,
+                     const struct GNUNET_CADET_ChannelManageMessage *msg,
                      int fwd)
 {
   struct CadetChannelReliability *rel;
@@ -2374,13 +2383,13 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
   data_id = 0;
   switch (type)
   {
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
     {
-      struct GNUNET_CADET_Data *data_msg;
+      struct GNUNET_CADET_ChannelAppDataMessage *data_msg;
       struct GNUNET_MessageHeader *payload_msg;
       uint16_t payload_type;
 
-      data_msg = (struct GNUNET_CADET_Data *) message;
+      data_msg = (struct GNUNET_CADET_ChannelAppDataMessage *) message;
       data_id = ntohl (data_msg->mid);
       payload_msg = (struct GNUNET_MessageHeader *) &data_msg[1];
       payload_type = ntohs (payload_msg->type);
@@ -2388,28 +2397,29 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
       info[31] = '\0';
       break;
     }
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
     {
-      struct GNUNET_CADET_DataACK *ack_msg;
-      ack_msg = (struct GNUNET_CADET_DataACK *) message;
+      struct GNUNET_CADET_ChannelDataAckMessage *ack_msg;
+      ack_msg = (struct GNUNET_CADET_ChannelDataAckMessage *) message;
       data_id = ntohl (ack_msg->mid);
-      SPRINTF (info, "0x%010lX", ack_msg->futures);
+      SPRINTF (info, "0x%010lX",
+              (unsigned long int) ack_msg->futures);
       break;
     }
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
     {
-      struct GNUNET_CADET_ChannelCreate *cc_msg;
-      cc_msg = (struct GNUNET_CADET_ChannelCreate *) message;
-      SPRINTF (info, "  0x%08X", ntohl (cc_msg->chid));
+      struct GNUNET_CADET_ChannelOpenMessage *cc_msg;
+      cc_msg = (struct GNUNET_CADET_ChannelOpenMessage *) message;
+      SPRINTF (info, "  0x%08X", ntohl (cc_msg->chid.cn));
       break;
     }
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
     case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
     {
-      struct GNUNET_CADET_ChannelManage *m_msg;
-      m_msg = (struct GNUNET_CADET_ChannelManage *) message;
-      SPRINTF (info, "  0x%08X", ntohl (m_msg->chid));
+      struct GNUNET_CADET_ChannelManageMessage *m_msg;
+      m_msg = (struct GNUNET_CADET_ChannelManageMessage *) message;
+      SPRINTF (info, "  0x%08X", ntohl (m_msg->chid.cn));
       break;
     }
     default:
@@ -2428,7 +2438,7 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
 
   switch (type)
   {
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
       if (GNUNET_YES == ch->reliable)
       {
         chq = GNUNET_new (struct CadetChannelQueue);
@@ -2474,9 +2484,9 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
       break;
 
 
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
       chq = GNUNET_new (struct CadetChannelQueue);
       chq->type = type;
       chq->rel = fwd ? ch->root_rel : ch->dest_rel;
@@ -2495,22 +2505,23 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
         }
       }
 
+      chq->rel->uniq = chq;
       chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES,
                                            &ch_message_sent, chq);
       if (NULL == chq->tq)
       {
         GNUNET_break (0);
+       chq->rel->uniq = NULL;
         GCT_debug (ch->t, GNUNET_ERROR_TYPE_ERROR);
         GNUNET_free (chq);
         chq = NULL;
         return;
       }
-      chq->rel->uniq = chq;
       break;
 
 
     case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
       fire_and_forget (message, ch, GNUNET_YES);
       break;
 
@@ -2538,9 +2549,13 @@ GCCH_2s (const struct CadetChannel *ch)
   if (NULL == ch)
     return "(NULL Channel)";
 
-  SPRINTF (buf, "%s:%s gid:%X (%X / %X)",
-           GCT_2s (ch->t), GNUNET_h2s (&ch->port),
-           ch->gid, ch->lid_root, ch->lid_dest);
+  SPRINTF (buf,
+           "%s:%s gid:%X (%X / %X)",
+           GCT_2s (ch->t),
+           GNUNET_h2s (&ch->port),
+           ntohl (ch->gid.cn),
+           ntohl (ch->lid_root.channel_of_client),
+           ntohl (ch->lid_dest.channel_of_client));
 
   return buf;
 }
index eeea02712f098311440c1a9cd783d03590e85628..1eeebf34b55e6fd92b2d23ed3523175918fdabc0 100644 (file)
@@ -69,7 +69,7 @@ GCCH_destroy (struct CadetChannel *ch);
  *
  * @return ID used to identify the channel with the remote peer.
  */
-CADET_ChannelNumber
+struct GNUNET_CADET_ChannelTunnelNumber
 GCCH_get_id (const struct CadetChannel *ch);
 
 /**
@@ -224,7 +224,7 @@ GCCH_handle_local_destroy (struct CadetChannel *ch,
  */
 int
 GCCH_handle_local_create (struct CadetClient *c,
-                          struct GNUNET_CADET_ChannelCreateMessage *msg);
+                          struct GNUNET_CADET_ChannelOpenMessageMessage *msg);
 
 /**
  * Handler for cadet network payload traffic.
@@ -238,7 +238,7 @@ GCCH_handle_local_create (struct CadetClient *c,
  */
 void
 GCCH_handle_data (struct CadetChannel *ch,
-                  const struct GNUNET_CADET_Data *msg,
+                  const struct GNUNET_CADET_ChannelAppDataMessage *msg,
                   int fwd);
 
 
@@ -254,7 +254,7 @@ GCCH_handle_data (struct CadetChannel *ch,
  */
 void
 GCCH_handle_data_ack (struct CadetChannel *ch,
-                      const struct GNUNET_CADET_DataACK *msg,
+                      const struct GNUNET_CADET_ChannelDataAckMessage *msg,
                       int fwd);
 
 
@@ -268,7 +268,7 @@ GCCH_handle_data_ack (struct CadetChannel *ch,
  */
 struct CadetChannel *
 GCCH_handle_create (struct CadetTunnel *t,
-                    const struct GNUNET_CADET_ChannelCreate *msg);
+                    const struct GNUNET_CADET_ChannelOpenMessage *msg);
 
 
 /**
@@ -294,7 +294,7 @@ GCCH_handle_nack (struct CadetChannel *ch);
  */
 void
 GCCH_handle_ack (struct CadetChannel *ch,
-                 const struct GNUNET_CADET_ChannelManage *msg,
+                 const struct GNUNET_CADET_ChannelManageMessage *msg,
                  int fwd);
 
 
@@ -310,7 +310,7 @@ GCCH_handle_ack (struct CadetChannel *ch,
  */
 void
 GCCH_handle_destroy (struct CadetChannel *ch,
-                     const struct GNUNET_CADET_ChannelManage *msg,
+                     const struct GNUNET_CADET_ChannelManageMessage *msg,
                      int fwd);
 
 
@@ -347,6 +347,8 @@ const char *
 GCCH_2s (const struct CadetChannel *ch);
 
 
+
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
index 1c500f716bfcd09654bc88126244ab78bfc79d83..931b32b951295230bf7f0fc2a723ce8394b152c1 100644 (file)
@@ -112,17 +112,17 @@ struct CadetFlowControl
   /**
    * ID of the next packet to send.
    */
-  uint32_t next_pid;
+  struct CadetEncryptedMessageIdentifier next_pid;
 
   /**
    * ID of the last packet sent towards the peer.
    */
-  uint32_t last_pid_sent;
+  struct CadetEncryptedMessageIdentifier last_pid_sent;
 
   /**
    * ID of the last packet received from the peer.
    */
-  uint32_t last_pid_recv;
+  struct CadetEncryptedMessageIdentifier last_pid_recv;
 
   /**
    * Bitmap of past 32 messages received:
@@ -132,14 +132,15 @@ struct CadetFlowControl
   uint32_t recv_bitmap;
 
   /**
-   * Last ACK sent to the peer (peer can't send more than this PID).
+   * Last ACK sent to the peer (peer is not allowed to send
+   * messages with PIDs higher than this value).
    */
-  uint32_t last_ack_sent;
+  struct CadetEncryptedMessageIdentifier last_ack_sent;
 
   /**
    * Last ACK sent towards the origin (for traffic towards leaf node).
    */
-  uint32_t last_ack_recv;
+  struct CadetEncryptedMessageIdentifier last_ack_recv;
 
   /**
    * Task to poll the peer in case of a lost ACK causes stall.
@@ -217,7 +218,7 @@ struct CadetConnection
   /**
    * ID of the connection.
    */
-  struct GNUNET_CADET_Hash id;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier id;
 
   /**
    * Path being used for the tunnel. At the origin of the connection
@@ -321,7 +322,7 @@ extern struct GNUNET_PeerIdentity my_full_id;
 /**
  * Connections known, indexed by cid (CadetConnection).
  */
-static struct GNUNET_CONTAINER_MultiHashMap *connections;
+static struct GNUNET_CONTAINER_MultiShortmap *connections;
 
 /**
  * How many connections are we willing to maintain.
@@ -358,7 +359,8 @@ static void
 fc_debug (struct CadetFlowControl *fc)
 {
   LOG (GNUNET_ERROR_TYPE_DEBUG, "    IN: %u/%u\n",
-              fc->last_pid_recv, fc->last_ack_sent);
+       ntohl (fc->last_pid_recv.pid),
+       ntohl (fc->last_ack_sent.pid));
   LOG (GNUNET_ERROR_TYPE_DEBUG, "    OUT: %u/%u\n",
               fc->last_pid_sent, fc->last_ack_recv);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "    QUEUE: %u/%u\n",
@@ -452,11 +454,11 @@ GCC_state2s (enum CadetConnectionState s)
 static void
 fc_init (struct CadetFlowControl *fc)
 {
-  fc->next_pid = (uint32_t) 0;
-  fc->last_pid_sent = (uint32_t) -1;
-  fc->last_pid_recv = (uint32_t) -1;
-  fc->last_ack_sent = (uint32_t) 0;
-  fc->last_ack_recv = (uint32_t) 0;
+  fc->next_pid.pid = 0;
+  fc->last_pid_sent.pid = htonl (UINT32_MAX);
+  fc->last_pid_recv.pid = htonl (UINT32_MAX);
+  fc->last_ack_sent.pid = (uint32_t) 0;
+  fc->last_ack_recv.pid = (uint32_t) 0;
   fc->poll_task = NULL;
   fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
   fc->queue_n = 0;
@@ -472,9 +474,10 @@ fc_init (struct CadetFlowControl *fc)
  * @return conntection with the given ID @cid or NULL if not found.
  */
 static struct CadetConnection *
-connection_get (const struct GNUNET_CADET_Hash *cid)
+connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
 {
-  return GNUNET_CONTAINER_multihashmap_get (connections, GC_h2hc (cid));
+  return GNUNET_CONTAINER_multishortmap_get (connections,
+                                             &cid->connection_of_tunnel);
 }
 
 
@@ -540,12 +543,16 @@ send_poll (void *cls);
  * @param force Don't optimize out.
  */
 static void
-send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
+send_ack (struct CadetConnection *c,
+         unsigned int buffer,
+         int fwd,
+         int force)
 {
+  static struct CadetEncryptedMessageIdentifier zero;
   struct CadetFlowControl *next_fc;
   struct CadetFlowControl *prev_fc;
-  struct GNUNET_CADET_ACK msg;
-  uint32_t ack;
+  struct GNUNET_CADET_ConnectionEncryptedAckMessage msg;
+  struct CadetEncryptedMessageIdentifier ack_cemi;
   int delta;
 
   GCC_check_connections ();
@@ -558,24 +565,28 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
        GC_f2s (fwd), GCC_2s (c));
 
   /* Check if we need to transmit the ACK. */
-  delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv;
+  delta = ntohl (prev_fc->last_ack_sent.pid) - ntohl (prev_fc->last_pid_recv.pid);
   if (3 < delta && buffer < delta && GNUNET_NO == force)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, delta > 3\n");
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "  last pid recv: %u, last ack sent: %u\n",
-         prev_fc->last_pid_recv, prev_fc->last_ack_sent);
+         ntohl (prev_fc->last_pid_recv.pid),
+         ntohl (prev_fc->last_ack_sent.pid));
     GCC_check_connections ();
     return;
   }
 
   /* Ok, ACK might be necessary, what PID to ACK? */
-  ack = prev_fc->last_pid_recv + buffer;
+  ack_cemi.pid = htonl (ntohl (prev_fc->last_pid_recv.pid) + buffer);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        " ACK %u, last PID %u, last ACK %u, qmax %u, q %u\n",
-       ack, prev_fc->last_pid_recv, prev_fc->last_ack_sent,
+       ntohl (ack_cemi.pid),
+       ntohl (prev_fc->last_pid_recv.pid),
+       ntohl (prev_fc->last_ack_sent.pid),
        next_fc->queue_max, next_fc->queue_n);
-  if (ack == prev_fc->last_ack_sent && GNUNET_NO == force)
+  if ( (ack_cemi.pid == prev_fc->last_ack_sent.pid) &&
+       (GNUNET_NO == force) )
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
     GCC_check_connections ();
@@ -585,7 +596,8 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
   /* Check if message is already in queue */
   if (NULL != prev_fc->ack_msg)
   {
-    if (GC_is_pid_bigger (ack, prev_fc->last_ack_sent))
+    if (GC_is_pid_bigger (ntohl (ack_cemi.pid),
+                          ntohl (prev_fc->last_ack_sent.pid)))
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n");
       GCC_cancel (prev_fc->ack_msg);
@@ -598,17 +610,22 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
       return;
     }
   }
-
-  prev_fc->last_ack_sent = ack;
+  GNUNET_break (GC_is_pid_bigger (ntohl (ack_cemi.pid),
+                                 ntohl (prev_fc->last_ack_sent.pid)));
+  prev_fc->last_ack_sent = ack_cemi;
 
   /* Build ACK message and send on conn */
   msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ACK);
-  msg.ack = htonl (ack);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK);
+  msg.cemi = ack_cemi;
   msg.cid = c->id;
 
-  prev_fc->ack_msg = GCC_send_prebuilt_message (&msg.header, UINT16_MAX, ack,
-                                                c, !fwd, GNUNET_YES,
+  prev_fc->ack_msg = GCC_send_prebuilt_message (&msg.header,
+                                               UINT16_MAX,
+                                               zero,
+                                                c,
+                                                !fwd,
+                                                GNUNET_YES,
                                                 NULL, NULL);
   GNUNET_assert (NULL != prev_fc->ack_msg);
   GCC_check_connections ();
@@ -672,8 +689,12 @@ update_perf (struct CadetConnection *c,
  */
 static void
 conn_message_sent (void *cls,
-                   struct CadetConnection *c, int fwd, int sent,
-                   uint16_t type, uint16_t payload_type, uint32_t pid,
+                   struct CadetConnection *c,
+                   int fwd,
+                   int sent,
+                   uint16_t type,
+                   uint16_t payload_type,
+                   struct CadetEncryptedMessageIdentifier pid,
                    size_t size,
                    struct GNUNET_TIME_Relative wait)
 {
@@ -684,8 +705,11 @@ conn_message_sent (void *cls,
   GCC_check_connections ();
     LOG (GNUNET_ERROR_TYPE_INFO,
          ">>> %s (%s %4u) on conn %s (%p) %s [%5u] in queue %s\n",
-         GC_m2s (type), GC_m2s (payload_type), pid, GCC_2s (c), c,
-         GC_f2s(fwd), size,
+         GC_m2s (type), GC_m2s (payload_type),
+         ntohl (pid.pid),
+         GCC_2s (c),
+         c,
+         GC_f2s (fwd), size,
          GNUNET_STRINGS_relative_time_to_string (wait, GNUNET_YES));
 
   /* If c is NULL, nothing to update. */
@@ -703,7 +727,8 @@ conn_message_sent (void *cls,
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s pid %u\n",
        sent ? "" : "not ", GC_f2s (fwd),
-       GC_m2s (type), GC_m2s (payload_type), pid);
+       GC_m2s (type), GC_m2s (payload_type),
+       ntohl (pid.pid));
   GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG);
 
   /* Update flow control info. */
@@ -722,7 +747,7 @@ conn_message_sent (void *cls,
   }
   else /* CONN_CREATE or CONN_ACK */
   {
-    GNUNET_assert (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED != type);
+    GNUNET_assert (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED != type);
     forced = GNUNET_YES;
   }
 
@@ -742,18 +767,19 @@ conn_message_sent (void *cls,
   switch (type)
   {
     case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
       c->maintenance_q = NULL;
       /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */
       if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd)
         schedule_next_keepalive (c, fwd);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
       if (GNUNET_YES == sent)
       {
         fc->last_pid_sent = pid;
-        if (GC_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
+        if (GC_is_pid_bigger (ntohl (fc->last_pid_sent.pid) + 1,
+                              ntohl (fc->last_ack_recv.pid)) )
           GCC_start_poll (c, fwd);
         GCC_send_ack (c, fwd, GNUNET_NO);
         connection_reset_timeout (c, fwd);
@@ -764,23 +790,23 @@ conn_message_sent (void *cls,
       {
         fc->queue_n--;
         LOG (GNUNET_ERROR_TYPE_DEBUG,
-            "!   accounting pid %u\n",
-            fc->last_pid_sent);
+             "!   accounting pid %u\n",
+             ntohl (fc->last_pid_sent.pid));
       }
       else
       {
         LOG (GNUNET_ERROR_TYPE_DEBUG,
              "!   forced, Q_N not accounting pid %u\n",
-             fc->last_pid_sent);
+             ntohl (fc->last_pid_sent.pid));
       }
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_KX:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
       if (GNUNET_YES == sent)
         connection_reset_timeout (c, fwd);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_POLL:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
       fc->poll_msg = NULL;
       if (2 == c->destroy)
       {
@@ -801,7 +827,7 @@ conn_message_sent (void *cls,
       LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
       fc->ack_msg = NULL;
       break;
 
@@ -905,7 +931,7 @@ check_neighbours (const struct CadetConnection *c)
  */
 static int
 check_connection (void *cls,
-                  const struct GNUNET_HashCode *key,
+                  const struct GNUNET_ShortHashCode *key,
                   void *value)
 {
   struct CadetConnection *c = value;
@@ -925,9 +951,9 @@ GCC_check_connections ()
     return;
   if (NULL == connections)
     return;
-  GNUNET_CONTAINER_multihashmap_iterate (connections,
-                                         &check_connection,
-                                         NULL);
+  GNUNET_CONTAINER_multishortmap_iterate (connections,
+                                          &check_connection,
+                                          NULL);
 }
 
 
@@ -953,9 +979,11 @@ get_hop (struct CadetConnection *c, int fwd)
  * @param ooo_pid PID of the out-of-order message.
  */
 static uint32_t
-get_recv_bitmask (uint32_t last_pid_recv, uint32_t ooo_pid)
+get_recv_bitmask (struct CadetEncryptedMessageIdentifier last_pid_recv,
+                  struct CadetEncryptedMessageIdentifier ooo_pid)
 {
-  return 1 << (last_pid_recv - ooo_pid);
+  // FIXME: should assert that the delta is in range...
+  return 1 << (ntohl (last_pid_recv.pid) - ntohl (ooo_pid.pid));
 }
 
 
@@ -967,14 +995,18 @@ get_recv_bitmask (uint32_t last_pid_recv, uint32_t ooo_pid)
  * @param last_pid_recv Last in-order PID received.
  */
 static int
-is_ooo_ok (uint32_t last_pid_recv, uint32_t ooo_pid, uint32_t ooo_bitmap)
+is_ooo_ok (struct CadetEncryptedMessageIdentifier last_pid_recv,
+           struct CadetEncryptedMessageIdentifier ooo_pid,
+           uint32_t ooo_bitmap)
 {
   uint32_t mask;
 
-  if (GC_is_pid_bigger (last_pid_recv - 31, ooo_pid))
+  if (GC_is_pid_bigger (ntohl (last_pid_recv.pid) - 31,
+                        ntohl (ooo_pid.pid)))
     return GNUNET_NO;
 
-  mask = get_recv_bitmask (last_pid_recv, ooo_pid);
+  mask = get_recv_bitmask (last_pid_recv,
+                           ooo_pid);
   if (0 != (ooo_bitmap & mask))
     return GNUNET_NO;
 
@@ -1021,10 +1053,11 @@ is_fwd (const struct CadetConnection *c,
 static void
 send_connection_ack (struct CadetConnection *c, int fwd)
 {
-  struct GNUNET_CADET_ConnectionACK msg;
+  static struct CadetEncryptedMessageIdentifier zero;
+  struct GNUNET_CADET_ConnectionCreateMessageAckMessage msg;
   struct CadetTunnel *t;
-  const uint16_t size = sizeof (struct GNUNET_CADET_ConnectionACK);
-  const uint16_t type = GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK;
+  const uint16_t size = sizeof (struct GNUNET_CADET_ConnectionCreateMessageAckMessage);
+  const uint16_t type = GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK;
 
   GCC_check_connections ();
   t = c->t;
@@ -1038,9 +1071,12 @@ send_connection_ack (struct CadetConnection *c, int fwd)
   msg.cid = c->id;
 
   GNUNET_assert (NULL == c->maintenance_q);
-  c->maintenance_q = GCP_send (get_hop (c, fwd), &msg.header,
-                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0,
-                               c, fwd,
+  c->maintenance_q = GCP_send (get_hop (c, fwd),
+                               &msg.header,
+                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
+                               zero,
+                               c,
+                               fwd,
                                &conn_message_sent, NULL);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u (conn`ACK)\n",
        c, c->pending_messages);
@@ -1068,17 +1104,23 @@ send_broken (struct CadetConnection *c,
              const struct GNUNET_PeerIdentity *id2,
              int fwd)
 {
-  struct GNUNET_CADET_ConnectionBroken msg;
+  static struct CadetEncryptedMessageIdentifier zero;
+  struct GNUNET_CADET_ConnectionBrokenMessage msg;
 
   GCC_check_connections ();
-  msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken));
+  msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage));
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
   msg.cid = c->id;
   msg.reserved = htonl (0);
   msg.peer1 = *id1;
   msg.peer2 = *id2;
-  (void) GCC_send_prebuilt_message (&msg.header, UINT16_MAX, 0, c, fwd,
-                                    GNUNET_YES, NULL, NULL);
+  (void) GCC_send_prebuilt_message (&msg.header,
+                                    UINT16_MAX,
+                                    zero,
+                                    c,
+                                    fwd,
+                                    GNUNET_YES,
+                                    NULL, NULL);
   GCC_check_connections ();
 }
 
@@ -1093,18 +1135,19 @@ send_broken (struct CadetConnection *c,
  * @param neighbor Peer to notify (neighbor who sent the connection).
  */
 static void
-send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id,
+send_broken_unknown (const struct GNUNET_CADET_ConnectionTunnelIdentifier *connection_id,
                      const struct GNUNET_PeerIdentity *id1,
                      const struct GNUNET_PeerIdentity *id2,
                      struct CadetPeer *neighbor)
 {
-  struct GNUNET_CADET_ConnectionBroken msg;
+  static struct CadetEncryptedMessageIdentifier zero;
+  struct GNUNET_CADET_ConnectionBrokenMessage msg;
 
   GCC_check_connections ();
   LOG (GNUNET_ERROR_TYPE_INFO, "--> BROKEN on unknown connection %s\n",
-       GNUNET_h2s (GC_h2hc (connection_id)));
+       GNUNET_sh2s (&connection_id->connection_of_tunnel));
 
-  msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken));
+  msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage));
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
   msg.cid = *connection_id;
   msg.reserved = htonl (0);
@@ -1113,9 +1156,12 @@ send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id,
     msg.peer2 = *id2;
   else
     memset (&msg.peer2, 0, sizeof (msg.peer2));
-  GNUNET_assert (NULL != GCP_send (neighbor, &msg.header,
-                                   UINT16_MAX, 2,
-                                   NULL, GNUNET_SYSERR, /* connection, fwd */
+  GNUNET_assert (NULL != GCP_send (neighbor,
+                                   &msg.header,
+                                   UINT16_MAX,
+                                   zero,
+                                   NULL,
+                                   GNUNET_SYSERR, /* connection, fwd */
                                    NULL, NULL)); /* continuation */
   GCC_check_connections ();
 }
@@ -1153,7 +1199,7 @@ send_connection_keepalive (struct CadetConnection *c, int fwd)
 
   GNUNET_assert (NULL != c->t);
   msg.size = htons (sizeof (msg));
-  msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE);
+  msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
 
   GNUNET_assert (NULL ==
                  GCT_send_prebuilt_message (&msg, c->t, c,
@@ -1410,8 +1456,9 @@ connection_cancel_queues (struct CadetConnection *c,
 static void
 send_poll (void *cls)
 {
+  static struct CadetEncryptedMessageIdentifier zero;
   struct CadetFlowControl *fc = cls;
-  struct GNUNET_CADET_Poll msg;
+  struct GNUNET_CADET_ConnectionHopByHopPollMessage msg;
   struct CadetConnection *c;
   int fwd;
 
@@ -1422,14 +1469,20 @@ send_poll (void *cls)
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Polling connection %s %s\n",
        GCC_2s (c),  GC_f2s (fwd));
 
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_POLL);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL);
   msg.header.size = htons (sizeof (msg));
   msg.cid = c->id;
-  msg.pid = htonl (fc->last_pid_sent);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid sent: %u\n", fc->last_pid_sent);
-  fc->poll_msg =
-      GCC_send_prebuilt_message (&msg.header, UINT16_MAX, fc->last_pid_sent, c,
-                                 fc == &c->fwd_fc, GNUNET_YES, NULL, NULL);
+  msg.cemi = fc->last_pid_sent;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid sent: %u\n", ntohl (fc->last_pid_sent.pid));
+  fc->poll_msg
+    = GCC_send_prebuilt_message (&msg.header,
+                                 UINT16_MAX,
+                                 zero,
+                                 c,
+                                 fc == &c->fwd_fc,
+                                 GNUNET_YES,
+                                 NULL,
+                                 NULL);
   GNUNET_assert (NULL != fc->poll_msg);
   GCC_check_connections ();
 }
@@ -1829,7 +1882,7 @@ add_to_peer (struct CadetConnection *c,
 static void
 log_message (const struct GNUNET_MessageHeader *message,
              const struct CadetPeer *peer,
-             const struct GNUNET_CADET_Hash *conn_id)
+             const struct GNUNET_CADET_ConnectionTunnelIdentifier *conn_id)
 {
   uint16_t size;
   uint16_t type;
@@ -1840,7 +1893,7 @@ log_message (const struct GNUNET_MessageHeader *message,
   switch (type)
   {
     case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
     case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
     case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
       arrow = "==";
@@ -1848,9 +1901,13 @@ log_message (const struct GNUNET_MessageHeader *message,
     default:
       arrow = "--";
   }
-  LOG (GNUNET_ERROR_TYPE_INFO, "<%s %s on conn %s from %s, %6u bytes\n",
-       arrow, GC_m2s (type), GNUNET_h2s (GC_h2hc (conn_id)),
-       GCP_2s(peer), (unsigned int) size);
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "<%s %s on conn %s from %s, %6u bytes\n",
+       arrow,
+       GC_m2s (type),
+       GNUNET_sh2s (&conn_id->connection_of_tunnel),
+       GCP_2s(peer),
+       (unsigned int) size);
 }
 
 /******************************************************************************/
@@ -1865,9 +1922,10 @@ log_message (const struct GNUNET_MessageHeader *message,
  */
 void
 GCC_handle_create (struct CadetPeer *peer,
-                   const struct GNUNET_CADET_ConnectionCreate *msg)
+                   const struct GNUNET_CADET_ConnectionCreateMessage *msg)
 {
-  const struct GNUNET_CADET_Hash *cid;
+  static struct CadetEncryptedMessageIdentifier zero;
+  const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid;
   struct GNUNET_PeerIdentity *id;
   struct CadetPeerPath *path;
   struct CadetPeer *dest_peer;
@@ -1880,7 +1938,7 @@ GCC_handle_create (struct CadetPeer *peer,
   size = ntohs (msg->header.size);
 
   /* Calculate hops */
-  size -= sizeof (struct GNUNET_CADET_ConnectionCreate);
+  size -= sizeof (struct GNUNET_CADET_ConnectionCreateMessage);
   if (0 != size % sizeof (struct GNUNET_PeerIdentity))
   {
     GNUNET_break_op (0);
@@ -1989,8 +2047,12 @@ GCC_handle_create (struct CadetPeer *peer,
     LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
     GCP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
     GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
-    (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c,
-                                      GNUNET_YES, GNUNET_YES, NULL, NULL);
+    (void) GCC_send_prebuilt_message (&msg->header,
+                                      0,
+                                      zero,
+                                      c,
+                                      GNUNET_YES, GNUNET_YES,
+                                      NULL, NULL);
   }
   path_destroy (path);
   GCC_check_connections ();
@@ -2005,8 +2067,9 @@ GCC_handle_create (struct CadetPeer *peer,
  */
 void
 GCC_handle_confirm (struct CadetPeer *peer,
-                    const struct GNUNET_CADET_ConnectionACK *msg)
+                    const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
 {
+  static struct CadetEncryptedMessageIdentifier zero;
   struct CadetConnection *c;
   enum CadetConnectionState oldstate;
   int fwd;
@@ -2114,7 +2177,10 @@ GCC_handle_confirm (struct CadetPeer *peer,
   else
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
-    (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd,
+    (void) GCC_send_prebuilt_message (&msg->header, 0,
+                                      zero,
+                                      c,
+                                      fwd,
                                       GNUNET_YES, NULL, NULL);
   }
   GCC_check_connections ();
@@ -2129,8 +2195,9 @@ GCC_handle_confirm (struct CadetPeer *peer,
  */
 void
 GCC_handle_broken (struct CadetPeer *peer,
-                   const struct GNUNET_CADET_ConnectionBroken *msg)
+                   const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
 {
+  static struct CadetEncryptedMessageIdentifier zero;
   struct CadetConnection *c;
   struct CadetTunnel *t;
   int fwd;
@@ -2183,7 +2250,8 @@ GCC_handle_broken (struct CadetPeer *peer,
   }
   else
   {
-    (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd,
+    (void) GCC_send_prebuilt_message (&msg->header, 0,
+                                      zero, c, fwd,
                                       GNUNET_YES, NULL, NULL);
     connection_cancel_queues (c, !fwd);
   }
@@ -2200,8 +2268,9 @@ GCC_handle_broken (struct CadetPeer *peer,
  */
 void
 GCC_handle_destroy (struct CadetPeer *peer,
-                    const struct GNUNET_CADET_ConnectionDestroy *msg)
+                    const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
 {
+  static struct CadetEncryptedMessageIdentifier zero;
   struct CadetConnection *c;
   int fwd;
 
@@ -2233,7 +2302,8 @@ GCC_handle_destroy (struct CadetPeer *peer,
 
   if (GNUNET_NO == GCC_is_terminal (c, fwd))
   {
-    (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd,
+    (void) GCC_send_prebuilt_message (&msg->header, 0,
+                                      zero, c, fwd,
                                       GNUNET_YES, NULL, NULL);
   }
   else if (0 == c->pending_messages)
@@ -2262,11 +2332,11 @@ GCC_handle_destroy (struct CadetPeer *peer,
  */
 void
 GCC_handle_ack (struct CadetPeer *peer,
-                const struct GNUNET_CADET_ACK *msg)
+                const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
 {
   struct CadetConnection *c;
   struct CadetFlowControl *fc;
-  uint32_t ack;
+  struct CadetEncryptedMessageIdentifier ack;
   int fwd;
 
   GCC_check_connections ();
@@ -2303,15 +2373,19 @@ GCC_handle_ack (struct CadetPeer *peer,
     return;
   }
 
-  ack = ntohl (msg->ack);
+  ack = msg->cemi;
   LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n",
-       GC_f2s (fwd), ack, fc->last_ack_recv);
-  if (GC_is_pid_bigger (ack, fc->last_ack_recv))
+       GC_f2s (fwd),
+       ntohl (ack.pid),
+       ntohl (fc->last_ack_recv.pid));
+  if (GC_is_pid_bigger (ntohl (ack.pid),
+                        ntohl (fc->last_ack_recv.pid)))
     fc->last_ack_recv = ack;
 
   /* Cancel polling if the ACK is big enough. */
-  if (NULL != fc->poll_task &&
-      GC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
+  if ( (NULL != fc->poll_task) &
+       GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid),
+                         ntohl (fc->last_pid_sent.pid)))
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Cancel poll\n");
     GNUNET_SCHEDULER_cancel (fc->poll_task);
@@ -2331,11 +2405,11 @@ GCC_handle_ack (struct CadetPeer *peer,
  */
 void
 GCC_handle_poll (struct CadetPeer *peer,
-                 const struct GNUNET_CADET_Poll *msg)
+                 const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
 {
   struct CadetConnection *c;
   struct CadetFlowControl *fc;
-  uint32_t pid;
+  struct CadetEncryptedMessageIdentifier pid;
   int fwd;
 
   GCC_check_connections ();
@@ -2347,7 +2421,7 @@ GCC_handle_poll (struct CadetPeer *peer,
                               GNUNET_NO);
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "POLL message on unknown connection %s!\n",
-         GNUNET_h2s (GC_h2hc (&msg->cid)));
+         GNUNET_sh2s (&msg->cid.connection_of_tunnel));
     send_broken_unknown (&msg->cid,
                          &my_full_id,
                          NULL,
@@ -2377,8 +2451,11 @@ GCC_handle_poll (struct CadetPeer *peer,
     return;
   }
 
-  pid = ntohl (msg->pid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n", pid, fc->last_pid_recv);
+  pid = msg->cemi;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "  PID %u, OLD %u\n",
+       ntohl (pid.pid),
+       ntohl (fc->last_pid_recv.pid));
   fc->last_pid_recv = pid;
   fwd = fc == &c->bck_fc;
   GCC_send_ack (c, fwd, GNUNET_YES);
@@ -2402,10 +2479,10 @@ GCC_handle_poll (struct CadetPeer *peer,
  */
 static int
 check_message (const struct GNUNET_MessageHeader *message,
-               const struct GNUNET_CADET_Hash* cid,
+               const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid,
                struct CadetConnection *c,
                struct CadetPeer *sender,
-               uint32_t pid)
+               struct CadetEncryptedMessageIdentifier pid)
 {
   struct CadetFlowControl *fc;
   struct CadetPeer *hop;
@@ -2421,7 +2498,8 @@ check_message (const struct GNUNET_MessageHeader *message,
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "%s on unknown connection %s\n",
          GC_m2s (ntohs (message->type)),
-         GNUNET_h2s (GC_h2hc (cid)));
+         GNUNET_sh2s (&cid->connection_of_tunnel));
+    GNUNET_break_op (0);
     send_broken_unknown (cid,
                          &my_full_id,
                          NULL,
@@ -2453,43 +2531,59 @@ check_message (const struct GNUNET_MessageHeader *message,
 
   /* Check PID for payload messages */
   type = ntohs (message->type);
-  if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type)
+  if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type)
   {
     fc = fwd ? &c->bck_fc : &c->fwd_fc;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u - %u)\n",
-         pid, fc->last_pid_recv + 1, fc->last_ack_sent);
-    if (GC_is_pid_bigger (pid, fc->last_ack_sent))
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected in interval [%u,%u])\n",
+         ntohl (pid.pid),
+        ntohl (fc->last_pid_recv.pid) + 1,
+        ntohl (fc->last_ack_sent.pid));
+    if (GC_is_pid_bigger (ntohl (pid.pid),
+                          ntohl (fc->last_ack_sent.pid)))
     {
-      GNUNET_break_op (0);
-      GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
-      LOG (GNUNET_ERROR_TYPE_WARNING, "Received PID %u, (prev %u), ACK %u\n",
-          pid, fc->last_pid_recv, fc->last_ack_sent);
+      GNUNET_STATISTICS_update (stats,
+                               "# unsolicited message",
+                               1,
+                               GNUNET_NO);
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+          "Received PID %u, (prev %u), ACK %u\n",
+          pid, fc->last_pid_recv, fc->last_ack_sent);
       return GNUNET_SYSERR;
     }
-    if (GC_is_pid_bigger (pid, fc->last_pid_recv))
+    if (GC_is_pid_bigger (ntohl (pid.pid),
+                          ntohl (fc->last_pid_recv.pid)))
     {
       unsigned int delta;
 
-      delta = pid - fc->last_pid_recv;
+      delta = ntohl (pid.pid) - ntohl (fc->last_pid_recv.pid);
       fc->last_pid_recv = pid;
       fc->recv_bitmap <<= delta;
       fc->recv_bitmap |= 1;
     }
     else
     {
-      GNUNET_STATISTICS_update (stats, "# out of order PID", 1, GNUNET_NO);
-      if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv, pid, fc->recv_bitmap))
+      GNUNET_STATISTICS_update (stats,
+                               "# out of order PID",
+                               1,
+                               GNUNET_NO);
+      if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv,
+                                 pid,
+                                 fc->recv_bitmap))
       {
-        LOG (GNUNET_ERROR_TYPE_WARNING, "PID %u unexpected (%u+), dropping!\n",
-             pid, fc->last_pid_recv - 31);
+        LOG (GNUNET_ERROR_TYPE_WARNING,
+            "PID %u unexpected (%u+), dropping!\n",
+             ntohl (pid.pid),
+             ntohl (fc->last_pid_recv.pid) - 31);
         return GNUNET_SYSERR;
       }
-      fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv, pid);
+      fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv,
+                                           pid);
     }
   }
 
   /* Count as connection confirmation. */
-  if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state)
+  if ( (CADET_CONNECTION_SENT == c->state) ||
+       (CADET_CONNECTION_ACK == c->state) )
   {
     connection_change_state (c, CADET_CONNECTION_READY);
     if (NULL != c->t)
@@ -2512,9 +2606,10 @@ check_message (const struct GNUNET_MessageHeader *message,
  */
 void
 GCC_handle_kx (struct CadetPeer *peer,
-               const struct GNUNET_CADET_KX *msg)
+               const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
 {
-  const struct GNUNET_CADET_Hash* cid;
+  static struct CadetEncryptedMessageIdentifier zero;
+  const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid;
   struct CadetConnection *c;
   int fwd;
 
@@ -2527,7 +2622,7 @@ GCC_handle_kx (struct CadetPeer *peer,
                        cid,
                        c,
                        peer,
-                       0);
+                       zero);
 
   /* If something went wrong, discard message. */
   if (GNUNET_SYSERR == fwd)
@@ -2555,7 +2650,8 @@ GCC_handle_kx (struct CadetPeer *peer,
   /* Message not for us: forward to next hop */
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
-  (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd,
+  (void) GCC_send_prebuilt_message (&msg->header, 0,
+                                    zero, c, fwd,
                                     GNUNET_NO, NULL, NULL);
   GCC_check_connections ();
 }
@@ -2569,16 +2665,17 @@ GCC_handle_kx (struct CadetPeer *peer,
  */
 void
 GCC_handle_encrypted (struct CadetPeer *peer,
-                      const struct GNUNET_CADET_Encrypted *msg)
+                      const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
 {
-  const struct GNUNET_CADET_Hash* cid;
+  static struct CadetEncryptedMessageIdentifier zero;
+  const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid;
   struct CadetConnection *c;
-  uint32_t pid;
+  struct CadetEncryptedMessageIdentifier pid;
   int fwd;
 
   GCC_check_connections ();
   cid = &msg->cid;
-  pid = ntohl (msg->pid);
+  pid = msg->cemi;
   log_message (&msg->header, peer, cid);
 
   c = connection_get (cid);
@@ -2591,7 +2688,6 @@ GCC_handle_encrypted (struct CadetPeer *peer,
   /* If something went wrong, discard message. */
   if (GNUNET_SYSERR == fwd)
   {
-    GNUNET_break_op (0);
     GCC_check_connections ();
     return;
   }
@@ -2615,7 +2711,8 @@ GCC_handle_encrypted (struct CadetPeer *peer,
   /* Message not for us: forward to next hop */
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
-  (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd,
+  (void) GCC_send_prebuilt_message (&msg->header, 0,
+                                    zero, c, fwd,
                                     GNUNET_NO, NULL, NULL);
   GCC_check_connections ();
 }
@@ -2661,7 +2758,8 @@ GCC_init (const struct GNUNET_CONFIGURATION_Handle *c)
   }
   create_connection_time = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
                                                      refresh_connection_time);
-  connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO);
+  connections = GNUNET_CONTAINER_multishortmap_create (1024,
+                                                       GNUNET_YES);
 }
 
 
@@ -2676,7 +2774,7 @@ GCC_init (const struct GNUNET_CONFIGURATION_Handle *c)
  */
 static int
 shutdown_iterator (void *cls,
-                   const struct GNUNET_HashCode *key,
+                   const struct GNUNET_ShortHashCode *key,
                    void *value)
 {
   struct CadetConnection *c = value;
@@ -2695,10 +2793,10 @@ GCC_shutdown (void)
 {
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connections\n");
   GCC_check_connections ();
-  GNUNET_CONTAINER_multihashmap_iterate (connections,
-                                         &shutdown_iterator,
-                                         NULL);
-  GNUNET_CONTAINER_multihashmap_destroy (connections);
+  GNUNET_CONTAINER_multishortmap_iterate (connections,
+                                          &shutdown_iterator,
+                                          NULL);
+  GNUNET_CONTAINER_multishortmap_destroy (connections);
   connections = NULL;
 }
 
@@ -2715,7 +2813,7 @@ GCC_shutdown (void)
  *         NULL in case of error: own id not in path, wrong neighbors, ...
 */
 struct CadetConnection *
-GCC_new (const struct GNUNET_CADET_Hash *cid,
+GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
          struct CadetTunnel *t,
          struct CadetPeerPath *path,
          unsigned int own_pos)
@@ -2729,9 +2827,10 @@ GCC_new (const struct GNUNET_CADET_Hash *cid,
   c = GNUNET_new (struct CadetConnection);
   c->id = *cid;
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_put (connections,
-                                                    GCC_get_h (c), c,
-                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+                 GNUNET_CONTAINER_multishortmap_put (connections,
+                                                     &c->id.connection_of_tunnel,
+                                                     c,
+                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
   fc_init (&c->fwd_fc);
   fc_init (&c->bck_fc);
   c->fwd_fc.c = c;
@@ -2832,9 +2931,9 @@ GCC_destroy (struct CadetConnection *c)
   if (GNUNET_NO == c->was_removed)
   {
     GNUNET_break (GNUNET_YES ==
-                  GNUNET_CONTAINER_multihashmap_remove (connections,
-                                                        GCC_get_h (c),
-                                                        c));
+                  GNUNET_CONTAINER_multishortmap_remove (connections,
+                                                         &c->id.connection_of_tunnel,
+                                                         c));
   }
   GNUNET_STATISTICS_update (stats,
                             "# connections",
@@ -2852,27 +2951,13 @@ GCC_destroy (struct CadetConnection *c)
  *
  * @return ID of the connection.
  */
-const struct GNUNET_CADET_Hash *
+const struct GNUNET_CADET_ConnectionTunnelIdentifier *
 GCC_get_id (const struct CadetConnection *c)
 {
   return &c->id;
 }
 
 
-/**
- * Get the connection ID.
- *
- * @param c Connection to get the ID from.
- *
- * @return ID of the connection.
- */
-const struct GNUNET_HashCode *
-GCC_get_h (const struct CadetConnection *c)
-{
-  return GC_h2hc (&c->id);
-}
-
-
 /**
  * Get the connection path.
  *
@@ -2953,12 +3038,13 @@ GCC_get_allowed (struct CadetConnection *c, int fwd)
   struct CadetFlowControl *fc;
 
   fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  if (CADET_CONNECTION_READY != c->state
-      || GC_is_pid_bigger (fc->last_pid_recv, fc->last_ack_sent))
+  if ( (CADET_CONNECTION_READY != c->state) ||
+       GC_is_pid_bigger (ntohl (fc->last_pid_recv.pid),
+                        ntohl (fc->last_ack_sent.pid)) )
   {
     return 0;
   }
-  return (fc->last_ack_sent - fc->last_pid_recv);
+  return (ntohl (fc->last_ack_sent.pid) - ntohl (fc->last_pid_recv.pid));
 }
 
 
@@ -2986,18 +3072,17 @@ GCC_get_qn (struct CadetConnection *c, int fwd)
  *
  * @param c Connection.
  * @param fwd Is query about FWD traffic?
- *
  * @return Next PID to use.
  */
-uint32_t
+struct CadetEncryptedMessageIdentifier
 GCC_get_pid (struct CadetConnection *c, int fwd)
 {
   struct CadetFlowControl *fc;
-  uint32_t pid;
+  struct CadetEncryptedMessageIdentifier pid;
 
   fc = fwd ? &c->fwd_fc : &c->bck_fc;
   pid = fc->next_pid;
-  fc->next_pid++;
+  fc->next_pid.pid = htonl (1 + ntohl (pid.pid));
   return pid;
 }
 
@@ -3072,9 +3157,9 @@ GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer)
   GNUNET_assert (GNUNET_NO == c->was_removed);
   c->was_removed = GNUNET_YES;
   GNUNET_break (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_remove (connections,
-                                                      GCC_get_h (c),
-                                                      c));
+                GNUNET_CONTAINER_multishortmap_remove (connections,
+                                                       &c->id.connection_of_tunnel,
+                                                       c));
   /* Cancel queue in the direction that just died. */
   connection_cancel_queues (c, ! fwd);
   GCC_stop_poll (c, ! fwd);
@@ -3142,8 +3227,10 @@ GCC_is_sendable (struct CadetConnection *c, int fwd)
   fc = fwd ? &c->fwd_fc : &c->bck_fc;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        " last ack recv: %u, last pid sent: %u\n",
-       fc->last_ack_recv, fc->last_pid_sent);
-  if (GC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
+       ntohl (fc->last_ack_recv.pid),
+       ntohl (fc->last_pid_sent.pid));
+  if (GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid),
+                        ntohl (fc->last_pid_sent.pid)))
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n");
     return GNUNET_YES;
@@ -3188,7 +3275,8 @@ GCC_is_direct (struct CadetConnection *c)
  */
 struct CadetConnectionQueue *
 GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                           uint16_t payload_type, uint32_t payload_id,
+                           uint16_t payload_type,
+                           struct CadetEncryptedMessageIdentifier payload_id,
                            struct CadetConnection *c, int fwd, int force,
                            GCC_sent cont, void *cont_cls)
 {
@@ -3214,27 +3302,30 @@ GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
        GC_f2s(fwd), size);
   switch (type)
   {
-    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
       LOG (GNUNET_ERROR_TYPE_DEBUG, "  Q_N+ %p %u, PIDsnt: %u, ACKrcv: %u\n",
-            fc, fc->queue_n, fc->last_pid_sent, fc->last_ack_recv);
+           fc,
+           fc->queue_n,
+           ntohl (fc->last_pid_sent.pid),
+           ntohl (fc->last_ack_recv.pid));
       if (GNUNET_NO == force)
       {
         fc->queue_n++;
       }
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_KX:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
       /* nothing to do here */
       break;
 
     case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
        /* Should've only be used for restransmissions. */
       GNUNET_break (0 == payload_type);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_POLL:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
     case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
     case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
       GNUNET_assert (GNUNET_YES == force);
@@ -3252,7 +3343,7 @@ GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
     GNUNET_break (0);
     LOG (GNUNET_ERROR_TYPE_DEBUG, "queue full: %u/%u\n",
          fc->queue_n, fc->queue_max);
-    if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type)
+    if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type)
     {
       fc->queue_n--;
     }
@@ -3264,21 +3355,25 @@ GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
   c->pending_messages++;
 
   q = GNUNET_new (struct CadetConnectionQueue);
+  q->cont = cont;
+  q->cont_cls = cont_cls;
   q->forced = force;
-  q->peer_q = GCP_send (get_hop (c, fwd), message,
-                        payload_type, payload_id,
-                        c, fwd,
+  GNUNET_CONTAINER_DLL_insert (fc->q_head, fc->q_tail, q);
+  q->peer_q = GCP_send (get_hop (c, fwd),
+                        message,
+                        payload_type,
+                        payload_id,
+                        c,
+                        fwd,
                         &conn_message_sent, q);
   if (NULL == q->peer_q)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "dropping msg on %s, NULL q\n", GCC_2s (c));
+    GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q);
     GNUNET_free (q);
     GCC_check_connections ();
     return NULL;
   }
-  q->cont = cont;
-  q->cont_cls = cont_cls;
-  GNUNET_CONTAINER_DLL_insert (fc->q_head, fc->q_tail, q);
   GCC_check_connections ();
   return q;
 }
@@ -3313,19 +3408,21 @@ GCC_cancel (struct CadetConnectionQueue *q)
 void
 GCC_send_create (struct CadetConnection *c)
 {
+  static struct CadetEncryptedMessageIdentifier zero;
   enum CadetTunnelCState state;
   size_t size;
 
   GCC_check_connections ();
-  size = sizeof (struct GNUNET_CADET_ConnectionCreate);
+  size = sizeof (struct GNUNET_CADET_ConnectionCreateMessage);
   size += c->path->length * sizeof (struct GNUNET_PeerIdentity);
   {
     /* Allocate message on the stack */
     unsigned char cbuf[size];
-    struct GNUNET_CADET_ConnectionCreate *msg;
+    struct GNUNET_CADET_ConnectionCreateMessage *msg;
     struct GNUNET_PeerIdentity *peers;
 
-    msg = (struct GNUNET_CADET_ConnectionCreate *) cbuf;
+
+    msg = (struct GNUNET_CADET_ConnectionCreateMessage *) cbuf;
     msg->header.size = htons (size);
     msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
     msg->reserved = htonl (0);
@@ -3338,7 +3435,8 @@ GCC_send_create (struct CadetConnection *c)
     GNUNET_assert (NULL == c->maintenance_q);
     c->maintenance_q = GCP_send (get_next_hop (c),
                                  &msg->header,
-                                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0,
+                                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
+                                 zero,
                                  c, GNUNET_YES,
                                  &conn_message_sent, NULL);
   }
@@ -3435,7 +3533,8 @@ GCC_send_ack (struct CadetConnection *c, int fwd, int force)
 void
 GCC_send_destroy (struct CadetConnection *c)
 {
-  struct GNUNET_CADET_ConnectionDestroy msg;
+  static struct CadetEncryptedMessageIdentifier zero;
+  struct GNUNET_CADET_ConnectionDestroyMessage msg;
 
   if (GNUNET_YES == c->destroy)
     return;
@@ -3449,10 +3548,16 @@ GCC_send_destroy (struct CadetConnection *c)
               GCC_2s (c));
 
   if (GNUNET_NO == GCC_is_terminal (c, GNUNET_YES))
-    (void) GCC_send_prebuilt_message (&msg.header, UINT16_MAX, 0, c,
+    (void) GCC_send_prebuilt_message (&msg.header,
+                                      UINT16_MAX,
+                                      zero,
+                                      c,
                                       GNUNET_YES, GNUNET_YES, NULL, NULL);
   if (GNUNET_NO == GCC_is_terminal (c, GNUNET_NO))
-    (void) GCC_send_prebuilt_message (&msg.header, UINT16_MAX, 0, c,
+    (void) GCC_send_prebuilt_message (&msg.header,
+                                      UINT16_MAX,
+                                      zero,
+                                      c,
                                       GNUNET_NO, GNUNET_YES, NULL, NULL);
   mark_destroyed (c);
   GCC_check_connections ();
@@ -3538,10 +3643,11 @@ GCC_2s (const struct CadetConnection *c)
     static char buf[128];
 
     SPRINTF (buf, "%s (->%s)",
-             GNUNET_h2s (GC_h2hc (GCC_get_id (c))), GCT_2s (c->t));
+             GNUNET_sh2s (&GCC_get_id (c)->connection_of_tunnel),
+             GCT_2s (c->t));
     return buf;
   }
-  return GNUNET_h2s (GC_h2hc (&c->id));
+  return GNUNET_sh2s (&c->id.connection_of_tunnel);
 }
 
 
@@ -3582,9 +3688,11 @@ GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level)
   LOG2 (level, "CCC  FWD flow control:\n");
   LOG2 (level, "CCC   queue: %u/%u\n", c->fwd_fc.queue_n, c->fwd_fc.queue_max);
   LOG2 (level, "CCC   last PID sent: %5u, recv: %5u\n",
-        c->fwd_fc.last_pid_sent, c->fwd_fc.last_pid_recv);
+        ntohl (c->fwd_fc.last_pid_sent.pid),
+        ntohl (c->fwd_fc.last_pid_recv.pid));
   LOG2 (level, "CCC   last ACK sent: %5u, recv: %5u\n",
-        c->fwd_fc.last_ack_sent, c->fwd_fc.last_ack_recv);
+        ntohl (c->fwd_fc.last_ack_sent.pid),
+        ntohl (c->fwd_fc.last_ack_recv.pid));
   LOG2 (level, "CCC   recv PID bitmap: %X\n", c->fwd_fc.recv_bitmap);
   LOG2 (level, "CCC   poll: task %d, msg  %p, msg_ack %p)\n",
         c->fwd_fc.poll_task, c->fwd_fc.poll_msg, c->fwd_fc.ack_msg);
@@ -3592,9 +3700,11 @@ GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level)
   LOG2 (level, "CCC  BCK flow control:\n");
   LOG2 (level, "CCC   queue: %u/%u\n", c->bck_fc.queue_n, c->bck_fc.queue_max);
   LOG2 (level, "CCC   last PID sent: %5u, recv: %5u\n",
-        c->bck_fc.last_pid_sent, c->bck_fc.last_pid_recv);
+        ntohl (c->bck_fc.last_pid_sent.pid),
+        ntohl (c->bck_fc.last_pid_recv.pid));
   LOG2 (level, "CCC   last ACK sent: %5u, recv: %5u\n",
-        c->bck_fc.last_ack_sent, c->bck_fc.last_ack_recv);
+        ntohl (c->bck_fc.last_ack_sent.pid),
+        ntohl (c->bck_fc.last_ack_recv.pid));
   LOG2 (level, "CCC   recv PID bitmap: %X\n", c->bck_fc.recv_bitmap);
   LOG2 (level, "CCC   poll: task %d, msg  %p, msg_ack %p)\n",
         c->bck_fc.poll_task, c->bck_fc.poll_msg, c->bck_fc.ack_msg);
index 18f33ce7c16a6ea13b81f0c5e7b7dc6160169d7c..1c3160dfd89697e47bd4f234cce3dcdf170df890 100644 (file)
@@ -125,7 +125,7 @@ typedef void
  */
 void
 GCC_handle_create (struct CadetPeer *peer,
-                   const struct GNUNET_CADET_ConnectionCreate *msg);
+                   const struct GNUNET_CADET_ConnectionCreateMessage *msg);
 
 
 /**
@@ -136,7 +136,7 @@ GCC_handle_create (struct CadetPeer *peer,
  */
 void
 GCC_handle_confirm (struct CadetPeer *peer,
-                    const struct GNUNET_CADET_ConnectionACK *msg);
+                    const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg);
 
 
 /**
@@ -147,7 +147,7 @@ GCC_handle_confirm (struct CadetPeer *peer,
  */
 void
 GCC_handle_broken (struct CadetPeer *peer,
-                   const struct GNUNET_CADET_ConnectionBroken *msg);
+                   const struct GNUNET_CADET_ConnectionBrokenMessage *msg);
 
 /**
  * Handler for notifications of destroyed connections.
@@ -157,7 +157,7 @@ GCC_handle_broken (struct CadetPeer *peer,
  */
 void
 GCC_handle_destroy (struct CadetPeer *peer,
-                    const struct GNUNET_CADET_ConnectionDestroy *msg);
+                    const struct GNUNET_CADET_ConnectionDestroyMessage *msg);
 
 /**
  * Handler for cadet network traffic hop-by-hop acks.
@@ -167,7 +167,7 @@ GCC_handle_destroy (struct CadetPeer *peer,
  */
 void
 GCC_handle_ack (struct CadetPeer *peer,
-                const struct GNUNET_CADET_ACK *msg);
+                const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg);
 
 /**
  * Handler for cadet network traffic hop-by-hop data counter polls.
@@ -177,7 +177,7 @@ GCC_handle_ack (struct CadetPeer *peer,
  */
 void
 GCC_handle_poll (struct CadetPeer *peer,
-                 const struct GNUNET_CADET_Poll *msg);
+                 const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg);
 
 /**
  * Handler for key exchange traffic (Axolotl KX).
@@ -187,7 +187,7 @@ GCC_handle_poll (struct CadetPeer *peer,
  */
 void
 GCC_handle_kx (struct CadetPeer *peer,
-               const struct GNUNET_CADET_KX *msg);
+               const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
 
 /**
  * Handler for encrypted cadet network traffic (channel mgmt, data).
@@ -197,7 +197,7 @@ GCC_handle_kx (struct CadetPeer *peer,
  */
 void
 GCC_handle_encrypted (struct CadetPeer *peer,
-                      const struct GNUNET_CADET_Encrypted *msg);
+                      const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
 
 /**
  * Core handler for axolotl key exchange traffic.
@@ -277,7 +277,7 @@ GCC_shutdown (void);
  *         NULL in case of error: own id not in path, wrong neighbors, ...
  */
 struct CadetConnection *
-GCC_new (const struct GNUNET_CADET_Hash *cid,
+GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
          struct CadetTunnel *t,
          struct CadetPeerPath *path,
          unsigned int own_pos);
@@ -300,21 +300,10 @@ GCC_destroy (struct CadetConnection *c);
  *
  * @return ID of the connection.
  */
-const struct GNUNET_CADET_Hash *
+const struct GNUNET_CADET_ConnectionTunnelIdentifier *
 GCC_get_id (const struct CadetConnection *c);
 
 
-/**
- * Get a hash for the connection ID.
- *
- * @param c Connection to get the hash.
- *
- * @return Hash expanded from the ID of the connection.
- */
-const struct GNUNET_HashCode *
-GCC_get_h (const struct CadetConnection *c);
-
-
 /**
  * Get the connection path.
  *
@@ -383,10 +372,9 @@ GCC_get_qn (struct CadetConnection *c, int fwd);
  *
  * @param c Connection.
  * @param fwd Is query about FWD traffic?
- *
  * @return Next PID to use.
  */
-uint32_t
+struct CadetEncryptedMessageIdentifier
 GCC_get_pid (struct CadetConnection *c, int fwd);
 
 /**
@@ -508,7 +496,8 @@ GCC_cancel (struct CadetConnectionQueue *q);
  */
 struct CadetConnectionQueue *
 GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                           uint16_t payload_type, uint32_t payload_id,
+                           uint16_t payload_type,
+                           struct CadetEncryptedMessageIdentifier payload_id,
                            struct CadetConnection *c, int fwd, int force,
                            GCC_sent cont, void *cont_cls);
 
index 9b11ebf181c88df46592d8f3d9514a491533b4b7..22673b16706f49ddec79a97f094982e92e39a864 100644 (file)
  */
 struct GCD_search_handle
 {
-  /** DHT_GET handle. */
+  /**
+   * DHT_GET handle.
+   */
   struct GNUNET_DHT_GetHandle *dhtget;
 
-  /** Provided callback to call when a path is found. */
+  /**
+   * Provided callback to call when a path is found.
+   */
   GCD_search_callback callback;
 
-  /** Provided closure. */
+  /**
+   * Provided closure.
+   */
   void *cls;
 
-  /** Peer ID searched for */
+  /**
+   * Peer ID searched for
+   */
   GNUNET_PEER_Id peer_id;
 };
 
@@ -224,13 +232,16 @@ announce_id (void *cls)
   announce_id_task = NULL;
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n");
   hello = GCH_get_mine ();
-  size = NULL != hello ? GNUNET_HELLO_size (hello) : 0;
-  if (NULL == hello || 0 == size)
+  size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
+  if ( (NULL == hello) || (0 == size) )
   {
     /* Peerinfo gave us no hello yet, try again soon. */
-    LOG (GNUNET_ERROR_TYPE_INFO, "  no hello, waiting!\n");
-    GNUNET_STATISTICS_update (stats, "# DHT announce skipped (no hello)",
-                              1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_INFO,
+        "  no hello, waiting!\n");
+    GNUNET_STATISTICS_update (stats,
+                             "# DHT announce skipped (no hello)",
+                              1,
+                             GNUNET_NO);
     expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
                                            announce_delay);
     announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
@@ -241,29 +252,43 @@ announce_id (void *cls)
     announce_delay = GNUNET_TIME_UNIT_SECONDS;
   }
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Hello %p size: %u\n", hello, size);
-  GNUNET_STATISTICS_update (stats, "# DHT announce",
-                            1, GNUNET_NO);
-  memset (&phash, 0, sizeof (phash));
-  GNUNET_memcpy (&phash, &my_full_id, sizeof (my_full_id));
-  GNUNET_DHT_put (dht_handle,   /* DHT handle */
-                  &phash,       /* Key to use */
-                  dht_replication_level,     /* Replication level */
-                  GNUNET_DHT_RO_RECORD_ROUTE
-                  | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
-                  GNUNET_BLOCK_TYPE_DHT_HELLO,       /* Block type */
-                  size,  /* Size of the data */
-                  (const char *) hello, /* Data itself */
-                  expiration,  /* Data expiration */
-                  NULL,         /* Continuation */
-                  NULL);        /* Continuation closure */
-
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Hello %p size: %u\n",
+       hello,
+       size);
+  if (NULL != hello)
+  {
+    GNUNET_STATISTICS_update (stats,
+                             "# DHT announce",
+                             1, GNUNET_NO);
+    memset (&phash,
+           0,
+           sizeof (phash));
+    GNUNET_memcpy (&phash,
+                  &my_full_id,
+                  sizeof (my_full_id));
+    GNUNET_DHT_put (dht_handle,   /* DHT handle */
+                   &phash,       /* Key to use */
+                   dht_replication_level,     /* Replication level */
+                   GNUNET_DHT_RO_RECORD_ROUTE
+                   | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
+                   GNUNET_BLOCK_TYPE_DHT_HELLO,       /* Block type */
+                   size,  /* Size of the data */
+                   (const char *) hello, /* Data itself */
+                   expiration,  /* Data expiration */
+                   NULL,         /* Continuation */
+                   NULL);        /* Continuation closure */
+  }
   /* Call again in id_announce_time, unless HELLO expires first,
    * but wait at least 1s. */
   next_put = GNUNET_TIME_absolute_get_remaining (expiration);
-  next_put = GNUNET_TIME_relative_min (next_put, id_announce_time);
-  next_put = GNUNET_TIME_relative_max (next_put, GNUNET_TIME_UNIT_SECONDS);
-  announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put, &announce_id, cls);
+  next_put = GNUNET_TIME_relative_min (next_put,
+                                      id_announce_time);
+  next_put = GNUNET_TIME_relative_max (next_put,
+                                      GNUNET_TIME_UNIT_SECONDS);
+  announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put,
+                                                  &announce_id,
+                                                  cls);
 }
 
 /**
@@ -378,8 +403,11 @@ GCD_search (const struct GNUNET_PeerIdentity *peer_id,
                                     GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
                                     NULL,       /* xquery */
                                     0,     /* xquery bits */
-                                    &dht_get_id_handler, h);
-  GNUNET_CONTAINER_multihashmap32_put (get_requests, h->peer_id, h,
+                                    &dht_get_id_handler,
+                                   h);
+  GNUNET_CONTAINER_multihashmap32_put (get_requests,
+                                      h->peer_id,
+                                      h,
                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
   return h;
 }
index 5f535b496f6e19e4e1968ad728547463e115a7c7..34121e1e0106f18bf46ea6516823ceb3b033215b 100644 (file)
@@ -50,11 +50,13 @@ extern "C"
 void
 GCH_init (const struct GNUNET_CONFIGURATION_Handle *c);
 
+
 /**
  * Shut down the hello subsystem.
  */
 void
-GCH_shutdown ();
+GCH_shutdown (void);
+
 
 /**
  * Get own hello message.
@@ -64,6 +66,7 @@ GCH_shutdown ();
 const struct GNUNET_HELLO_Message *
 GCH_get_mine (void);
 
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
index 9be1224c1393863ebfb60ba085e07d5815ac4022..e1f6ac4c37db39414a05e29c1149c4bf1d82f574 100644 (file)
@@ -61,7 +61,7 @@ struct CadetClient
    * Tunnels that belong to this client, indexed by local id
    */
   struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
-  
+
   /**
    * Tunnels this client has accepted, indexed by incoming local id
    */
@@ -70,7 +70,7 @@ struct CadetClient
   /**
    * Channel ID for the next incoming channel.
    */
-  CADET_ChannelNumber next_chid;
+  struct GNUNET_CADET_ClientChannelNumber next_chid;
 
   /**
    * Handle to communicate with the client
@@ -188,7 +188,9 @@ channel_destroy_iterator (void *cls,
        " Channel %s destroy, due to client %s shutdown.\n",
        GCCH_2s (ch), GML_2s (c));
 
-  GCCH_handle_local_destroy (ch, c, key < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV);
+  GCCH_handle_local_destroy (ch,
+                             c,
+                             key < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
   return GNUNET_OK;
 }
 
@@ -247,7 +249,6 @@ client_new (struct GNUNET_SERVER_Client *client)
   c = GNUNET_new (struct CadetClient);
   c->handle = client;
   c->id = next_client_id++; /* overflow not important: just for debug */
-  c->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
 
   c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32);
   c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32);
@@ -439,7 +440,7 @@ handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
 
   /* Message size sanity check */
-  if (sizeof (struct GNUNET_CADET_ChannelCreateMessage)
+  if (sizeof (struct GNUNET_CADET_ChannelOpenMessageMessage)
       != ntohs (message->size))
   {
     GNUNET_break (0);
@@ -449,7 +450,7 @@ handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
 
   if (GNUNET_OK !=
       GCCH_handle_local_create (c,
-                                (struct GNUNET_CADET_ChannelCreateMessage *)
+                                (struct GNUNET_CADET_ChannelOpenMessageMessage *)
                                 message))
   {
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
@@ -474,7 +475,7 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
   struct GNUNET_CADET_ChannelDestroyMessage *msg;
   struct CadetClient *c;
   struct CadetChannel *ch;
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n");
 
@@ -499,7 +500,7 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
   msg = (struct GNUNET_CADET_ChannelDestroyMessage *) message;
 
   /* Retrieve tunnel */
-  chid = ntohl (msg->channel_id);
+  chid = msg->channel_id;
   ch = GML_channel_get (c, chid);
 
   LOG (GNUNET_ERROR_TYPE_INFO, "Client %u is destroying channel %X\n",
@@ -515,7 +516,9 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
     return;
   }
 
-  GCCH_handle_local_destroy (ch, c, chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV);
+  GCCH_handle_local_destroy (ch,
+                             c,
+                             ntohl (chid.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
 
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
   return;
@@ -537,7 +540,7 @@ handle_data (void *cls, struct GNUNET_SERVER_Client *client,
   struct GNUNET_CADET_LocalData *msg;
   struct CadetClient *c;
   struct CadetChannel *ch;
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
   size_t message_size;
   size_t payload_size;
   size_t payload_claimed_size;
@@ -583,12 +586,12 @@ handle_data (void *cls, struct GNUNET_SERVER_Client *client,
     return;
   }
 
-  chid = ntohl (msg->id);
+  chid = msg->id;
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  %u bytes (%u payload) by client %u\n",
        payload_size, payload_claimed_size, c->id);
 
   /* Channel exists? */
-  fwd = chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+  fwd = ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
   ch = GML_channel_get (c, chid);
   if (NULL == ch)
   {
@@ -626,7 +629,7 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
   struct GNUNET_CADET_LocalAck *msg;
   struct CadetChannel *ch;
   struct CadetClient *c;
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
   int fwd;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
@@ -644,13 +647,16 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
   msg = (struct GNUNET_CADET_LocalAck *) message;
 
   /* Channel exists? */
-  chid = ntohl (msg->channel_id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n", chid);
+  chid = msg->channel_id;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n",
+       ntohl (chid.channel_of_client));
   ch = GML_channel_get (c, chid);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "   -- ch %p\n", ch);
   if (NULL == ch)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X unknown.\n", chid);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Channel %X unknown.\n",
+         ntohl (chid.channel_of_client));
     LOG (GNUNET_ERROR_TYPE_DEBUG, "  for client %u.\n", c->id);
     GNUNET_STATISTICS_update (stats,
                               "# client ack messages on unknown channel",
@@ -661,12 +667,10 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
 
   /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */
   /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */
-  fwd = chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+  fwd = ntohl (chid.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
 
   GCCH_handle_local_ack (ch, fwd);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
 }
 
 
@@ -961,8 +965,9 @@ static void
 iter_connection (void *cls, struct CadetConnection *c)
 {
   struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
-  struct GNUNET_CADET_Hash *h = (struct GNUNET_CADET_Hash *) &msg[1];
+  struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
 
+  h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
   h[msg->connections] = *(GCC_get_id (c));
   msg->connections++;
 }
@@ -971,10 +976,10 @@ static void
 iter_channel (void *cls, struct CadetChannel *ch)
 {
   struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
-  struct GNUNET_CADET_Hash *h = (struct GNUNET_CADET_Hash *) &msg[1];
-  CADET_ChannelNumber *chn = (CADET_ChannelNumber *) &h[msg->connections];
+  struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
+  struct GNUNET_CADET_ChannelTunnelNumber *chn = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections];
 
-  chn[msg->channels] = htonl (GCCH_get_id (ch));
+  chn[msg->channels] = GCCH_get_id (ch);
   msg->channels++;
 }
 
@@ -1039,8 +1044,8 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
   c_n = GCT_count_any_connections (t);
 
   size = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
-  size += c_n * sizeof (struct GNUNET_CADET_Hash);
-  size += ch_n * sizeof (CADET_ChannelNumber);
+  size += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
+  size += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
 
   resp = GNUNET_malloc (size);
   resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
@@ -1123,8 +1128,8 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
     sizeof (struct GNUNET_CADET_PortMessage)},
   {&handle_port_close, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
     sizeof (struct GNUNET_CADET_PortMessage)},
-  {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE,
-   sizeof (struct GNUNET_CADET_ChannelCreateMessage)},
+  {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
+   sizeof (struct GNUNET_CADET_ChannelOpenMessageMessage)},
   {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
    sizeof (struct GNUNET_CADET_ChannelDestroyMessage)},
   {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0},
@@ -1214,26 +1219,16 @@ GML_shutdown (void)
  * @return non-NULL if channel exists in the clients lists
  */
 struct CadetChannel *
-GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid)
+GML_channel_get (struct CadetClient *c,
+                 struct GNUNET_CADET_ClientChannelNumber chid)
 {
   struct GNUNET_CONTAINER_MultiHashMap32 *map;
 
-  if (0 == (chid & GNUNET_CADET_LOCAL_CHANNEL_ID_CLI))
-  {
-    GNUNET_break_op (0);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid);
-    return NULL;
-  }
-
-  if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
-    map = c->incoming_channels;
-  else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+  if (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
     map = c->own_channels;
   else
-  {
-    GNUNET_break (0);
-    map = NULL;
-  }
+    map = c->incoming_channels;
+
   if (NULL == map)
   {
     GNUNET_break (0);
@@ -1242,7 +1237,8 @@ GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid)
          GML_2s (c), chid);
     return NULL;
   }
-  return GNUNET_CONTAINER_multihashmap32_get (map, chid);
+  return GNUNET_CONTAINER_multihashmap32_get (map,
+                                              chid.channel_of_client);
 }
 
 
@@ -1255,17 +1251,19 @@ GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid)
  */
 void
 GML_channel_add (struct CadetClient *client,
-                 uint32_t chid,
+                 struct GNUNET_CADET_ClientChannelNumber chid,
                  struct CadetChannel *ch)
 {
-  if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
-    GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch,
-                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
-    GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch,
+  if (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+    GNUNET_CONTAINER_multihashmap32_put (client->own_channels,
+                                         chid.channel_of_client,
+                                         ch,
                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
   else
-    GNUNET_break (0);
+    GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels,
+                                         chid.channel_of_client,
+                                         ch,
+                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
 }
 
 
@@ -1278,19 +1276,17 @@ GML_channel_add (struct CadetClient *client,
  */
 void
 GML_channel_remove (struct CadetClient *client,
-                    uint32_t chid,
+                    struct GNUNET_CADET_ClientChannelNumber chid,
                     struct CadetChannel *ch)
 {
-  if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= chid)
-    GNUNET_break (GNUNET_YES ==
-                  GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels,
-                                                          chid, ch));
-  else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= chid)
-    GNUNET_break (GNUNET_YES ==
-                  GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
-                                                          chid, ch));
+  if (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+    GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
+                                            chid.channel_of_client,
+                                            ch);
   else
-    GNUNET_break (0);
+    GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels,
+                                            chid.channel_of_client,
+                                            ch);
 }
 
 
@@ -1301,18 +1297,26 @@ GML_channel_remove (struct CadetClient *client,
  *
  * @return LID of a channel free to use.
  */
-CADET_ChannelNumber
+struct GNUNET_CADET_ClientChannelNumber
 GML_get_next_chid (struct CadetClient *c)
 {
-  CADET_ChannelNumber chid;
+  struct GNUNET_CADET_ClientChannelNumber chid;
 
-  while (NULL != GML_channel_get (c, c->next_chid))
+  while (NULL != GML_channel_get (c,
+                                  c->next_chid))
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid);
-    c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Channel %u exists...\n",
+         c->next_chid);
+    c->next_chid.channel_of_client
+      = htonl (1 + (ntohl (c->next_chid.channel_of_client)));
+    if (ntohl (c->next_chid.channel_of_client) >=
+        GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+      c->next_chid.channel_of_client = htonl (0);
   }
   chid = c->next_chid;
-  c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+  c->next_chid.channel_of_client
+    = htonl (1 + (ntohl (c->next_chid.channel_of_client)));
 
   return chid;
 }
@@ -1330,9 +1334,11 @@ GML_client_get (struct GNUNET_SERVER_Client *client)
 {
   if (NULL == client)
     return NULL;
-  return GNUNET_SERVER_client_get_user_context (client, struct CadetClient);
+  return GNUNET_SERVER_client_get_user_context (client,
+                                                struct CadetClient);
 }
 
+
 /**
  * Find a client that has opened a port
  *
@@ -1357,27 +1363,25 @@ GML_client_get_by_port (const struct GNUNET_HashCode *port)
 void
 GML_client_delete_channel (struct CadetClient *c,
                            struct CadetChannel *ch,
-                           CADET_ChannelNumber id)
+                           struct GNUNET_CADET_ClientChannelNumber id)
 {
   int res;
 
-  if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= id)
-  {
-    res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
-                                                  id, ch);
-    if (GNUNET_YES != res)
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
-  }
-  else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= id)
+  if (ntohl (id.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
   {
     res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
-                                                  id, ch);
+                                                  id.channel_of_client,
+                                                  ch);
     if (GNUNET_YES != res)
       LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n");
   }
   else
   {
-    GNUNET_break (0);
+    res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
+                                                  id.channel_of_client,
+                                                  ch);
+    if (GNUNET_YES != res)
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
   }
 }
 
@@ -1390,17 +1394,21 @@ GML_client_delete_channel (struct CadetClient *c,
  * @param id Channel ID to use
  */
 void
-GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id)
+GML_send_ack (struct CadetClient *c,
+              struct GNUNET_CADET_ClientChannelNumber id)
 {
   struct GNUNET_CADET_LocalAck msg;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-              "send local %s ack on %X towards %p\n",
-              id < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c);
+       "send local %s ack on %X towards %p\n",
+       ntohl (id.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI
+       ? "FWD" : "BCK",
+       ntohl (id.channel_of_client),
+       c);
 
   msg.header.size = htons (sizeof (msg));
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
-  msg.channel_id = htonl (id);
+  msg.channel_id = id;
   GNUNET_SERVER_notification_context_unicast (nc,
                                               c->handle,
                                               &msg.header,
@@ -1421,14 +1429,16 @@ GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id)
  */
 void
 GML_send_channel_create (struct CadetClient *c,
-                         uint32_t id, struct GNUNET_HashCode *port,
-                         uint32_t opt, const struct GNUNET_PeerIdentity *peer)
+                         struct GNUNET_CADET_ClientChannelNumber id,
+                         const struct GNUNET_HashCode *port,
+                         uint32_t opt,
+                         const struct GNUNET_PeerIdentity *peer)
 {
-  struct GNUNET_CADET_ChannelCreateMessage msg;
+  struct GNUNET_CADET_ChannelOpenMessageMessage msg;
 
   msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
-  msg.channel_id = htonl (id);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
+  msg.channel_id = id;
   msg.port = *port;
   msg.opt = htonl (opt);
   msg.peer = *peer;
@@ -1444,17 +1454,19 @@ GML_send_channel_create (struct CadetClient *c,
  * @param id Channel ID to use
  */
 void
-GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id)
+GML_send_channel_nack (struct CadetClient *c,
+                       struct GNUNET_CADET_ClientChannelNumber id)
 {
   struct GNUNET_CADET_LocalAck msg;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "send local nack on %X towards %p\n",
-       id, c);
+       ntohl (id.channel_of_client),
+       c);
 
   msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK);
-  msg.channel_id = htonl (id);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED);
+  msg.channel_id = id;
   GNUNET_SERVER_notification_context_unicast (nc,
                                               c->handle,
                                               &msg.header,
@@ -1469,7 +1481,8 @@ GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id)
  * @param id ID of the channel that is destroyed.
  */
 void
-GML_send_channel_destroy (struct CadetClient *c, uint32_t id)
+GML_send_channel_destroy (struct CadetClient *c,
+                          struct GNUNET_CADET_ClientChannelNumber id)
 {
   struct GNUNET_CADET_ChannelDestroyMessage msg;
 
@@ -1482,7 +1495,7 @@ GML_send_channel_destroy (struct CadetClient *c, uint32_t id)
     return;
   msg.header.size = htons (sizeof (msg));
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
-  msg.channel_id = htonl (id);
+  msg.channel_id = id;
   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
                                               &msg.header, GNUNET_NO);
 }
@@ -1497,11 +1510,11 @@ GML_send_channel_destroy (struct CadetClient *c, uint32_t id)
  */
 void
 GML_send_data (struct CadetClient *c,
-               const struct GNUNET_CADET_Data *msg,
-               CADET_ChannelNumber id)
+               const struct GNUNET_CADET_ChannelAppDataMessage *msg,
+               struct GNUNET_CADET_ClientChannelNumber id)
 {
   struct GNUNET_CADET_LocalData *copy;
-  uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_Data);
+  uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_ChannelAppDataMessage);
   char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)];
 
   if (size < sizeof (struct GNUNET_MessageHeader))
@@ -1518,7 +1531,7 @@ GML_send_data (struct CadetClient *c,
   GNUNET_memcpy (&copy[1], &msg[1], size);
   copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size);
   copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
-  copy->id = htonl (id);
+  copy->id = id;
   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
                                               &copy->header, GNUNET_NO);
 }
index f89745092ca702149a70f57d26dce0f4729b329f..bf691f9c376a481cac684b0046ea28dc5d353a1d 100644 (file)
@@ -80,7 +80,8 @@ GML_shutdown (void);
  * @return non-NULL if channel exists in the clients lists
  */
 struct CadetChannel *
-GML_channel_get (struct CadetClient *c, uint32_t chid);
+GML_channel_get (struct CadetClient *c,
+                 struct GNUNET_CADET_ClientChannelNumber chid);
 
 /**
  * Add a channel to a client
@@ -91,7 +92,7 @@ GML_channel_get (struct CadetClient *c, uint32_t chid);
  */
 void
 GML_channel_add (struct CadetClient *client,
-                 uint32_t chid,
+                 struct GNUNET_CADET_ClientChannelNumber chid,
                  struct CadetChannel *ch);
 
 /**
@@ -103,7 +104,7 @@ GML_channel_add (struct CadetClient *client,
  */
 void
 GML_channel_remove (struct CadetClient *client,
-                    uint32_t chid,
+                    struct GNUNET_CADET_ClientChannelNumber chid,
                     struct CadetChannel *ch);
 
 /**
@@ -113,7 +114,7 @@ GML_channel_remove (struct CadetClient *client,
  *
  * @return LID of a channel free to use.
  */
-CADET_ChannelNumber
+struct GNUNET_CADET_ClientChannelNumber
 GML_get_next_chid (struct CadetClient *c);
 
 /**
@@ -146,7 +147,7 @@ GML_client_get_by_port (const struct GNUNET_HashCode *port);
 void
 GML_client_delete_channel (struct CadetClient *c,
                            struct CadetChannel *ch,
-                           CADET_ChannelNumber id);
+                           struct GNUNET_CADET_ClientChannelNumber id);
 
 /**
  * Build a local ACK message and send it to a local client, if needed.
@@ -157,7 +158,8 @@ GML_client_delete_channel (struct CadetClient *c,
  * @param id Channel ID to use
  */
 void
-GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id);
+GML_send_ack (struct CadetClient *c,
+              struct GNUNET_CADET_ClientChannelNumber id);
 
 /**
  * Notify the appropriate client that a new incoming channel was created.
@@ -170,8 +172,10 @@ GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id);
  */
 void
 GML_send_channel_create (struct CadetClient *c,
-                         uint32_t id, struct GNUNET_HashCode *port,
-                         uint32_t opt, const struct GNUNET_PeerIdentity *peer);
+                         struct GNUNET_CADET_ClientChannelNumber id,
+                         const struct GNUNET_HashCode *port,
+                         uint32_t opt,
+                         const struct GNUNET_PeerIdentity *peer);
 
 /**
  * Build a local channel NACK message and send it to a local client.
@@ -180,7 +184,9 @@ GML_send_channel_create (struct CadetClient *c,
  * @param id Channel ID to use
  */
 void
-GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id);
+GML_send_channel_nack (struct CadetClient *c,
+                       struct GNUNET_CADET_ClientChannelNumber id);
+
 
 /**
  * Notify a client that a channel is no longer valid.
@@ -189,7 +195,9 @@ GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id);
  * @param id ID of the channel that is destroyed.
  */
 void
-GML_send_channel_destroy (struct CadetClient *c, uint32_t id);
+GML_send_channel_destroy (struct CadetClient *c,
+                          struct GNUNET_CADET_ClientChannelNumber id);
+
 
 /**
  * Modify the cadet message ID from global to local and send to client.
@@ -200,8 +208,8 @@ GML_send_channel_destroy (struct CadetClient *c, uint32_t id);
  */
 void
 GML_send_data (struct CadetClient *c,
-               const struct GNUNET_CADET_Data *msg,
-               CADET_ChannelNumber id);
+               const struct GNUNET_CADET_ChannelAppDataMessage *msg,
+               struct GNUNET_CADET_ClientChannelNumber id);
 
 /**
  * Get the static string to represent a client.
index c312d56bfc82364ac67128042ec4f2663a2a35d9..3f8b7bbb8529f0915bb8d1cec09548181f84f6cf 100644 (file)
@@ -72,6 +72,11 @@ struct CadetPeerQueue {
      */
     void *cont_cls;
 
+    /**
+     * Task to asynchronously run the drop continuation.
+     */
+    struct GNUNET_SCHEDULER_Task *drop_task;
+
     /**
      * Time when message was queued for sending.
      */
@@ -98,9 +103,9 @@ struct CadetPeerQueue {
     uint16_t payload_type;
 
     /**
-     *ID of the payload (PID, ACK #, ...).
+     * ID of the payload (PID, ACK #, ...).
      */
-    uint16_t payload_id;
+    struct CadetEncryptedMessageIdentifier payload_id;
 
     /**
      * Connection this message was sent on.
@@ -160,7 +165,7 @@ struct CadetPeer
     /**
      * Connections that go through this peer; indexed by tid.
      */
-    struct GNUNET_CONTAINER_MultiHashMap *connections;
+    struct GNUNET_CONTAINER_MultiShortmap  *connections;
 
     /**
      * Handle for core transmissions.
@@ -263,7 +268,7 @@ static int in_shutdown;
  */
 static int
 notify_broken (void *cls,
-               const struct GNUNET_HashCode *key,
+               const struct GNUNET_ShortHashCode *key,
                void *value)
 {
     struct CadetPeer *peer = cls;
@@ -368,7 +373,8 @@ core_connect_handler (void *cls,
 
     /* Create the connections hashmap */
     GNUNET_assert (NULL == neighbor->connections);
-    neighbor->connections = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
+    neighbor->connections = GNUNET_CONTAINER_multishortmap_create (16,
+                                                                   GNUNET_YES);
     GNUNET_STATISTICS_update (stats,
                               "# peers",
                               1,
@@ -420,11 +426,11 @@ core_disconnect_handler (void *cls,
     direct_path = pop_direct_path (p);
     if (NULL != p->connections)
     {
-        GNUNET_CONTAINER_multihashmap_iterate (p->connections,
-                                               &notify_broken,
-                                               p);
-        GNUNET_CONTAINER_multihashmap_destroy (p->connections);
-        p->connections = NULL;
+      GNUNET_CONTAINER_multishortmap_iterate (p->connections,
+                                              &notify_broken,
+                                              p);
+      GNUNET_CONTAINER_multishortmap_destroy (p->connections);
+      p->connections = NULL;
     }
     GNUNET_STATISTICS_update (stats,
                               "# peers",
@@ -450,7 +456,7 @@ core_disconnect_handler (void *cls,
  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
  */
 static int
-check_create (void *cls, const struct GNUNET_CADET_ConnectionCreate *msg)
+check_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
 {
     uint16_t size;
 
@@ -470,7 +476,7 @@ check_create (void *cls, const struct GNUNET_CADET_ConnectionCreate *msg)
  * @param msg Message itself.
  */
 static void
-handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreate *msg)
+handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
 {
     struct CadetPeer *peer = cls;
     GCC_handle_create (peer, msg);
@@ -478,13 +484,13 @@ handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreate *msg)
 
 
 /**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
  *
  * @param cls Closure (CadetPeer for neighbor that sent the message).
  * @param msg Message itself.
  */
 static void
-handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionACK *msg)
+handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
 {
     struct CadetPeer *peer = cls;
     GCC_handle_confirm (peer, msg);
@@ -498,7 +504,7 @@ handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionACK *msg)
  * @param msg Message itself.
  */
 static void
-handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBroken *msg)
+handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
 {
     struct CadetPeer *peer = cls;
     GCC_handle_broken (peer, msg);
@@ -512,7 +518,7 @@ handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBroken *msg)
  * @param msg Message itself.
  */
 static void
-handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroy *msg)
+handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
 {
     struct CadetPeer *peer = cls;
     GCC_handle_destroy (peer, msg);
@@ -520,13 +526,13 @@ handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroy *msg)
 
 
 /**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_ACK
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
  *
  * @param cls Closure (CadetPeer for neighbor that sent the message).
  * @param msg Message itself.
  */
 static void
-handle_ack (void *cls, const struct GNUNET_CADET_ACK *msg)
+handle_ack (void *cls, const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
 {
     struct CadetPeer *peer = cls;
     GCC_handle_ack (peer, msg);
@@ -534,13 +540,13 @@ handle_ack (void *cls, const struct GNUNET_CADET_ACK *msg)
 
 
 /**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_POLL
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
  *
  * @param cls Closure (CadetPeer for neighbor that sent the message).
  * @param msg Message itself.
  */
 static void
-handle_poll (void *cls, const struct GNUNET_CADET_Poll *msg)
+handle_poll (void *cls, const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
 {
     struct CadetPeer *peer = cls;
     GCC_handle_poll (peer, msg);
@@ -548,13 +554,13 @@ handle_poll (void *cls, const struct GNUNET_CADET_Poll *msg)
 
 
 /**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_KX
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
  *
  * @param cls Closure (CadetPeer for neighbor that sent the message).
  * @param msg Message itself.
  */
 static void
-handle_kx (void *cls, const struct GNUNET_CADET_KX *msg)
+handle_kx (void *cls, const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
 {
     struct CadetPeer *peer = cls;
     GCC_handle_kx (peer, msg);
@@ -570,13 +576,13 @@ handle_kx (void *cls, const struct GNUNET_CADET_KX *msg)
  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
  */
 static int
-check_encrypted (void *cls, const struct GNUNET_CADET_Encrypted *msg)
+check_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
 {
     uint16_t size;
     uint16_t minimum_size;
 
     size = ntohs (msg->header.size);
-    minimum_size = sizeof (struct GNUNET_CADET_Encrypted)
+    minimum_size = sizeof (struct GNUNET_CADET_TunnelEncryptedMessage)
                    + sizeof (struct GNUNET_MessageHeader);
 
     if (size < minimum_size)
@@ -588,13 +594,13 @@ check_encrypted (void *cls, const struct GNUNET_CADET_Encrypted *msg)
 }
 
 /**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED.
+ * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
  *
  * @param cls Closure (CadetPeer for neighbor that sent the message).
  * @param msg Message itself.
  */
 static void
-handle_encrypted (void *cls, const struct GNUNET_CADET_Encrypted *msg)
+handle_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
 {
     struct CadetPeer *peer = cls;
     GCC_handle_encrypted (peer, msg);
@@ -618,39 +624,39 @@ connect_to_core (const struct GNUNET_CONFIGURATION_Handle *c)
     struct GNUNET_MQ_MessageHandler core_handlers[] = {
         GNUNET_MQ_hd_var_size (create,
                                GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
-                               struct GNUNET_CADET_ConnectionCreate,
+                               struct GNUNET_CADET_ConnectionCreateMessage,
                                NULL),
         GNUNET_MQ_hd_fixed_size (confirm,
-                                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK,
-                                 struct GNUNET_CADET_ConnectionACK,
+                                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
+                                 struct GNUNET_CADET_ConnectionCreateMessageAckMessage,
                                  NULL),
         GNUNET_MQ_hd_fixed_size (broken,
                                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
-                                struct GNUNET_CADET_ConnectionBroken,
+                                struct GNUNET_CADET_ConnectionBrokenMessage,
                                 NULL),
         GNUNET_MQ_hd_fixed_size (destroy,
                                  GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
-                                 struct GNUNET_CADET_ConnectionDestroy,
+                                 struct GNUNET_CADET_ConnectionDestroyMessage,
                                  NULL),
         GNUNET_MQ_hd_fixed_size (ack,
-                                 GNUNET_MESSAGE_TYPE_CADET_ACK,
-                                 struct GNUNET_CADET_ACK,
+                                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
+                                 struct GNUNET_CADET_ConnectionEncryptedAckMessage,
                                  NULL),
         GNUNET_MQ_hd_fixed_size (poll,
-                                 GNUNET_MESSAGE_TYPE_CADET_POLL,
-                                 struct GNUNET_CADET_Poll,
+                                 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
+                                 struct GNUNET_CADET_ConnectionHopByHopPollMessage,
                                  NULL),
         GNUNET_MQ_hd_fixed_size (kx,
-                                 GNUNET_MESSAGE_TYPE_CADET_KX,
-                                 struct GNUNET_CADET_KX,
+                                 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
+                                 struct GNUNET_CADET_TunnelKeyExchangeMessage,
                                  NULL),
         GNUNET_MQ_hd_var_size (encrypted,
-                               GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED,
-                               struct GNUNET_CADET_Encrypted,
+                               GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
+                               struct GNUNET_CADET_TunnelEncryptedMessage,
                                NULL),
         GNUNET_MQ_handler_end ()
     };
-    core_handle = GNUNET_CORE_connecT (c, NULL,
+    core_handle = GNUNET_CORE_connect (c, NULL,
                                        &core_init_notify,
                                        &core_connect_handler,
                                        &core_disconnect_handler,
@@ -681,7 +687,7 @@ core_init_notify (void *cls,
         LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
         LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (core_identity));
         LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id));
-        GNUNET_CORE_disconnecT (core_handle);
+        GNUNET_CORE_disconnect (core_handle);
         connect_to_core (c);
         return;
     }
@@ -729,7 +735,7 @@ get_priority (struct CadetPeerQueue *q)
     }
 
     /* Bulky payload has lower priority, control traffic has higher. */
-    if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == q->type)
+    if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == q->type)
         return low;
     return high;
 }
@@ -795,8 +801,8 @@ peer_destroy (struct CadetPeer *peer)
         GCT_destroy_empty (peer->tunnel);
     if (NULL != peer->connections)
     {
-        GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (peer->connections));
-        GNUNET_CONTAINER_multihashmap_destroy (peer->connections);
+        GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (peer->connections));
+        GNUNET_CONTAINER_multishortmap_destroy (peer->connections);
         peer->connections = NULL;
     }
     if (NULL != peer->hello_offer)
@@ -1053,8 +1059,8 @@ search_handler (void *cls, const struct CadetPeerPath *path)
 static int
 is_connection_management (uint16_t type)
 {
-    return type == GNUNET_MESSAGE_TYPE_CADET_ACK ||
-           type == GNUNET_MESSAGE_TYPE_CADET_POLL;
+    return type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK ||
+           type == GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL;
 }
 
 
@@ -1104,8 +1110,11 @@ call_peer_cont (struct CadetPeerQueue *q, int sent)
              GNUNET_STRINGS_relative_time_to_string (wait_time, GNUNET_NO));
         q->cont (q->cont_cls,
                  q->c, q->c_fwd, sent,
-                 q->type, q->payload_type, q->payload_id,
+                 q->type,
+                 q->payload_type,
+                 q->payload_id,
                  q->size, wait_time);
+       q->cont = NULL;
     }
     GNUNET_CONTAINER_DLL_remove (q->peer->q_head, q->peer->q_tail, q);
 }
@@ -1130,6 +1139,22 @@ mq_sent (void *cls)
 }
 
 
+/**
+ * Finish the drop operation.
+ *
+ * @param cls queue entry to finish drop for
+ */
+static void
+drop_cb (void *cls)
+{
+  struct CadetPeerQueue *q = cls;
+
+  GNUNET_MQ_discard (q->env);
+  call_peer_cont (q, GNUNET_YES);
+  GNUNET_free (q);
+}
+
+
 /**
  * @brief Send a message to another peer (using CORE).
  *
@@ -1150,7 +1175,7 @@ struct CadetPeerQueue *
 GCP_send (struct CadetPeer *peer,
           const struct GNUNET_MessageHeader *message,
           uint16_t payload_type,
-          uint32_t payload_id,
+          struct CadetEncryptedMessageIdentifier payload_id,
           struct CadetConnection *c,
           int fwd,
           GCP_sent cont,
@@ -1165,7 +1190,8 @@ GCP_send (struct CadetPeer *peer,
     size = ntohs (message->size);
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "que %s (%s %4u) on conn %s (%p) %s towards %s (size %u)\n",
-         GC_m2s (type), GC_m2s (payload_type), payload_id,
+         GC_m2s (type), GC_m2s (payload_type),
+         ntohl (payload_id.pid),
          GCC_2s (c), c, GC_f2s (fwd), GCP_2s (peer), size);
 
     if (NULL == peer->connections)
@@ -1191,7 +1217,8 @@ GCP_send (struct CadetPeer *peer,
     q->payload_id = payload_id;
     q->c = c;
     q->c_fwd = fwd;
-    GNUNET_MQ_notify_sent (q->env, mq_sent, q);
+    GNUNET_MQ_notify_sent (q->env, &mq_sent, q);
+    GNUNET_CONTAINER_DLL_insert (peer->q_head, peer->q_tail, q);
 
     if (GNUNET_YES == q->management_traffic)
     {
@@ -1201,19 +1228,21 @@ GCP_send (struct CadetPeer *peer,
     {
         if (GNUNET_YES == should_I_drop ())
         {
-            LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s (%s %u) on conn %s %s\n",
-                 GC_m2s (q->type), GC_m2s (q->payload_type),
-                 q->payload_id, GCC_2s (c), GC_f2s (q->c_fwd));
-            GNUNET_MQ_discard (q->env);
-            call_peer_cont (q, GNUNET_YES);
-            GNUNET_free (q);
-            return NULL;
+            LOG (GNUNET_ERROR_TYPE_WARNING,
+                "DD %s (%s %u) on conn %s %s (random drop for testing)\n",
+                 GC_m2s (q->type),
+                 GC_m2s (q->payload_type),
+                 ntohl (q->payload_id.pid),
+                 GCC_2s (c),
+                 GC_f2s (q->c_fwd));
+           q->drop_task = GNUNET_SCHEDULER_add_now (&drop_cb,
+                                                    q);
+           return q;
         }
         GNUNET_MQ_send (peer->core_mq, q->env);
         peer->queue_n++;
     }
 
-    GNUNET_CONTAINER_DLL_insert (peer->q_head, peer->q_tail, q);
     GCC_check_connections ();
     return q;
 }
@@ -1231,9 +1260,18 @@ GCP_send (struct CadetPeer *peer,
 void
 GCP_send_cancel (struct CadetPeerQueue *q)
 {
-    call_peer_cont (q, GNUNET_NO);
+  if (NULL != q->drop_task)
+  {
+    GNUNET_SCHEDULER_cancel (q->drop_task);
+    q->drop_task = NULL;
+    GNUNET_MQ_discard (q->env);
+  }
+  else
+  {
     GNUNET_MQ_send_cancel (q->env);
-    GNUNET_free (q);
+  }
+  call_peer_cont (q, GNUNET_NO);
+  GNUNET_free (q);
 }
 
 
@@ -1294,12 +1332,12 @@ GCP_shutdown (void)
     in_shutdown = GNUNET_YES;
     if (NULL != core_handle)
     {
-        GNUNET_CORE_disconnecT (core_handle);
+        GNUNET_CORE_disconnect (core_handle);
         core_handle = NULL;
     }
     GNUNET_PEER_change_rc (myid, -1);
     /* With MQ API, CORE calls the disconnect handler for every peer
-     * after calling GNUNET_CORE_disconnecT, shutdown must occur *after* that.
+     * after calling GNUNET_CORE_disconnect, shutdown must occur *after* that.
      */
     GNUNET_CONTAINER_multipeermap_iterate (peers,
                                            &shutdown_peer,
@@ -1543,14 +1581,14 @@ GCP_add_connection (struct CadetPeer *peer,
          GCP_2s (peer));
     GNUNET_assert (NULL != peer->connections);
     GNUNET_assert (GNUNET_OK ==
-                   GNUNET_CONTAINER_multihashmap_put (peer->connections,
-                           GCC_get_h (c),
-                           c,
-                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+                   GNUNET_CONTAINER_multishortmap_put (peer->connections,
+                                                       &GCC_get_id (c)->connection_of_tunnel,
+                                                       c,
+                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Peer %s has now %u connections.\n",
          GCP_2s (peer),
-         GNUNET_CONTAINER_multihashmap_size (peer->connections));
+         GNUNET_CONTAINER_multishortmap_size (peer->connections));
 }
 
 
@@ -1761,13 +1799,13 @@ void
 GCP_check_connection (const struct CadetPeer *peer,
                       const struct CadetConnection *c)
 {
-    GNUNET_assert (NULL != peer);
-    GNUNET_assert (NULL != peer->connections);
-    return;
-    GNUNET_assert (GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_contains_value (peer->connections,
-                           GCC_get_h (c),
-                           c));
+  GNUNET_assert (NULL != peer);
+  GNUNET_assert (NULL != peer->connections);
+  return; // ????
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multishortmap_contains_value (peer->connections,
+                                                                &GCC_get_id (c)->connection_of_tunnel,
+                                                                c));
 }
 
 
@@ -1791,13 +1829,13 @@ GCP_remove_connection (struct CadetPeer *peer,
             (NULL == peer->connections) )
         return;
     GNUNET_assert (GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_remove (peer->connections,
-                           GCC_get_h (c),
-                           c));
+                   GNUNET_CONTAINER_multishortmap_remove (peer->connections,
+                                                          &GCC_get_id (c)->connection_of_tunnel,
+                                                          c));
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Peer %s remains with %u connections.\n",
          GCP_2s (peer),
-         GNUNET_CONTAINER_multihashmap_size (peer->connections));
+         GNUNET_CONTAINER_multishortmap_size (peer->connections));
 }
 
 
index 093cfa21aa94ff61283fac3bc6baf05c2e21fa04..1e206e10f1ce059142a26395fbc68be18d9c326b 100644 (file)
@@ -69,8 +69,12 @@ struct CadetPeerQueue;
  */
 typedef void
 (*GCP_sent) (void *cls,
-             struct CadetConnection *c, int fwd, int sent,
-             uint16_t type, uint16_t payload_type, uint32_t pid,
+             struct CadetConnection *c,
+             int fwd,
+             int sent,
+             uint16_t type,
+             uint16_t payload_type,
+             struct CadetEncryptedMessageIdentifier pid,
              size_t size,
              struct GNUNET_TIME_Relative wait);
 
@@ -122,6 +126,7 @@ GCP_shutdown (void);
 struct CadetPeer *
 GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create);
 
+
 /**
  * Retrieve the CadetPeer stucture associated with the peer. Optionally create
  * one and insert it in the appropriate structures if the peer is not known yet.
@@ -136,6 +141,7 @@ GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create);
 struct CadetPeer *
 GCP_get_short (const GNUNET_PEER_Id peer, int create);
 
+
 /**
  * Try to establish a new connection to this peer (in its tunnel).
  * If the peer doesn't have any path to it yet, try to get one.
@@ -164,7 +170,7 @@ struct CadetPeerQueue *
 GCP_send (struct CadetPeer *peer,
           const struct GNUNET_MessageHeader *message,
           uint16_t payload_type,
-          uint32_t payload_id,
+          struct CadetEncryptedMessageIdentifier payload_id,
           struct CadetConnection *c,
           int fwd,
           GCP_sent cont,
@@ -440,7 +446,8 @@ GCP_iterate_paths (struct CadetPeer *peer,
  * @param cls Closure for @c iter.
  */
 void
-GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls);
+GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
+                 void *cls);
 
 
 /**
index 5b07e42c068be3103a68aa11820cc4292d53bc91..65775ce669030520f79ef2bac94566e6a50b29fb 100644 (file)
@@ -63,7 +63,7 @@ struct CadetTChannel
 
 
 /**
- * Connection list and metadata.
+ * Entry in list of connections used by tunnel, with metadata.
  */
 struct CadetTConnection
 {
@@ -243,6 +243,7 @@ struct CadetTunnelAxolotl
   struct GNUNET_TIME_Absolute ratchet_expiration;
 };
 
+
 /**
  * Struct containing all information regarding a tunnel to a peer.
  */
@@ -309,7 +310,7 @@ struct CadetTunnel
   /**
    * Channel ID for the next created channel.
    */
-  CADET_ChannelNumber next_chid;
+  struct GNUNET_CADET_ChannelTunnelNumber next_chid;
 
   /**
    * Destroy flag: if true, destroy on last message.
@@ -648,7 +649,7 @@ new_ephemeral (struct CadetTunnel *t)
 static void
 t_hmac (const void *plaintext, size_t size,
         uint32_t iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
-        struct GNUNET_CADET_Hash *hmac)
+        struct GNUNET_ShortHashCode *hmac)
 {
   static const char ctx[] = "cadet authentication key";
   struct GNUNET_CRYPTO_AuthKey auth_key;
@@ -842,7 +843,7 @@ t_ax_decrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size)
  * @param msg Message whose header to encrypt.
  */
 static void
-t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_Encrypted *msg)
+t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_TunnelEncryptedMessage *msg)
 {
   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
   struct CadetTunnelAxolotl *ax;
@@ -873,8 +874,8 @@ t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_Encrypted *msg)
  * @param dst Where to decrypt header to.
  */
 static void
-t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_Encrypted *src,
-             struct GNUNET_CADET_Encrypted *dst)
+t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_TunnelEncryptedMessage *src,
+             struct GNUNET_CADET_TunnelEncryptedMessage *dst)
 {
   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
   struct CadetTunnelAxolotl *ax;
@@ -912,12 +913,12 @@ t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_Encrypted *src,
  */
 static int
 try_old_ax_keys (struct CadetTunnel *t, void *dst,
-                 const struct GNUNET_CADET_Encrypted *src, size_t size)
+                 const struct GNUNET_CADET_TunnelEncryptedMessage *src, size_t size)
 {
   struct CadetTunnelSkippedKey *key;
-  struct GNUNET_CADET_Hash *hmac;
+  struct GNUNET_ShortHashCode *hmac;
   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-  struct GNUNET_CADET_Encrypted plaintext_header;
+  struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
   struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
   size_t esize;
   size_t res;
@@ -926,7 +927,7 @@ try_old_ax_keys (struct CadetTunnel *t, void *dst,
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying old keys\n");
   hmac = &plaintext_header.hmac;
-  esize = size - sizeof (struct GNUNET_CADET_Encrypted);
+  esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
 
   /* Find a correct Header Key */
   for (key = t->ax->skipped_head; NULL != key; key = key->next)
@@ -947,8 +948,8 @@ try_old_ax_keys (struct CadetTunnel *t, void *dst,
     return -1;
 
   /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
-  GNUNET_assert (size > sizeof (struct GNUNET_CADET_Encrypted));
-  len = size - sizeof (struct GNUNET_CADET_Encrypted);
+  GNUNET_assert (size > sizeof (struct GNUNET_CADET_TunnelEncryptedMessage));
+  len = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
   GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader));
 
   /* Decrypt header */
@@ -1091,19 +1092,19 @@ store_ax_keys (struct CadetTunnel *t,
  */
 static int
 t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst,
-                           const struct GNUNET_CADET_Encrypted *src,
+                           const struct GNUNET_CADET_TunnelEncryptedMessage *src,
                            size_t size)
 {
   struct CadetTunnelAxolotl *ax;
-  struct GNUNET_CADET_Hash msg_hmac;
+  struct GNUNET_ShortHashCode msg_hmac;
   struct GNUNET_HashCode hmac;
-  struct GNUNET_CADET_Encrypted plaintext_header;
+  struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
   uint32_t Np;
   uint32_t PNp;
   size_t esize; /* Size of encryped payload */
   size_t osize; /* Size of output (decrypted payload) */
 
-  esize = size - sizeof (struct GNUNET_CADET_Encrypted);
+  esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
   ax = t->ax;
   if (NULL == ax)
     return -1;
@@ -1321,12 +1322,11 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
                        struct CadetTunnelQueue *existing_q)
 {
   struct GNUNET_MessageHeader *msg;
-  struct GNUNET_CADET_Encrypted *ax_msg;
+  struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
   struct CadetTunnelQueue *tq;
   size_t size = ntohs (message->size);
-  char cbuf[sizeof (struct GNUNET_CADET_Encrypted) + size] GNUNET_ALIGN;
+  char cbuf[sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size] GNUNET_ALIGN;
   size_t esize;
-  uint32_t mid;
   uint16_t type;
   int fwd;
 
@@ -1352,10 +1352,10 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
 
   GNUNET_assert (GNUNET_NO == GCT_is_loopback (t));
 
-  ax_msg = (struct GNUNET_CADET_Encrypted *) cbuf;
+  ax_msg = (struct GNUNET_CADET_TunnelEncryptedMessage *) cbuf;
   msg = &ax_msg->header;
-  msg->size = htons (sizeof (struct GNUNET_CADET_Encrypted) + size);
-  msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED);
+  msg->size = htons (sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size);
+  msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
   esize = t_ax_encrypt (t, &ax_msg[1], message, size);
   ax_msg->Ns = htonl (t->ax->Ns++);
   ax_msg->PNs = htonl (t->ax->PNs);
@@ -1378,34 +1378,22 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
   }
   fwd = GCC_is_origin (c, GNUNET_YES);
   ax_msg->cid = *GCC_get_id (c);
-  ax_msg->pid = htonl (GCC_get_pid (c, fwd));
+  ax_msg->cemi = GCC_get_pid (c, fwd);
 
-  mid = 0;
-  type = ntohs (message->type);
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-      if (GNUNET_MESSAGE_TYPE_CADET_DATA == type)
-        mid = ntohl (((struct GNUNET_CADET_Data *) message)->mid);
-      else
-        mid = ntohl (((struct GNUNET_CADET_DataACK *) message)->mid);
-      /* Fall thru */
-    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
-      break;
-    default:
-      GNUNET_break (0);
-      LOG (GNUNET_ERROR_TYPE_ERROR, "type %s not valid\n", GC_m2s (type));
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s\n", GC_m2s (type));
+  type = htons (message->type);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Sending message of type %s with CEMI %u and CID %s\n",
+       GC_m2s (type),
+       htonl (ax_msg->cemi.pid),
+       GNUNET_sh2s (&ax_msg->cid.connection_of_tunnel));
 
   if (NULL == cont)
   {
-    (void) GCC_send_prebuilt_message (msg, type, mid, c, fwd,
+    (void) GCC_send_prebuilt_message (msg,
+                                      type,
+                                      ax_msg->cemi,
+                                      c,
+                                      fwd,
                                       force, NULL, NULL);
     return NULL;
   }
@@ -1418,11 +1406,16 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
     tq = existing_q;
     tq->tqd = NULL;
   }
-  tq->cq = GCC_send_prebuilt_message (msg, type, mid, c, fwd, force,
-                                      &tun_message_sent, tq);
-  GNUNET_assert (NULL != tq->cq);
   tq->cont = cont;
   tq->cont_cls = cont_cls;
+  tq->cq = GCC_send_prebuilt_message (msg,
+                                      type,
+                                      ax_msg->cemi,
+                                      c,
+                                      fwd,
+                                      force,
+                                      &tun_message_sent, tq);
+  GNUNET_assert (NULL != tq->cq);
 
   return tq;
 }
@@ -1562,17 +1555,19 @@ destroy_iterator (void *cls,
  * @param gid ID of the channel.
  */
 static void
-send_channel_destroy (struct CadetTunnel *t, unsigned int gid)
+send_channel_destroy (struct CadetTunnel *t,
+                      struct GNUNET_CADET_ChannelTunnelNumber gid)
 {
-  struct GNUNET_CADET_ChannelManage msg;
+  struct GNUNET_CADET_ChannelManageMessage msg;
 
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
   msg.header.size = htons (sizeof (msg));
-  msg.chid = htonl (gid);
+  msg.chid = gid;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "WARNING destroying unknown channel %u on tunnel %s\n",
-       gid, GCT_2s (t));
+       ntohl (gid.cn),
+       GCT_2s (t));
   send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL);
 }
 
@@ -1589,7 +1584,7 @@ send_channel_destroy (struct CadetTunnel *t, unsigned int gid)
  */
 static void
 handle_data (struct CadetTunnel *t,
-             const struct GNUNET_CADET_Data *msg,
+             const struct GNUNET_CADET_ChannelAppDataMessage *msg,
              int fwd)
 {
   struct CadetChannel *ch;
@@ -1600,7 +1595,7 @@ handle_data (struct CadetTunnel *t,
   /* Check size */
   size = ntohs (msg->header.size);
   if (size <
-      sizeof (struct GNUNET_CADET_Data) +
+      sizeof (struct GNUNET_CADET_ChannelAppDataMessage) +
       sizeof (struct GNUNET_MessageHeader))
   {
     GNUNET_break (0);
@@ -1613,13 +1608,17 @@ handle_data (struct CadetTunnel *t,
 
 
   /* Check channel */
-  ch = GCT_get_channel (t, ntohl (msg->chid));
+  ch = GCT_get_channel (t, msg->chid);
   if (NULL == ch)
   {
-    GNUNET_STATISTICS_update (stats, "# data on unknown channel",
-                              1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "channel 0x%X unknown\n", ntohl (msg->chid));
-    send_channel_destroy (t, ntohl (msg->chid));
+    GNUNET_STATISTICS_update (stats,
+                              "# data on unknown channel",
+                              1,
+                              GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "channel 0x%X unknown\n",
+         ntohl (msg->chid.cn));
+    send_channel_destroy (t, msg->chid);
     return;
   }
 
@@ -1639,7 +1638,7 @@ handle_data (struct CadetTunnel *t,
  */
 static void
 handle_data_ack (struct CadetTunnel *t,
-                 const struct GNUNET_CADET_DataACK *msg,
+                 const struct GNUNET_CADET_ChannelDataAckMessage *msg,
                  int fwd)
 {
   struct CadetChannel *ch;
@@ -1647,20 +1646,20 @@ handle_data_ack (struct CadetTunnel *t,
 
   /* Check size */
   size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_DataACK))
+  if (size != sizeof (struct GNUNET_CADET_ChannelDataAckMessage))
   {
     GNUNET_break (0);
     return;
   }
 
   /* Check channel */
-  ch = GCT_get_channel (t, ntohl (msg->chid));
+  ch = GCT_get_channel (t, msg->chid);
   if (NULL == ch)
   {
     GNUNET_STATISTICS_update (stats, "# data ack on unknown channel",
                               1, GNUNET_NO);
     LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
-         ntohl (msg->chid));
+         ntohl (msg->chid.cn));
     return;
   }
 
@@ -1676,21 +1675,21 @@ handle_data_ack (struct CadetTunnel *t,
  */
 static void
 handle_ch_create (struct CadetTunnel *t,
-                  const struct GNUNET_CADET_ChannelCreate *msg)
+                  const struct GNUNET_CADET_ChannelOpenMessage *msg)
 {
   struct CadetChannel *ch;
   size_t size;
 
   /* Check size */
   size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_ChannelCreate))
+  if (size != sizeof (struct GNUNET_CADET_ChannelOpenMessage))
   {
     GNUNET_break_op (0);
     return;
   }
 
   /* Check channel */
-  ch = GCT_get_channel (t, ntohl (msg->chid));
+  ch = GCT_get_channel (t, msg->chid);
   if (NULL != ch && ! GCT_is_loopback (t))
   {
     /* Probably a retransmission, safe to ignore */
@@ -1711,27 +1710,28 @@ handle_ch_create (struct CadetTunnel *t,
  */
 static void
 handle_ch_nack (struct CadetTunnel *t,
-                const struct GNUNET_CADET_ChannelManage *msg)
+                const struct GNUNET_CADET_ChannelManageMessage *msg)
 {
   struct CadetChannel *ch;
   size_t size;
 
   /* Check size */
   size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
+  if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
   {
     GNUNET_break (0);
     return;
   }
 
   /* Check channel */
-  ch = GCT_get_channel (t, ntohl (msg->chid));
+  ch = GCT_get_channel (t, msg->chid);
   if (NULL == ch)
   {
     GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel",
                               1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
-         ntohl (msg->chid));
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "WARNING channel %u unknown\n",
+         ntohl (msg->chid.cn));
     return;
   }
 
@@ -1751,7 +1751,7 @@ handle_ch_nack (struct CadetTunnel *t,
  */
 static void
 handle_ch_ack (struct CadetTunnel *t,
-               const struct GNUNET_CADET_ChannelManage *msg,
+               const struct GNUNET_CADET_ChannelManageMessage *msg,
                int fwd)
 {
   struct CadetChannel *ch;
@@ -1759,20 +1759,23 @@ handle_ch_ack (struct CadetTunnel *t,
 
   /* Check size */
   size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
+  if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
   {
     GNUNET_break (0);
     return;
   }
 
   /* Check channel */
-  ch = GCT_get_channel (t, ntohl (msg->chid));
+  ch = GCT_get_channel (t, msg->chid);
   if (NULL == ch)
   {
-    GNUNET_STATISTICS_update (stats, "# channel ack on unknown channel",
-                              1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
-         ntohl (msg->chid));
+    GNUNET_STATISTICS_update (stats,
+                              "# channel ack on unknown channel",
+                              1,
+                              GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "WARNING channel %u unknown\n",
+         ntohl (msg->chid.cn));
     return;
   }
 
@@ -1792,7 +1795,7 @@ handle_ch_ack (struct CadetTunnel *t,
  */
 static void
 handle_ch_destroy (struct CadetTunnel *t,
-                   const struct GNUNET_CADET_ChannelManage *msg,
+                   const struct GNUNET_CADET_ChannelManageMessage *msg,
                    int fwd)
 {
   struct CadetChannel *ch;
@@ -1800,14 +1803,14 @@ handle_ch_destroy (struct CadetTunnel *t,
 
   /* Check size */
   size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
+  if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
   {
     GNUNET_break (0);
     return;
   }
 
   /* Check channel */
-  ch = GCT_get_channel (t, ntohl (msg->chid));
+  ch = GCT_get_channel (t, msg->chid);
   if (NULL == ch)
   {
     /* Probably a retransmission, safe to ignore */
@@ -1877,34 +1880,34 @@ handle_decrypted (struct CadetTunnel *t,
 
   switch (type)
   {
-    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE:
       /* Do nothing, connection aleady got updated. */
       GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
       /* Don't send hop ACK, wait for client to ACK */
-      handle_data (t, (struct GNUNET_CADET_Data *) msgh, fwd);
+      handle_data (t, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-      handle_data_ack (t, (struct GNUNET_CADET_DataACK *) msgh, fwd);
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
+      handle_data_ack (t, (struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-      handle_ch_create (t, (struct GNUNET_CADET_ChannelCreate *) msgh);
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
+      handle_ch_create (t, (struct GNUNET_CADET_ChannelOpenMessage *) msgh);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
-      handle_ch_nack (t, (struct GNUNET_CADET_ChannelManage *) msgh);
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
+      handle_ch_nack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh);
       break;
 
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-      handle_ch_ack (t, (struct GNUNET_CADET_ChannelManage *) msgh, fwd);
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
+      handle_ch_ack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd);
       break;
 
     case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-      handle_ch_destroy (t, (struct GNUNET_CADET_ChannelManage *) msgh, fwd);
+      handle_ch_destroy (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd);
       break;
 
     default:
@@ -1931,7 +1934,7 @@ handle_decrypted (struct CadetTunnel *t,
  */
 void
 GCT_handle_encrypted (struct CadetTunnel *t,
-                      const struct GNUNET_CADET_Encrypted *msg)
+                      const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
 {
   uint16_t size = ntohs (msg->header.size);
   char cbuf [size];
@@ -1990,7 +1993,7 @@ GCT_handle_encrypted (struct CadetTunnel *t,
  */
 void
 GCT_handle_kx (struct CadetTunnel *t,
-               const struct GNUNET_CADET_KX *msg)
+               const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
 {
   struct CadetTunnelAxolotl *ax;
   struct GNUNET_HashCode key_material[3];
@@ -2143,9 +2146,9 @@ GCT_init (const struct GNUNET_CONFIGURATION_Handle *c,
   LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
 
   expected_overhead = 0;
-  expected_overhead += sizeof (struct GNUNET_CADET_Encrypted);
-  expected_overhead += sizeof (struct GNUNET_CADET_Data);
-  expected_overhead += sizeof (struct GNUNET_CADET_ACK);
+  expected_overhead += sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
+  expected_overhead += sizeof (struct GNUNET_CADET_ChannelAppDataMessage);
+  expected_overhead += sizeof (struct GNUNET_CADET_ConnectionEncryptedAckMessage);
   GNUNET_assert (GNUNET_CONSTANTS_CADET_P2P_OVERHEAD == expected_overhead);
 
   if (GNUNET_OK !=
@@ -2200,7 +2203,7 @@ GCT_new (struct CadetPeer *destination)
   struct CadetTunnel *t;
 
   t = GNUNET_new (struct CadetTunnel);
-  t->next_chid = 0;
+  t->next_chid.cn = 0;
   t->peer = destination;
 
   if (GNUNET_OK !=
@@ -2442,7 +2445,8 @@ GCT_remove_connection (struct CadetTunnel *t,
  * @param ch Channel.
  */
 void
-GCT_add_channel (struct CadetTunnel *t, struct CadetChannel *ch)
+GCT_add_channel (struct CadetTunnel *t,
+                 struct CadetChannel *ch)
 {
   struct CadetTChannel *aux;
 
@@ -2510,7 +2514,8 @@ GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch)
  * @return channel handler, NULL if doesn't exist
  */
 struct CadetChannel *
-GCT_get_channel (struct CadetTunnel *t, CADET_ChannelNumber chid)
+GCT_get_channel (struct CadetTunnel *t,
+                 struct GNUNET_CADET_ChannelTunnelNumber chid)
 {
   struct CadetTChannel *iter;
 
@@ -2519,7 +2524,7 @@ GCT_get_channel (struct CadetTunnel *t, CADET_ChannelNumber chid)
 
   for (iter = t->channel_head; NULL != iter; iter = iter->next)
   {
-    if (GCCH_get_id (iter->ch) == chid)
+    if (GCCH_get_id (iter->ch).cn == chid.cn)
       break;
   }
 
@@ -2659,7 +2664,7 @@ GCT_destroy (struct CadetTunnel *t)
 
     mh = (struct GNUNET_MessageHeader *) &t->tq_head[1];
     type = ntohs (mh->type);
-    if (0 == keepalives_queued && GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE == type)
+    if (0 == keepalives_queued && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE == type)
     {
       keepalives_queued = 1;
       LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -2727,7 +2732,7 @@ struct CadetConnection *
 GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *path)
 {
   struct CadetConnection *c;
-  struct GNUNET_CADET_Hash cid;
+  struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
   unsigned int own_pos;
 
   if (NULL == t || NULL == path)
@@ -2966,11 +2971,11 @@ GCT_get_destination (struct CadetTunnel *t)
  *
  * @return GID of a channel free to use.
  */
-CADET_ChannelNumber
+struct GNUNET_CADET_ChannelTunnelNumber
 GCT_get_next_chid (struct CadetTunnel *t)
 {
-  CADET_ChannelNumber chid;
-  CADET_ChannelNumber mask;
+  struct GNUNET_CADET_ChannelTunnelNumber chid;
+  struct GNUNET_CADET_ChannelTunnelNumber mask;
   int result;
 
   /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID.
@@ -2979,20 +2984,22 @@ GCT_get_next_chid (struct CadetTunnel *t)
    */
   result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GCP_get_id (t->peer));
   if (0 > result)
-    mask = 0x40000000;
+    mask.cn = htonl (0x40000000);
   else
-    mask = 0x0;
-  t->next_chid |= mask;
+    mask.cn = 0x0;
+  t->next_chid.cn |= mask.cn;
 
   while (NULL != GCT_get_channel (t, t->next_chid))
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", t->next_chid);
-    t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
-    t->next_chid |= mask;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Channel %u exists...\n",
+         t->next_chid.cn);
+    t->next_chid.cn = htonl ((ntohl (t->next_chid.cn) + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
+    t->next_chid.cn |= mask.cn;
   }
   chid = t->next_chid;
-  t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
-  t->next_chid |= mask;
+  t->next_chid.cn = (t->next_chid.cn + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
+  t->next_chid.cn |= mask.cn;
 
   return chid;
 }
@@ -3185,7 +3192,8 @@ GCT_has_queued_traffic (struct CadetTunnel *t)
  */
 struct CadetTunnelQueue *
 GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                           struct CadetTunnel *t, struct CadetConnection *c,
+                           struct CadetTunnel *t,
+                           struct CadetConnection *c,
                            int force, GCT_sent cont, void *cont_cls)
 {
   return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL);
@@ -3201,8 +3209,9 @@ GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
 void
 GCT_send_kx (struct CadetTunnel *t, int force_reply)
 {
+  static struct CadetEncryptedMessageIdentifier zero;
   struct CadetConnection *c;
-  struct GNUNET_CADET_KX msg;
+  struct GNUNET_CADET_TunnelKeyExchangeMessage msg;
   enum GNUNET_CADET_KX_Flags flags;
 
   LOG (GNUNET_ERROR_TYPE_INFO, "==> {        KX} on %s\n", GCT_2s (t));
@@ -3225,7 +3234,7 @@ GCT_send_kx (struct CadetTunnel *t, int force_reply)
   }
 
   msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
   flags = GNUNET_CADET_KX_FLAG_NONE;
   if (GNUNET_YES == force_reply)
     flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
@@ -3234,8 +3243,11 @@ GCT_send_kx (struct CadetTunnel *t, int force_reply)
   GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->kx_0, &msg.ephemeral_key);
   GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &msg.ratchet_key);
 
-  t->ephm_h = GCC_send_prebuilt_message (&msg.header, UINT16_MAX, 0,
-                                         c, GCC_is_origin (c, GNUNET_YES),
+  t->ephm_h = GCC_send_prebuilt_message (&msg.header,
+                                         UINT16_MAX,
+                                         zero,
+                                         c,
+                                         GCC_is_origin (c, GNUNET_YES),
                                          GNUNET_YES, &ephm_sent, t);
   if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
     GCT_change_estate (t, CADET_TUNNEL_KEY_SENT);
@@ -3486,4 +3498,3 @@ GCT_iterate_channels (struct CadetTunnel *t, GCT_chan_iter iter, void *cls)
   for (cht = t->channel_head; NULL != cht; cht = cht->next)
     iter (cls, cht->ch);
 }
-
index e3ca57e9cb17dbf75bb401ba7b12d0f1714db203..c10815a3be2ff4c7c0096ee0535be45ec8b377e1 100644 (file)
@@ -291,7 +291,7 @@ GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch);
  * @return channel handler, NULL if doesn't exist
  */
 struct CadetChannel *
-GCT_get_channel (struct CadetTunnel *t, CADET_ChannelNumber chid);
+GCT_get_channel (struct CadetTunnel *t, struct GNUNET_CADET_ChannelTunnelNumber chid);
 
 
 /**
@@ -304,7 +304,7 @@ GCT_get_channel (struct CadetTunnel *t, CADET_ChannelNumber chid);
  */
 void
 GCT_handle_encrypted (struct CadetTunnel *t,
-                      const struct GNUNET_CADET_Encrypted *msg);
+                      const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
 
 
 /**
@@ -315,7 +315,7 @@ GCT_handle_encrypted (struct CadetTunnel *t,
  */
 void
 GCT_handle_kx (struct CadetTunnel *t,
-               const struct GNUNET_CADET_KX *msg);
+               const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
 
 
 /**
@@ -427,7 +427,7 @@ GCT_get_destination (struct CadetTunnel *t);
  *
  * @return ID of a channel free to use.
  */
-CADET_ChannelNumber
+struct GNUNET_CADET_ChannelTunnelNumber
 GCT_get_next_chid (struct CadetTunnel *t);
 
 
index b6ed64c582434607b23fd5316951dffb73c6db70..e0c00858e986e988b29bebfdd95daa880f705b11 100644 (file)
@@ -59,11 +59,6 @@ USE_EPHEMERAL_KEYS = NO
 [PATHS]
 GNUNET_TEST_HOME = /tmp/test-cadet/
 
-[nat]
-RETURN_LOCAL_ADDRESSES = YES
-DISABLEV6 = YES
-USE_LOCALADDR = YES
-
 [peerinfo]
 NO_IO = YES
 
index c226563d54403ed23dc6e5447322cd6cde37011f..d15785cb00c11f4a65b82f0d2e087646d4cdc2ca 100644 (file)
@@ -178,7 +178,8 @@ inbound_channel (void *cls,
  *                    with the channel is stored
  */
 static void
-channel_end (void *cls, const struct GNUNET_CADET_Channel *channel,
+channel_end (void *cls,
+             const struct GNUNET_CADET_Channel *channel,
              void *channel_ctx)
 {
   long id = (long) cls;
@@ -191,6 +192,8 @@ channel_end (void *cls, const struct GNUNET_CADET_Channel *channel,
     GNUNET_CADET_notify_transmit_ready_cancel (mth);
     mth = NULL;
   }
+  if (channel == ch)
+    ch = NULL;
   if (GNUNET_NO == got_data)
   {
     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
index 18898bebd36c40107333fc6098d97f87fd936c92..d5ed8db80f1cc67b4cf109d23a037ac574de3177 100644 (file)
@@ -222,7 +222,7 @@ GNUNET_CONSENSUS_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
   consensus->new_element_cb = new_element_cb;
   consensus->new_element_cls = new_element_cls;
   consensus->session_id = *session_id;
-  consensus->mq = GNUNET_CLIENT_connecT (cfg,
+  consensus->mq = GNUNET_CLIENT_connect (cfg,
                                          "consensus",
                                          mq_handlers,
                                          &mq_error_handler,
index 8a74f0ca69eca9bcce6d2edbd0f7c43900865b93..0b3920633443bbbe8ce50c734c533988ff782e20 100644 (file)
@@ -584,7 +584,7 @@ reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
     phone->mq = NULL;
   }
   phone->state = PS_REGISTER;
-  phone->mq = GNUNET_CLIENT_connecT (phone->cfg,
+  phone->mq = GNUNET_CLIENT_connect (phone->cfg,
                                      "conversation",
                                      handlers,
                                      &phone_error_handler,
index 17e26465e1430353edaa22fd386e013fa1731453..a6bc506bc67784f086606e2a41cfb3bff5d793ad 100644 (file)
@@ -570,7 +570,7 @@ GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
   };
   struct GNUNET_CRYPTO_EcdsaPublicKey my_zone;
 
-  call->mq = GNUNET_CLIENT_connecT (cfg,
+  call->mq = GNUNET_CLIENT_connect (cfg,
                                     "conversation",
                                     handlers,
                                     &call_error_handler,
index 42b7030b37c6f4269c3af702bc84cc8d4a507a48..cdd1f93c2e932c7db05828fe26480a1aebcf541c 100644 (file)
@@ -1,2 +1,9 @@
 gnunet-service-core
 gnunet-core
+test_core_api
+test_core_api_reliability
+test_core_api_send_to_self
+test_core_api_start_only
+test_core_quota_compliance_asymmetric_recv_limited
+test_core_quota_compliance_asymmetric_send_limited
+test_core_quota_compliance_symmetric
index aea64fa34cbbd55902152e75205d115d22941d7e..ed80bae73ac8d127d93a73eb459b33e38e6e133f 100644 (file)
@@ -23,7 +23,6 @@ lib_LTLIBRARIES = \
 
 libgnunetcore_la_SOURCES = \
   core_api.c core.h \
-  core_api_2.c \
   core_api_monitor_peers.c
 libgnunetcore_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
index fda49e25957d6dfb43180daaf609a2943386fe02..ace80b952b09b53eef6c8441b72853477c93983b 100644 (file)
 
 
 /**
- * Handle for a transmission request.
+ * Information we track for each peer.
  */
-struct GNUNET_CORE_TransmitHandle
+struct PeerRecord
 {
 
   /**
-   * Corresponding peer record.
-   */
-  struct PeerRecord *peer;
-
-  /**
-   * Function that will be called to get the actual request
-   * (once we are ready to transmit this request to the core).
-   * The function will be called with a NULL buffer to signal
-   * timeout.
-   */
-  GNUNET_CONNECTION_TransmitReadyNotify get_message;
-
-  /**
-   * Closure for @e get_message.
-   */
-  void *get_message_cls;
-
-  /**
-   * Deadline for the transmission (the request does not get cancelled
-   * at this time, this is merely how soon the application wants this out).
-   */
-  struct GNUNET_TIME_Absolute deadline;
-
-  /**
-   * When did this request get queued?
-   */
-  struct GNUNET_TIME_Absolute request_time;
-
-  /**
-   * How important is this message?
-   */
-  enum GNUNET_CORE_Priority priority;
-
-  /**
-   * Is corking allowed?
-   */
-  int cork;
-
-  /**
-   * Size of this request.
+   * Corresponding CORE handle.
    */
-  uint16_t msize;
+  struct GNUNET_CORE_Handle *h;
 
   /**
-   * Send message request ID for this request.
+   * Message queue for the peer.
    */
-  uint16_t smr_id;
-
-};
-
-
-/**
- * Information we track for each peer.
- */
-struct PeerRecord
-{
+  struct GNUNET_MQ_Handle *mq;
 
   /**
-   * Corresponding CORE handle.
+   * Message we are currently trying to pass to the CORE service
+   * for this peer (from @e mq).
    */
-  struct GNUNET_CORE_Handle *ch;
+  struct GNUNET_MQ_Envelope *env;
 
   /**
-   * Pending request, if any. 'th->peer' is set to NULL if the
-   * request is not active.
+   * Value the client returned when we connected, used
+   * as the closure in various places.
    */
-  struct GNUNET_CORE_TransmitHandle th;
+  void *client_cls;
 
   /**
    * Peer the record is about.
@@ -151,20 +104,10 @@ struct GNUNET_CORE_Handle
    */
   GNUNET_CORE_DisconnectEventHandler disconnects;
 
-  /**
-   * Function to call whenever we receive an inbound message.
-   */
-  GNUNET_CORE_MessageCallback inbound_notify;
-
-  /**
-   * Function to call whenever we receive an outbound message.
-   */
-  GNUNET_CORE_MessageCallback outbound_notify;
-
   /**
    * Function handlers for messages of particular type.
    */
-  struct GNUNET_CORE_MessageHandler *handlers;
+  struct GNUNET_MQ_MessageHandler *handlers;
 
   /**
    * Our message queue for transmissions to the service.
@@ -197,24 +140,6 @@ struct GNUNET_CORE_Handle
    */
   unsigned int hcnt;
 
-  /**
-   * For inbound notifications without a specific handler, do
-   * we expect to only receive headers?
-   */
-  int inbound_hdr_only;
-
-  /**
-   * For outbound notifications without a specific handler, do
-   * we expect to only receive headers?
-   */
-  int outbound_hdr_only;
-
-  /**
-   * Are we currently disconnected and hence unable to forward
-   * requests?
-   */
-  int currently_down;
-
   /**
    * Did we ever get INIT?
    */
@@ -266,25 +191,19 @@ disconnect_and_free_peer_entry (void *cls,
                                 void *value)
 {
   struct GNUNET_CORE_Handle *h = cls;
-  struct GNUNET_CORE_TransmitHandle *th;
   struct PeerRecord *pr = value;
 
+  GNUNET_assert (pr->h == h);
   if (NULL != h->disconnects)
     h->disconnects (h->cls,
-                    &pr->peer);
-  /* all requests should have been cancelled, clean up anyway, just in case */
-  th = &pr->th;
-  if (NULL != th->peer)
-  {
-    GNUNET_break (0);
-    th->peer = NULL;
-  }
-  /* done with 'voluntary' cleanups, now on to normal freeing */
+                    &pr->peer,
+                   pr->client_cls);
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CONTAINER_multipeermap_remove (h->peers,
                                                        key,
                                                        pr));
-  GNUNET_assert (pr->ch == h);
+  GNUNET_MQ_destroy (pr->mq);
+  GNUNET_assert (NULL == pr->mq);
   GNUNET_free (pr);
   return GNUNET_YES;
 }
@@ -305,8 +224,7 @@ reconnect_later (struct GNUNET_CORE_Handle *h)
     GNUNET_MQ_destroy (h->mq);
     h->mq = NULL;
   }
-  h->currently_down = GNUNET_YES;
-  GNUNET_assert (h->reconnect_task == NULL);
+  GNUNET_assert (NULL == h->reconnect_task);
   h->reconnect_task =
       GNUNET_SCHEDULER_add_delayed (h->retry_backoff,
                                     &reconnect_task,
@@ -319,9 +237,8 @@ reconnect_later (struct GNUNET_CORE_Handle *h)
 
 
 /**
- * Generic error handler, called with the appropriate error code and
- * the same closure specified at the creation of the message queue.
- * Not every message queue implementation supports an error handler.
+ * Error handler for the message queue to the CORE service.
+ * On errors, we reconnect.
  *
  * @param cls closure, a `struct GNUNET_CORE_Handle *`
  * @param error error code
@@ -339,6 +256,209 @@ handle_mq_error (void *cls,
 }
 
 
+/**
+ * Inquire with CORE what options should be set for a message
+ * so that it is transmitted with the given @a priority and
+ * the given @a cork value.
+ *
+ * @param cork desired corking
+ * @param priority desired message priority
+ * @param[out] flags set to `flags` value for #GNUNET_MQ_set_options()
+ * @return `extra` argument to give to #GNUNET_MQ_set_options()
+ */
+const void *
+GNUNET_CORE_get_mq_options (int cork,
+                           enum GNUNET_CORE_Priority priority,
+                           uint64_t *flags)
+{
+  *flags = ((uint64_t) priority) + (((uint64_t) cork) << 32);
+  return NULL;
+}
+
+
+/**
+ * Implement sending functionality of a message queue for
+ * us sending messages to a peer.
+ *
+ * @param mq the message queue
+ * @param msg the message to send
+ * @param impl_state state of the implementation
+ */
+static void
+core_mq_send_impl (struct GNUNET_MQ_Handle *mq,
+                  const struct GNUNET_MessageHeader *msg,
+                  void *impl_state)
+{
+  struct PeerRecord *pr = impl_state;
+  struct GNUNET_CORE_Handle *h = pr->h;
+  struct SendMessageRequest *smr;
+  struct SendMessage *sm;
+  struct GNUNET_MQ_Envelope *env;
+  uint16_t msize;
+  uint64_t flags;
+  int cork;
+  enum GNUNET_CORE_Priority priority;
+
+  if (NULL == h->mq)
+  {
+    /* We're currently reconnecting, pretend this worked */
+    GNUNET_MQ_impl_send_continue (mq);
+    return;
+  }
+  GNUNET_assert (NULL == pr->env);
+  /* extract options from envelope */
+  env = GNUNET_MQ_get_current_envelope (mq);
+  GNUNET_break (NULL ==
+               GNUNET_MQ_env_get_options (env,
+                                          &flags));
+  cork = (int) (flags >> 32);
+  priority = (uint32_t) flags;
+
+  /* check message size for sanity */
+  msize = ntohs (msg->size);
+  if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct SendMessage))
+  {
+    GNUNET_break (0);
+    GNUNET_MQ_impl_send_continue (mq);
+    return;
+  }
+
+  /* ask core for transmission */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Asking core for transmission of %u bytes to `%s'\n",
+       (unsigned int) msize,
+       GNUNET_i2s (&pr->peer));
+  env = GNUNET_MQ_msg (smr,
+                       GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
+  smr->priority = htonl ((uint32_t) priority);
+  // smr->deadline = GNUNET_TIME_absolute_hton (deadline);
+  smr->peer = pr->peer;
+  smr->reserved = htonl (0);
+  smr->size = htons (msize);
+  smr->smr_id = htons (++pr->smr_id_gen);
+  GNUNET_MQ_send (h->mq,
+                  env);
+
+  /* prepare message with actual transmission data */
+  pr->env = GNUNET_MQ_msg_nested_mh (sm,
+                                    GNUNET_MESSAGE_TYPE_CORE_SEND,
+                                    msg);
+  sm->priority = htonl ((uint32_t) priority);
+  // sm->deadline = GNUNET_TIME_absolute_hton (deadline);
+  sm->peer = pr->peer;
+  sm->cork = htonl ((uint32_t) cork);
+  sm->reserved = htonl (0);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Calling get_message with buffer of %u bytes (%s)\n",
+              (unsigned int) msize,
+             cork ? "corked" : "uncorked");
+}
+
+
+/**
+ * Handle destruction of a message queue.  Implementations must not
+ * free @a mq, but should take care of @a impl_state.
+ *
+ * @param mq the message queue to destroy
+ * @param impl_state state of the implementation
+ */
+static void
+core_mq_destroy_impl (struct GNUNET_MQ_Handle *mq,
+                     void *impl_state)
+{
+  struct PeerRecord *pr = impl_state;
+
+  GNUNET_assert (mq == pr->mq);
+  pr->mq = NULL;
+}
+
+
+/**
+ * Implementation function that cancels the currently sent message.
+ * Should basically undo whatever #mq_send_impl() did.
+ *
+ * @param mq message queue
+ * @param impl_state state specific to the implementation
+ */
+static void
+core_mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
+                    void *impl_state)
+{
+  struct PeerRecord *pr = impl_state;
+
+  GNUNET_assert (NULL != pr->env);
+  GNUNET_MQ_discard (pr->env);
+  pr->env = NULL;
+}
+
+
+/**
+ * We had an error processing a message we forwarded from a peer to
+ * the CORE service.  We should just complain about it but otherwise
+ * continue processing.
+ *
+ * @param cls closure
+ * @param error error code
+ */
+static void
+core_mq_error_handler (void *cls,
+                       enum GNUNET_MQ_Error error)
+{
+  /* struct PeerRecord *pr = cls; */
+
+  GNUNET_break_op (0);
+}
+
+
+/**
+ * Add the given peer to the list of our connected peers
+ * and create the respective data structures and notify
+ * the application.
+ *
+ * @param h the core handle
+ * @param peer the peer that is connecting to us
+ */
+static void
+connect_peer (struct GNUNET_CORE_Handle *h,
+             const struct GNUNET_PeerIdentity *peer)
+{
+  struct PeerRecord *pr;
+  uint64_t flags;
+  const void *extra;
+
+  pr = GNUNET_new (struct PeerRecord);
+  pr->peer = *peer;
+  pr->h = h;
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multipeermap_put (h->peers,
+                                                    &pr->peer,
+                                                    pr,
+                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  pr->mq = GNUNET_MQ_queue_for_callbacks (&core_mq_send_impl,
+                                         &core_mq_destroy_impl,
+                                         &core_mq_cancel_impl,
+                                         pr,
+                                         h->handlers,
+                                         &core_mq_error_handler,
+                                         pr);
+  /* get our default options */
+  extra = GNUNET_CORE_get_mq_options (GNUNET_NO,
+                                     GNUNET_CORE_PRIO_BEST_EFFORT,
+                                     &flags);
+  GNUNET_MQ_set_options (pr->mq,
+                        flags,
+                        extra);
+  if (NULL != h->connects)
+  {
+    pr->client_cls = h->connects (h->cls,
+                                 &pr->peer,
+                                 pr->mq);
+    GNUNET_MQ_set_handlers_closure (pr->mq,
+                                   pr->client_cls);
+  }
+}
+
+
 /**
  * Handle  init  reply message  received  from  CORE service.   Notify
  * application  that we  are now  connected  to the  CORE.  Also  fake
@@ -353,11 +473,8 @@ handle_init_reply (void *cls,
 {
   struct GNUNET_CORE_Handle *h = cls;
   GNUNET_CORE_StartupCallback init;
-  struct PeerRecord *pr;
 
   GNUNET_break (0 == ntohl (m->reserved));
-  GNUNET_break (GNUNET_YES == h->currently_down);
-  h->currently_down = GNUNET_NO;
   h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
   if (NULL != (init = h->init))
   {
@@ -388,17 +505,8 @@ handle_init_reply (void *cls,
     }
   }
   /* fake 'connect to self' */
-  pr = GNUNET_new (struct PeerRecord);
-  pr->peer = h->me;
-  pr->ch = h;
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multipeermap_put (h->peers,
-                                                    &h->me,
-                                                    pr,
-                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  if (NULL != h->connects)
-    h->connects (h->cls,
-                 &pr->peer);
+  connect_peer (h,
+               &h->me);
 }
 
 
@@ -416,7 +524,6 @@ handle_connect_notify (void *cls,
   struct GNUNET_CORE_Handle *h = cls;
   struct PeerRecord *pr;
 
-  GNUNET_break (GNUNET_NO == h->currently_down);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received notification about connection from `%s'.\n",
        GNUNET_i2s (&cnm->peer));
@@ -436,17 +543,8 @@ handle_connect_notify (void *cls,
     reconnect_later (h);
     return;
   }
-  pr = GNUNET_new (struct PeerRecord);
-  pr->peer = cnm->peer;
-  pr->ch = h;
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multipeermap_put (h->peers,
-                                                    &cnm->peer,
-                                                    pr,
-                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  if (NULL != h->connects)
-    h->connects (h->cls,
-                 &pr->peer);
+  connect_peer (h,
+               &cnm->peer);
 }
 
 
@@ -459,17 +557,16 @@ handle_connect_notify (void *cls,
  */
 static void
 handle_disconnect_notify (void *cls,
-                          const struct DisconnectNotifyMessage * dnm)
+                          const struct DisconnectNotifyMessage *dnm)
 {
   struct GNUNET_CORE_Handle *h = cls;
   struct PeerRecord *pr;
 
-  GNUNET_break (GNUNET_NO == h->currently_down);
   if (0 == memcmp (&h->me,
                    &dnm->peer,
                    sizeof (struct GNUNET_PeerIdentity)))
   {
-    /* connection to self!? */
+    /* disconnect from self!? */
     GNUNET_break (0);
     return;
   }
@@ -486,7 +583,7 @@ handle_disconnect_notify (void *cls,
     return;
   }
   disconnect_and_free_peer_entry (h,
-                                  &dnm->peer,
+                                  &pr->peer,
                                   pr);
 }
 
@@ -502,11 +599,9 @@ static int
 check_notify_inbound (void *cls,
                       const struct NotifyTrafficMessage *ntm)
 {
-  struct GNUNET_CORE_Handle *h = cls;
   uint16_t msize;
   const struct GNUNET_MessageHeader *em;
 
-  GNUNET_break (GNUNET_NO == h->currently_down);
   msize = ntohs (ntm->header.size) - sizeof (struct NotifyTrafficMessage);
   if (msize < sizeof (struct GNUNET_MessageHeader))
   {
@@ -514,8 +609,7 @@ check_notify_inbound (void *cls,
     return GNUNET_SYSERR;
   }
   em = (const struct GNUNET_MessageHeader *) &ntm[1];
-  if ( (GNUNET_NO == h->inbound_hdr_only) &&
-       (msize != ntohs (em->size)) )
+  if (msize != ntohs (em->size))
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
@@ -538,120 +632,21 @@ handle_notify_inbound (void *cls,
   struct GNUNET_CORE_Handle *h = cls;
   const struct GNUNET_MessageHeader *em;
   struct PeerRecord *pr;
-  uint16_t et;
 
-  GNUNET_break (GNUNET_NO == h->currently_down);
-  em = (const struct GNUNET_MessageHeader *) &ntm[1];
-  et = ntohs (em->type);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received inbound message of type %d from `%s'.\n",
-       (int) et,
+       "Received inbound message from `%s'.\n",
        GNUNET_i2s (&ntm->peer));
-  for (unsigned int hpos = 0; NULL != h->handlers[hpos].callback; hpos++)
-  {
-    const struct GNUNET_CORE_MessageHandler *mh;
-
-    mh = &h->handlers[hpos];
-    if (mh->type != et)
-      continue;
-    if ( (mh->expected_size != ntohs (em->size)) &&
-         (0 != mh->expected_size) )
-    {
-      LOG (GNUNET_ERROR_TYPE_ERROR,
-           "Unexpected message size %u for message of type %u from peer `%s'\n",
-           htons (em->size),
-           mh->type,
-           GNUNET_i2s (&ntm->peer));
-      GNUNET_break_op (0);
-      continue;
-    }
-    pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
-                                            &ntm->peer);
-    if (NULL == pr)
-    {
-      GNUNET_break (0);
-      reconnect_later (h);
-      return;
-    }
-    if (GNUNET_OK !=
-        h->handlers[hpos].callback (h->cls,
-                                    &ntm->peer,
-                                    em))
-    {
-      /* error in processing, do not process other messages! */
-      break;
-    }
-  }
-  if (NULL != h->inbound_notify)
-    h->inbound_notify (h->cls,
-                       &ntm->peer,
-                       em);
-}
-
-
-/**
- * Check that message received from CORE service is well-formed.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param ntm the message we got
- * @return #GNUNET_OK if the message is well-formed
- */
-static int
-check_notify_outbound (void *cls,
-                       const struct NotifyTrafficMessage *ntm)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  uint16_t msize;
-  const struct GNUNET_MessageHeader *em;
-
-  GNUNET_break (GNUNET_NO == h->currently_down);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received outbound message from `%s'.\n",
-       GNUNET_i2s (&ntm->peer));
-  msize = ntohs (ntm->header.size) - sizeof (struct NotifyTrafficMessage);
-  if (msize < sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  em = (const struct GNUNET_MessageHeader *) &ntm[1];
-  if ( (GNUNET_NO == h->outbound_hdr_only) &&
-       (msize != ntohs (em->size)) )
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle outbound message received from CORE service.  If applicable,
- * notify the application.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param ntm the message we got
- */
-static void
-handle_notify_outbound (void *cls,
-                        const struct NotifyTrafficMessage *ntm)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  const struct GNUNET_MessageHeader *em;
-
-  GNUNET_break (GNUNET_NO == h->currently_down);
   em = (const struct GNUNET_MessageHeader *) &ntm[1];
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received notification about transmission to `%s'.\n",
-       GNUNET_i2s (&ntm->peer));
-  if (NULL == h->outbound_notify)
+  pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
+                                         &ntm->peer);
+  if (NULL == pr)
   {
     GNUNET_break (0);
+    reconnect_later (h);
     return;
   }
-  h->outbound_notify (h->cls,
-                      &ntm->peer,
-                      em);
+  GNUNET_MQ_inject_message (pr->mq,
+                           em);
 }
 
 
@@ -661,7 +656,7 @@ handle_notify_outbound (void *cls,
  * pending, put it into the queue to be transmitted.
  *
  * @param cls the `struct GNUNET_CORE_Handle`
- * @param ntm the message we got
+ * @param smr the message we got
  */
 static void
 handle_send_ready (void *cls,
@@ -669,16 +664,7 @@ handle_send_ready (void *cls,
 {
   struct GNUNET_CORE_Handle *h = cls;
   struct PeerRecord *pr;
-  struct GNUNET_CORE_TransmitHandle *th;
-  struct SendMessage *sm;
-  struct GNUNET_MQ_Envelope *env;
-  struct GNUNET_TIME_Relative delay;
-  struct GNUNET_TIME_Relative overdue;
-  unsigned int ret;
-  unsigned int priority;
-  int cork;
 
-  GNUNET_break (GNUNET_NO == h->currently_down);
   pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
                                           &smr->peer);
   if (NULL == pr)
@@ -690,72 +676,24 @@ handle_send_ready (void *cls,
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received notification about transmission readiness to `%s'.\n",
        GNUNET_i2s (&smr->peer));
-  if (NULL == pr->th.peer)
+  if (NULL == pr->env)
   {
     /* request must have been cancelled between the original request
      * and the response from CORE, ignore CORE's readiness */
     return;
   }
-  th = &pr->th;
-  if (ntohs (smr->smr_id) != th->smr_id)
+  if (ntohs (smr->smr_id) != pr->smr_id_gen)
   {
     /* READY message is for expired or cancelled message,
      * ignore! (we should have already sent another request) */
     return;
   }
+
   /* ok, all good, send message out! */
-  th->peer = NULL;
-  env = GNUNET_MQ_msg_extra (sm,
-                             th->msize,
-                             GNUNET_MESSAGE_TYPE_CORE_SEND);
-  sm->priority = htonl ((uint32_t) th->priority);
-  sm->deadline = GNUNET_TIME_absolute_hton (th->deadline);
-  sm->peer = pr->peer;
-  sm->cork = htonl ((uint32_t) (cork = th->cork));
-  sm->reserved = htonl (0);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Calling get_message with buffer of %u bytes (%s)\n",
-              (unsigned int) th->msize,
-             cork ? "corked" : "uncorked");
-  /* FIXME: this is ugly and a bit brutal, but "get_message"
-     may call GNUNET_CORE_notify_transmit_ready() which
-     may call GNUNET_MQ_send() as well, and we MUST get this
-     message out before the next SEND_REQUEST.  So we queue
-     it (even though incomplete) and then---relying on MQ being
-     nice and not actually touching 'env' until much later---
-     fill it afterwards.  This is horrible style, and once
-     the core_api abandons GNUNET_CORE_notify_transmit_ready
-     in favor of an MQ-style API, this hack should no longer
-     be required */
   GNUNET_MQ_send (h->mq,
-                  env);
-  delay = GNUNET_TIME_absolute_get_duration (th->request_time);
-  overdue = GNUNET_TIME_absolute_get_duration (th->deadline);
-  priority = th->priority;
-  ret = th->get_message (th->get_message_cls,
-                         th->msize,
-                         &sm[1]);
-  /* after this point, 'th' should not be used anymore, it
-     may now be about another message! */
-  sm->header.size = htons (ret + sizeof (struct SendMessage));
-  if (overdue.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Transmitting overdue %u bytes to `%s' at priority %u with %s delay %s\n",
-         ret,
-         GNUNET_i2s (&pr->peer),
-         priority,
-         GNUNET_STRINGS_relative_time_to_string (delay,
-                                                 GNUNET_YES),
-         (cork) ? " (corked)" : " (uncorked)");
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Transmitting %u bytes to `%s' at priority %u with %s delay %s\n",
-         ret,
-         GNUNET_i2s (&pr->peer),
-         priority,
-         GNUNET_STRINGS_relative_time_to_string (delay,
-                                                 GNUNET_YES),
-         (cork) ? " (corked)" : " (uncorked)");
+                 pr->env);
+  pr->env = NULL;
+  GNUNET_MQ_impl_send_continue (pr->mq);
 }
 
 
@@ -785,10 +723,6 @@ reconnect (struct GNUNET_CORE_Handle *h)
                            GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND,
                            struct NotifyTrafficMessage,
                            h),
-    GNUNET_MQ_hd_var_size (notify_outbound,
-                           GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND,
-                           struct NotifyTrafficMessage,
-                           h),
     GNUNET_MQ_hd_fixed_size (send_ready,
                              GNUNET_MESSAGE_TYPE_CORE_SEND_READY,
                              struct SendMessageReady,
@@ -797,12 +731,10 @@ reconnect (struct GNUNET_CORE_Handle *h)
   };
   struct InitMessage *init;
   struct GNUNET_MQ_Envelope *env;
-  uint32_t opt;
   uint16_t *ts;
 
   GNUNET_assert (NULL == h->mq);
-  GNUNET_assert (GNUNET_YES == h->currently_down);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "core",
                                  handlers,
                                  &handle_mq_error,
@@ -815,25 +747,9 @@ reconnect (struct GNUNET_CORE_Handle *h)
   env = GNUNET_MQ_msg_extra (init,
                              sizeof (uint16_t) * h->hcnt,
                              GNUNET_MESSAGE_TYPE_CORE_INIT);
-  opt = GNUNET_CORE_OPTION_NOTHING;
-  if (NULL != h->inbound_notify)
-  {
-    if (h->inbound_hdr_only)
-      opt |= GNUNET_CORE_OPTION_SEND_HDR_INBOUND;
-    else
-      opt |= GNUNET_CORE_OPTION_SEND_FULL_INBOUND;
-  }
-  if (NULL != h->outbound_notify)
-  {
-    if (h->outbound_hdr_only)
-      opt |= GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND;
-    else
-      opt |= GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND;
-  }
   LOG (GNUNET_ERROR_TYPE_INFO,
-       "(Re)connecting to CORE service, monitoring messages of type %u\n",
-       opt);
-  init->options = htonl (opt);
+       "(Re)connecting to CORE service\n");
+  init->options = htonl (0);
   ts = (uint16_t *) &init[1];
   for (unsigned int hpos = 0; hpos < h->hcnt; hpos++)
     ts[hpos] = htons (h->handlers[hpos].type);
@@ -852,14 +768,6 @@ reconnect (struct GNUNET_CORE_Handle *h)
  *        connected to the core service
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be NULL
- * @param inbound_notify function to call for all inbound messages, can be NULL
- * @param inbound_hdr_only set to #GNUNET_YES if inbound_notify will only read the
- *                GNUNET_MessageHeader and hence we do not need to give it the full message;
- *                can be used to improve efficiency, ignored if @a inbound_notify is NULL
- * @param outbound_notify function to call for all outbound messages, can be NULL
- * @param outbound_hdr_only set to #GNUNET_YES if outbound_notify will only read the
- *                GNUNET_MessageHeader and hence we do not need to give it the full message
- *                can be used to improve efficiency, ignored if @a outbound_notify is NULL
  * @param handlers callbacks for messages we care about, NULL-terminated
  * @return handle to the core service (only useful for disconnect until @a init is called);
  *                NULL on error (in this case, init is never called)
@@ -870,11 +778,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                      GNUNET_CORE_StartupCallback init,
                      GNUNET_CORE_ConnectEventHandler connects,
                      GNUNET_CORE_DisconnectEventHandler disconnects,
-                     GNUNET_CORE_MessageCallback inbound_notify,
-                     int inbound_hdr_only,
-                     GNUNET_CORE_MessageCallback outbound_notify,
-                     int outbound_hdr_only,
-                     const struct GNUNET_CORE_MessageHandler *handlers)
+                     const struct GNUNET_MQ_MessageHandler *handlers)
 {
   struct GNUNET_CORE_Handle *h;
   unsigned int hcnt;
@@ -885,22 +789,18 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
   h->init = init;
   h->connects = connects;
   h->disconnects = disconnects;
-  h->inbound_notify = inbound_notify;
-  h->outbound_notify = outbound_notify;
-  h->inbound_hdr_only = inbound_hdr_only;
-  h->outbound_hdr_only = outbound_hdr_only;
-  h->currently_down = GNUNET_YES;
-  h->peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
+  h->peers = GNUNET_CONTAINER_multipeermap_create (128,
+                                                  GNUNET_NO);
   hcnt = 0;
   if (NULL != handlers)
-    while (NULL != handlers[hcnt].callback)
+    while (NULL != handlers[hcnt].cb)
       hcnt++;
   h->handlers = GNUNET_new_array (hcnt + 1,
-                                  struct GNUNET_CORE_MessageHandler);
+                                  struct GNUNET_MQ_MessageHandler);
   if (NULL != handlers)
     GNUNET_memcpy (h->handlers,
-            handlers,
-            hcnt * sizeof (struct GNUNET_CORE_MessageHandler));
+                  handlers,
+                  hcnt * sizeof (struct GNUNET_MQ_MessageHandler));
   h->hcnt = hcnt;
   GNUNET_assert (hcnt <
                  (GNUNET_SERVER_MAX_MESSAGE_SIZE -
@@ -918,9 +818,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
 
 
 /**
- * Disconnect from the core service.  This function can only
- * be called *after* all pending #GNUNET_CORE_notify_transmit_ready()
- * requests have been explicitly canceled.
+ * Disconnect from the core service.
  *
  * @param handle connection to core to disconnect
  */
@@ -950,148 +848,23 @@ GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
 
 
 /**
- * Ask the core to call @a notify once it is ready to transmit the
- * given number of bytes to the specified @a target.  Must only be
- * called after a connection to the respective peer has been
- * established (and the client has been informed about this).  You may
- * have one request of this type pending for each connected peer at
- * any time.  If a peer disconnects, the application MUST call
- * #GNUNET_CORE_notify_transmit_ready_cancel on the respective
- * transmission request, if one such request is pending.
+ * Obtain the message queue for a connected peer.
  *
- * @param handle connection to core service
- * @param cork is corking allowed for this transmission?
- * @param priority how important is the message?
- * @param maxdelay how long can the message wait? Only effective if @a cork is #GNUNET_YES
- * @param target who should receive the message, never NULL (can be this peer's identity for loopback)
- * @param notify_size how many bytes of buffer space does @a notify want?
- * @param notify function to call when buffer space is available;
- *        will be called with NULL on timeout; clients MUST cancel
- *        all pending transmission requests DURING the disconnect
- *        handler
- * @param notify_cls closure for @a notify
- * @return non-NULL if the notify callback was queued,
- *         NULL if we can not even queue the request (request already pending);
- *         if NULL is returned, @a notify will NOT be called.
+ * @param h the core handle
+ * @param pid the identity of the peer to check if it has been connected to us
+ * @return NULL if peer is not connected
  */
-struct GNUNET_CORE_TransmitHandle *
-GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
-                                   int cork,
-                                   enum GNUNET_CORE_Priority priority,
-                                   struct GNUNET_TIME_Relative maxdelay,
-                                   const struct GNUNET_PeerIdentity *target,
-                                   size_t notify_size,
-                                   GNUNET_CONNECTION_TransmitReadyNotify notify,
-                                   void *notify_cls)
+struct GNUNET_MQ_Handle *
+GNUNET_CORE_get_mq (const struct GNUNET_CORE_Handle *h,
+                   const struct GNUNET_PeerIdentity *pid)
 {
   struct PeerRecord *pr;
-  struct GNUNET_CORE_TransmitHandle *th;
-  struct SendMessageRequest *smr;
-  struct GNUNET_MQ_Envelope *env;
 
-  if (NULL == handle->mq)
-  {
-    GNUNET_break (0); /* SEE #4588: do not call NTR from disconnect notification! */
-    return NULL;
-  }
-  GNUNET_assert (NULL != notify);
-  if ( (notify_size > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) ||
-       (notify_size + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) )
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Asking core for transmission of %u bytes to `%s'%s\n",
-       (unsigned int) notify_size,
-       GNUNET_i2s (target),
-       cork ? " (corked)" : "");
-  pr = GNUNET_CONTAINER_multipeermap_get (handle->peers,
-                                          target);
+  pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
+                                         pid);
   if (NULL == pr)
-  {
-    /* attempt to send to peer that is not connected */
-    GNUNET_break (0);
     return NULL;
-  }
-  if (NULL != pr->th.peer)
-  {
-    /* attempting to queue a second request for the same destination */
-    GNUNET_break (0);
-    return NULL;
-  }
-  th = &pr->th;
-  memset (th,
-          0,
-          sizeof (struct GNUNET_CORE_TransmitHandle));
-  th->peer = pr;
-  th->get_message = notify;
-  th->get_message_cls = notify_cls;
-  th->request_time = GNUNET_TIME_absolute_get ();
-  if (GNUNET_YES == cork)
-    th->deadline = GNUNET_TIME_relative_to_absolute (maxdelay);
-  else
-    th->deadline = th->request_time;
-  th->priority = priority;
-  th->msize = notify_size;
-  th->cork = cork;
-  if (NULL == handle->mq)
-    return th; /* see #4588 (hack until we transition core fully to MQ) */
-  env = GNUNET_MQ_msg (smr,
-                       GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
-  smr->priority = htonl ((uint32_t) th->priority);
-  smr->deadline = GNUNET_TIME_absolute_hton (th->deadline);
-  smr->peer = pr->peer;
-  smr->reserved = htonl (0);
-  smr->size = htons (th->msize);
-  smr->smr_id = htons (th->smr_id = pr->smr_id_gen++);
-  GNUNET_MQ_send (handle->mq,
-                  env);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Transmission request added to queue\n");
-  return th;
-}
-
-
-/**
- * Cancel the specified transmission-ready notification.
- *
- * @param th handle that was returned by #GNUNET_CORE_notify_transmit_ready().
- */
-void
-GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle *th)
-{
-  struct PeerRecord *pr = th->peer;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Aborting transmission request to core for %u bytes to `%s'\n",
-       (unsigned int) th->msize,
-       GNUNET_i2s (&pr->peer));
-  th->peer = NULL;
-}
-
-
-/**
- * Check if the given peer is currently connected. This function is for special
- * cirumstances (GNUNET_TESTBED uses it), normal users of the CORE API are
- * expected to track which peers are connected based on the connect/disconnect
- * callbacks from #GNUNET_CORE_connect().  This function is NOT part of the
- * 'versioned', 'official' API. The difference between this function and the
- * function GNUNET_CORE_is_peer_connected() is that this one returns
- * synchronously after looking in the CORE API cache. The function
- * GNUNET_CORE_is_peer_connected() sends a message to the CORE service and hence
- * its response is given asynchronously.
- *
- * @param h the core handle
- * @param pid the identity of the peer to check if it has been connected to us
- * @return #GNUNET_YES if the peer is connected to us; #GNUNET_NO if not
- */
-int
-GNUNET_CORE_is_peer_connected_sync (const struct GNUNET_CORE_Handle *h,
-                                    const struct GNUNET_PeerIdentity *pid)
-{
-  return GNUNET_CONTAINER_multipeermap_contains (h->peers,
-                                                 pid);
+  return pr->mq;
 }
 
 
diff --git a/src/core/core_api_2.c b/src/core/core_api_2.c
deleted file mode 100644 (file)
index d810bf2..0000000
+++ /dev/null
@@ -1,865 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2009-2016 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-/**
- * @file core/core_api_2.c
- * @brief core service; this is the main API for encrypted P2P
- *        communications
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_core_service.h"
-#include "core.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "core-api",__VA_ARGS__)
-
-
-/**
- * Information we track for each peer.
- */
-struct PeerRecord
-{
-
-  /**
-   * Corresponding CORE handle.
-   */
-  struct GNUNET_CORE_Handle *h;
-
-  /**
-   * Message queue for the peer.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Message we are currently trying to pass to the CORE service
-   * for this peer (from @e mq).
-   */
-  struct GNUNET_MQ_Envelope *env;
-
-  /**
-   * Value the client returned when we connected, used
-   * as the closure in various places.
-   */
-  void *client_cls;
-
-  /**
-   * Peer the record is about.
-   */
-  struct GNUNET_PeerIdentity peer;
-
-  /**
-   * SendMessageRequest ID generator for this peer.
-   */
-  uint16_t smr_id_gen;
-
-};
-
-
-/**
- * Context for the core service connection.
- */
-struct GNUNET_CORE_Handle
-{
-
-  /**
-   * Configuration we're using.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Closure for the various callbacks.
-   */
-  void *cls;
-
-  /**
-   * Function to call once we've handshaked with the core service.
-   */
-  GNUNET_CORE_StartupCallback init;
-
-  /**
-   * Function to call whenever we're notified about a peer connecting.
-   */
-  GNUNET_CORE_ConnecTEventHandler connects;
-
-  /**
-   * Function to call whenever we're notified about a peer disconnecting.
-   */
-  GNUNET_CORE_DisconnecTEventHandler disconnects;
-
-  /**
-   * Function handlers for messages of particular type.
-   */
-  struct GNUNET_MQ_MessageHandler *handlers;
-
-  /**
-   * Our message queue for transmissions to the service.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Hash map listing all of the peers that we are currently
-   * connected to.
-   */
-  struct GNUNET_CONTAINER_MultiPeerMap *peers;
-
-  /**
-   * Identity of this peer.
-   */
-  struct GNUNET_PeerIdentity me;
-
-  /**
-   * ID of reconnect task (if any).
-   */
-  struct GNUNET_SCHEDULER_Task *reconnect_task;
-
-  /**
-   * Current delay we use for re-trying to connect to core.
-   */
-  struct GNUNET_TIME_Relative retry_backoff;
-
-  /**
-   * Number of entries in the handlers array.
-   */
-  unsigned int hcnt;
-
-  /**
-   * Did we ever get INIT?
-   */
-  int have_init;
-
-};
-
-
-/**
- * Our current client connection went down.  Clean it up
- * and try to reconnect!
- *
- * @param h our handle to the core service
- */
-static void
-reconnect (struct GNUNET_CORE_Handle *h);
-
-
-/**
- * Task schedule to try to re-connect to core.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param tc task context
- */
-static void
-reconnect_task (void *cls)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-
-  h->reconnect_task = NULL;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Connecting to CORE service after delay\n");
-  reconnect (h);
-}
-
-
-/**
- * Notify clients about disconnect and free the entry for connected
- * peer.
- *
- * @param cls the `struct GNUNET_CORE_Handle *`
- * @param key the peer identity (not used)
- * @param value the `struct PeerRecord` to free.
- * @return #GNUNET_YES (continue)
- */
-static int
-disconnect_and_free_peer_entry (void *cls,
-                               const struct GNUNET_PeerIdentity *key,
-                                void *value)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  struct PeerRecord *pr = value;
-
-  GNUNET_assert (pr->h == h);
-  if (NULL != h->disconnects)
-    h->disconnects (h->cls,
-                    &pr->peer,
-                   pr->client_cls);
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multipeermap_remove (h->peers,
-                                                       key,
-                                                       pr));
-  GNUNET_MQ_destroy (pr->mq);
-  GNUNET_assert (NULL == pr->mq);
-  GNUNET_free (pr);
-  return GNUNET_YES;
-}
-
-
-/**
- * Close down any existing connection to the CORE service and
- * try re-establishing it later.
- *
- * @param h our handle
- */
-static void
-reconnect_later (struct GNUNET_CORE_Handle *h)
-{
-  GNUNET_assert (NULL == h->reconnect_task);
-  if (NULL != h->mq)
-  {
-    GNUNET_MQ_destroy (h->mq);
-    h->mq = NULL;
-  }
-  GNUNET_assert (NULL == h->reconnect_task);
-  h->reconnect_task =
-      GNUNET_SCHEDULER_add_delayed (h->retry_backoff,
-                                    &reconnect_task,
-                                    h);
-  GNUNET_CONTAINER_multipeermap_iterate (h->peers,
-                                         &disconnect_and_free_peer_entry,
-                                         h);
-  h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff);
-}
-
-
-/**
- * Error handler for the message queue to the CORE service.
- * On errors, we reconnect.
- *
- * @param cls closure, a `struct GNUNET_CORE_Handle *`
- * @param error error code
- */
-static void
-handle_mq_error (void *cls,
-                 enum GNUNET_MQ_Error error)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "MQ ERROR: %d\n",
-              error);
-  reconnect_later (h);
-}
-
-
-/**
- * Inquire with CORE what options should be set for a message
- * so that it is transmitted with the given @a priority and
- * the given @a cork value.
- *
- * @param cork desired corking
- * @param priority desired message priority
- * @param[out] flags set to `flags` value for #GNUNET_MQ_set_options()
- * @return `extra` argument to give to #GNUNET_MQ_set_options()
- */
-const void *
-GNUNET_CORE_get_mq_options (int cork,
-                           enum GNUNET_CORE_Priority priority,
-                           uint64_t *flags)
-{
-  *flags = ((uint64_t) priority) + (((uint64_t) cork) << 32);
-  return NULL;
-}
-
-
-/**
- * Implement sending functionality of a message queue for
- * us sending messages to a peer.
- *
- * @param mq the message queue
- * @param msg the message to send
- * @param impl_state state of the implementation
- */
-static void
-core_mq_send_impl (struct GNUNET_MQ_Handle *mq,
-                  const struct GNUNET_MessageHeader *msg,
-                  void *impl_state)
-{
-  struct PeerRecord *pr = impl_state;
-  struct GNUNET_CORE_Handle *h = pr->h;
-  struct SendMessageRequest *smr;
-  struct SendMessage *sm;
-  struct GNUNET_MQ_Envelope *env;
-  uint16_t msize;
-  uint64_t flags;
-  int cork;
-  enum GNUNET_CORE_Priority priority;
-
-  GNUNET_assert (NULL == pr->env);
-  /* extract options from envelope */
-  env = GNUNET_MQ_get_current_envelope (mq);
-  GNUNET_break (NULL ==
-               GNUNET_MQ_env_get_options (env,
-                                          &flags));
-  cork = (int) (flags >> 32);
-  priority = (uint32_t) flags;
-
-  /* check message size for sanity */
-  msize = ntohs (msg->size);
-  if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct SendMessage))
-  {
-    GNUNET_break (0);
-    GNUNET_MQ_impl_send_continue (mq);
-    return;
-  }
-
-  /* ask core for transmission */
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Asking core for transmission of %u bytes to `%s'\n",
-       (unsigned int) msize,
-       GNUNET_i2s (&pr->peer));
-  env = GNUNET_MQ_msg (smr,
-                       GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
-  smr->priority = htonl ((uint32_t) priority);
-  // smr->deadline = GNUNET_TIME_absolute_hton (deadline);
-  smr->peer = pr->peer;
-  smr->reserved = htonl (0);
-  smr->size = htons (msize);
-  smr->smr_id = htons (++pr->smr_id_gen);
-  GNUNET_MQ_send (h->mq,
-                  env);
-
-  /* prepare message with actual transmission data */
-  pr->env = GNUNET_MQ_msg_nested_mh (sm,
-                                    GNUNET_MESSAGE_TYPE_CORE_SEND,
-                                    msg);
-  sm->priority = htonl ((uint32_t) priority);
-  // sm->deadline = GNUNET_TIME_absolute_hton (deadline);
-  sm->peer = pr->peer;
-  sm->cork = htonl ((uint32_t) cork);
-  sm->reserved = htonl (0);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Calling get_message with buffer of %u bytes (%s)\n",
-              (unsigned int) msize,
-             cork ? "corked" : "uncorked");
-}
-
-
-/**
- * Handle destruction of a message queue.  Implementations must not
- * free @a mq, but should take care of @a impl_state.
- *
- * @param mq the message queue to destroy
- * @param impl_state state of the implementation
- */
-static void
-core_mq_destroy_impl (struct GNUNET_MQ_Handle *mq,
-                     void *impl_state)
-{
-  struct PeerRecord *pr = impl_state;
-
-  GNUNET_assert (mq == pr->mq);
-  pr->mq = NULL;
-}
-
-
-/**
- * Implementation function that cancels the currently sent message.
- * Should basically undo whatever #mq_send_impl() did.
- *
- * @param mq message queue
- * @param impl_state state specific to the implementation
- */
-static void
-core_mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
-                    void *impl_state)
-{
-  struct PeerRecord *pr = impl_state;
-
-  GNUNET_assert (NULL != pr->env);
-  GNUNET_MQ_discard (pr->env);
-  pr->env = NULL;
-}
-
-
-/**
- * We had an error processing a message we forwarded from a peer to
- * the CORE service.  We should just complain about it but otherwise
- * continue processing.
- *
- * @param cls closure
- * @param error error code
- */
-static void
-core_mq_error_handler (void *cls,
-                       enum GNUNET_MQ_Error error)
-{
-  /* struct PeerRecord *pr = cls; */
-
-  GNUNET_break_op (0);
-}
-
-
-/**
- * Add the given peer to the list of our connected peers
- * and create the respective data structures and notify
- * the application.
- *
- * @param h the core handle
- * @param peer the peer that is connecting to us
- */
-static void
-connect_peer (struct GNUNET_CORE_Handle *h,
-             const struct GNUNET_PeerIdentity *peer)
-{
-  struct PeerRecord *pr;
-  uint64_t flags;
-  const void *extra;
-
-  pr = GNUNET_new (struct PeerRecord);
-  pr->peer = *peer;
-  pr->h = h;
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multipeermap_put (h->peers,
-                                                    &pr->peer,
-                                                    pr,
-                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  pr->mq = GNUNET_MQ_queue_for_callbacks (&core_mq_send_impl,
-                                         &core_mq_destroy_impl,
-                                         &core_mq_cancel_impl,
-                                         pr,
-                                         h->handlers,
-                                         &core_mq_error_handler,
-                                         pr);
-  /* get our default options */
-  extra = GNUNET_CORE_get_mq_options (GNUNET_NO,
-                                     GNUNET_CORE_PRIO_BEST_EFFORT,
-                                     &flags);
-  GNUNET_MQ_set_options (pr->mq,
-                        flags,
-                        extra);
-  if (NULL != h->connects)
-  {
-    pr->client_cls = h->connects (h->cls,
-                                 &pr->peer,
-                                 pr->mq);
-    GNUNET_MQ_set_handlers_closure (pr->mq,
-                                   pr->client_cls);
-  }
-}
-
-
-/**
- * Handle  init  reply message  received  from  CORE service.   Notify
- * application  that we  are now  connected  to the  CORE.  Also  fake
- * loopback connection.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param m the init reply
- */
-static void
-handle_init_reply (void *cls,
-                   const struct InitReplyMessage *m)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  GNUNET_CORE_StartupCallback init;
-
-  GNUNET_break (0 == ntohl (m->reserved));
-  h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
-  if (NULL != (init = h->init))
-  {
-    /* mark so we don't call init on reconnect */
-    h->init = NULL;
-    h->me = m->my_identity;
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Connected to core service of peer `%s'.\n",
-         GNUNET_i2s (&h->me));
-    h->have_init = GNUNET_YES;
-    init (h->cls,
-          &h->me);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Successfully reconnected to core service.\n");
-    if (GNUNET_NO == h->have_init)
-    {
-      h->me = m->my_identity;
-      h->have_init = GNUNET_YES;
-    }
-    else
-    {
-      GNUNET_break (0 == memcmp (&h->me,
-                                 &m->my_identity,
-                                 sizeof (struct GNUNET_PeerIdentity)));
-    }
-  }
-  /* fake 'connect to self' */
-  connect_peer (h,
-               &h->me);
-}
-
-
-/**
- * Handle connect message received from CORE service.
- * Notify the application about the new connection.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param cnm the connect message
- */
-static void
-handle_connect_notify (void *cls,
-                       const struct ConnectNotifyMessage *cnm)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  struct PeerRecord *pr;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received notification about connection from `%s'.\n",
-       GNUNET_i2s (&cnm->peer));
-  if (0 == memcmp (&h->me,
-                   &cnm->peer,
-                   sizeof (struct GNUNET_PeerIdentity)))
-  {
-    /* connect to self!? */
-    GNUNET_break (0);
-    return;
-  }
-  pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
-                                          &cnm->peer);
-  if (NULL != pr)
-  {
-    GNUNET_break (0);
-    reconnect_later (h);
-    return;
-  }
-  connect_peer (h,
-               &cnm->peer);
-}
-
-
-/**
- * Handle disconnect message received from CORE service.
- * Notify the application about the lost connection.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param dnm message about the disconnect event
- */
-static void
-handle_disconnect_notify (void *cls,
-                          const struct DisconnectNotifyMessage *dnm)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  struct PeerRecord *pr;
-
-  if (0 == memcmp (&h->me,
-                   &dnm->peer,
-                   sizeof (struct GNUNET_PeerIdentity)))
-  {
-    /* disconnect from self!? */
-    GNUNET_break (0);
-    return;
-  }
-  GNUNET_break (0 == ntohl (dnm->reserved));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received notification about disconnect from `%s'.\n",
-       GNUNET_i2s (&dnm->peer));
-  pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
-                                          &dnm->peer);
-  if (NULL == pr)
-  {
-    GNUNET_break (0);
-    reconnect_later (h);
-    return;
-  }
-  disconnect_and_free_peer_entry (h,
-                                  &pr->peer,
-                                  pr);
-}
-
-
-/**
- * Check that message received from CORE service is well-formed.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param ntm the message we got
- * @return #GNUNET_OK if the message is well-formed
- */
-static int
-check_notify_inbound (void *cls,
-                      const struct NotifyTrafficMessage *ntm)
-{
-  uint16_t msize;
-  const struct GNUNET_MessageHeader *em;
-
-  msize = ntohs (ntm->header.size) - sizeof (struct NotifyTrafficMessage);
-  if (msize < sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  em = (const struct GNUNET_MessageHeader *) &ntm[1];
-  if (msize != ntohs (em->size))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle inbound message received from CORE service.  If applicable,
- * notify the application.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param ntm the message we got from CORE.
- */
-static void
-handle_notify_inbound (void *cls,
-                       const struct NotifyTrafficMessage *ntm)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  const struct GNUNET_MessageHeader *em;
-  struct PeerRecord *pr;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received inbound message from `%s'.\n",
-       GNUNET_i2s (&ntm->peer));
-  em = (const struct GNUNET_MessageHeader *) &ntm[1];
-  pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
-                                         &ntm->peer);
-  if (NULL == pr)
-  {
-    GNUNET_break (0);
-    reconnect_later (h);
-    return;
-  }
-  GNUNET_MQ_inject_message (pr->mq,
-                           em);
-}
-
-
-/**
- * Handle message received from CORE service notifying us that we are
- * now allowed to send a message to a peer.  If that message is still
- * pending, put it into the queue to be transmitted.
- *
- * @param cls the `struct GNUNET_CORE_Handle`
- * @param smr the message we got
- */
-static void
-handle_send_ready (void *cls,
-                   const struct SendMessageReady *smr)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  struct PeerRecord *pr;
-
-  pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
-                                          &smr->peer);
-  if (NULL == pr)
-  {
-    GNUNET_break (0);
-    reconnect_later (h);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received notification about transmission readiness to `%s'.\n",
-       GNUNET_i2s (&smr->peer));
-  if (NULL == pr->env)
-  {
-    /* request must have been cancelled between the original request
-     * and the response from CORE, ignore CORE's readiness */
-    return;
-  }
-  if (ntohs (smr->smr_id) != pr->smr_id_gen)
-  {
-    /* READY message is for expired or cancelled message,
-     * ignore! (we should have already sent another request) */
-    return;
-  }
-
-  /* ok, all good, send message out! */
-  GNUNET_MQ_send (h->mq,
-                 pr->env);
-  pr->env = NULL;
-  GNUNET_MQ_impl_send_continue (pr->mq);
-}
-
-
-/**
- * Our current client connection went down.  Clean it up and try to
- * reconnect!
- *
- * @param h our handle to the core service
- */
-static void
-reconnect (struct GNUNET_CORE_Handle *h)
-{
-  struct GNUNET_MQ_MessageHandler handlers[] = {
-    GNUNET_MQ_hd_fixed_size (init_reply,
-                             GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY,
-                             struct InitReplyMessage,
-                             h),
-    GNUNET_MQ_hd_fixed_size (connect_notify,
-                             GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT,
-                             struct ConnectNotifyMessage,
-                             h),
-    GNUNET_MQ_hd_fixed_size (disconnect_notify,
-                             GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT,
-                             struct DisconnectNotifyMessage,
-                             h),
-    GNUNET_MQ_hd_var_size (notify_inbound,
-                           GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND,
-                           struct NotifyTrafficMessage,
-                           h),
-    GNUNET_MQ_hd_fixed_size (send_ready,
-                             GNUNET_MESSAGE_TYPE_CORE_SEND_READY,
-                             struct SendMessageReady,
-                             h),
-    GNUNET_MQ_handler_end ()
-  };
-  struct InitMessage *init;
-  struct GNUNET_MQ_Envelope *env;
-  uint16_t *ts;
-
-  GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
-                                 "core",
-                                 handlers,
-                                 &handle_mq_error,
-                                 h);
-  if (NULL == h->mq)
-  {
-    reconnect_later (h);
-    return;
-  }
-  env = GNUNET_MQ_msg_extra (init,
-                             sizeof (uint16_t) * h->hcnt,
-                             GNUNET_MESSAGE_TYPE_CORE_INIT);
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "(Re)connecting to CORE service\n");
-  init->options = htonl (0);
-  ts = (uint16_t *) &init[1];
-  for (unsigned int hpos = 0; hpos < h->hcnt; hpos++)
-    ts[hpos] = htons (h->handlers[hpos].type);
-  GNUNET_MQ_send (h->mq,
-                  env);
-}
-
-
-/**
- * Connect to the core service.  Note that the connection may complete
- * (or fail) asynchronously.
- *
- * @param cfg configuration to use
- * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
- * @param init callback to call once we have successfully
- *        connected to the core service
- * @param connects function to call on peer connect, can be NULL
- * @param disconnects function to call on peer disconnect / timeout, can be NULL
- * @param handlers callbacks for messages we care about, NULL-terminated
- * @return handle to the core service (only useful for disconnect until @a init is called);
- *                NULL on error (in this case, init is never called)
- */
-struct GNUNET_CORE_Handle *
-GNUNET_CORE_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                     void *cls,
-                     GNUNET_CORE_StartupCallback init,
-                     GNUNET_CORE_ConnecTEventHandler connects,
-                     GNUNET_CORE_DisconnecTEventHandler disconnects,
-                     const struct GNUNET_MQ_MessageHandler *handlers)
-{
-  struct GNUNET_CORE_Handle *h;
-  unsigned int hcnt;
-
-  h = GNUNET_new (struct GNUNET_CORE_Handle);
-  h->cfg = cfg;
-  h->cls = cls;
-  h->init = init;
-  h->connects = connects;
-  h->disconnects = disconnects;
-  h->peers = GNUNET_CONTAINER_multipeermap_create (128,
-                                                  GNUNET_NO);
-  hcnt = 0;
-  if (NULL != handlers)
-    while (NULL != handlers[hcnt].cb)
-      hcnt++;
-  h->handlers = GNUNET_new_array (hcnt + 1,
-                                  struct GNUNET_MQ_MessageHandler);
-  if (NULL != handlers)
-    GNUNET_memcpy (h->handlers,
-                  handlers,
-                  hcnt * sizeof (struct GNUNET_MQ_MessageHandler));
-  h->hcnt = hcnt;
-  GNUNET_assert (hcnt <
-                 (GNUNET_SERVER_MAX_MESSAGE_SIZE -
-                  sizeof (struct InitMessage)) / sizeof (uint16_t));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Connecting to CORE service\n");
-  reconnect (h);
-  if (NULL == h->mq)
-  {
-    GNUNET_CORE_disconnect (h);
-    return NULL;
-  }
-  return h;
-}
-
-
-/**
- * Disconnect from the core service.
- *
- * @param handle connection to core to disconnect
- */
-void
-GNUNET_CORE_disconnecT (struct GNUNET_CORE_Handle *handle)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Disconnecting from CORE service\n");
-  GNUNET_CONTAINER_multipeermap_iterate (handle->peers,
-                                         &disconnect_and_free_peer_entry,
-                                         handle);
-  GNUNET_CONTAINER_multipeermap_destroy (handle->peers);
-  handle->peers = NULL;
-  if (NULL != handle->reconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (handle->reconnect_task);
-    handle->reconnect_task = NULL;
-  }
-  if (NULL != handle->mq)
-  {
-    GNUNET_MQ_destroy (handle->mq);
-    handle->mq = NULL;
-  }
-  GNUNET_free (handle->handlers);
-  GNUNET_free (handle);
-}
-
-
-/**
- * Obtain the message queue for a connected peer.
- *
- * @param h the core handle
- * @param pid the identity of the peer to check if it has been connected to us
- * @return NULL if peer is not connected
- */
-struct GNUNET_MQ_Handle *
-GNUNET_CORE_get_mq (const struct GNUNET_CORE_Handle *h,
-                   const struct GNUNET_PeerIdentity *pid)
-{
-  struct PeerRecord *pr;
-
-  pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
-                                         pid);
-  if (NULL == pr)
-    return NULL;
-  return pr->mq;
-}
-
-
-/* end of core_api.c */
index 1455eb2b01633a1e8f659e8dbe33e241bb80d65e..796fdb9d5b85669b0af2502c8f07626a3cf5a7da 100644 (file)
@@ -127,7 +127,7 @@ reconnect (struct GNUNET_CORE_MonitorHandle *mh)
   if (NULL != mh->mq)
     GNUNET_MQ_destroy (mh->mq);
   /* FIXME: use backoff? */
-  mh->mq = GNUNET_CLIENT_connecT (mh->cfg,
+  mh->mq = GNUNET_CLIENT_connect (mh->cfg,
                                   "core",
                                   handlers,
                                   &handle_mq_error,
diff --git a/src/core/core_api_mq.c b/src/core/core_api_mq.c
deleted file mode 100644 (file)
index 12c7a3b..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2009-2014 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-/**
- * @file core/core_api_mq.c
- * @brief MQ support for core service
- * @author Christian Grothoff
- * @author Florian Dold
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_core_service.h"
-#include "core.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "core-api",__VA_ARGS__)
-
-
-/**
- * Internal state of a GNUNET-MQ queue for CORE.
- */
-struct CoreMQState
-{
-  /**
-   * Which peer does this queue target?
-   */
-  struct GNUNET_PeerIdentity target;
-
-  /**
-   * Handle to the CORE service used by this MQ.
-   */
-  struct GNUNET_CORE_Handle *core;
-
-  /**
-   * Transmission handle (if in use).
-   */
-  struct GNUNET_CORE_TransmitHandle *th;
-};
-
-
-/**
- * Function called to notify a client about the connection
- * begin ready to queue more data.  @a buf will be
- * NULL and @a size zero if the connection was closed for
- * writing in the meantime.
- *
- * @param cls closure
- * @param size number of bytes available in @a buf
- * @param buf where the callee should write the message
- * @return number of bytes written to @a buf
- */
-static size_t
-core_mq_ntr (void *cls, size_t size,
-             void *buf)
-{
-  struct GNUNET_MQ_Handle *mq = cls;
-  struct CoreMQState *mqs = GNUNET_MQ_impl_state (mq);
-  const struct GNUNET_MessageHeader *mh = GNUNET_MQ_impl_current (mq);
-  size_t msg_size = ntohs (mh->size);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "ntr called (size %u, type %u)\n",
-       msg_size,
-       ntohs (mh->type));
-  mqs->th = NULL;
-  if (NULL == buf)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "send error\n");
-    GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
-    return 0;
-  }
-  GNUNET_memcpy (buf, mh, msg_size);
-  GNUNET_MQ_impl_send_continue (mq);
-  return msg_size;
-}
-
-
-/**
- * Signature of functions implementing the
- * sending functionality of a message queue.
- *
- * @param mq the message queue
- * @param msg the message to send
- * @param impl_state state of the implementation
- */
-static void
-core_mq_send (struct GNUNET_MQ_Handle *mq,
-              const struct GNUNET_MessageHeader *msg,
-              void *impl_state)
-{
-  struct CoreMQState *mqs = impl_state;
-
-  GNUNET_assert (NULL == mqs->th);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Sending queued message (size %u)\n",
-       ntohs (msg->size));
-  mqs->th = GNUNET_CORE_notify_transmit_ready (mqs->core, GNUNET_YES, 0,
-                                               GNUNET_TIME_UNIT_FOREVER_REL,
-                                               &mqs->target,
-                                               ntohs (msg->size),
-                                               &core_mq_ntr, mq);
-}
-
-
-/**
- * Signature of functions implementing the
- * destruction of a message queue.
- * Implementations must not free @a mq, but should
- * take care of @a impl_state.
- *
- * @param mq the message queue to destroy
- * @param impl_state state of the implementation
- */
-static void
-core_mq_destroy (struct GNUNET_MQ_Handle *mq,
-                 void *impl_state)
-{
-  struct CoreMQState *mqs = impl_state;
-
-  if (NULL != mqs->th)
-  {
-    GNUNET_CORE_notify_transmit_ready_cancel (mqs->th);
-    mqs->th = NULL;
-  }
-  GNUNET_free (mqs);
-}
-
-
-/**
- * Implementation function that cancels the currently sent message.
- *
- * @param mq message queue
- * @param impl_state state specific to the implementation
- */
-static void
-core_mq_cancel (struct GNUNET_MQ_Handle *mq,
-                void *impl_state)
-{
-  struct CoreMQState *mqs = impl_state;
-
-  GNUNET_assert (NULL != mqs->th);
-  GNUNET_CORE_notify_transmit_ready_cancel (mqs->th);
-}
-
-
-/**
- * Create a message queue for sending messages to a peer with CORE.
- * Messages may only be queued with #GNUNET_MQ_send once the init callback has
- * been called for the given handle.
- * There must only be one queue per peer for each core handle.
- * The message queue can only be used to transmit messages,
- * not to receive them.
- *
- * @param h the core handle
- * @param target the target peer for this queue, may not be NULL
- * @return a message queue for sending messages over the core handle
- *         to the target peer
- */
-struct GNUNET_MQ_Handle *
-GNUNET_CORE_mq_create (struct GNUNET_CORE_Handle *h,
-                       const struct GNUNET_PeerIdentity *target)
-{
-  struct CoreMQState *mqs = GNUNET_new (struct CoreMQState);
-
-  mqs->core = h;
-  mqs->target = *target;
-  return GNUNET_MQ_queue_for_callbacks (&core_mq_send,
-                                        &core_mq_destroy,
-                                        &core_mq_cancel,
-                                        mqs,
-                                        NULL, NULL, NULL);
-}
-
-/* end of core_api_mq.c */
index e6a113b52870076b81077d2df69d60cebdb07135..847ba6e757543af6de9b60988204686e33abe285 100644 (file)
@@ -92,7 +92,7 @@ terminate_peer (struct PeerContext *p)
 {
   if (NULL != p->ch)
   {
-    GNUNET_CORE_disconnecT (p->ch);
+    GNUNET_CORE_disconnect (p->ch);
     p->ch = NULL;
   }
   if (NULL != p->ghh)
@@ -243,7 +243,7 @@ init_notify (void *cls,
     GNUNET_assert (ok == 2);
     OKPP;
     /* connect p2 */
-    p2.ch = GNUNET_CORE_connecT (p2.cfg,
+    p2.ch = GNUNET_CORE_connect (p2.cfg,
                                 &p2,
                                 &init_notify,
                                 &connect_notify,
@@ -317,7 +317,7 @@ run (void *cls,
                                     (GNUNET_TIME_UNIT_SECONDS, 300),
                                     &terminate_task_error, NULL);
   p1.ch =
-      GNUNET_CORE_connecT (p1.cfg,
+      GNUNET_CORE_connect (p1.cfg,
                           &p1,
                            &init_notify,
                            &connect_notify,
index cd2bcad83639cf9d8acaa95e8ba6eb0741271237..900c9f73270d92e6d1a0f37ae0e014c29174e56d 100644 (file)
@@ -103,7 +103,7 @@ terminate_peer (struct PeerContext *p)
 {
   if (NULL != p->ch)
   {
-    GNUNET_CORE_disconnecT (p->ch);
+    GNUNET_CORE_disconnect (p->ch);
     p->ch = NULL;
   }
   if (NULL != p->ghh)
@@ -341,7 +341,7 @@ init_notify (void *cls,
     OKPP;
     /* connect p2 */
     GNUNET_assert (NULL !=
-                  (p2.ch = GNUNET_CORE_connecT (p2.cfg,
+                  (p2.ch = GNUNET_CORE_connect (p2.cfg,
                                                 &p2,
                                                 &init_notify,
                                                 &connect_notify,
@@ -464,7 +464,7 @@ run (void *cls,
                                 NULL);
 
   GNUNET_assert (NULL !=
-                (p1.ch = GNUNET_CORE_connecT (p1.cfg,
+                (p1.ch = GNUNET_CORE_connect (p1.cfg,
                                               &p1,
                                               &init_notify,
                                               &connect_notify,
index d29da651b37cc2bacda01d27bc2e24cc0b4121a0..5cfc8b35f780ed668ebb5054b07e0eca760c317b 100644 (file)
@@ -65,7 +65,7 @@ cleanup (void *cls)
   }
   if (NULL != core)
   {
-    GNUNET_CORE_disconnecT (core);
+    GNUNET_CORE_disconnect (core);
     core = NULL;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -159,7 +159,7 @@ run (void *cls,
   };
 
   core =
-    GNUNET_CORE_connecT (cfg,
+    GNUNET_CORE_connect (cfg,
                         NULL,
                         &init,
                          &connect_cb,
index 6abc3cc895efb9dc78ec96460a520e8ec5c1f8b2..31e300b148c05167edbba710f17fd944e9cbe44c 100644 (file)
@@ -74,9 +74,9 @@ static struct GNUNET_MQ_MessageHandler handlers[] = {
 static void
 shutdown_task (void *cls)
 {
-  GNUNET_CORE_disconnecT (p1.ch);
+  GNUNET_CORE_disconnect (p1.ch);
   p1.ch = NULL;
-  GNUNET_CORE_disconnecT (p2.ch);
+  GNUNET_CORE_disconnect (p2.ch);
   p2.ch = NULL;
   ok = 0;
 }
@@ -91,7 +91,7 @@ init_notify (void *cls,
   if (p == &p1)
   {
     /* connect p2 */
-    p2.ch = GNUNET_CORE_connecT (p2.cfg,
+    p2.ch = GNUNET_CORE_connect (p2.cfg,
                                 &p2,
                                 &init_notify,
                                 &connect_notify,
@@ -140,12 +140,12 @@ timeout_task (void *cls)
           "Timeout.\n");
   if (NULL != p1.ch)
   {
-    GNUNET_CORE_disconnecT (p1.ch);
+    GNUNET_CORE_disconnect (p1.ch);
     p1.ch = NULL;
   }
   if (NULL != p2.ch)
   {
-    GNUNET_CORE_disconnecT (p2.ch);
+    GNUNET_CORE_disconnect (p2.ch);
     p2.ch = NULL;
   }
   ok = 42;
@@ -168,7 +168,7 @@ run (void *cls,
                                     TIMEOUT),
                                     &timeout_task,
                                    NULL);
-  p1.ch = GNUNET_CORE_connecT (p1.cfg,
+  p1.ch = GNUNET_CORE_connect (p1.cfg,
                               &p1,
                               &init_notify,
                               &connect_notify,
index eb9a1c379b381ccd371bf0522f4a7be78bb69ebd..4c956987cac970a883dd3af3eb116b44ffcb3f24 100644 (file)
@@ -5,13 +5,7 @@
 GNUNET_TEST_HOME = /tmp/test-gnunet-core/
 
 [nat]
-DISABLEV6 = YES
 ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-USE_LOCALADDR = NO
 
 [ats]
 WAN_QUOTA_IN = 1 GB
index 4dee958f2db0d6586b2b2b7a4df99da0e9bcea1c..dcc33288dc07ebacb5cbe3fcb5a1068d109204a4 100644 (file)
@@ -117,7 +117,7 @@ terminate_peer (struct PeerContext *p)
 {
   if (NULL != p->ch)
   {
-    GNUNET_CORE_disconnecT (p->ch);
+    GNUNET_CORE_disconnect (p->ch);
     p->ch = NULL;
   }
   if (NULL != p->ghh)
@@ -480,7 +480,7 @@ init_notify (void *cls,
     GNUNET_assert (ok == 2);
     OKPP;
     /* connect p2 */
-    p2.ch = GNUNET_CORE_connecT (p2.cfg,
+    p2.ch = GNUNET_CORE_connect (p2.cfg,
                                  &p2,
                                  &init_notify,
                                  &connect_notify,
@@ -653,7 +653,7 @@ run (void *cls,
                                                       "WAN_QUOTA_OUT",
                                                       &current_quota_p2_out));
 
-  p1.ch = GNUNET_CORE_connecT (p1.cfg,
+  p1.ch = GNUNET_CORE_connect (p1.cfg,
                                &p1,
                                &init_notify,
                                &connect_notify,
index b201d4d9ce23c0ae6d75a00a3406c116b61df664..f90bf96305a27cbc3a5740058c21e5656aa137da 100644 (file)
@@ -283,7 +283,7 @@ reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
   GNUNET_assert (NULL == handle->mq);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Trying to connect to CREDENTIAL\n");
-  handle->mq = GNUNET_CLIENT_connecT (handle->cfg,
+  handle->mq = GNUNET_CLIENT_connect (handle->cfg,
                                       "credential",
                                       handlers,
                                       &mq_error_handler,
diff --git a/src/datacache/.gitignore b/src/datacache/.gitignore
new file mode 100644 (file)
index 0000000..8e42aa1
--- /dev/null
@@ -0,0 +1,6 @@
+test_datacache_heap
+test_datacache_postgres
+test_datacache_quota_heap
+test_datacache_quota_postgres
+test_datacache_quota_sqlite
+test_datacache_sqlite
index 185d54f2f81d18d02630e6bae8c1dab8607ea177..49e60bca1dc04347d1e842e99504a5d44379eabb 100644 (file)
@@ -180,8 +180,7 @@ put_cb (void *cls,
     GNUNET_memcpy (val->path_info,
            put_ctx->path_info,
            put_ctx->path_info_len * sizeof (struct GNUNET_PeerIdentity));
-    GNUNET_CONTAINER_heap_update_cost (put_ctx->heap,
-                                      val->hn,
+    GNUNET_CONTAINER_heap_update_cost (val->hn,
                                       val->discard_time.abs_value_us);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Got same value for key %s and type %d (size %u vs %u)\n",
index 38dff999342649c870c1525fb50fb49ce70b1e36..51d3391b99fad2018875957421e0ec30d8584817 100644 (file)
@@ -1,2 +1,16 @@
 gnunet-service-datastore
 gnunet-datastore
+perf_datastore_api_heap
+perf_plugin_datastore_heap
+test_datastore_api_heap
+test_datastore_api_management_heap
+test_datastore_api_management_mysql
+test_datastore_api_management_postgres
+test_datastore_api_management_sqlite
+test_datastore_api_mysql
+test_datastore_api_postgres
+test_datastore_api_sqlite
+test_plugin_datastore_heap
+test_plugin_datastore_mysql
+test_plugin_datastore_postgres
+test_plugin_datastore_sqlite
index d75a58552810f7045caedf999e2c2d656c966863..db485364ef9f3bffcd242436adcf2d6bc3163fd8 100644 (file)
@@ -443,7 +443,7 @@ GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Re-connecting to issue DROP!\n");
     GNUNET_assert (NULL == h->mq);
-    h->mq = GNUNET_CLIENT_connecT (h->cfg,
+    h->mq = GNUNET_CLIENT_connect (h->cfg,
                                    "datastore",
                                    NULL,
                                    &disconnect_on_mq_error,
@@ -868,7 +868,7 @@ try_reconnect (void *cls)
   h->retry_time = GNUNET_TIME_STD_BACKOFF (h->retry_time);
   h->reconnect_task = NULL;
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "datastore",
                                  handlers,
                                  &mq_error_handler,
index 51f61764c6c71df5cbdbf5b6efcab8deaffe7c87..977d599d20ba3e111388f9e10cddce82e3e7d116 100644 (file)
@@ -331,7 +331,7 @@ struct GetContext
    * The plugin.
    */
   struct Plugin *plugin;
-               
+
   /**
    * Requested value hash.
    */
@@ -608,7 +608,7 @@ heap_plugin_get_expiration (void *cls, PluginDatumProcessor proc,
  * priority should be added to the existing priority, ignoring the
  * priority in value.
  *
- * @param cls our "struct Plugin*"
+ * @param cls our `struct Plugin *`
  * @param uid unique identifier of the datum
  * @param delta by how much should the priority
  *     change?  If priority + delta < 0 the
@@ -628,7 +628,6 @@ heap_plugin_update (void *cls,
                    PluginUpdateCont cont,
                    void *cont_cls)
 {
-  struct Plugin *plugin = cls;
   struct Value *value;
 
   value = (struct Value*) (long) uid;
@@ -636,8 +635,7 @@ heap_plugin_update (void *cls,
   if (value->expiration.abs_value_us != expire.abs_value_us)
   {
     value->expiration = expire;
-    GNUNET_CONTAINER_heap_update_cost (plugin->by_expiration,
-                                      value->expire_heap,
+    GNUNET_CONTAINER_heap_update_cost (value->expire_heap,
                                       expire.abs_value_us);
   }
   if ( (delta < 0) && (value->priority < - delta) )
index b8b0ff7d4a315e964e6adfab646091a390169bb6..e7f3c2a860f9f70adc31bbd5b9429a04705e5c79 100644 (file)
@@ -5,3 +5,10 @@ gnunet-dht-profiler
 gnunet-dht-put
 gnunet-service-dht
 gnunet-service-dht-whanau
+test_dht_2dtorus
+test_dht_api
+test_dht_line
+test_dht_monitor
+test_dht_multipeer
+test_dht_tools.py
+test_dht_twopeer
index f91917768bed5118f5a04cffd71f3cda7c04b708..1a174165cc798651757277fd4220160fa1abf39b 100644 (file)
@@ -58,8 +58,12 @@ endif
 noinst_PROGRAMS = \
  gnunet-dht-monitor \
  gnunet-dht-get \
- gnunet-dht-put \
+ gnunet-dht-put
+
+if HAVE_TESTING
+noinst_PROGRAMS += \
  gnunet-dht-profiler
+endif
 
 gnunet_service_dht_SOURCES = \
  gnunet-service-dht.c gnunet-service-dht.h \
index 57880165eaa8e96c9ce7f509ae05efd45c6d7e8b..66eaf10647dad7e6a424e3440593f030603d4c46 100644 (file)
@@ -867,7 +867,7 @@ try_connect (struct GNUNET_DHT_Handle *h)
   };
   if (NULL != h->mq)
     return GNUNET_OK;
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "dht",
                                  handlers,
                                  &mq_error_handler,
index 3716ea3afcc9b7334a4727718ea8514c4cedecee..5a5c4156757b71476bc84981a7f70e7b8cc46213 100644 (file)
@@ -69,13 +69,15 @@ GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
  * FIXME this is called once per address. Merge instead of replacing?
  */
 static void
-process_hello (void *cls, const struct GNUNET_PeerIdentity *peer,
-               const struct GNUNET_HELLO_Message *hello, const char *err_msg)
+process_hello (void *cls,
+               const struct GNUNET_PeerIdentity *peer,
+               const struct GNUNET_HELLO_Message *hello,
+               const char *err_msg)
 {
   struct GNUNET_TIME_Absolute ex;
   struct GNUNET_HELLO_Message *hm;
 
-  if (hello == NULL)
+  if (NULL == hello)
     return;
   ex = GNUNET_HELLO_get_last_expiration (hello);
   if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
@@ -100,8 +102,12 @@ process_hello (void *cls, const struct GNUNET_PeerIdentity *peer,
 void
 GDS_HELLO_init ()
 {
-  pnc = GNUNET_PEERINFO_notify (GDS_cfg, GNUNET_NO, &process_hello, NULL);
-  peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
+  pnc = GNUNET_PEERINFO_notify (GDS_cfg,
+                                GNUNET_NO,
+                                &process_hello,
+                                NULL);
+  peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256,
+                                                        GNUNET_NO);
 }
 
 
@@ -131,7 +137,9 @@ GDS_HELLO_done ()
   }
   if (NULL != peer_to_hello)
   {
-    GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello, &free_hello, NULL);
+    GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello,
+                                           &free_hello,
+                                           NULL);
     GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
   }
 }
index 574ed9ad020d7f325ed733af9dfd1842026d3074..20bdc0ce4d7ff8467a564d255519b0a1e0e6b604 100644 (file)
@@ -1830,10 +1830,16 @@ handle_find_peer (const struct GNUNET_PeerIdentity *sender,
   /* first, check about our own HELLO */
   if (NULL != GDS_my_hello)
   {
-    GNUNET_BLOCK_mingle_hash (&my_identity_hash, bf_mutator, &mhash);
+    GNUNET_BLOCK_mingle_hash (&my_identity_hash,
+                             bf_mutator,
+                             &mhash);
     if ((NULL == bf) ||
         (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (bf, &mhash)))
     {
+      size_t hello_size;
+
+      hello_size = GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message *) GDS_my_hello);
+      GNUNET_break (hello_size >= sizeof (struct GNUNET_MessageHeader));
       GDS_NEIGHBOURS_handle_reply (sender,
                                   GNUNET_BLOCK_TYPE_DHT_HELLO,
                                    GNUNET_TIME_relative_to_absolute
@@ -1844,9 +1850,7 @@ handle_find_peer (const struct GNUNET_PeerIdentity *sender,
                                   0,
                                   NULL,
                                   GDS_my_hello,
-                                   GNUNET_HELLO_size ((const struct
-                                                       GNUNET_HELLO_Message *)
-                                                      GDS_my_hello));
+                                   hello_size);
     }
     else
     {
@@ -2377,7 +2381,7 @@ GDS_NEIGHBOURS_init ()
   log_route_details_stderr =
     (NULL != getenv("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO;
   ats_ch = GNUNET_ATS_connectivity_init (GDS_cfg);
-  core_api = GNUNET_CORE_connecT (GDS_cfg,
+  core_api = GNUNET_CORE_connect (GDS_cfg,
                                  NULL,
                                  &core_init,
                                  &handle_core_connect,
@@ -2401,7 +2405,7 @@ GDS_NEIGHBOURS_done ()
 {
   if (NULL == core_api)
     return;
-  GNUNET_CORE_disconnecT (core_api);
+  GNUNET_CORE_disconnect (core_api);
   core_api = NULL;
   GNUNET_assert (0 ==
                 GNUNET_CONTAINER_multipeermap_size (all_connected_peers));
index 48bece35e3a835c8c414a73968217dbc3439674b..978c46d73ae99a29e931e57f01cada975ce7495d 100644 (file)
@@ -160,7 +160,9 @@ struct ProcessContext
  *         #GNUNET_SYSERR if the result is malformed or type unsupported
  */
 static int
-process (void *cls, const struct GNUNET_HashCode * key, void *value)
+process (void *cls,
+         const struct GNUNET_HashCode *key,
+         void *value)
 {
   struct ProcessContext *pc = cls;
   struct RecentRequest *rr = value;
@@ -170,7 +172,8 @@ process (void *cls, const struct GNUNET_HashCode * key, void *value)
   struct GNUNET_HashCode hc;
   const struct GNUNET_HashCode *eval_key;
 
-  if ((rr->type != GNUNET_BLOCK_TYPE_ANY) && (rr->type != pc->type))
+  if ( (rr->type != GNUNET_BLOCK_TYPE_ANY) &&
+       (rr->type != pc->type) )
     return GNUNET_OK;           /* type missmatch */
 
   if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE))
@@ -183,23 +186,26 @@ process (void *cls, const struct GNUNET_HashCode * key, void *value)
     gpl = 0;
     ppl = 0;
   }
-  if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
-      (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO))
+  if ( (0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
+       (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO) )
   {
     /* key may not match HELLO, which is OK since
      * the search is approximate.  Still, the evaluation
      * would fail since the match is not exact.  So
      * we fake it by changing the key to the actual PID ... */
-    GNUNET_BLOCK_get_key (GDS_block_context, GNUNET_BLOCK_TYPE_DHT_HELLO,
-                          pc->data, pc->data_size, &hc);
+    GNUNET_BLOCK_get_key (GDS_block_context,
+                         GNUNET_BLOCK_TYPE_DHT_HELLO,
+                          pc->data,
+                          pc->data_size,
+                         &hc);
     eval_key = &hc;
   }
   else
   {
     eval_key = key;
   }
-  eval =
-      GNUNET_BLOCK_evaluate (GDS_block_context,
+  eval
+    = GNUNET_BLOCK_evaluate (GDS_block_context,
                              pc->type,
                              GNUNET_BLOCK_EO_NONE,
                              eval_key,
@@ -308,7 +314,10 @@ GDS_ROUTING_process (void *cls,
     pc.data_size = 0;
     pc.data = ""; /* something not null */
   }
-  GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, &process, &pc);
+  GNUNET_CONTAINER_multihashmap_get_multiple (recent_map,
+                                              key,
+                                              &process,
+                                              &pc);
 }
 
 
@@ -345,11 +354,13 @@ expire_oldest_entry ()
  * @param cls the new 'struct RecentRequest' (to discard upon successful combination)
  * @param key the query
  * @param value the existing 'struct RecentRequest' (to update upon successful combination)
- * @return GNUNET_OK (continue to iterate),
- *         GNUNET_SYSERR if the request was successfully combined
+ * @return #GNUNET_OK (continue to iterate),
+ *         #GNUNET_SYSERR if the request was successfully combined
  */
 static int
-try_combine_recent (void *cls, const struct GNUNET_HashCode * key, void *value)
+try_combine_recent (void *cls,
+                    const struct GNUNET_HashCode *key,
+                    void *value)
 {
   struct RecentRequest *in = cls;
   struct RecentRequest *rr = value;
@@ -396,7 +407,8 @@ void
 GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
                  enum GNUNET_BLOCK_Type type,
                  enum GNUNET_DHT_RouteOption options,
-                 const struct GNUNET_HashCode * key, const void *xquery,
+                 const struct GNUNET_HashCode *key,
+                 const void *xquery,
                  size_t xquery_size,
                  const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
                  uint32_t reply_bf_mutator)
@@ -419,8 +431,10 @@ GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
   recent_req->xquery_size = xquery_size;
   recent_req->reply_bf_mutator = reply_bf_mutator;
   if (GNUNET_SYSERR ==
-      GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key,
-                                                 &try_combine_recent, recent_req))
+      GNUNET_CONTAINER_multihashmap_get_multiple (recent_map,
+                                                  key,
+                                                 &try_combine_recent,
+                                                  recent_req))
   {
     GNUNET_STATISTICS_update (GDS_stats,
                               gettext_noop
index d3b92585b313c0d6cef5a3b6dc4a46376c98d673..78a04d66d0564f95eef09b6aa28afa5c6fbb8415 100644 (file)
@@ -1712,7 +1712,7 @@ GDS_NEIGHBOURS_init (void)
     GNUNET_MQ_handler_end ()
   };
 
-  core_api = GNUNET_CORE_connecT (GDS_cfg, NULL,
+  core_api = GNUNET_CORE_connect (GDS_cfg, NULL,
                                  &core_init,
                                  &handle_core_connect,
                                  &handle_core_disconnect,
@@ -1736,7 +1736,7 @@ GDS_NEIGHBOURS_done (void)
 {
   if (NULL == core_api)
     return;
-  GNUNET_CORE_disconnecT (core_api);
+  GNUNET_CORE_disconnect (core_api);
   core_api = NULL;
   GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friends_peermap));
   GNUNET_CONTAINER_multipeermap_destroy (friends_peermap);
index e3462f6188aa4281b3a5853cf94ddbda01963dcb..d41eb19003ec2915045d91517aa8d0241827bc6f 100644 (file)
@@ -6150,7 +6150,7 @@ GDS_NEIGHBOURS_init (void)
     GNUNET_MQ_handler_end ()
   };
 
-  core_api = GNUNET_CORE_connecT (GDS_cfg,
+  core_api = GNUNET_CORE_connect (GDS_cfg,
                                  NULL,
                                  &core_init,
                                  &handle_core_connect,
@@ -6212,7 +6212,7 @@ GDS_NEIGHBOURS_done (void)
   if (NULL == core_api)
     return;
 
-  GNUNET_CORE_disconnecT (core_api);
+  GNUNET_CORE_disconnect (core_api);
   core_api = NULL;
 
   delete_finger_table_entries();
index 17594efcb4308440c0ee142cb57938d1758a6501..8bb53396166a36db6a0aebe770f1e91c282e757e 100644 (file)
@@ -70,12 +70,13 @@ block_plugin_dht_evaluate (void *cls,
 
   if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
     return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
-  if (xquery_size != 0)
+  if (0 != xquery_size)
   {
     GNUNET_break_op (0);
     return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
   }
-  if (NULL == reply_block)
+  if ( (NULL == reply_block) ||
+       (0 == reply_block_size) )
     return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
   if (reply_block_size < sizeof (struct GNUNET_MessageHeader))
   {
@@ -121,14 +122,16 @@ block_plugin_dht_evaluate (void *cls,
  * @param type block type
  * @param block block to get the key for
  * @param block_size number of bytes @a block
- * @param key set to the key (query) for the given block
+ * @param[out] key set to the key (query) for the given block
  * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
  *         (or if extracting a key from a block of this type does not work)
  */
 static int
-block_plugin_dht_get_key (void *cls, enum GNUNET_BLOCK_Type type,
-                          const void *block, size_t block_size,
-                          struct GNUNET_HashCode * key)
+block_plugin_dht_get_key (void *cls,
+                         enum GNUNET_BLOCK_Type type,
+                          const void *block,
+                         size_t block_size,
+                          struct GNUNET_HashCode *key)
 {
   const struct GNUNET_MessageHeader *msg;
   const struct GNUNET_HELLO_Message *hello;
index ef9125c509c6ffdc6129ae38272d340236b84495..952f6fb9a9617dd0ee2c53dbb177d95a75721f12 100644 (file)
@@ -2,3 +2,4 @@ gnunet-service-dns
 gnunet-dns-monitor
 gnunet-dns-redirector
 gnunet-helper-dns
+test_hexcoder
index 4803fe3fc006ae7c8c9eb78fedc09c6dbe9122b7..e7450a1d490d98617b13bcd1660c04b7df9b5174 100644 (file)
@@ -217,7 +217,7 @@ reconnect (void *cls)
   struct GNUNET_DNS_Register *msg;
 
   dh->reconnect_task = NULL;
-  dh->mq = GNUNET_CLIENT_connecT (dh->cfg,
+  dh->mq = GNUNET_CLIENT_connect (dh->cfg,
                                   "dns",
                                   handlers,
                                   &mq_error_handler,
index 43b6c7db173dcc5ccb95ff9ac42b379d0cd79bbd..062f9a95ff04ffa4214f583f0617d890fcdba8c4 100644 (file)
@@ -346,7 +346,7 @@ reconnect (struct GNUNET_DV_ServiceHandle *sh)
                                         sh);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Connecting to DV service\n");
-  sh->mq = GNUNET_CLIENT_connecT (sh->cfg,
+  sh->mq = GNUNET_CLIENT_connect (sh->cfg,
                                   "dv",
                                   handlers,
                                   &mq_error_handler,
index fdd871bbd307b3c6a312571d0c6c420d03811fbb..6adaa04d9dfe92f916a4587b615656601ee74282 100644 (file)
@@ -1936,7 +1936,7 @@ shutdown_task (void *cls)
 
   in_shutdown = GNUNET_YES;
   GNUNET_assert (NULL != core_api);
-  GNUNET_CORE_disconnecT (core_api);
+  GNUNET_CORE_disconnect (core_api);
   core_api = NULL;
   GNUNET_ATS_performance_done (ats);
   ats = NULL;
@@ -2059,7 +2059,7 @@ run (void *cls,
                                                           GNUNET_NO);
   all_routes = GNUNET_CONTAINER_multipeermap_create (65536,
                                                     GNUNET_NO);
-  core_api = GNUNET_CORE_connecT (cfg,
+  core_api = GNUNET_CORE_connect (cfg,
                                  NULL,
                                  &core_init,
                                  &handle_core_connect,
@@ -2073,7 +2073,7 @@ run (void *cls,
                                     NULL);
   if (NULL == ats)
   {
-    GNUNET_CORE_disconnecT (core_api);
+    GNUNET_CORE_disconnect (core_api);
     core_api = NULL;
     return;
   }
index 1b129c64363bb6afd21859a7b61c1845f5f75807..68699db717fa98fad9f225affb4fa0d68c1ef755 100644 (file)
@@ -747,9 +747,8 @@ get_redirect_state (int af,
     return NULL;
   /* Mark this connection as freshly used */
   if (NULL == state_key)
-    GNUNET_CONTAINER_heap_update_cost (connections_heap,
-                                      state->specifics.tcp_udp.heap_node,
-                                      GNUNET_TIME_absolute_get ().abs_value_us);
+    GNUNET_CONTAINER_heap_update_cost (state->specifics.tcp_udp.heap_node,
+                                       GNUNET_TIME_absolute_get ().abs_value_us);
   return state;
 }
 
diff --git a/src/fragmentation/.gitignore b/src/fragmentation/.gitignore
new file mode 100644 (file)
index 0000000..c3293ab
--- /dev/null
@@ -0,0 +1,2 @@
+test_fragmentation
+test_fragmentation_parallel
index eacc3c2dfbd33a45587b5f713fd8e164f9b2bbfb..53b836f2253fb77fa67354b13dc5e96701d87bdd 100644 (file)
@@ -1335,7 +1335,7 @@ do_reconnect (void *cls)
   };
 
   dc->task = NULL;
-  dc->mq = GNUNET_CLIENT_connecT (dc->h->cfg,
+  dc->mq = GNUNET_CLIENT_connect (dc->h->cfg,
                                   "fs",
                                   handlers,
                                   &download_mq_error_handler,
index 67183fce2472a42526088910a84226daf6d1faef..eec125a10c744312f3afd4e0e439e704a31cb675 100644 (file)
@@ -185,7 +185,7 @@ GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
   struct GNUNET_MQ_Envelope *env;
   struct GNUNET_MessageHeader *msg;
 
-  gic->mq = GNUNET_CLIENT_connecT (h->cfg,
+  gic->mq = GNUNET_CLIENT_connect (h->cfg,
                                    "fs",
                                    handlers,
                                    &mq_error_handler,
index 5820c3d0c8ac34d320408d8c2f1d6a3209b622fb..86a58a58bb5b1ae94e68305277304212c9e80c5e 100644 (file)
@@ -863,7 +863,7 @@ hash_for_index_cb (void *cls,
     GNUNET_free (fn);
     return;
   }
-  pc->mq = GNUNET_CLIENT_connecT (pc->h->cfg,
+  pc->mq = GNUNET_CLIENT_connect (pc->h->cfg,
                                   "fs",
                                   handlers,
                                   &index_mq_error_handler,
@@ -1016,7 +1016,7 @@ create_loc_uri (struct GNUNET_FS_PublishContext *pc)
 
   if (NULL != pc->mq)
     GNUNET_MQ_destroy (pc->mq);
-  pc->mq = GNUNET_CLIENT_connecT (pc->h->cfg,
+  pc->mq = GNUNET_CLIENT_connect (pc->h->cfg,
                                   "fs",
                                   handlers,
                                   &loc_mq_error_handler,
index 198577b08ecb76ec2ab58b5ce40a8188300a46ff..75ce4b54f323a7568e33761548445f12fa9b7b6c 100644 (file)
@@ -1244,7 +1244,7 @@ do_reconnect (void *cls)
   };
 
   sc->task = NULL;
-  sc->mq = GNUNET_CLIENT_connecT (sc->h->cfg,
+  sc->mq = GNUNET_CLIENT_connect (sc->h->cfg,
                                   "fs",
                                   handlers,
                                   &search_mq_error_handler,
index 2a024ecbba22342f1657f86c8250fc21d5944b2a..a672b84d54172f5079527c01c97970b29a9dcbb3 100644 (file)
@@ -316,7 +316,7 @@ unindex_finish (struct GNUNET_FS_UnindexContext *uc)
   uc->seen_dh = NULL;
   uc->state = UNINDEX_STATE_FS_NOTIFY;
   GNUNET_FS_unindex_sync_ (uc);
-  uc->mq = GNUNET_CLIENT_connecT (uc->h->cfg,
+  uc->mq = GNUNET_CLIENT_connect (uc->h->cfg,
                                   "fs",
                                   handlers,
                                   &unindex_mq_error_handler,
index c83d73555d8389703552ada63cc069b88985b8eb..e38fdb0323da4eb943a51dec8c55a2465337d1f9 100644 (file)
@@ -1181,7 +1181,7 @@ shutdown_task (void *cls)
   GSF_cadet_stop_server ();
   if (NULL != GSF_core)
   {
-    GNUNET_CORE_disconnecT (GSF_core);
+    GNUNET_CORE_disconnect (GSF_core);
     GSF_core = NULL;
   }
   if (NULL != GSF_ats)
@@ -1219,7 +1219,7 @@ shutdown_task (void *cls)
 
 
 /**
- * Function called after GNUNET_CORE_connecT has succeeded
+ * Function called after GNUNET_CORE_connect has succeeded
  * (or failed for good).  Note that the private key of the
  * peer is intentionally not exposed here; if you need it,
  * your process should try to read the private key file
@@ -1299,7 +1299,7 @@ main_init (const struct GNUNET_CONFIGURATION_Handle *c)
               "I am peer %s\n",
               GNUNET_i2s (&GSF_my_id));
   GSF_core
-    = GNUNET_CORE_connecT (GSF_cfg,
+    = GNUNET_CORE_connect (GSF_cfg,
                           NULL,
                            &peer_init_handler,
                            &GSF_peer_connect_handler,
index bf59cac15028aafe6781701048d027bcd8893710..b34246cef906edc5aea6950ca40be5844e226938 100644 (file)
@@ -5,7 +5,6 @@ HOSTNAME = localhost
 BINARY = gnunet-service-gns
 UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-gns.sock
 @JAVAPORT@PORT = 2102
-USER_SERVICE = YES
 
 # Do we require users that want to access GNS to run this process
 # (usually not a good idea)
@@ -17,9 +16,6 @@ UNIX_MATCH_GID = YES
 # How many queries is GNS allowed to perform in the background at the same time?
 MAX_PARALLEL_BACKGROUND_QUERIES = 1000
 
-# How frequently do we try to publish our full zone?
-ZONE_PUBLISH_TIME_WINDOW = 4 h
-
 # Using caching or always ask DHT
 # USE_CACHE = YES
 
index 5ad7b4faeda74b0be71116df753fa218bb394ee3..f6f9889ac20843c36a64ea927c9c737abd90ade4 100644 (file)
@@ -397,7 +397,7 @@ reconnect (struct GNUNET_GNS_Handle *handle)
   GNUNET_assert (NULL == handle->mq);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Trying to connect to GNS\n");
-  handle->mq = GNUNET_CLIENT_connecT (handle->cfg,
+  handle->mq = GNUNET_CLIENT_connect (handle->cfg,
                                       "gns",
                                       handlers,
                                       &mq_error_handler,
index 3e718dac851831fced2178b0e9ef4040020319d1..cec31ff480fbd0bf0f267769ce04060f15879e26 100644 (file)
 #include "gnunet-service-gns_interceptor.h"
 #include "gnunet_protocols.h"
 
-/**
- * The initial interval in milliseconds btween puts in
- * a zone iteration
- */
-#define INITIAL_PUT_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS
-
-/**
- * The lower bound for the zone iteration interval
- */
-#define MINIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_SECONDS
-
-/**
- * The upper bound for the zone iteration interval
- */
-#define MAXIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
-
-/**
- * The default put interval for the zone iteration. In case
- * no option is found
- */
-#define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
-
-/**
- * The factor the current zone iteration interval is divided by for each
- * additional new record
- */
-#define LATE_ITERATION_SPEEDUP_FACTOR 2
-
-/**
- * How long until a DHT PUT attempt should time out?
- */
-#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
-
-/**
- * What replication level do we use for DHT PUT operations?
- */
-#define DHT_GNS_REPLICATION_LEVEL 5
 
 /**
  * GnsClient prototype
@@ -145,48 +108,21 @@ struct GnsClient
 };
 
 
-/**
- * Handle for DHT PUT activity triggered from the namestore monitor.
- */
-struct MonitorActivity
-{
-  /**
-   * Kept in a DLL.
-   */
-  struct MonitorActivity *next;
-
-  /**
-   * Kept in a DLL.
-   */
-  struct MonitorActivity *prev;
-
-  /**
-   * Handle for the DHT PUT operation.
-   */
-  struct GNUNET_DHT_PutHandle *ph;
-};
-
-
 /**
  * Our handle to the DHT
  */
 static struct GNUNET_DHT_Handle *dht_handle;
 
 /**
- * Active DHT put operation (or NULL)
+ * Our handle to the namecache service
  */
-static struct GNUNET_DHT_PutHandle *active_put;
+static struct GNUNET_NAMECACHE_Handle *namecache_handle;
 
 /**
  * Our handle to the namestore service
  */
 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
 
-/**
- * Our handle to the namecache service
- */
-static struct GNUNET_NAMECACHE_Handle *namecache_handle;
-
 /**
  * Our handle to the identity service
  */
@@ -198,68 +134,6 @@ static struct GNUNET_IDENTITY_Handle *identity_handle;
  */
 static struct GNUNET_IDENTITY_Operation *identity_op;
 
-/**
- * Handle to iterate over our authoritative zone in namestore
- */
-static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
-
-/**
- * Handle to monitor namestore changes to instant propagation.
- */
-static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
-
-/**
- * Head of monitor activities; kept in a DLL.
- */
-static struct MonitorActivity *ma_head;
-
-/**
- * Tail of monitor activities; kept in a DLL.
- */
-static struct MonitorActivity *ma_tail;
-
-/**
- * Useful for zone update for DHT put
- */
-static unsigned long long num_public_records;
-
-/**
- * Last seen record count
- */
-static unsigned long long last_num_public_records;
-
-/**
- * Minimum relative expiration time of records seem during the current
- * zone iteration.
- */
-static struct GNUNET_TIME_Relative min_relative_record_time;
-
-/**
- * Zone iteration PUT interval.
- */
-static struct GNUNET_TIME_Relative put_interval;
-
-/**
- * Default time window for zone iteration
- */
-static struct GNUNET_TIME_Relative zone_publish_time_window_default;
-
-/**
- * Time window for zone iteration, adjusted based on relative record
- * expiration times in our zone.
- */
-static struct GNUNET_TIME_Relative zone_publish_time_window;
-
-/**
- * zone publish task
- */
-static struct GNUNET_SCHEDULER_Task *zone_publish_task;
-
-/**
- * #GNUNET_YES if zone has never been published before
- */
-static int first_zone_iteration;
-
 /**
  * #GNUNET_YES if ipv6 is supported
  */
@@ -285,8 +159,6 @@ static struct GNUNET_STATISTICS_Handle *statistics;
 static void
 shutdown_task (void *cls)
 {
-  struct MonitorActivity *ma;
-
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Shutting down!\n");
   GNS_interceptor_done ();
@@ -303,35 +175,12 @@ shutdown_task (void *cls)
   GNS_resolver_done ();
   GNS_reverse_done ();
   GNS_shorten_done ();
-  while (NULL != (ma = ma_head))
-  {
-    GNUNET_DHT_put_cancel (ma->ph);
-    GNUNET_CONTAINER_DLL_remove (ma_head,
-                                 ma_tail,
-                                 ma);
-    GNUNET_free (ma);
-  }
   if (NULL != statistics)
   {
     GNUNET_STATISTICS_destroy (statistics,
                                GNUNET_NO);
     statistics = NULL;
   }
-  if (NULL != zone_publish_task)
-  {
-    GNUNET_SCHEDULER_cancel (zone_publish_task);
-    zone_publish_task = NULL;
-  }
-  if (NULL != namestore_iter)
-  {
-    GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
-    namestore_iter = NULL;
-  }
-  if (NULL != zmon)
-  {
-    GNUNET_NAMESTORE_zone_monitor_stop (zmon);
-    zmon = NULL;
-  }
   if (NULL != namestore_handle)
   {
     GNUNET_NAMESTORE_disconnect (namestore_handle);
@@ -342,11 +191,6 @@ shutdown_task (void *cls)
     GNUNET_NAMECACHE_disconnect (namecache_handle);
     namecache_handle = NULL;
   }
-  if (NULL != active_put)
-  {
-    GNUNET_DHT_put_cancel (active_put);
-    active_put = NULL;
-  }
   if (NULL != dht_handle)
   {
     GNUNET_DHT_disconnect (dht_handle);
@@ -354,6 +198,7 @@ shutdown_task (void *cls)
   }
 }
 
+
 /**
  * Called whenever a client is disconnected.
  *
@@ -412,408 +257,6 @@ client_connect_cb (void *cls,
 }
 
 
-/**
- * Method called periodically that triggers iteration over authoritative records
- *
- * @param cls closure
- */
-static void
-publish_zone_dht_next (void *cls)
-{
-  zone_publish_task = NULL;
-  GNUNET_assert (NULL != namestore_iter);
-  GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
-}
-
-
-/**
- * Periodically iterate over our zone and store everything in dht
- *
- * @param cls NULL
- */
-static void
-publish_zone_dht_start (void *cls);
-
-
-/**
- * Continuation called from DHT once the PUT operation is done.
- *
- * @param cls closure, NULL if called from regular iteration,
- *        `struct MonitorActivity` if called from #handle_monitor_event.
- * @param success #GNUNET_OK on success
- */
-static void
-dht_put_continuation (void *cls,
-                      int success)
-{
-  struct MonitorActivity *ma = cls;
-  struct GNUNET_TIME_Relative next_put_interval;
-
-  num_public_records++;
-  if (NULL == ma)
-  {
-    active_put = NULL;
-    if ( (num_public_records > last_num_public_records) &&
-         (GNUNET_NO == first_zone_iteration) )
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Last record count was lower than current record count.  Reducing interval.\n");
-      put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
-                                                  num_public_records);
-      next_put_interval = GNUNET_TIME_relative_divide (put_interval,
-                                                       LATE_ITERATION_SPEEDUP_FACTOR);
-    }
-    else
-      next_put_interval = put_interval;
-    next_put_interval = GNUNET_TIME_relative_min (next_put_interval,
-                                                  MAXIMUM_ZONE_ITERATION_INTERVAL);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "PUT complete, next PUT in %s!\n",
-                GNUNET_STRINGS_relative_time_to_string (next_put_interval,
-                                                        GNUNET_YES));
-
-    GNUNET_STATISTICS_set (statistics,
-                           "Current zone iteration interval (ms)",
-                           next_put_interval.rel_value_us / 1000LL,
-                           GNUNET_NO);
-    GNUNET_assert (NULL == zone_publish_task);
-    zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval,
-                                                      &publish_zone_dht_next,
-                                                      NULL);
-  }
-  else
-  {
-    GNUNET_CONTAINER_DLL_remove (ma_head,
-                                 ma_tail,
-                                 ma);
-    GNUNET_free (ma);
-  }
-}
-
-
-/**
- * Convert namestore records from the internal format to that
- * suitable for publication (removes private records, converts
- * to absolute expiration time).
- *
- * @param rd input records
- * @param rd_count size of the @a rd and @a rd_public arrays
- * @param rd_public where to write the converted records
- * @return number of records written to @a rd_public
- */
-static unsigned int
-convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
-                            unsigned int rd_count,
-                            struct GNUNET_GNSRECORD_Data *rd_public)
-{
-  struct GNUNET_TIME_Absolute now;
-  unsigned int rd_public_count;
-  unsigned int i;
-
-  rd_public_count = 0;
-  now = GNUNET_TIME_absolute_get ();
-  for (i=0;i<rd_count;i++)
-    if (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
-    {
-      rd_public[rd_public_count] = rd[i];
-      if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
-      {
-        /* GNUNET_GNSRECORD_block_create will convert to absolute time;
-           we just need to adjust our iteration frequency */
-        min_relative_record_time.rel_value_us =
-          GNUNET_MIN (rd_public[rd_public_count].expiration_time,
-                      min_relative_record_time.rel_value_us);
-      }
-      else if (rd_public[rd_public_count].expiration_time < now.abs_value_us)
-      {
-        /* record already expired, skip it */
-        continue;
-      }
-      rd_public_count++;
-    }
-  return rd_public_count;
-}
-
-
-/**
- * Store GNS records in the DHT.
- *
- * @param key key of the zone
- * @param label label to store under
- * @param rd_public public record data
- * @param rd_public_count number of records in @a rd_public
- * @param pc_arg closure argument to pass to the #dht_put_continuation
- * @return DHT PUT handle, NULL on error
- */
-static struct GNUNET_DHT_PutHandle *
-perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
-                 const char *label,
-                 const struct GNUNET_GNSRECORD_Data *rd_public,
-                 unsigned int rd_public_count,
-                 void *pc_arg)
-{
-  struct GNUNET_GNSRECORD_Block *block;
-  struct GNUNET_HashCode query;
-  struct GNUNET_TIME_Absolute expire;
-  size_t block_size;
-  struct GNUNET_DHT_PutHandle *ret;
-
-  expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
-                                                        rd_public);
-  block = GNUNET_GNSRECORD_block_create (key,
-                                         expire,
-                                         label,
-                                         rd_public,
-                                         rd_public_count);
-  if (NULL == block)
-    return NULL; /* whoops */
-  block_size = ntohl (block->purpose.size)
-    + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)
-    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
-  GNUNET_GNSRECORD_query_from_private_key (key,
-                                           label,
-                                           &query);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n",
-              rd_public_count,
-              label,
-              GNUNET_STRINGS_absolute_time_to_string (expire),
-              GNUNET_h2s (&query));
-  ret = GNUNET_DHT_put (dht_handle,
-                        &query,
-                        DHT_GNS_REPLICATION_LEVEL,
-                        GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
-                        GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
-                        block_size,
-                        block,
-                        expire,
-                        &dht_put_continuation,
-                        pc_arg);
-  GNUNET_free (block);
-  return ret;
-}
-
-
-/**
- * We encountered an error in our zone iteration.
- */
-static void
-zone_iteration_error (void *cls)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got disconnected from namestore database, retrying.\n");
-  namestore_iter = NULL;
-  /* We end up here on error/disconnect/shutdown, so potentially
-     while a zone publish task or a DHT put is still running; hence
-     we need to cancel those. */
-  if (NULL != zone_publish_task)
-  {
-    GNUNET_SCHEDULER_cancel (zone_publish_task);
-    zone_publish_task = NULL;
-  }
-  if (NULL != active_put)
-  {
-    GNUNET_DHT_put_cancel (active_put);
-    active_put = NULL;
-  }
-  zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
-                                                NULL);
-}
-
-
-/**
- * Zone iteration is completed.
- */
-static void
-zone_iteration_finished (void *cls)
-{
-  /* we're done with one iteration, calculate when to do the next one */
-  namestore_iter = NULL;
-  last_num_public_records = num_public_records;
-  first_zone_iteration = GNUNET_NO;
-  if (0 == num_public_records)
-  {
-    /**
-     * If no records are known (startup) or none present
-     * we can safely set the interval to the value for a single
-     * record
-     */
-    put_interval = zone_publish_time_window;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-                "No records in namestore database.\n");
-  }
-  else
-  {
-    /* If records are present, next publication is based on the minimum
-     * relative expiration time of the records published divided by 4
-     */
-    zone_publish_time_window
-      = GNUNET_TIME_relative_min (GNUNET_TIME_relative_divide (min_relative_record_time, 4),
-                                  zone_publish_time_window_default);
-    put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
-                                                num_public_records);
-  }
-  /* reset for next iteration */
-  min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL;
-  put_interval = GNUNET_TIME_relative_max (MINIMUM_ZONE_ITERATION_INTERVAL,
-                                           put_interval);
-  put_interval = GNUNET_TIME_relative_min (put_interval,
-                                           MAXIMUM_ZONE_ITERATION_INTERVAL);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Zone iteration finished. Adjusted zone iteration interval to %s\n",
-              GNUNET_STRINGS_relative_time_to_string (put_interval,
-                                                      GNUNET_YES));
-  GNUNET_STATISTICS_set (statistics,
-                         "Current zone iteration interval (in ms)",
-                         put_interval.rel_value_us / 1000LL,
-                         GNUNET_NO);
-  GNUNET_STATISTICS_update (statistics,
-                            "Number of zone iterations",
-                            1,
-                            GNUNET_NO);
-  GNUNET_STATISTICS_set (statistics,
-                         "Number of public records in DHT",
-                         last_num_public_records,
-                         GNUNET_NO);
-  GNUNET_assert (NULL == zone_publish_task);
-  if (0 == num_public_records)
-    zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval,
-                                                      &publish_zone_dht_start,
-                                                      NULL);
-  else
-    zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
-                                                  NULL);
-}
-
-
-/**
- * Function used to put all records successively into the DHT.
- *
- * @param cls the closure (NULL)
- * @param key the private key of the authority (ours)
- * @param label the name of the records, NULL once the iteration is done
- * @param rd_count the number of records in @a rd
- * @param rd the record data
- */
-static void
-put_gns_record (void *cls,
-                const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
-                const char *label,
-                unsigned int rd_count,
-                const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct GNUNET_GNSRECORD_Data rd_public[rd_count];
-  unsigned int rd_public_count;
-
-  rd_public_count = convert_records_for_export (rd,
-                                                rd_count,
-                                                rd_public);
-
-  if (0 == rd_public_count)
-  {
-    GNUNET_assert (NULL == zone_publish_task);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Record set empty, moving to next record set\n");
-    zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next,
-                                                  NULL);
-    return;
-  }
-  /* We got a set of records to publish */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Starting DHT PUT\n");
-  active_put = perform_dht_put (key,
-                                label,
-                                rd_public,
-                                rd_public_count,
-                                NULL);
-  if (NULL == active_put)
-  {
-    GNUNET_break (0);
-    dht_put_continuation (NULL, GNUNET_NO);
-  }
-}
-
-
-/**
- * Periodically iterate over all zones and store everything in DHT
- *
- * @param cls NULL
- */
-static void
-publish_zone_dht_start (void *cls)
-{
-  zone_publish_task = NULL;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Starting DHT zone update!\n");
-  /* start counting again */
-  num_public_records = 0;
-  GNUNET_assert (NULL == namestore_iter);
-  namestore_iter
-    = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
-                                             NULL, /* All zones */
-                                             &zone_iteration_error,
-                                             NULL,
-                                             &put_gns_record,
-                                             NULL,
-                                             &zone_iteration_finished,
-                                             NULL);
-}
-
-
-/**
- * Process a record that was stored in the namestore
- * (invoked by the monitor).
- *
- * @param cls closure, NULL
- * @param zone private key of the zone; NULL on disconnect
- * @param label label of the records; NULL on disconnect
- * @param rd_count number of entries in @a rd array, 0 if label was deleted
- * @param rd array of records with data to store
- */
-static void
-handle_monitor_event (void *cls,
-                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                      const char *label,
-                      unsigned int rd_count,
-                      const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct GNUNET_GNSRECORD_Data rd_public[rd_count];
-  unsigned int rd_public_count;
-  struct MonitorActivity *ma;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received %u records for label `%s' via namestore monitor\n",
-              rd_count,
-              label);
-  /* filter out records that are not public, and convert to
-     absolute expiration time. */
-  rd_public_count = convert_records_for_export (rd,
-                                                rd_count,
-                                                rd_public);
-  if (0 == rd_public_count)
-    return; /* nothing to do */
-  ma = GNUNET_new (struct MonitorActivity);
-  ma->ph = perform_dht_put (zone,
-                            label,
-                            rd,
-                            rd_count,
-                            ma);
-  if (NULL == ma->ph)
-  {
-    /* PUT failed, do not remember operation */
-    GNUNET_free (ma);
-    return;
-  }
-  GNUNET_CONTAINER_DLL_insert (ma_head,
-                               ma_tail,
-                               ma);
-}
-
-
-/* END DHT ZONE PROPAGATION */
-
-
 /**
  * Reply to client with the result from our lookup.
  *
@@ -1019,49 +462,6 @@ handle_rev_lookup (void *cls,
 }
 
 
-/**
- * The zone monitor is now in SYNC with the current state of the
- * name store.  Start to perform periodic iterations.
- *
- * @param cls NULL
- */
-static void
-monitor_sync_event (void *cls)
-{
-  GNUNET_assert (NULL == zone_publish_task);
-  zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
-                                                NULL);
-}
-
-
-/**
- * The zone monitor is now in SYNC with the current state of the
- * name store.  Start to perform periodic iterations.
- *
- * @param cls NULL
- */
-static void
-handle_monitor_error (void *cls)
-{
-  if (NULL != zone_publish_task)
-  {
-    GNUNET_SCHEDULER_cancel (zone_publish_task);
-    zone_publish_task = NULL;
-  }
-  if (NULL != namestore_iter)
-  {
-    GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
-    namestore_iter = NULL;
-  }
-  if (NULL != active_put)
-  {
-    GNUNET_DHT_put_cancel (active_put);
-    active_put = NULL;
-  }
-  zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
-                                                NULL);
-}
-
 /**
  * Method called to inform about the ego to be used for the master zone
  * for DNS interceptions.
@@ -1107,7 +507,6 @@ identity_reverse_cb (void *cls,
 }
 
 
-
 /**
  * Method called to inform about the ego to be used for the master zone
  * for DNS interceptions.
@@ -1175,11 +574,10 @@ run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *c,
      struct GNUNET_SERVICE_Handle *service)
 {
-  unsigned long long max_parallel_bg_queries = 0;
+  unsigned long long max_parallel_bg_queries = 16;
 
   v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6);
-  v4_enabled = GNUNET_NETWORK_test_pf (PF_INET);
-  min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL;
+  v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); 
   namestore_handle = GNUNET_NAMESTORE_connect (c);
   if (NULL == namestore_handle)
   {
@@ -1188,7 +586,7 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
 namecache_handle = GNUNET_NAMECACHE_connect (c);
+ namecache_handle = GNUNET_NAMECACHE_connect (c);
   if (NULL == namecache_handle)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1196,22 +594,9 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-
-  put_interval = INITIAL_PUT_INTERVAL;
-  zone_publish_time_window_default = DEFAULT_ZONE_PUBLISH_TIME_WINDOW;
   if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_time (c, "gns",
-                                           "ZONE_PUBLISH_TIME_WINDOW",
-                                           &zone_publish_time_window_default))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Time window for zone iteration: %s\n",
-                GNUNET_STRINGS_relative_time_to_string (zone_publish_time_window,
-                                                        GNUNET_YES));
-  }
-  zone_publish_time_window = zone_publish_time_window_default;
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_number (c, "gns",
+      GNUNET_CONFIGURATION_get_value_number (c,
+                                            "gns",
                                              "MAX_PARALLEL_BACKGROUND_QUERIES",
                                              &max_parallel_bg_queries))
   {
@@ -1219,7 +604,6 @@ run (void *cls,
                 "Number of allowed parallel background queries: %llu\n",
                 max_parallel_bg_queries);
   }
-
   dht_handle = GNUNET_DHT_connect (c,
                                    (unsigned int) max_parallel_bg_queries);
   if (NULL == dht_handle)
@@ -1254,19 +638,7 @@ run (void *cls,
   GNS_shorten_init (namestore_handle,
                     namecache_handle,
                     dht_handle);
-  /* Schedule periodic put for our records. */
-  first_zone_iteration = GNUNET_YES;
   statistics = GNUNET_STATISTICS_create ("gns", c);
-  zmon = GNUNET_NAMESTORE_zone_monitor_start (c,
-                                              NULL,
-                                              GNUNET_NO,
-                                              &handle_monitor_error,
-                                              NULL,
-                                              &handle_monitor_event,
-                                              NULL,
-                                              &monitor_sync_event,
-                                              NULL);
-  GNUNET_break (NULL != zmon);
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
 }
 
index 931dc68091da22a24909cca6d68b93c0cf7605dd..b5b8b31b7cad22722e96a135653e36ae185c93d9 100644 (file)
@@ -394,6 +394,7 @@ handle_gns_result_iter (void *cls,
   it_task = GNUNET_SCHEDULER_add_now (&next_it, ith);
 }
 
+
 static void
 next_it (void *cls)
 {
@@ -402,6 +403,7 @@ next_it (void *cls)
   GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
 }
 
+
 static void
 iterator_cb (void *cls,
              const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
@@ -487,6 +489,7 @@ store_reverse (void *cls,
   GNUNET_free (ith);
 }
 
+
 static void
 finished_cb (void *cls)
 {
@@ -522,6 +525,7 @@ finished_cb (void *cls)
 
 }
 
+
 static void
 it_error (void *cls)
 {
@@ -529,6 +533,7 @@ it_error (void *cls)
               "Error iterating for REVERSE\n");
 }
 
+
 static void
 check_reverse_records (void *cls)
 {
diff --git a/src/gnsrecord/.gitignore b/src/gnsrecord/.gitignore
new file mode 100644 (file)
index 0000000..374abdb
--- /dev/null
@@ -0,0 +1,4 @@
+test_gnsrecord_block_expiration
+test_gnsrecord_crypto
+test_gnsrecord_serialization
+zonefiles
index 237e1a10e33b7e52b775931dc6d597d52d9e9350..bb49ceb204fd315a614c497474d1e86bf995ec8e 100644 (file)
@@ -1 +1,3 @@
 gnunet-hello
+test_friend_hello
+test_hello
index f20bc2d58c3c1aa5839bcb21a487c23cdd551c24..b16e3444aa1a320e23b8d3e5aca97ecdc2c732b8 100644 (file)
@@ -1 +1,4 @@
 gnunet-daemon-hostlist
+test_gnunet_daemon_hostlist
+test_gnunet_daemon_hostlist_learning
+test_gnunet_daemon_hostlist_reconnect
index 7181a913b51c5665871f2df2dd92c02e23cc2034..a83d46e0711635456e5e53516c2ec9c361579ad2 100644 (file)
@@ -47,7 +47,7 @@ static int provide_hostlist;
 /**
  * Handle to hostlist server's connect handler
  */
-static GNUNET_CORE_ConnecTEventHandler server_ch;
+static GNUNET_CORE_ConnectEventHandler server_ch;
 
 #endif
 
@@ -81,12 +81,12 @@ static GNUNET_HOSTLIST_UriHandler client_adv_handler;
 /**
  * Handle to hostlist client's connect handler
  */
-static GNUNET_CORE_ConnecTEventHandler client_ch;
+static GNUNET_CORE_ConnectEventHandler client_ch;
 
 /**
  * Handle to hostlist client's disconnect handler
  */
-static GNUNET_CORE_DisconnecTEventHandler client_dh;
+static GNUNET_CORE_DisconnectEventHandler client_dh;
 
 GNUNET_NETWORK_STRUCT_BEGIN
 
@@ -260,7 +260,7 @@ cleaning_task (void *cls)
              "Hostlist daemon is shutting down\n");
   if (NULL != core)
   {
-    GNUNET_CORE_disconnecT (core);
+    GNUNET_CORE_disconnect (core);
     core = NULL;
   }
   if (bootstrapping)
@@ -330,7 +330,7 @@ run (void *cls,
                                   &client_adv_handler,
                                   learning);
   core =
-    GNUNET_CORE_connecT (cfg,
+    GNUNET_CORE_connect (cfg,
                         NULL,
                         &core_init,
                         &connect_handler,
index c1a2c2721883275364a5c71f9a92ed72df196d13..a973fcc280b2a89092c47012be36b84647c53440 100644 (file)
@@ -1548,8 +1548,8 @@ save_hostlist_file (int shutdown)
 int
 GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
                               struct GNUNET_STATISTICS_Handle *st,
-                              GNUNET_CORE_ConnecTEventHandler *ch,
-                              GNUNET_CORE_DisconnecTEventHandler *dh,
+                              GNUNET_CORE_ConnectEventHandler *ch,
+                              GNUNET_CORE_DisconnectEventHandler *dh,
                               GNUNET_HOSTLIST_UriHandler *msgh,
                               int learn)
 {
index dd80d4a4882e200f1c8618bc65dd4b3eb4a6f6ad..e41b90876ca442435aa828c71dc223a8397f6ff7 100644 (file)
@@ -53,8 +53,8 @@ typedef void
 int
 GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
                               struct GNUNET_STATISTICS_Handle *st,
-                              GNUNET_CORE_ConnecTEventHandler *ch,
-                              GNUNET_CORE_DisconnecTEventHandler *dh,
+                              GNUNET_CORE_ConnectEventHandler *ch,
+                              GNUNET_CORE_DisconnectEventHandler *dh,
                               GNUNET_HOSTLIST_UriHandler *msgh,
                               int learn);
 
index b01dbc09ed117f66f51b18511435190692601411..48c1a56221011ddabb11504affd709d72261ddfb 100644 (file)
@@ -644,7 +644,7 @@ int
 GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
                               struct GNUNET_STATISTICS_Handle *st,
                               struct GNUNET_CORE_Handle *co,
-                              GNUNET_CORE_ConnecTEventHandler *server_ch,
+                              GNUNET_CORE_ConnectEventHandler *server_ch,
                               int advertise)
 {
   unsigned long long port;
index f18ad0ca2d0bb665770b07c885c9e8ed66317125..d9f778a4bc544e2dc83158951f1c6512c589b72b 100644 (file)
@@ -46,7 +46,7 @@ int
 GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
                               struct GNUNET_STATISTICS_Handle *st,
                               struct GNUNET_CORE_Handle *core,
-                              GNUNET_CORE_ConnecTEventHandler *server_ch,
+                              GNUNET_CORE_ConnectEventHandler *server_ch,
                              int advertise);
 
 
index c39c57eb369f504cc8f9ed7749bbd64d75860abd..88ad22a1ab29b5aa7bdef344302c037e760201bf 100644 (file)
@@ -125,12 +125,12 @@ shutdown_testcase ()
   }
   if (NULL != adv_peer.core)
   {
-    GNUNET_CORE_disconnecT (adv_peer.core);
+    GNUNET_CORE_disconnect (adv_peer.core);
     adv_peer.core = NULL;
   }
   if (NULL != learn_peer.core)
   {
-    GNUNET_CORE_disconnecT (learn_peer.core);
+    GNUNET_CORE_disconnect (learn_peer.core);
     learn_peer.core = NULL;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -432,7 +432,7 @@ setup_learn_peer (struct PeerContext *p,
     }
     GNUNET_free (filename);
   }
-  p->core = GNUNET_CORE_connecT (p->cfg,
+  p->core = GNUNET_CORE_connect (p->cfg,
                                 NULL,
                                 NULL,
                                 NULL,
@@ -567,13 +567,6 @@ main (int argc, char *argv[])
   GNUNET_log_setup ("test-gnunet-daemon-hostlist",
                     "WARNING",
                     NULL);
-#if !WINDOWS
-  system ("gnunet-peerinfo -s -c test_learning_adv_peer.conf > /dev/null");
-  system ("gnunet-peerinfo -s -c test_learning_learn_peer.conf > /dev/null");
-#else
-  system ("gnunet-peerinfo -s -c test_learning_adv_peer.conf > NUL");
-  system ("gnunet-peerinfo -s -c test_learning_learn_peer.conf > NUL");
-#endif
   ret = check ();
   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1");
   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2");
index 220c36656f6ec605235258888f35939f678ea4ef..21ec235b630aab59df7c00f206e5a3385827a3b4 100644 (file)
@@ -380,7 +380,7 @@ reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Connecting to identity provider service.\n");
 
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "identity-provider",
                                  handlers,
                                  &mq_error_handler,
index cbabc187e7014ae6652df716cee6d935621823ae..634a0bdd6a361704f2494ad3e2eb126b265e9383 100644 (file)
@@ -1,2 +1,4 @@
 gnunet-service-identity
 gnunet-identity
+test_identity
+test_identity_defaults
index 10a64d1ba44a897610ed1b91fc41407f8501b19c..905b3fd8b5a216fe716445c10e7afa8771d0782b 100644 (file)
@@ -575,7 +575,7 @@ reconnect (void *cls)
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Connecting to identity service.\n");
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "identity",
                                  handlers,
                                  &mq_error_handler,
index f27fd6e36a01a6c08b892ffe30beb0062bd005f7..bf3ffe4821fd2409f73a8b8b67199628d173d8fb 100644 (file)
@@ -78,7 +78,7 @@ gnunetinclude_HEADERS = \
   gnunet_namecache_service.h \
   gnunet_namestore_plugin.h \
   gnunet_namestore_service.h \
-  gnunet_nat_lib.h \
+  gnunet_nat_auto_service.h \
   gnunet_nat_service.h \
   gnunet_nc_lib.h \
   gnunet_network_lib.h \
index c32311643b8c130022b6561d0c637efe5eaf2dd8..7090d44108e6fcdfb7e453716ff4cd822c538dee 100644 (file)
@@ -67,15 +67,6 @@ struct GNUNET_CADET_Channel;
  */
 struct GNUNET_CADET_Port;
 
-/**
- * Hash to be used in Cadet communication. Only 256 bits needed,
- * instead of the 512 from `struct GNUNET_HashCode`.
- */
-struct GNUNET_CADET_Hash
-{
-  unsigned char bits[256 / 8];
-};
-
 
 /**
  * Channel options.  Second line indicates filed in the
@@ -102,9 +93,9 @@ enum GNUNET_CADET_ChannelOption
 
   /**
    * Enable out of order delivery of messages.
-   * Yes/No.
+   * Set bit for out-of-order delivery.
    */
-  GNUNET_CADET_OPTION_OOORDER    = 0x4,
+  GNUNET_CADET_OPTION_OUT_OF_ORDER = 0x4,
 
   /**
    * Who is the peer at the other end of the channel.
@@ -255,8 +246,7 @@ GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle);
 struct GNUNET_CADET_Port *
 GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
                        const struct GNUNET_HashCode *port,
-                       GNUNET_CADET_InboundChannelNotificationHandler
-                           new_channel,
+                       GNUNET_CADET_InboundChannelNotificationHandler new_channel,
                        void *new_channel_cls);
 
 /**
@@ -332,7 +322,8 @@ union GNUNET_CADET_ChannelInfo
  */
 const union GNUNET_CADET_ChannelInfo *
 GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
-                              enum GNUNET_CADET_ChannelOption option, ...);
+                              enum GNUNET_CADET_ChannelOption option,
+                               ...);
 
 
 /**
@@ -421,10 +412,10 @@ typedef void
 (*GNUNET_CADET_ChannelCB) (void *cls,
                            const struct GNUNET_PeerIdentity *root,
                            const struct GNUNET_PeerIdentity *dest,
-                           uint32_t port,
-                           uint32_t root_channel_number,
-                           uint32_t dest_channel_number,
-                           uint32_t public_channel_number);
+                           uint32_t /* UGH */ port,
+                           uint32_t /* ugh */ root_channel_number,
+                           uint32_t /* ugh */ dest_channel_number,
+                           uint32_t /* ugh */ public_channel_number);
 
 /**
  * Method called to retrieve information about all peers in CADET, called
@@ -490,6 +481,28 @@ typedef void
                            uint16_t cstate);
 
 
+/**
+ * Hash uniquely identifying a connection below a tunnel.
+ */
+struct GNUNET_CADET_ConnectionTunnelIdentifier
+{
+  struct GNUNET_ShortHashCode connection_of_tunnel;
+};
+
+
+/**
+ * Number identifying a CADET channel within a tunnel.
+ */
+struct GNUNET_CADET_ChannelTunnelNumber
+{
+  /**
+   * Which number does this channel have that uniquely identfies
+   * it within its tunnel?
+   */
+  uint32_t cn GNUNET_PACKED;
+};
+
+
 /**
  * Method called to retrieve information about a specific tunnel the cadet peer
  * has established, o`r is trying to establish.
@@ -508,8 +521,8 @@ typedef void
                           const struct GNUNET_PeerIdentity *peer,
                           unsigned int n_channels,
                           unsigned int n_connections,
-                          uint32_t *channels,
-                          struct GNUNET_CADET_Hash *connections,
+                          const struct GNUNET_CADET_ChannelTunnelNumber *channels,
+                          const struct GNUNET_CADET_ConnectionTunnelIdentifier *connections,
                           unsigned int estate,
                           unsigned int cstate);
 
@@ -528,7 +541,7 @@ typedef void
 void
 GNUNET_CADET_get_channel (struct GNUNET_CADET_Handle *h,
                           struct GNUNET_PeerIdentity *peer,
-                          uint32_t channel_number,
+                          uint32_t /* UGH */ channel_number,
                           GNUNET_CADET_ChannelCB callback,
                           void *callback_cls);
 
index f98620dfaa5155eeced1142d1e23f4c5651922d8..613349fddd9211380263378cd739233ed7d9e7e7 100644 (file)
@@ -57,7 +57,7 @@ extern "C"
  * @return the message queue, NULL on error
  */
 struct GNUNET_MQ_Handle *
-GNUNET_CLIENT_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
+GNUNET_CLIENT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                        const char *service_name,
                        const struct GNUNET_MQ_MessageHandler *handlers,
                        GNUNET_MQ_ErrorHandler error_handler,
index 897502155c67a6b7edf2b60dfd441b5411af9261..9ad60471177b8ea9455d72f58a2ffc5ebaac0184 100644 (file)
@@ -66,7 +66,7 @@ extern "C"
 /**
  * Version of the API (for entire gnunetutil.so library).
  */
-#define GNUNET_UTIL_VERSION 0x000A0101
+#define GNUNET_UTIL_VERSION 0x000A0102
 
 
 /**
@@ -556,6 +556,19 @@ GNUNET_logger_remove (GNUNET_Logger logger,
                       void *logger_cls);
 
 
+/**
+ * @ingroup logging
+ * Convert a short hash value to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant!
+ *
+ * @param shc the hash code
+ * @return string
+ */
+const char *
+GNUNET_sh2s (const struct GNUNET_ShortHashCode *shc);
+
+
 /**
  * @ingroup logging
  * Convert a hash value to a string (for printing debug messages).
@@ -655,7 +668,7 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
 /**
  * @ingroup logging
  * Use this for fatal errors that cannot be handled
- * 
+ *
  * @param cond Condition to evaluate
  * @param comp Component string to use for logging
  */
index ef9b2731898f8a376bbb8e6f3aa218e4a1e1b7bc..1d0232cea11973413e29e6097038569065059420 100644 (file)
@@ -127,9 +127,9 @@ extern "C"
 
 /**
  * Size of the CADET message overhead:
- * = sizeof (struct GNUNET_CADET_Encrypted)
- * + sizeof (struct GNUNET_CADET_Data)
- * + sizeof (struct GNUNET_CADET_ACK))
+ * = sizeof (struct GNUNET_CADET_TunnelEncryptedMessage)
+ * + sizeof (struct GNUNET_CADET_ChannelAppDataMessage)
+ * + sizeof (struct GNUNET_CADET_ConnectionEncryptedAckMessage))
  *
  * Checked for correcteness in gnunet-service-cadet_tunnel.c: GCT_init().
  */
index 03c47c2019b701d24858411c7ce4748759e8e7b0..f3aaa943b2e91603202a2f8bfdfd41fe9c3b9fb2 100644 (file)
@@ -1285,6 +1285,275 @@ GNUNET_CONTAINER_multipeermap_get_random (const struct GNUNET_CONTAINER_MultiPee
                                           void *it_cls);
 
 
+/* ***************** Version of Multihashmap for short hashes ****************** */
+
+/**
+ * @ingroup hashmap
+ * Iterator over hash map entries.
+ *
+ * @param cls closure
+ * @param key current public key
+ * @param value value in the hash map
+ * @return #GNUNET_YES if we should continue to
+ *         iterate,
+ *         #GNUNET_NO if not.
+ */
+typedef int
+(*GNUNET_CONTAINER_ShortmapIterator) (void *cls,
+                                     const struct GNUNET_ShortHashCode *key,
+                                     void *value);
+
+
+/**
+ * Hash map from peer identities to values.
+ */
+struct GNUNET_CONTAINER_MultiShortmap;
+
+
+/**
+ * @ingroup hashmap
+ * Create a multi peer map (hash map for public keys of peers).
+ *
+ * @param len initial size (map will grow as needed)
+ * @param do_not_copy_keys #GNUNET_NO is always safe and should be used by default;
+ *                         #GNUNET_YES means that on 'put', the 'key' does not have
+ *                         to be copied as the destination of the pointer is
+ *                         guaranteed to be life as long as the value is stored in
+ *                         the hashmap.  This can significantly reduce memory
+ *                         consumption, but of course is also a recipie for
+ *                         heap corruption if the assumption is not true.  Only
+ *                         use this if (1) memory use is important in this case and
+ *                         (2) you have triple-checked that the invariant holds
+ * @return NULL on error
+ */
+struct GNUNET_CONTAINER_MultiShortmap *
+GNUNET_CONTAINER_multishortmap_create (unsigned int len,
+                                       int do_not_copy_keys);
+
+
+/**
+ * @ingroup hashmap
+ * Destroy a hash map.  Will not free any values
+ * stored in the hash map!
+ *
+ * @param map the map
+ */
+void
+GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap *map);
+
+
+/**
+ * @ingroup hashmap
+ * Given a key find a value in the map matching the key.
+ *
+ * @param map the map
+ * @param key what to look for
+ * @return NULL if no value was found; note that
+ *   this is indistinguishable from values that just
+ *   happen to be NULL; use "contains" to test for
+ *   key-value pairs with value NULL
+ */
+void *
+GNUNET_CONTAINER_multishortmap_get (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                    const struct GNUNET_ShortHashCode *key);
+
+
+/**
+ * @ingroup hashmap
+ * Remove the given key-value pair from the map.  Note that if the
+ * key-value pair is in the map multiple times, only one of the pairs
+ * will be removed.
+ *
+ * @param map the map
+ * @param key key of the key-value pair
+ * @param value value of the key-value pair
+ * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair
+ *  is not in the map
+ */
+int
+GNUNET_CONTAINER_multishortmap_remove (struct GNUNET_CONTAINER_MultiShortmap *map,
+                                       const struct GNUNET_ShortHashCode * key,
+                                       const void *value);
+
+/**
+ * @ingroup hashmap
+ * Remove all entries for the given key from the map.
+ * Note that the values would not be "freed".
+ *
+ * @param map the map
+ * @param key identifies values to be removed
+ * @return number of values removed
+ */
+int
+GNUNET_CONTAINER_multishortmap_remove_all (struct GNUNET_CONTAINER_MultiShortmap *map,
+                                           const struct GNUNET_ShortHashCode *key);
+
+
+/**
+ * @ingroup hashmap
+ * Check if the map contains any value under the given
+ * key (including values that are NULL).
+ *
+ * @param map the map
+ * @param key the key to test if a value exists for it
+ * @return #GNUNET_YES if such a value exists,
+ *         #GNUNET_NO if not
+ */
+int
+GNUNET_CONTAINER_multishortmap_contains (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                         const struct GNUNET_ShortHashCode *key);
+
+
+/**
+ * @ingroup hashmap
+ * Check if the map contains the given value under the given
+ * key.
+ *
+ * @param map the map
+ * @param key the key to test if a value exists for it
+ * @param value value to test for
+ * @return #GNUNET_YES if such a value exists,
+ *         #GNUNET_NO if not
+ */
+int
+GNUNET_CONTAINER_multishortmap_contains_value (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                               const struct GNUNET_ShortHashCode * key,
+                                               const void *value);
+
+
+/**
+ * @ingroup hashmap
+ * Store a key-value pair in the map.
+ *
+ * @param map the map
+ * @param key key to use
+ * @param value value to use
+ * @param opt options for put
+ * @return #GNUNET_OK on success,
+ *         #GNUNET_NO if a value was replaced (with REPLACE)
+ *         #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the
+ *                       value already exists
+ */
+int
+GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map,
+                                    const struct GNUNET_ShortHashCode *key,
+                                    void *value,
+                                    enum GNUNET_CONTAINER_MultiHashMapOption opt);
+
+
+/**
+ * @ingroup hashmap
+ * Get the number of key-value pairs in the map.
+ *
+ * @param map the map
+ * @return the number of key value pairs
+ */
+unsigned int
+GNUNET_CONTAINER_multishortmap_size (const struct GNUNET_CONTAINER_MultiShortmap *map);
+
+
+/**
+ * @ingroup hashmap
+ * Iterate over all entries in the map.
+ *
+ * @param map the map
+ * @param it function to call on each entry
+ * @param it_cls extra argument to @a it
+ * @return the number of key value pairs processed,
+ *         #GNUNET_SYSERR if it aborted iteration
+ */
+int
+GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                        GNUNET_CONTAINER_ShortmapIterator it,
+                                        void *it_cls);
+
+
+struct GNUNET_CONTAINER_MultiShortmapIterator;
+
+
+/**
+ * @ingroup hashmap
+ * Create an iterator for a multihashmap.
+ * The iterator can be used to retrieve all the elements in the multihashmap
+ * one by one, without having to handle all elements at once (in contrast to
+ * #GNUNET_CONTAINER_multishortmap_iterate).  Note that the iterator can not be
+ * used anymore if elements have been removed from @a map after the creation of
+ * the iterator, or 'map' has been destroyed.  Adding elements to @a map may
+ * result in skipped or repeated elements.
+ *
+ * @param map the map to create an iterator for
+ * @return an iterator over the given multihashmap @a map
+ */
+struct GNUNET_CONTAINER_MultiShortmapIterator *
+GNUNET_CONTAINER_multishortmap_iterator_create (const struct GNUNET_CONTAINER_MultiShortmap *map);
+
+
+/**
+ * @ingroup hashmap
+ * Retrieve the next element from the hash map at the iterator's
+ * position.  If there are no elements left, #GNUNET_NO is returned,
+ * and @a key and @a value are not modified.  This operation is only
+ * allowed if no elements have been removed from the multihashmap
+ * since the creation of @a iter, and the map has not been destroyed.
+ * Adding elements may result in repeating or skipping elements.
+ *
+ * @param iter the iterator to get the next element from
+ * @param key pointer to store the key in, can be NULL
+ * @param value pointer to store the value in, can be NULL
+ * @return #GNUNET_YES we returned an element,
+ *         #GNUNET_NO if we are out of elements
+ */
+int
+GNUNET_CONTAINER_multishortmap_iterator_next (struct GNUNET_CONTAINER_MultiShortmapIterator *iter,
+                                              struct GNUNET_ShortHashCode *key,
+                                              const void **value);
+
+
+/**
+ * @ingroup hashmap
+ * Destroy a multishortmap iterator.
+ *
+ * @param iter the iterator to destroy
+ */
+void
+GNUNET_CONTAINER_multishortmap_iterator_destroy (struct GNUNET_CONTAINER_MultiShortmapIterator *iter);
+
+
+/**
+ * @ingroup hashmap
+ * Iterate over all entries in the map that match a particular key.
+ *
+ * @param map the map
+ * @param key public key that the entries must correspond to
+ * @param it function to call on each entry
+ * @param it_cls extra argument to @a it
+ * @return the number of key value pairs processed,
+ *         #GNUNET_SYSERR if it aborted iteration
+ */
+int
+GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                             const struct GNUNET_ShortHashCode *key,
+                                             GNUNET_CONTAINER_ShortmapIterator it,
+                                             void *it_cls);
+
+
+/**
+ * @ingroup hashmap
+ * Call @a it on a random value from the map, or not at all
+ * if the map is empty.  Note that this function has linear
+ * complexity (in the size of the map).
+ *
+ * @param map the map
+ * @param it function to call on a random entry
+ * @param it_cls extra argument to @a it
+ * @return the number of key value pairs processed, zero or one.
+ */
+unsigned int
+GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                          GNUNET_CONTAINER_ShortmapIterator it,
+                                          void *it_cls);
+
+
 /* Version of multihashmap with 32 bit keys */
 
 /**
@@ -1915,8 +2184,8 @@ GNUNET_CONTAINER_heap_get_size (const struct GNUNET_CONTAINER_Heap *heap);
  * @return cost of the node
  */
 GNUNET_CONTAINER_HeapCostType
-GNUNET_CONTAINER_heap_node_get_cost (const struct GNUNET_CONTAINER_HeapNode
-                                     *node);
+GNUNET_CONTAINER_heap_node_get_cost (const struct GNUNET_CONTAINER_HeapNode *node);
+
 
 /**
  * @ingroup heap
@@ -2006,13 +2275,11 @@ GNUNET_CONTAINER_heap_remove_node (struct GNUNET_CONTAINER_HeapNode *node);
  * @ingroup heap
  * Updates the cost of any node in the tree
  *
- * @param heap heap to modify
  * @param node node for which the cost is to be changed
  * @param new_cost new cost for the node
  */
 void
-GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_Heap *heap,
-                                   struct GNUNET_CONTAINER_HeapNode *node,
+GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_HeapNode *node,
                                    GNUNET_CONTAINER_HeapCostType new_cost);
 
 
index 6ec486b26c0cbcebe3e9cb0be39e503f987ef39b..8136770b7803ad304a3c7010d3d68d935258da59 100644 (file)
@@ -85,28 +85,6 @@ enum GNUNET_CORE_Priority
 struct GNUNET_CORE_Handle;
 
 
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-typedef void
-(*GNUNET_CORE_ConnectEventHandler) (void *cls,
-                                    const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Method called whenever a peer disconnects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-typedef void
-(*GNUNET_CORE_DisconnectEventHandler) (void *cls,
-                                       const struct GNUNET_PeerIdentity *peer);
-
-
 /**
  * Method called whenever a given peer connects.
  *
@@ -114,7 +92,7 @@ typedef void
  * @param peer peer identity this notification is about
  */
 typedef void *
-(*GNUNET_CORE_ConnecTEventHandler) (void *cls,
+(*GNUNET_CORE_ConnectEventHandler) (void *cls,
                                     const struct GNUNET_PeerIdentity *peer,
                                    struct GNUNET_MQ_Handle *mq);
 
@@ -126,54 +104,11 @@ typedef void *
  * @param peer peer identity this notification is about
  */
 typedef void
-(*GNUNET_CORE_DisconnecTEventHandler) (void *cls,
+(*GNUNET_CORE_DisconnectEventHandler) (void *cls,
                                        const struct GNUNET_PeerIdentity *peer,
                                       void *peer_cls);
 
 
-/**
- * Functions with this signature are called whenever a message is
- * received or transmitted.
- *
- * @param cls closure (set from #GNUNET_CORE_connect)
- * @param peer the other peer involved (sender or receiver, NULL
- *        for loopback messages where we are both sender and receiver)
- * @param message the actual message
- * @return #GNUNET_OK to keep the connection open,
- *         #GNUNET_SYSERR to close connection to the peer (signal serious error)
- */
-typedef int
-(*GNUNET_CORE_MessageCallback) (void *cls,
-                                const struct GNUNET_PeerIdentity *other,
-                                const struct GNUNET_MessageHeader *message);
-
-
-/**
- * Message handler.  Each struct specifies how to handle on particular
- * type of message received.
- */
-struct GNUNET_CORE_MessageHandler
-{
-  /**
-   * Function to call for messages of @e type.
-   */
-  GNUNET_CORE_MessageCallback callback;
-
-  /**
-   * Type of the message this handler covers.
-   */
-  uint16_t type;
-
-  /**
-   * Expected size of messages of this type.  Use 0 for variable-size.
-   * If non-zero, messages of the given type will be discarded if they
-   * do not have the right size.
-   */
-  uint16_t expected_size;
-
-};
-
-
 /**
  * Function called after #GNUNET_CORE_connect has succeeded (or failed
  * for good).  Note that the private key of the peer is intentionally
@@ -208,26 +143,6 @@ typedef void
  *        connected to the core service
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be NULL
- * @param inbound_notify function to call for all inbound messages, can be NULL
- *                note that the core is allowed to drop notifications about inbound
- *                messages if the client does not process them fast enough (for this
- *                notification type, a bounded queue is used)
- * @param inbound_hdr_only set to #GNUNET_YES if @a inbound_notify will only read the
- *                `struct GNUNET_MessageHeader` and hence we do not need to give it the full message;
- *                can be used to improve efficiency, ignored if inbound_notify is NULL
- *                note that the core is allowed to drop notifications about inbound
- *                messages if the client does not process them fast enough (for this
- *                notification type, a bounded queue is used)
- * @param outbound_notify function to call for all outbound messages, can be NULL;
- *                note that the core is allowed to drop notifications about outbound
- *                messages if the client does not process them fast enough (for this
- *                notification type, a bounded queue is used)
- * @param outbound_hdr_only set to #GNUNET_YES if @a outbound_notify will only read the
- *                `struct GNUNET_MessageHeader` and hence we do not need to give it the full message
- *                can be used to improve efficiency, ignored if outbound_notify is NULL
- *                note that the core is allowed to drop notifications about outbound
- *                messages if the client does not process them fast enough (for this
- *                notification type, a bounded queue is used)
  * @param handlers callbacks for messages we care about, NULL-terminated
  *                note that the core is allowed to drop notifications about inbound
  *                messages if the client does not process them fast enough (for this
@@ -241,53 +156,6 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                      GNUNET_CORE_StartupCallback init,
                      GNUNET_CORE_ConnectEventHandler connects,
                      GNUNET_CORE_DisconnectEventHandler disconnects,
-                     GNUNET_CORE_MessageCallback inbound_notify,
-                     int inbound_hdr_only,
-                     GNUNET_CORE_MessageCallback outbound_notify,
-                     int outbound_hdr_only,
-                     const struct GNUNET_CORE_MessageHandler *handlers);
-
-/**
- * Disconnect from the core service.    This function can only
- * be called *after* all pending #GNUNET_CORE_notify_transmit_ready
- * requests have been explicitly cancelled.
- *
- * @param handle connection to core to disconnect
- */
-void
-GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle);
-
-
-/**
- * Connect to the core service.  Note that the connection may complete
- * (or fail) asynchronously.  This function primarily causes the given
- * callback notification functions to be invoked whenever the
- * specified event happens.  The maximum number of queued
- * notifications (queue length) is per client; the queue is shared
- * across all types of notifications.  So a slow client that registers
- * for @a outbound_notify also risks missing @a inbound_notify messages.
- * Certain events (such as connect/disconnect notifications) are not
- * subject to queue size limitations.
- *
- * @param cfg configuration to use
- * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
- * @param init callback to call once we have successfully
- *        connected to the core service
- * @param connects function to call on peer connect, can be NULL
- * @param disconnects function to call on peer disconnect / timeout, can be NULL
- * @param handlers callbacks for messages we care about, NULL-terminated
- *                note that the core is allowed to drop notifications about inbound
- *                messages if the client does not process them fast enough (for this
- *                notification type, a bounded queue is used)
- * @return handle to the core service (only useful for disconnect until @a init is called),
- *           NULL on error (in this case, init is never called)
- */
-struct GNUNET_CORE_Handle *
-GNUNET_CORE_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                     void *cls,
-                     GNUNET_CORE_StartupCallback init,
-                     GNUNET_CORE_ConnecTEventHandler connects,
-                     GNUNET_CORE_DisconnecTEventHandler disconnects,
                      const struct GNUNET_MQ_MessageHandler *handlers);
 
 
@@ -297,7 +165,7 @@ GNUNET_CORE_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
  * @param handle connection to core to disconnect
  */
 void
-GNUNET_CORE_disconnecT (struct GNUNET_CORE_Handle *handle);
+GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle);
 
 
 /**
@@ -305,7 +173,7 @@ GNUNET_CORE_disconnecT (struct GNUNET_CORE_Handle *handle);
  * so that it is transmitted with the given @a priority and
  * the given @a cork value.
  *
- * @param cork desired corking 
+ * @param cork desired corking
  * @param priority desired message priority
  * @param[out] flags set to `flags` value for #GNUNET_MQ_set_options()
  * @return `extra` argument to give to #GNUNET_MQ_set_options()
@@ -320,7 +188,7 @@ GNUNET_CORE_get_mq_options (int cork,
  * Obtain the message queue for a connected peer.
  *
  * @param h the core handle
- * @param pid the identity of the peer 
+ * @param pid the identity of the peer
  * @return NULL if @a pid is not connected
  */
 struct GNUNET_MQ_Handle *
index 8002b771098b5cac3c960f1e6069d1a4798dd3ef..43fd32a588ddead9745a739f7d42de9442333e57 100644 (file)
@@ -52,9 +52,24 @@ extern "C"
 #endif
 
 /**
- * @brief A 512-bit hashcode
+ * @brief A 512-bit hashcode.  These are the default length for GNUnet, using SHA-512.
  */
-struct GNUNET_HashCode;
+struct GNUNET_HashCode
+{
+  uint32_t bits[512 / 8 / sizeof (uint32_t)];   /* = 16 */
+};
+
+
+
+/**
+ * @brief A 256-bit hashcode.  Used under special conditions, like when space
+ * is critical and security is not impacted by it.
+ */
+struct GNUNET_ShortHashCode
+{
+  uint32_t bits[256 / 8 / sizeof (uint32_t)];   /* = 8 */
+};
+
 
 /**
  * The identity of the host (wraps the signing key of the peer).
@@ -65,15 +80,6 @@ struct GNUNET_PeerIdentity;
 #include <gcrypt.h>
 
 
-/**
- * @brief A 512-bit hashcode
- */
-struct GNUNET_HashCode
-{
-  uint32_t bits[512 / 8 / sizeof (uint32_t)];   /* = 16 */
-};
-
-
 /**
  * Maximum length of an ECC signature.
  * Note: round up to multiple of 8 minus 2 for alignment.
index d1a045b8bfe98738138398924ba600c123864e34..108ba5d543fc8896b2e5e401a8689edd12ff0037 100644 (file)
@@ -254,15 +254,6 @@ typedef void
                          void *impl_state);
 
 
-/**
- * Callback used for notifications
- *
- * @param cls closure
- */
-typedef void
-(*GNUNET_MQ_NotifyCallback) (void *cls);
-
-
 /**
  * Generic error handler, called with the appropriate
  * error code and the same closure specified at the creation of
@@ -402,7 +393,7 @@ struct GNUNET_MQ_MessageHandler
  * @param ctx context for the callbacks
  */
 #define GNUNET_MQ_hd_var_size(name,code,str,ctx)             \
-  ({                                                         \
+  __extension__ ({                                           \
     int (*_mv)(void *cls, const str *msg) = &check_##name;   \
     void (*_cb)(void *cls, const str *msg) = &handle_##name; \
     ((struct GNUNET_MQ_MessageHandler)                       \
@@ -634,7 +625,7 @@ GNUNET_MQ_set_handlers_closure (struct GNUNET_MQ_Handle *mq,
  */
 void
 GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *ev,
-                       GNUNET_MQ_NotifyCallback cb,
+                       GNUNET_SCHEDULER_TaskCallback cb,
                        void *cb_cls);
 
 
diff --git a/src/include/gnunet_nat_auto_service.h b/src/include/gnunet_nat_auto_service.h
new file mode 100644 (file)
index 0000000..a369c49
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2007-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @author Christian Grothoff
+ * @author Milan Bouchet-Valat
+ *
+ * @file
+ * Service for testing and autoconfiguration of
+ * NAT traversal functionality
+ *
+ * @defgroup nat  NAT testing library
+ *
+ * @{
+ */
+
+#ifndef GNUNET_NAT_AUTO_SERVICE_H
+#define GNUNET_NAT_AUTO_SERVICE_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet_nat_service.h"
+
+
+/**
+ * Handle to a NAT test.
+ */
+struct GNUNET_NAT_AUTO_Test;
+
+
+/**
+ * Start testing if NAT traversal works using the given configuration.
+ *  The transport adapters should be down while using this function.
+ *
+ * @param cfg configuration for the NAT traversal
+ * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
+ * @param section_name configuration section to use for configuration
+ * @param report function to call with the result of the test
+ * @param report_cls closure for @a report
+ * @return handle to cancel NAT test
+ */
+struct GNUNET_NAT_AUTO_Test *
+GNUNET_NAT_AUTO_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                           uint8_t proto,
+                           const char *section_name,
+                           GNUNET_NAT_TestCallback report,
+                           void *report_cls);
+
+
+/**
+ * Stop an active NAT test.
+ *
+ * @param tst test to stop.
+ */
+void
+GNUNET_NAT_AUTO_test_stop (struct GNUNET_NAT_AUTO_Test *tst);
+
+
+/**
+ * Handle to auto-configuration in progress.
+ */
+struct GNUNET_NAT_AUTO_AutoHandle;
+
+
+/**
+ * Converts `enum GNUNET_NAT_StatusCode` to string
+ *
+ * @param err error code to resolve to a string
+ * @return point to a static string containing the error code
+ */
+const char *
+GNUNET_NAT_AUTO_status2string (enum GNUNET_NAT_StatusCode err);
+
+
+/**
+ * Function called with the result from the autoconfiguration.
+ *
+ * @param cls closure
+ * @param diff minimal suggested changes to the original configuration
+ *             to make it work (as best as we can)
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ * @param type what the situation of the NAT
+ */
+typedef void
+(*GNUNET_NAT_AUTO_AutoResultCallback)(void *cls,
+                                     const struct GNUNET_CONFIGURATION_Handle *diff,
+                                     enum GNUNET_NAT_StatusCode result,
+                                     enum GNUNET_NAT_Type type);
+
+
+/**
+ * Start auto-configuration routine.  The transport adapters should
+ * be stopped while this function is called.
+ *
+ * @param cfg initial configuration
+ * @param cb function to call with autoconfiguration result
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel operation
+ */
+struct GNUNET_NAT_AUTO_AutoHandle *
+GNUNET_NAT_AUTO_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                 GNUNET_NAT_AUTO_AutoResultCallback cb,
+                                 void *cb_cls);
+
+
+/**
+ * Abort autoconfiguration.
+ *
+ * @param ah handle for operation to abort
+ */
+void
+GNUNET_NAT_AUTO_autoconfig_cancel (struct GNUNET_NAT_AUTO_AutoHandle *ah);
+
+
+#endif
+
+/** @} */  /* end of group */
+
+/* end of gnunet_nat_auto_service.h */
diff --git a/src/include/gnunet_nat_lib.h b/src/include/gnunet_nat_lib.h
deleted file mode 100644 (file)
index 853a86c..0000000
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2007-2014 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @author Christian Grothoff
- * @author Milan Bouchet-Valat
- *
- * @file
- * Library handling UPnP and NAT-PMP port forwarding
- * and external IP address retrieval
- *
- * @defgroup nat  NAT library
- * Library handling UPnP and NAT-PMP port forwarding
- * and external IP address retrieval
- *
- * @{
- */
-
-#ifndef GNUNET_NAT_LIB_H
-#define GNUNET_NAT_LIB_H
-
-#include "gnunet_util_lib.h"
-
-
-/**
- * Signature of the callback passed to #GNUNET_NAT_register() for
- * a function to call whenever our set of 'valid' addresses changes.
- *
- * @param cls closure
- * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
- *     the previous (now invalid) one
- * @param addr either the previous or the new public IP address
- * @param addrlen actual length of the @a addr
- */
-typedef void
-(*GNUNET_NAT_AddressCallback) (void *cls,
-                               int add_remove,
-                               const struct sockaddr *addr,
-                               socklen_t addrlen);
-
-
-/**
- * Signature of the callback passed to #GNUNET_NAT_register().
- * for a function to call whenever someone asks us to do connection
- * reversal.
- *
- * @param cls closure
- * @param addr public IP address of the other peer
- * @param addrlen actual lenght of the @a addr
- */
-typedef void
-(*GNUNET_NAT_ReversalCallback) (void *cls,
-                                const struct sockaddr *addr,
-                                socklen_t addrlen);
-
-
-/**
- * Handle for active NAT registrations.
- */
-struct GNUNET_NAT_Handle;
-
-
-
-/**
- * What the situation of the NAT connectivity
- */
-enum GNUNET_NAT_Type
-{
-  /**
-   * We have a direct connection
-   */
-  GNUNET_NAT_TYPE_NO_NAT = GNUNET_OK,
-
-  /**
-   * We are under a NAT but cannot traverse it
-   */
-  GNUNET_NAT_TYPE_UNREACHABLE_NAT,
-
-  /**
-   * We can traverse using STUN
-   */
-  GNUNET_NAT_TYPE_STUN_PUNCHED_NAT,
-
-  /**
-   * WE can traverse using UPNP
-   */
-  GNUNET_NAT_TYPE_UPNP_NAT
-
-};
-
-/**
- * Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
- */
-enum GNUNET_NAT_StatusCode
-{
-  /**
-   * Just the default
-   */
-  GNUNET_NAT_ERROR_SUCCESS = GNUNET_OK,
-
-  /**
-   * IPC Failure
-   */
-  GNUNET_NAT_ERROR_IPC_FAILURE,
-
-  /**
-   * Failure in network subsystem, check permissions
-   */
-  GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR,
-
-  /**
-   * test timed out
-   */
-  GNUNET_NAT_ERROR_TIMEOUT,
-
-  /**
-   * detected that we are offline
-   */
-  GNUNET_NAT_ERROR_NOT_ONLINE,
-
-  /**
-   * `upnpc` command not found
-   */
-  GNUNET_NAT_ERROR_UPNPC_NOT_FOUND,
-
-  /**
-   * Failed to run `upnpc` command
-   */
-  GNUNET_NAT_ERROR_UPNPC_FAILED,
-
-  /**
-   * `upnpc' command took too long, process killed
-   */
-  GNUNET_NAT_ERROR_UPNPC_TIMEOUT,
-
-  /**
-   * `upnpc' command failed to establish port mapping
-   */
-  GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED,
-
-  /**
-   * `external-ip' command not found
-   */
-  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND,
-
-  /**
-   * Failed to run `external-ip` command
-   */
-  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED,
-
-  /**
-   * `external-ip' command output invalid
-   */
-  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID,
-
-  /**
-   * "no valid address was returned by `external-ip'"
-   */
-  GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID,
-
-  /**
-   * Could not determine interface with internal/local network address
-   */
-  GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO,
-
-  /**
-   * No working gnunet-helper-nat-server found
-   */
-  GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND,
-
-  /**
-   * NAT test could not be initialized
-   */
-  GNUNET_NAT_ERROR_NAT_TEST_START_FAILED,
-
-  /**
-   * NAT test timeout
-   */
-  GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT,
-
-  /**
-   * NAT test failed to initiate
-   */
-  GNUNET_NAT_ERROR_NAT_REGISTER_FAILED,
-
-  /**
-   *
-   */
-  GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND,
-
-  /**
-   *
-   */
-  GNUNET_NAT_ERROR_
-};
-
-
-/**
- * Converts `enum GNUNET_NAT_StatusCode` to string
- *
- * @param err error code to resolve to a string
- * @return point to a static string containing the error code
- */
-const char *
-GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err);
-
-
-/**
- * Attempt to enable port redirection and detect public IP address
- * contacting UPnP or NAT-PMP routers on the local network. Use addr
- * to specify to which of the local host's addresses should the
- * external port be mapped. The port is taken from the corresponding
- * sockaddr_in[6] field.  The NAT module should call the given
- * callback for any 'plausible' external address.
- *
- * @param cfg configuration to use
- * @param is_tcp #GNUNET_YES for TCP, #GNUNET_NO for UDP
- * @param adv_port advertised port (port we are either bound to or that our OS
- *                 locally performs redirection from to our bound port).
- * @param num_addrs number of addresses in @a addrs
- * @param addrs list of local addresses packets should be redirected to
- * @param addrlens actual lengths of the addresses in @a addrs
- * @param address_callback function to call everytime the public IP address changes
- * @param reversal_callback function to call if someone wants connection reversal from us,
- *        NULL if connection reversal is not supported
- * @param callback_cls closure for callbacks
- * @return NULL on error, otherwise handle that can be used to unregister
- */
-struct GNUNET_NAT_Handle *
-GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                     int is_tcp,
-                     uint16_t adv_port,
-                     unsigned int num_addrs,
-                     const struct sockaddr **addrs,
-                     const socklen_t *addrlens,
-                     GNUNET_NAT_AddressCallback address_callback,
-                     GNUNET_NAT_ReversalCallback reversal_callback,
-                     void *callback_cls,
-                     struct GNUNET_NETWORK_Handle* sock);
-
-
-/**
- * Test if the given address is (currently) a plausible IP address for
- * this peer.
- *
- * @param h the handle returned by register
- * @param addr IP address to test (IPv4 or IPv6)
- * @param addrlen number of bytes in @a addr
- * @return #GNUNET_YES if the address is plausible,
- *         #GNUNET_NO if the address is not plausible,
- *         #GNUNET_SYSERR if the address is malformed
- */
-int
-GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
-                         const void *addr,
-                         socklen_t addrlen);
-
-
-/**
- * We learned about a peer (possibly behind NAT) so run the
- * gnunet-nat-client to send dummy ICMP responses to cause
- * that peer to connect to us (connection reversal).
- *
- * @param h handle (used for configuration)
- * @param sa the address of the peer (IPv4-only)
- * @return #GNUNET_SYSERR on error, #GNUNET_NO if nat client is disabled,
- *         #GNUNET_OK otherwise
- */
-int
-GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h,
-                       const struct sockaddr_in *sa);
-
-
-/**
- * Stop port redirection and public IP address detection for the given
- * handle.  This frees the handle, after having sent the needed
- * commands to close open ports.
- *
- * @param h the handle to stop
- */
-void
-GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h);
-
-
-/**
- * Handle to a NAT test.
- */
-struct GNUNET_NAT_Test;
-
-
-/**
- * Function called to report success or failure for
- * NAT configuration test.
- *
- * @param cls closure
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-typedef void (*GNUNET_NAT_TestCallback) (void *cls,
-                                         enum GNUNET_NAT_StatusCode result);
-
-
-/**
- * Start testing if NAT traversal works using the
- * given configuration (IPv4-only).
- *
- * @param cfg configuration for the NAT traversal
- * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
- * @param bnd_port port to bind to, 0 for connection reversal
- * @param adv_port externally advertised port to use
- * @param timeout delay after which the test should be aborted
- * @param report function to call with the result of the test;
- *               you still must call #GNUNET_NAT_test_stop().
- * @param report_cls closure for @a report
- * @return handle to cancel NAT test
- */
-struct GNUNET_NAT_Test *
-GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                       int is_tcp,
-                       uint16_t bnd_port,
-                       uint16_t adv_port,
-                       struct GNUNET_TIME_Relative timeout,
-                       GNUNET_NAT_TestCallback report,
-                       void *report_cls);
-
-
-/**
- * Stop an active NAT test.
- *
- * @param tst test to stop.
- */
-void
-GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst);
-
-
-/**
- * Signature of a callback that is given an IP address.
- *
- * @param cls closure
- * @param addr the address, NULL on errors
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-typedef void
-(*GNUNET_NAT_IPCallback) (void *cls,
-                          const struct in_addr *addr,
-                          enum GNUNET_NAT_StatusCode result);
-
-
-/**
- * Opaque handle to cancel #GNUNET_NAT_mini_get_external_ipv4() operation.
- */
-struct GNUNET_NAT_ExternalHandle;
-
-
-/**
- * Try to get the external IPv4 address of this peer.
- *
- * @param timeout when to fail
- * @param cb function to call with result
- * @param cb_cls closure for @a cb
- * @return handle for cancellation (can only be used until @a cb is called), NULL on error
- */
-struct GNUNET_NAT_ExternalHandle *
-GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout,
-                                   GNUNET_NAT_IPCallback cb,
-                                   void *cb_cls);
-
-
-/**
- * Cancel operation.
- *
- * @param eh operation to cancel
- */
-void
-GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh);
-
-
-/**
- * Handle to a mapping created with upnpc.
- */
-struct GNUNET_NAT_MiniHandle;
-
-
-/**
- * Signature of the callback passed to #GNUNET_NAT_register() for
- * a function to call whenever our set of 'valid' addresses changes.
- *
- * @param cls closure
- * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
- *     the previous (now invalid) one, #GNUNET_SYSERR indicates an error
- * @param addr either the previous or the new public IP address
- * @param addrlen actual length of the @a addr
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-typedef void
-(*GNUNET_NAT_MiniAddressCallback) (void *cls,
-                                   int add_remove,
-                                   const struct sockaddr *addr,
-                                   socklen_t addrlen,
-                                   enum GNUNET_NAT_StatusCode result);
-
-
-/**
- * Start mapping the given port using (mini)upnpc.  This function
- * should typically not be used directly (it is used within the
- * general-purpose #GNUNET_NAT_register() code).  However, it can be
- * used if specifically UPnP-based NAT traversal is to be used or
- * tested.
- *
- * @param port port to map
- * @param is_tcp #GNUNET_YES to map TCP, #GNUNET_NO for UDP
- * @param ac function to call with mapping result
- * @param ac_cls closure for @a ac
- * @return NULL on error
- */
-struct GNUNET_NAT_MiniHandle *
-GNUNET_NAT_mini_map_start (uint16_t port,
-                           int is_tcp,
-                           GNUNET_NAT_MiniAddressCallback ac,
-                           void *ac_cls);
-
-
-/**
- * Remove a mapping created with (mini)upnpc.  Calling
- * this function will give 'upnpc' 1s to remove the mapping,
- * so while this function is non-blocking, a task will be
- * left with the scheduler for up to 1s past this call.
- *
- * @param mini the handle
- */
-void
-GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini);
-
-
-/**
- * Handle to auto-configuration in progress.
- */
-struct GNUNET_NAT_AutoHandle;
-
-
-/**
- * Function called with the result from the autoconfiguration.
- *
- * @param cls closure
- * @param diff minimal suggested changes to the original configuration
- *             to make it work (as best as we can)
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- * @param type what the situation of the NAT
- */
-typedef void
-(*GNUNET_NAT_AutoResultCallback)(void *cls,
-                                 const struct GNUNET_CONFIGURATION_Handle *diff,
-                                 enum GNUNET_NAT_StatusCode result,
-                                 enum GNUNET_NAT_Type type);
-
-
-/**
- * Start auto-configuration routine.  The resolver service should
- * be available when this function is called.
- *
- * @param cfg initial configuration
- * @param cb function to call with autoconfiguration result
- * @param cb_cls closure for @a cb
- * @return handle to cancel operation
- */
-struct GNUNET_NAT_AutoHandle *
-GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                            GNUNET_NAT_AutoResultCallback cb,
-                            void *cb_cls);
-
-
-/**
- * Abort autoconfiguration.
- *
- * @param ah handle for operation to abort
- */
-void
-GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah);
-
-/**
- * Handle for active STUN Requests.
- */
-struct GNUNET_NAT_STUN_Handle;
-
-
-/**
- * Function called with the result if an error happened during STUN request.
- *
- * @param cls closure
- * @param result the specific error code
- */
-typedef void
-(*GNUNET_NAT_STUN_ErrorCallback)(void *cls,
-                                 enum GNUNET_NAT_StatusCode error);
-
-
-/**
- * Handle to a request given to the resolver.  Can be used to cancel
- * the request prior to the timeout or successful execution.  Also
- * used to track our internal state for the request.
- */
-struct GNUNET_NAT_STUN_Handle;
-
-
-/**
- * Make generic STUN request.  Sends a generic stun request to the
- * server specified using the specified socket.  The caller must
- * wait for a reply on the @a sock and call
- * #GNUNET_NAT_stun_handle_packet() if a reply is received.
- *
- * @param server the address of the stun server
- * @param port port of the stun server
- * @param sock the socket used to send the request
- * @param cb callback in case of error (or completion)
- * @param cb_cls closure for @a cb
- * @return NULL on error
- */
-struct GNUNET_NAT_STUN_Handle *
-GNUNET_NAT_stun_make_request (const char *server,
-                              uint16_t port,
-                              struct GNUNET_NETWORK_Handle *sock,
-                              GNUNET_NAT_STUN_ErrorCallback cb,
-                              void *cb_cls);
-
-
-/**
- * Cancel active STUN request. Frees associated resources
- * and ensures that the callback is no longer invoked.
- *
- * @param rh request to cancel
- */
-void
-GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh);
-
-
-/**
- * Handle an incoming STUN message. Do some basic sanity checks on
- * packet size and content, try to extract a bit of information, and
- * possibly reply.  At the moment this only processes BIND requests,
- * and returns the externally visible address of the request.  If a
- * callback is specified, invoke it with the attribute.
- *
- * @param data the packet
- * @param len the length of the packet
- * @param arg sockaddr_in where we will set our discovered packet
- * @return #GNUNET_OK on OK,
- *          #GNUNET_NO if the packet is not a stun packet
- */
-int
-GNUNET_NAT_stun_handle_packet (const void *data,
-                               size_t len,
-                               struct sockaddr_in *arg);
-
-
-/**
- * CHECK if is a valid STUN packet sending to #GNUNET_NAT_stun_handle_packet().
- * It also check if it can handle the packet based on the NAT handler.
- * You don't need to call anything else to check if the packet is valid,
- *
- * @param cls the NAT handle
- * @param data packet
- * @param len length of @a data
- * @return #GNUNET_NO if it can't decode, #GNUNET_YES if is a packet
- */
-int
-GNUNET_NAT_is_valid_stun_packet (void *cls,
-                                 const void *data,
-                                 size_t len);
-
-
-#endif
-
-/** @} */  /* end of group */
-
-/* end of gnunet_nat_lib.h */
index 1620c9433fd5644bdd12cd5a8a4de16852a8c772..e758452073306ed18f0f2b094aa6c2335ea8991e 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2007-2016 GNUnet e.V.
+     Copyright (C) 2007-2017 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -122,6 +122,12 @@ enum GNUNET_NAT_AddressClass
    */
   GNUNET_NAT_AC_EXTERN = 128,
 
+  /**
+   * Addresses that were manually configured by the user.
+   * Used as a bit in combination with #GNUNET_NAT_AC_GLOBAL.
+   */
+  GNUNET_NAT_AC_MANUAL = 256,
+
   /**
    * Bitmask for "any" address.
    */
@@ -130,6 +136,144 @@ enum GNUNET_NAT_AddressClass
 };
 
 
+/**
+ * Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
+ */
+enum GNUNET_NAT_StatusCode
+{
+  /**
+   * Just the default
+   */
+  GNUNET_NAT_ERROR_SUCCESS = GNUNET_OK,
+
+  /**
+   * IPC Failure
+   */
+  GNUNET_NAT_ERROR_IPC_FAILURE,
+
+  /**
+   * Failure in network subsystem, check permissions
+   */
+  GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR,
+
+  /**
+   * test timed out
+   */
+  GNUNET_NAT_ERROR_TIMEOUT,
+
+  /**
+   * detected that we are offline
+   */
+  GNUNET_NAT_ERROR_NOT_ONLINE,
+
+  /**
+   * `upnpc` command not found
+   */
+  GNUNET_NAT_ERROR_UPNPC_NOT_FOUND,
+
+  /**
+   * Failed to run `upnpc` command
+   */
+  GNUNET_NAT_ERROR_UPNPC_FAILED,
+
+  /**
+   * `upnpc' command took too long, process killed
+   */
+  GNUNET_NAT_ERROR_UPNPC_TIMEOUT,
+
+  /**
+   * `upnpc' command failed to establish port mapping
+   */
+  GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED,
+
+  /**
+   * `external-ip' command not found
+   */
+  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND,
+
+  /**
+   * Failed to run `external-ip` command
+   */
+  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED,
+
+  /**
+   * `external-ip' command output invalid
+   */
+  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID,
+
+  /**
+   * "no valid address was returned by `external-ip'"
+   */
+  GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID,
+
+  /**
+   * Could not determine interface with internal/local network address
+   */
+  GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO,
+
+  /**
+   * No working gnunet-helper-nat-server found
+   */
+  GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND,
+
+  /**
+   * NAT test could not be initialized
+   */
+  GNUNET_NAT_ERROR_NAT_TEST_START_FAILED,
+
+  /**
+   * NAT test timeout
+   */
+  GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT,
+
+  /**
+   * NAT test failed to initiate
+   */
+  GNUNET_NAT_ERROR_NAT_REGISTER_FAILED,
+
+  /**
+   *
+   */
+  GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND
+  
+};
+
+
+
+/**
+ * What the situation of the NAT connectivity
+ */
+enum GNUNET_NAT_Type
+{
+  /**
+   * We have a direct connection
+   */
+  GNUNET_NAT_TYPE_NO_NAT = GNUNET_OK,
+
+  /**
+   * We are under a NAT but cannot traverse it
+   */
+  GNUNET_NAT_TYPE_UNREACHABLE_NAT,
+
+  /**
+   * We can traverse using STUN
+   */
+  GNUNET_NAT_TYPE_STUN_PUNCHED_NAT,
+
+  /**
+   * We can traverse using UPNP
+   */
+  GNUNET_NAT_TYPE_UPNP_NAT,
+
+  /**
+   * We know nothing about the NAT.
+   */
+  GNUNET_NAT_TYPE_UNKNOWN
+
+};
+
+
+
 /**
  * Signature of the callback passed to #GNUNET_NAT_register() for
  * a function to call whenever our set of 'valid' addresses changes.
@@ -179,8 +323,8 @@ struct GNUNET_NAT_Handle;
  * address_callback for any 'plausible' external address.
  *
  * @param cfg configuration to use
+ * @param config_section name of the configuration section for options
  * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
- * @param hole_external hostname and port of manually punched hole in NAT, otherwise NULL (or empty string)
  * @param num_addrs number of addresses in @a addrs
  * @param addrs list of local addresses packets should be redirected to
  * @param addrlens actual lengths of the addresses in @a addrs
@@ -192,8 +336,8 @@ struct GNUNET_NAT_Handle;
  */
 struct GNUNET_NAT_Handle *
 GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                     const char *config_section,
                      uint8_t proto,
-                     const char *hole_external,
                      unsigned int num_addrs,
                      const struct sockaddr **addrs,
                      const socklen_t *addrlens,
@@ -250,127 +394,6 @@ void
 GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh);
 
 
-/**
- * Handle to a NAT test.
- */
-struct GNUNET_NAT_Test;
-
-
-/**
- * Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
- */
-enum GNUNET_NAT_StatusCode
-{
-  /**
-   * Just the default
-   */
-  GNUNET_NAT_ERROR_SUCCESS = GNUNET_OK,
-
-  /**
-   * IPC Failure
-   */
-  GNUNET_NAT_ERROR_IPC_FAILURE,
-
-  /**
-   * Failure in network subsystem, check permissions
-   */
-  GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR,
-
-  /**
-   * test timed out
-   */
-  GNUNET_NAT_ERROR_TIMEOUT,
-
-  /**
-   * detected that we are offline
-   */
-  GNUNET_NAT_ERROR_NOT_ONLINE,
-
-  /**
-   * `upnpc` command not found
-   */
-  GNUNET_NAT_ERROR_UPNPC_NOT_FOUND,
-
-  /**
-   * Failed to run `upnpc` command
-   */
-  GNUNET_NAT_ERROR_UPNPC_FAILED,
-
-  /**
-   * `upnpc' command took too long, process killed
-   */
-  GNUNET_NAT_ERROR_UPNPC_TIMEOUT,
-
-  /**
-   * `upnpc' command failed to establish port mapping
-   */
-  GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED,
-
-  /**
-   * `external-ip' command not found
-   */
-  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND,
-
-  /**
-   * Failed to run `external-ip` command
-   */
-  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED,
-
-  /**
-   * `external-ip' command output invalid
-   */
-  GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID,
-
-  /**
-   * "no valid address was returned by `external-ip'"
-   */
-  GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID,
-
-  /**
-   * Could not determine interface with internal/local network address
-   */
-  GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO,
-
-  /**
-   * No working gnunet-helper-nat-server found
-   */
-  GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND,
-
-  /**
-   * NAT test could not be initialized
-   */
-  GNUNET_NAT_ERROR_NAT_TEST_START_FAILED,
-
-  /**
-   * NAT test timeout
-   */
-  GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT,
-
-  /**
-   * NAT test failed to initiate
-   */
-  GNUNET_NAT_ERROR_NAT_REGISTER_FAILED,
-
-  /**
-   *
-   */
-  GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND
-  
-};
-
-
-/**
- * Function called to report success or failure for
- * NAT configuration test.
- *
- * @param cls closure
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-typedef void
-(*GNUNET_NAT_TestCallback) (void *cls,
-                           enum GNUNET_NAT_StatusCode result);
-
-
 /**
  * Handle an incoming STUN message.  This function is useful as
  * some GNUnet service may be listening on a UDP port and might
@@ -410,6 +433,18 @@ GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
 struct GNUNET_NAT_STUN_Handle;
 
 
+/**
+ * Function called to report success or failure for
+ * NAT configuration test.
+ *
+ * @param cls closure
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ */
+typedef void
+(*GNUNET_NAT_TestCallback) (void *cls,
+                           enum GNUNET_NAT_StatusCode result);
+
+
 /**
  * Make Generic STUN request. Sends a generic stun request to the
  * server specified using the specified socket.  If we do this,
@@ -442,130 +477,6 @@ void
 GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh);
 
 
-/**
- * Start testing if NAT traversal works using the given configuration
- * (IPv4-only).  The transport adapters should be down while using
- * this function.
- *
- * @param cfg configuration for the NAT traversal
- * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
- * @param bind_ip IPv4 address to bind to
- * @param bnd_port port to bind to, 0 to test connection reversal
- * @param extern_ip IPv4 address to externally advertise
- * @param extern_port externally advertised port to use
- * @param report function to call with the result of the test
- * @param report_cls closure for @a report
- * @return handle to cancel NAT test
- */
-struct GNUNET_NAT_Test *
-GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                       uint8_t proto,
-                      struct in_addr bind_ip,
-                       uint16_t bnd_port,
-                      struct in_addr extern_ip,
-                       uint16_t extern_port,
-                       GNUNET_NAT_TestCallback report,
-                       void *report_cls);
-
-
-/**
- * Stop an active NAT test.
- *
- * @param tst test to stop.
- */
-void
-GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst);
-
-
-/**
- * Handle to auto-configuration in progress.
- */
-struct GNUNET_NAT_AutoHandle;
-
-
-/**
- * What the situation of the NAT connectivity
- */
-enum GNUNET_NAT_Type
-{
-  /**
-   * We have a direct connection
-   */
-  GNUNET_NAT_TYPE_NO_NAT = GNUNET_OK,
-
-  /**
-   * We are under a NAT but cannot traverse it
-   */
-  GNUNET_NAT_TYPE_UNREACHABLE_NAT,
-
-  /**
-   * We can traverse using STUN
-   */
-  GNUNET_NAT_TYPE_STUN_PUNCHED_NAT,
-
-  /**
-   * We can traverse using UPNP
-   */
-  GNUNET_NAT_TYPE_UPNP_NAT,
-
-  /**
-   * We know nothing about the NAT.
-   */
-  GNUNET_NAT_TYPE_UNKNOWN
-
-};
-
-
-/**
- * Converts `enum GNUNET_NAT_StatusCode` to string
- *
- * @param err error code to resolve to a string
- * @return point to a static string containing the error code
- */
-const char *
-GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err);
-
-
-/**
- * Function called with the result from the autoconfiguration.
- *
- * @param cls closure
- * @param diff minimal suggested changes to the original configuration
- *             to make it work (as best as we can)
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- * @param type what the situation of the NAT
- */
-typedef void
-(*GNUNET_NAT_AutoResultCallback)(void *cls,
-                                 const struct GNUNET_CONFIGURATION_Handle *diff,
-                                 enum GNUNET_NAT_StatusCode result,
-                                 enum GNUNET_NAT_Type type);
-
-
-/**
- * Start auto-configuration routine.  The transport adapters should
- * be stopped while this function is called.
- *
- * @param cfg initial configuration
- * @param cb function to call with autoconfiguration result
- * @param cb_cls closure for @a cb
- * @return handle to cancel operation
- */
-struct GNUNET_NAT_AutoHandle *
-GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                            GNUNET_NAT_AutoResultCallback cb,
-                            void *cb_cls);
-
-
-/**
- * Abort autoconfiguration.
- *
- * @param ah handle for operation to abort
- */
-void
-GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah);
-
-
 #endif
 
 /** @} */  /* end of group */
index 44df483a08fe431688e468bd52ec1c47f6eb67bc..b5c2153ac4982b71eab9df29b5346cf3de0ced8f 100644 (file)
@@ -101,7 +101,7 @@ GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h);
 struct GNUNET_MQ_Envelope *
 GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h,
                           const struct GNUNET_HELLO_Message *hello,
-                         GNUNET_MQ_NotifyCallback cont,
+                         GNUNET_SCHEDULER_TaskCallback cont,
                          void *cont_cls);
 
 
index cf26f1727c243a31db59cebbd7dce572e14390f2..e31b1f33cb4b8b077a4db55c0d34d2b68d60b6b1 100644 (file)
@@ -2645,7 +2645,7 @@ extern "C"
 /**
  * Send origin an ACK that the connection is complete
  */
-#define GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK 1001
+#define GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK 1001
 
 /**
  * Notify that a connection is no longer valid
@@ -2660,49 +2660,53 @@ extern "C"
 /**
  * At some point, the route will spontaneously change TODO
  */
-#define GNUNET_MESSAGE_TYPE_CADET_PATH_CHANGED 1004
+#define GNUNET_MESSAGE_TYPE_CADET_CONNECTION_PATH_CHANGED_UNIMPLEMENTED 1004
 
 /**
  * Hop-by-hop, connection dependent ACK.
  */
-#define GNUNET_MESSAGE_TYPE_CADET_ACK 1005
+#define GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK 1005
 
 /**
- * Poll for a hop-by-hop ACK.
+ * Axolotl key exchange.
  */
-#define GNUNET_MESSAGE_TYPE_CADET_POLL 1006
+#define GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX 1007
 
 /**
- * Key exchange encapsulation.
+ * Axolotl encrypted data.
  */
-#define GNUNET_MESSAGE_TYPE_CADET_KX 1007
+#define GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED 1008
 
 /**
- * Axolotl encrypted data.
+ * We do not bother with ACKs for
+ * #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED messages, but we instead
+ * poll for one if we got nothing for a while and start to be worried.
  */
-#define GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED 1008
+#define GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL 1006
+
+
 
 /**********************************  Channel  *********************************/
 
 /**
  * Payload data (inside an encrypted tunnel).
  */
-#define GNUNET_MESSAGE_TYPE_CADET_DATA 1010
+#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA 1010
 
 /**
  * Confirm payload data end-to-end.
  */
-#define GNUNET_MESSAGE_TYPE_CADET_DATA_ACK 1011
+#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK 1011
 
 /**
  * Announce connection is still alive (direction sensitive).
  */
-#define GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE 1012
+#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE 1012
 
 /**
  * Ask the cadet service to create a new channel.
  */
-#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE 1013
+#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN 1013
 
 /**
  * Ask the cadet service to destroy a channel.
@@ -2712,12 +2716,12 @@ extern "C"
 /**
  * Confirm the creation of a channel
  */
-#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK 1015
+#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK 1015
 
 /**
  * Reject the creation of a channel
  */
-#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK 1016
+#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED 1016
 
 /***********************************  Local  **********************************/
 
@@ -2789,6 +2793,11 @@ extern "C"
  */
 #define GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP 1038
 
+/**
+ * End of local information about all peers known to the service.
+ */
+#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END 1039
+
 /********************************  Application  *******************************/
 
 /**
@@ -2833,7 +2842,7 @@ extern "C"
 /**
  * Message to ask NAT service to request autoconfiguration.
  */
-#define GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG 1067
+#define GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG 1067
 
 /**
  * Message from NAT service with the autoconfiguration result.
@@ -2841,8 +2850,31 @@ extern "C"
 #define GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT 1068
 
 
+/* 1080-1109 reserved for TMCG (Heiko Stamer, see gnunet-developers, January 2017) */
+
+
+/******************************************************************************/
+/***********************************  AUCTION  ********************************/
+/******************************************************************************/
+
+/**
+ * Client wants to create a new auction.
+ */
+#define GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_CREATE 1110
+
+/**
+ * Client wants to join an existing auction.
+ */
+#define GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_JOIN 1111
+
+/**
+ * Service reports the auction outcome to the client.
+ */
+#define GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_OUTCOME 1112
+
+
 /**
- * Next available: 1080
+ * Next available: 1130
  */
 
 
index 353287cbf37fceebbb99faf03d22a3103a7544d9..03bc4575ed52f1e7c7698430b683e929415f8e0e 100644 (file)
@@ -150,11 +150,6 @@ extern "C"
  */
 #define GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING 20
 
-/**
- * Key exchange in CADET
- */
-#define GNUNET_SIGNATURE_PURPOSE_CADET_KX 21
-
 /**
  * Signature for the first round of distributed key generation.
  */
diff --git a/src/json/.gitignore b/src/json/.gitignore
new file mode 100644 (file)
index 0000000..6709c74
--- /dev/null
@@ -0,0 +1 @@
+test_json
diff --git a/src/jsonapi/.gitignore b/src/jsonapi/.gitignore
new file mode 100644 (file)
index 0000000..0776069
--- /dev/null
@@ -0,0 +1 @@
+test_jsonapi
index e84fdb20f3116447a126f5fac5741e3d528fec6a..de65e0ab743a773531cffefefca95a81ce17dfbd 100644 (file)
@@ -710,15 +710,19 @@ cadet_notify_transmit_ready (void *cls, size_t buf_size, void *buf)
 static void
 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
 {
+  uint16_t msg_size = ntohs (msg->size);
+  struct GNUNET_MessageHeader *msg_copy = GNUNET_malloc (msg_size);
+  GNUNET_memcpy (msg_copy, msg, msg_size);
+
   struct CadetTransmitClosure *tcls = GNUNET_malloc (sizeof (*tcls));
   tcls->chn = chn;
-  tcls->msg = msg;
+  tcls->msg = msg_copy;
 
   chn->msgs_pending++;
   chn->tmit_handle
     = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO,
                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                          ntohs (msg->size),
+                                          msg_size,
                                           &cadet_notify_transmit_ready,
                                           tcls);
   GNUNET_assert (NULL != chn->tmit_handle);
@@ -783,9 +787,21 @@ cadet_send_join_decision_cb (void *cls,
   const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
   struct Channel *chn = channel;
 
+  const struct MulticastJoinDecisionMessage *dcsn = 
+    (struct MulticastJoinDecisionMessage *) &hdcsn[1];
+
   if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
       && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
   {
+    if (GNUNET_YES == ntohl (dcsn->is_admitted))
+    {
+      chn->join_status = JOIN_ADMITTED;
+    }
+    else
+    {
+      chn->join_status = JOIN_REFUSED;
+    }
+
     cadet_send_channel (chn, &hdcsn->header);
     return GNUNET_NO;
   }
@@ -1019,6 +1035,7 @@ handle_client_member_join (void *cls,
   if (NULL == mem)
   {
     mem = GNUNET_new (struct Member);
+    mem->origin = msg->origin;
     mem->priv_key = msg->member_key;
     mem->pub_key = mem_pub_key;
     mem->pub_key_hash = mem_pub_key_hash;
@@ -1083,9 +1100,10 @@ handle_client_member_join (void *cls,
       join_msg_size = ntohs (join_msg->size);
     }
 
+    uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
     struct MulticastJoinRequestMessage *
-      req = GNUNET_malloc (sizeof (*req) + join_msg_size);
-    req->header.size = htons (sizeof (*req) + join_msg_size);
+      req = GNUNET_malloc (req_msg_size);
+    req->header.size = htons (req_msg_size);
     req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
     req->group_pub_key = grp->pub_key;
     req->peer = this_peer;
@@ -1094,7 +1112,7 @@ handle_client_member_join (void *cls,
       GNUNET_memcpy (&req[1], join_msg, join_msg_size);
 
     req->member_pub_key = mem->pub_key;
-    req->purpose.size = htonl (msg_size
+    req->purpose.size = htonl (req_msg_size
                                - sizeof (req->header)
                                - sizeof (req->reserved)
                                - sizeof (req->signature));
@@ -1534,6 +1552,7 @@ cadet_recv_join_request (void *cls,
                          void **ctx,
                          const struct GNUNET_MessageHeader *m)
 {
+  GNUNET_CADET_receive_done(channel);
   const struct MulticastJoinRequestMessage *
     req = (const struct MulticastJoinRequestMessage *) m;
   uint16_t size = ntohs (m->size);
@@ -1576,6 +1595,7 @@ cadet_recv_join_request (void *cls,
   chn->join_status = JOIN_WAITING;
   GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_pub_hash, chn,
                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+  *ctx = chn;
 
   client_send_all (&group_pub_hash, m);
   return GNUNET_OK;
@@ -1591,10 +1611,14 @@ cadet_recv_join_decision (void *cls,
                           void **ctx,
                           const struct GNUNET_MessageHeader *m)
 {
+  GNUNET_CADET_receive_done (channel);
+  const struct MulticastJoinDecisionMessageHeader *
+    hdcsn = (const struct MulticastJoinDecisionMessageHeader *) m;
   const struct MulticastJoinDecisionMessage *
-    dcsn = (const struct MulticastJoinDecisionMessage *) m;
+    dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
   uint16_t size = ntohs (m->size);
-  if (size < sizeof (*dcsn))
+  if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
+             sizeof (struct MulticastJoinDecisionMessage))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
@@ -1623,15 +1647,10 @@ cadet_recv_join_decision (void *cls,
     break;
   }
 
-  struct MulticastJoinDecisionMessageHeader *
-    hdcsn = GNUNET_malloc (sizeof (*hdcsn) + size);
-  hdcsn->peer = chn->peer;
-  GNUNET_memcpy (&hdcsn[1], dcsn, sizeof (*hdcsn) + size);
-
+  // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
   struct Member *mem = (struct Member *) chn->group;
   client_send_join_decision (mem, hdcsn);
-  GNUNET_free (hdcsn);
-  if (GNUNET_YES == ntohs (dcsn->is_admitted))
+  if (GNUNET_YES == ntohl (dcsn->is_admitted))
   {
     chn->join_status = JOIN_ADMITTED;
     return GNUNET_OK;
@@ -1652,6 +1671,7 @@ cadet_recv_message (void *cls,
                     void **ctx,
                     const struct GNUNET_MessageHeader *m)
 {
+  GNUNET_CADET_receive_done(channel);
   const struct GNUNET_MULTICAST_MessageHeader *
     msg = (const struct GNUNET_MULTICAST_MessageHeader *) m;
   uint16_t size = ntohs (m->size);
@@ -1697,6 +1717,7 @@ cadet_recv_request (void *cls,
                     void **ctx,
                     const struct GNUNET_MessageHeader *m)
 {
+  GNUNET_CADET_receive_done(channel);
   const struct GNUNET_MULTICAST_RequestHeader *
     req = (const struct GNUNET_MULTICAST_RequestHeader *) m;
   uint16_t size = ntohs (m->size);
@@ -1742,6 +1763,7 @@ cadet_recv_replay_request (void *cls,
                            void **ctx,
                            const struct GNUNET_MessageHeader *m)
 {
+  GNUNET_CADET_receive_done(channel);
   struct MulticastReplayRequestMessage rep;
   uint16_t size = ntohs (m->size);
   if (size < sizeof (rep))
@@ -1784,6 +1806,7 @@ cadet_recv_replay_response (void *cls,
                             void **ctx,
                             const struct GNUNET_MessageHeader *m)
 {
+  GNUNET_CADET_receive_done(channel);
   //struct Channel *chn = *ctx;
 
   /* @todo FIXME: got replay error response, send request to other members */
@@ -1882,6 +1905,9 @@ static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
   { cadet_recv_join_request,
     GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 },
 
+  { cadet_recv_join_decision,
+    GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
+
   { cadet_recv_message,
     GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
 
index 7cfe708359db25b447ffc246f3ffcb21ed38c69f..a8b1dee40ecd95b82ec66374aaed34e46d4c0f41 100644 (file)
@@ -556,7 +556,7 @@ group_disconnect (struct GNUNET_MULTICAST_Group *grp,
     if (NULL != last)
     {
       GNUNET_MQ_notify_sent (last,
-                             (GNUNET_MQ_NotifyCallback) group_cleanup, grp);
+                             (GNUNET_SCHEDULER_TaskCallback) group_cleanup, grp);
     }
     else
     {
@@ -786,7 +786,7 @@ origin_connect (struct GNUNET_MULTICAST_Origin *orig)
     GNUNET_MQ_handler_end ()
   };
 
-  grp->mq = GNUNET_CLIENT_connecT (grp->cfg, "multicast",
+  grp->mq = GNUNET_CLIENT_connect (grp->cfg, "multicast",
                                    handlers, origin_disconnected, orig);
   GNUNET_assert (NULL != grp->mq);
   GNUNET_MQ_send_copy (grp->mq, grp->connect_env);
@@ -1076,7 +1076,7 @@ member_connect (struct GNUNET_MULTICAST_Member *mem)
     GNUNET_MQ_handler_end ()
   };
 
-  grp->mq = GNUNET_CLIENT_connecT (grp->cfg, "multicast",
+  grp->mq = GNUNET_CLIENT_connect (grp->cfg, "multicast",
                                    handlers, member_disconnected, mem);
   GNUNET_assert (NULL != grp->mq);
   GNUNET_MQ_send_copy (grp->mq, grp->connect_env);
diff --git a/src/my/.gitignore b/src/my/.gitignore
new file mode 100644 (file)
index 0000000..3338ba2
--- /dev/null
@@ -0,0 +1 @@
+test_my
index 7f6924c27cd6686a10c4a4add56d3181e2b9e7af..6d2d8488a9bad25424b0b46d67fb27ad840f4b5b 100644 (file)
@@ -1,2 +1,6 @@
 gnunet-service-namecache
 gnunet-namecache
+test_namecache_api_cache_block
+test_plugin_namecache_postgres
+test_plugin_namecache_sqlite
+zonefiles
index 9ccb91bc878ca4d43f4220ac7544646207590f33..c12dacd4c00744536adbe90ba6acf2458b2d0c34 100644 (file)
@@ -336,7 +336,7 @@ reconnect (struct GNUNET_NAMECACHE_Handle *h)
     GNUNET_MQ_handler_end ()
   };
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "namecache",
                                  handlers,
                                  &mq_error_handler,
index 15482dd6955ee16cfe051b24635a2646aa704da5..a1153c6f9b515a5e50499a3a1cd6af63fc8b2511 100644 (file)
@@ -1,3 +1,20 @@
 gnunet-service-namestore
 gnunet-namestore
 gnunet-namestore-fcfsd
+test_namestore_api_lookup_nick
+test_namestore_api_lookup_private
+test_namestore_api_lookup_public
+test_namestore_api_lookup_shadow
+test_namestore_api_lookup_shadow_filter
+test_namestore_api_monitoring
+test_namestore_api_monitoring_existing
+test_namestore_api_remove
+test_namestore_api_remove_not_existing_record
+test_namestore_api_store
+test_namestore_api_store_update
+test_namestore_api_zone_iteration
+test_namestore_api_zone_iteration_nick
+test_namestore_api_zone_iteration_specific_zone
+test_namestore_api_zone_iteration_stop
+test_plugin_namestore_postgres
+test_plugin_namestore_sqlite
index fd232de812f93d7477f92e55755206888462991c..933ba7b950d808506f4483d3d6d108f910b73385 100644 (file)
@@ -806,7 +806,7 @@ reconnect (struct GNUNET_NAMESTORE_Handle *h)
   struct GNUNET_NAMESTORE_QueueEntry *qe;
 
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "namestore",
                                  handlers,
                                  &mq_error_handler,
index 00f0887d47bfd1287325515c20f79aeb7434a678..cd7c7dadba1793a1dccfe83c945863c47aa9c7df 100644 (file)
@@ -262,7 +262,7 @@ reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm)
     GNUNET_MQ_destroy (zm->mq);
     zm->error_cb (zm->error_cb_cls);
   }
-  zm->mq = GNUNET_CLIENT_connecT (zm->cfg,
+  zm->mq = GNUNET_CLIENT_connect (zm->cfg,
                                   "namestore",
                                   handlers,
                                   &mq_error_handler,
diff --git a/src/nat-auto/.gitignore b/src/nat-auto/.gitignore
new file mode 100644 (file)
index 0000000..6ba53d7
--- /dev/null
@@ -0,0 +1,3 @@
+gnunet-service-nat-auto
+gnunet-nat-auto
+gnunet-nat-server
diff --git a/src/nat-auto/Makefile.am b/src/nat-auto/Makefile.am
new file mode 100644 (file)
index 0000000..19695fa
--- /dev/null
@@ -0,0 +1,58 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+pkgcfg_DATA = \
+  nat-auto.conf
+
+bin_PROGRAMS = \
+ gnunet-nat-auto \
+ gnunet-nat-server
+
+libexec_PROGRAMS = \
+ gnunet-service-nat-auto
+
+gnunet_nat_server_SOURCES = \
+ gnunet-nat-server.c nat-auto.h
+gnunet_nat_server_LDADD = \
+  $(top_builddir)/src/nat/libgnunetnatnew.la \
+  $(top_builddir)/src/util/libgnunetutil.la
+
+gnunet_nat_auto_SOURCES = \
+  gnunet-nat-auto.c nat-auto.h
+gnunet_nat_auto_LDADD = \
+  libgnunetnatauto.la \
+  $(top_builddir)/src/util/libgnunetutil.la
+
+
+if USE_COVERAGE
+  AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+lib_LTLIBRARIES = \
+  libgnunetnatauto.la
+
+libgnunetnatauto_la_SOURCES = \
+  nat_auto_api.c \
+  nat_auto_api_test.c 
+libgnunetnatauto_la_LIBADD = \
+  $(top_builddir)/src/nat/libgnunetnatnew.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(GN_LIBINTL) @EXT_LIBS@ 
+libgnunetnatauto_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS) $(WINFLAGS) \
+  -version-info 0:0:0
+
+gnunet_service_nat_auto_SOURCES = \
+ gnunet-service-nat-auto.c
+gnunet_service_nat_auto_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/nat/libgnunetnatnew.la \
+  $(LIBGCRYPT_LIBS) \
+  -lgcrypt \
+  $(GN_LIBINTL)
+
diff --git a/src/nat-auto/gnunet-nat-auto.c b/src/nat-auto/gnunet-nat-auto.c
new file mode 100644 (file)
index 0000000..9ba81eb
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2015, 2016, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file src/nat/gnunet-nat-auto.c
+ * @brief Command-line tool for testing and autoconfiguration of NAT traversal
+ * @author Christian Grothoff
+ * @author Bruno Cabral
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_nat_service.h"
+#include "gnunet_nat_auto_service.h"
+
+/**
+ * Value to return from #main().
+ */
+static int global_ret;
+
+/**
+ * Handle to ongoing autoconfiguration.
+ */
+static struct GNUNET_NAT_AUTO_AutoHandle *ah;
+
+/**
+ * If we do auto-configuration, should we write the result
+ * to a file?
+ */
+static int write_cfg;
+
+/**
+ * Configuration filename.
+ */
+static const char *cfg_file;
+
+/**
+ * Original configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Adapter we are supposed to test.
+ */
+static char *section_name;
+
+/**
+ * Should we run autoconfiguration?
+ */
+static unsigned int do_auto;
+
+/**
+ * Handle to a NAT test operation.
+ */
+static struct GNUNET_NAT_AUTO_Test *nt;
+
+/**
+ * Flag set to 1 if we use IPPROTO_UDP.
+ */
+static int use_udp;
+
+/**
+ * Flag set to 1 if we use IPPROTO_TCP.
+ */
+static int use_tcp;
+
+/**
+ * Protocol to use.
+ */
+static uint8_t proto;
+
+/**
+ * Test if all activities have finished, and if so,
+ * terminate.
+ */
+static void
+test_finished ()
+{
+  if (NULL != ah)
+    return;
+  if (NULL != nt)
+    return;
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Function to iterate over sugested changes options
+ *
+ * @param cls closure
+ * @param section name of the section
+ * @param option name of the option
+ * @param value value of the option
+ */
+static void
+auto_conf_iter (void *cls,
+                const char *section,
+                const char *option,
+                const char *value)
+{
+  struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
+
+  PRINTF ("%s: %s\n",
+         option,
+         value);
+  if (NULL != new_cfg)
+    GNUNET_CONFIGURATION_set_value_string (new_cfg,
+                                          section,
+                                          option,
+                                          value);
+}
+
+
+/**
+ * Function called with the result from the autoconfiguration.
+ *
+ * @param cls closure
+ * @param diff minimal suggested changes to the original configuration
+ *             to make it work (as best as we can)
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ * @param type what the situation of the NAT
+ */
+static void
+auto_config_cb (void *cls,
+               const struct GNUNET_CONFIGURATION_Handle *diff,
+               enum GNUNET_NAT_StatusCode result,
+               enum GNUNET_NAT_Type type)
+{
+  const char *nat_type;
+  char unknown_type[64];
+  struct GNUNET_CONFIGURATION_Handle *new_cfg;
+
+  ah = NULL;
+  switch (type)
+  {
+  case GNUNET_NAT_TYPE_NO_NAT:
+    nat_type = "NO NAT";
+    break;
+  case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
+    nat_type = "NAT but we can traverse";
+    break;
+  case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
+    nat_type = "NAT but STUN is able to identify the correct information";
+    break;
+  case GNUNET_NAT_TYPE_UPNP_NAT:
+    nat_type = "NAT but UPNP opened the ports";
+    break;
+  default:
+    SPRINTF (unknown_type,
+            "NAT unknown, type %u",
+            type);
+    nat_type = unknown_type;
+    break;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+             "NAT status: %s/%s\n",
+             GNUNET_NAT_AUTO_status2string (result),
+             nat_type);
+
+  /* Shortcut: if there are no changes suggested, bail out early. */
+  if (GNUNET_NO ==
+      GNUNET_CONFIGURATION_is_dirty (diff))
+  {
+    test_finished ();
+    return;
+  }
+
+  /* Apply diff to original configuration and show changes
+     to the user */
+  new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
+
+  if (NULL != diff)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+               _("Suggested configuration changes:\n"));
+    GNUNET_CONFIGURATION_iterate_section_values (diff,
+                                                "nat",
+                                                &auto_conf_iter,
+                                                new_cfg);
+  }
+
+  /* If desired, write configuration to file; we write only the
+     changes to the defaults to keep things compact. */
+  if ( (write_cfg) &&
+       (NULL != diff) )
+  {
+    struct GNUNET_CONFIGURATION_Handle *def_cfg;
+
+    GNUNET_CONFIGURATION_set_value_string (new_cfg,
+                                          "ARM",
+                                          "CONFIG",
+                                          NULL);
+    def_cfg = GNUNET_CONFIGURATION_create ();
+    GNUNET_break (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_load (def_cfg,
+                                            NULL));
+    if (GNUNET_OK !=
+       GNUNET_CONFIGURATION_write_diffs (def_cfg,
+                                         new_cfg,
+                                         cfg_file))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                 _("Failed to write configuration to `%s'\n"),
+                 cfg_file);
+      global_ret = 1;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                 _("Wrote updated configuration to `%s'\n"),
+                 cfg_file);
+    }
+    GNUNET_CONFIGURATION_destroy (def_cfg);
+  }
+
+  if (NULL != new_cfg)
+    GNUNET_CONFIGURATION_destroy (new_cfg);
+  test_finished ();
+}
+
+
+/**
+ * Function called to report success or failure for
+ * NAT configuration test.
+ *
+ * @param cls closure
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ */
+static void
+test_report_cb (void *cls,
+               enum GNUNET_NAT_StatusCode result)
+{
+  nt = NULL;
+  PRINTF ("NAT test result: %s\n",
+         GNUNET_NAT_AUTO_status2string (result));
+  test_finished ();
+}
+
+
+/**
+ * Task run on shutdown.
+ *
+ * @param cls NULL
+ */
+static void
+do_shutdown (void *cls)
+{
+  if (NULL != ah)
+  {
+    GNUNET_NAT_AUTO_autoconfig_cancel (ah);
+    ah = NULL;
+  }
+  if (NULL != nt)
+  {
+    GNUNET_NAT_AUTO_test_stop (nt);
+    nt = NULL;
+  }
+}
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  cfg_file = cfgfile;
+  cfg = c;
+
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+                                NULL);
+
+  if (do_auto)
+  {
+    ah = GNUNET_NAT_AUTO_autoconfig_start (c,
+                                     &auto_config_cb,
+                                     NULL);
+  }
+
+  if (use_tcp && use_udp)
+  {
+    if (do_auto)
+      return;
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+               "Cannot use TCP and UDP\n");
+    global_ret = 1;
+    return;
+  }
+  proto = 0;
+  if (use_tcp)
+    proto = IPPROTO_TCP;
+  if (use_udp)
+    proto = IPPROTO_UDP;
+
+  if (NULL != section_name)
+  {
+    nt = GNUNET_NAT_AUTO_test_start (c,
+                                    proto,
+                                    section_name,
+                                    &test_report_cb,
+                                    NULL);
+  }
+  test_finished ();
+}
+
+
+/**
+ * Main function of gnunet-nat-auto
+ *
+ * @param argc number of command-line arguments
+ * @param argv command line
+ * @return 0 on success, -1 on error
+ */
+int
+main (int argc,
+      char *const argv[])
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    {'a', "auto", NULL,
+     gettext_noop ("run autoconfiguration"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
+    {'S', "section", "NAME",
+     gettext_noop ("section name providing the configuration for the adapter"),
+     GNUNET_YES, &GNUNET_GETOPT_set_string, &section_name },
+    {'t', "tcp", NULL,
+     gettext_noop ("use TCP"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &use_tcp },
+    {'u', "udp", NULL,
+     gettext_noop ("use UDP"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
+    {'w', "write", NULL,
+     gettext_noop ("write configuration file (for autoconfiguration)"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_get_utf8_args (argc, argv,
+                                   &argc, &argv))
+    return 2;
+  if (GNUNET_OK !=
+      GNUNET_PROGRAM_run (argc, argv,
+                         "gnunet-nat-auto [options]",
+                          _("GNUnet NAT traversal autoconfiguration"),
+                         options,
+                          &run,
+                         NULL))
+  {
+    global_ret = 1;
+  }
+  GNUNET_free ((void*) argv);
+  return global_ret;
+}
+
+
+/* end of gnunet-nat-auto.c */
diff --git a/src/nat-auto/gnunet-nat-auto_legacy.c b/src/nat-auto/gnunet-nat-auto_legacy.c
new file mode 100644 (file)
index 0000000..32f40c0
--- /dev/null
@@ -0,0 +1,645 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2011, 2016 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file nat/nat_test.c
+ * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server)
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_nat_lib.h"
+#include "nat.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
+
+#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+
+/**
+ * Entry we keep for each incoming connection.
+ */
+struct NatActivity
+{
+  /**
+   * This is a doubly-linked list.
+   */
+  struct NatActivity *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct NatActivity *prev;
+
+  /**
+   * Socket of the incoming connection.
+   */
+  struct GNUNET_NETWORK_Handle *sock;
+
+  /**
+   * Handle of the master context.
+   */
+  struct GNUNET_NAT_Test *h;
+
+  /**
+   * Task reading from the incoming connection.
+   */
+  struct GNUNET_SCHEDULER_Task *rtask;
+};
+
+
+/**
+ * Entry we keep for each connection to the gnunet-nat-service.
+ */
+struct ClientActivity
+{
+  /**
+   * This is a doubly-linked list.
+   */
+  struct ClientActivity *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct ClientActivity *prev;
+
+  /**
+   * Socket of the incoming connection.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Handle to overall NAT test.
+   */
+  struct GNUNET_NAT_Test *h;
+
+};
+
+
+/**
+ * Handle to a NAT test.
+ */
+struct GNUNET_NAT_Test
+{
+
+  /**
+   * Configuration used
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Function to call with success report
+   */
+  GNUNET_NAT_TestCallback report;
+
+  /**
+   * Closure for @e report.
+   */
+  void *report_cls;
+
+  /**
+   * Handle to NAT traversal in use
+   */
+  struct GNUNET_NAT_Handle *nat;
+
+  /**
+   * Handle to listen socket, or NULL
+   */
+  struct GNUNET_NETWORK_Handle *lsock;
+
+  /**
+   * Head of list of nat activities.
+   */
+  struct NatActivity *na_head;
+
+  /**
+   * Tail of list of nat activities.
+   */
+  struct NatActivity *na_tail;
+
+  /**
+   * Head of list of client activities.
+   */
+  struct ClientActivity *ca_head;
+
+  /**
+   * Tail of list of client activities.
+   */
+  struct ClientActivity *ca_tail;
+
+  /**
+   * Identity of task for the listen socket (if any)
+   */
+  struct GNUNET_SCHEDULER_Task *ltask;
+
+  /**
+   * Task identifier for the timeout (if any)
+   */
+  struct GNUNET_SCHEDULER_Task *ttask;
+
+  /**
+   * #GNUNET_YES if we're testing TCP
+   */
+  int is_tcp;
+
+  /**
+   * Data that should be transmitted or source-port.
+   */
+  uint16_t data;
+
+  /**
+   * Advertised port to the other peer.
+   */
+  uint16_t adv_port;
+
+  /**
+   * Status code to be reported to the timeout/status call
+   */
+  enum GNUNET_NAT_StatusCode status;
+};
+
+
+/**
+ * Function called from #GNUNET_NAT_register whenever someone asks us
+ * to do connection reversal.
+ *
+ * @param cls closure, our `struct GNUNET_NAT_Handle`
+ * @param addr public IP address of the other peer
+ * @param addrlen actual lenght of the @a addr
+ */
+static void
+reversal_cb (void *cls,
+             const struct sockaddr *addr,
+             socklen_t addrlen)
+{
+  struct GNUNET_NAT_Test *h = cls;
+  const struct sockaddr_in *sa;
+
+  if (sizeof (struct sockaddr_in) != addrlen)
+    return;
+  sa = (const struct sockaddr_in *) addr;
+  if (h->data != sa->sin_port)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Received connection reversal request for wrong port\n");
+    return;                     /* wrong port */
+  }
+  /* report success */
+  h->report (h->report_cls,
+             GNUNET_NAT_ERROR_SUCCESS);
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls the `struct GNUNET_NAT_Test`
+ */
+static void
+do_udp_read (void *cls)
+{
+  struct GNUNET_NAT_Test *tst = cls;
+  uint16_t data;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  tst->ltask =
+      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                     tst->lsock,
+                                     &do_udp_read,
+                                     tst);
+  if ((NULL != tc->write_ready) &&
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                   tst->lsock)) &&
+      (sizeof (data) ==
+       GNUNET_NETWORK_socket_recv (tst->lsock,
+                                   &data,
+                                   sizeof (data))))
+  {
+    if (data == tst->data)
+      tst->report (tst->report_cls,
+                   GNUNET_NAT_ERROR_SUCCESS);
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Received data mismatches expected value\n");
+  }
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Failed to receive data from inbound connection\n");
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls the `struct NatActivity`
+ */
+static void
+do_read (void *cls)
+{
+  struct NatActivity *na = cls;
+  struct GNUNET_NAT_Test *tst;
+  uint16_t data;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  na->rtask = NULL;
+  tst = na->h;
+  GNUNET_CONTAINER_DLL_remove (tst->na_head,
+                              tst->na_tail,
+                              na);
+  if ((NULL != tc->write_ready) &&
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                   na->sock)) &&
+      (sizeof (data) ==
+       GNUNET_NETWORK_socket_recv (na->sock,
+                                   &data,
+                                   sizeof (data))))
+  {
+    if (data == tst->data)
+      tst->report (tst->report_cls,
+                   GNUNET_NAT_ERROR_SUCCESS);
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Received data does not match expected value\n");
+  }
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Failed to receive data from inbound connection\n");
+  GNUNET_NETWORK_socket_close (na->sock);
+  GNUNET_free (na);
+}
+
+
+/**
+ * Activity on our listen socket. Accept the
+ * incoming connection.
+ *
+ * @param cls the `struct GNUNET_NAT_Test`
+ */
+static void
+do_accept (void *cls)
+{
+  struct GNUNET_NAT_Test *tst = cls;
+  struct GNUNET_NETWORK_Handle *s;
+  struct NatActivity *wl;
+
+  tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                              tst->lsock,
+                                              &do_accept,
+                                              tst);
+  s = GNUNET_NETWORK_socket_accept (tst->lsock,
+                                    NULL,
+                                    NULL);
+  if (NULL == s)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
+                         "accept");
+    return;                     /* odd error */
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got an inbound connection, waiting for data\n");
+  wl = GNUNET_new (struct NatActivity);
+  wl->sock = s;
+  wl->h = tst;
+  wl->rtask =
+    GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                   wl->sock,
+                                   &do_read,
+                                   wl);
+  GNUNET_CONTAINER_DLL_insert (tst->na_head,
+                              tst->na_tail,
+                              wl);
+}
+
+
+/**
+ * We got disconnected from the NAT server.  Stop
+ * waiting for a reply.
+ *
+ * @param cls the `struct ClientActivity`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+                  enum GNUNET_MQ_Error error)
+{
+  struct ClientActivity *ca = cls;
+  struct GNUNET_NAT_Test *tst = ca->h;
+
+  GNUNET_CONTAINER_DLL_remove (tst->ca_head,
+                               tst->ca_tail,
+                               ca);
+  GNUNET_MQ_destroy (ca->mq);
+  GNUNET_free (ca);
+}
+
+
+/**
+ * Address-callback, used to send message to gnunet-nat-server.
+ *
+ * @param cls closure
+ * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
+ *     the previous (now invalid) one
+ * @param addr either the previous or the new public IP address
+ * @param addrlen actual length of the @a addr
+ */
+static void
+addr_cb (void *cls,
+         int add_remove,
+         const struct sockaddr *addr,
+         socklen_t addrlen)
+{
+  struct GNUNET_NAT_Test *h = cls;
+  struct ClientActivity *ca;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_NAT_TestMessage *msg;
+  const struct sockaddr_in *sa;
+
+  if (GNUNET_YES != add_remove)
+    return;
+  if (addrlen != sizeof (struct sockaddr_in))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "NAT test ignores IPv6 address `%s' returned from NAT library\n",
+        GNUNET_a2s (addr,
+                     addrlen));
+    return;                     /* ignore IPv6 here */
+  }
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Asking gnunet-nat-server to connect to `%s'\n",
+       GNUNET_a2s (addr,
+                   addrlen));
+
+  ca = GNUNET_new (struct ClientActivity);
+  ca->h = h;
+  ca->mq = GNUNET_CLIENT_connect (h->cfg,
+                                  "gnunet-nat-server",
+                                  NULL,
+                                  &mq_error_handler,
+                                  ca);
+  if (NULL == ca->mq)
+  {
+    GNUNET_free (ca);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to connect to `gnunet-nat-server'\n"));
+    return;
+  }
+  GNUNET_CONTAINER_DLL_insert (h->ca_head,
+                               h->ca_tail,
+                               ca);
+  sa = (const struct sockaddr_in *) addr;
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_NAT_TEST);
+  msg->dst_ipv4 = sa->sin_addr.s_addr;
+  msg->dport = sa->sin_port;
+  msg->data = h->data;
+  msg->is_tcp = htonl ((uint32_t) h->is_tcp);
+  GNUNET_MQ_send (ca->mq,
+                  env);
+}
+
+
+/**
+ * Timeout task for a nat test.
+ * Calls the report-callback with a timeout return value
+ *
+ * Destroys the nat handle after the callback has been processed.
+ *
+ * @param cls handle to the timed out NAT test
+ */
+static void
+do_timeout (void *cls)
+{
+  struct GNUNET_NAT_Test *nh = cls;
+
+  nh->ttask = NULL;
+  nh->report (nh->report_cls,
+              (GNUNET_NAT_ERROR_SUCCESS == nh->status)
+              ? GNUNET_NAT_ERROR_TIMEOUT
+              : nh->status);
+}
+
+
+/**
+ * Start testing if NAT traversal works using the
+ * given configuration (IPv4-only).
+ *
+ * ALL failures are reported directly to the report callback
+ *
+ * @param cfg configuration for the NAT traversal
+ * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
+ * @param bnd_port port to bind to, 0 for connection reversal
+ * @param adv_port externally advertised port to use
+ * @param timeout delay after which the test should be aborted
+ * @param report function to call with the result of the test
+ * @param report_cls closure for @a report
+ * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback
+ */
+struct GNUNET_NAT_Test *
+GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                       int is_tcp,
+                       uint16_t bnd_port,
+                       uint16_t adv_port,
+                       struct GNUNET_TIME_Relative timeout,
+                       GNUNET_NAT_TestCallback report,
+                       void *report_cls)
+{
+  struct GNUNET_NAT_Test *nh;
+  struct sockaddr_in sa;
+  const struct sockaddr *addrs[] = {
+    (const struct sockaddr *) &sa
+  };
+  const socklen_t addrlens[] = {
+    sizeof (sa)
+  };
+
+  memset (&sa, 0, sizeof (sa));
+  sa.sin_family = AF_INET;
+  sa.sin_port = htons (bnd_port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa.sin_len = sizeof (sa);
+#endif
+
+  nh = GNUNET_new (struct GNUNET_NAT_Test);
+  nh->cfg = cfg;
+  nh->is_tcp = is_tcp;
+  nh->data = bnd_port;
+  nh->adv_port = adv_port;
+  nh->report = report;
+  nh->report_cls = report_cls;
+  nh->status = GNUNET_NAT_ERROR_SUCCESS;
+  if (0 == bnd_port)
+  {
+    nh->nat
+      = GNUNET_NAT_register (cfg,
+                             is_tcp,
+                             0,
+                             0,
+                            NULL,
+                             NULL,
+                            &addr_cb,
+                             &reversal_cb,
+                             nh,
+                             NULL);
+  }
+  else
+  {
+    nh->lsock =
+        GNUNET_NETWORK_socket_create (AF_INET,
+                                      (is_tcp ==
+                                       GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM,
+                                      0);
+    if ((nh->lsock == NULL) ||
+        (GNUNET_OK !=
+         GNUNET_NETWORK_socket_bind (nh->lsock,
+                                     (const struct sockaddr *) &sa,
+                                     sizeof (sa))))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
+                  GNUNET_a2s ((const struct sockaddr *) &sa,
+                              sizeof (sa)),
+                  STRERROR (errno));
+      if (NULL != nh->lsock)
+      {
+        GNUNET_NETWORK_socket_close (nh->lsock);
+        nh->lsock = NULL;
+      }
+      nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
+      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout,
+                                            nh);
+      return nh;
+    }
+    if (GNUNET_YES == is_tcp)
+    {
+      GNUNET_break (GNUNET_OK ==
+                    GNUNET_NETWORK_socket_listen (nh->lsock,
+                                                  5));
+      nh->ltask =
+          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                         nh->lsock,
+                                        &do_accept,
+                                         nh);
+    }
+    else
+    {
+      nh->ltask =
+          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                         nh->lsock,
+                                        &do_udp_read,
+                                         nh);
+    }
+    LOG (GNUNET_ERROR_TYPE_INFO,
+        "NAT test listens on port %u (%s)\n",
+        bnd_port,
+        (GNUNET_YES == is_tcp) ? "tcp" : "udp");
+    nh->nat = GNUNET_NAT_register (cfg,
+                                   is_tcp,
+                                   adv_port,
+                                   1,
+                                   addrs,
+                                   addrlens,
+                                   &addr_cb,
+                                   NULL,
+                                   nh,
+                                   NULL);
+    if (NULL == nh->nat)
+    {
+      LOG (GNUNET_ERROR_TYPE_INFO,
+          _("NAT test failed to start NAT library\n"));
+      if (NULL != nh->ltask)
+      {
+        GNUNET_SCHEDULER_cancel (nh->ltask);
+        nh->ltask = NULL;
+      }
+      if (NULL != nh->lsock)
+      {
+        GNUNET_NETWORK_socket_close (nh->lsock);
+        nh->lsock = NULL;
+      }
+      nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
+      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout,
+                                            nh);
+      return nh;
+    }
+  }
+  nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout,
+                                           &do_timeout,
+                                           nh);
+  return nh;
+}
+
+
+/**
+ * Stop an active NAT test.
+ *
+ * @param tst test to stop.
+ */
+void
+GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst)
+{
+  struct NatActivity *pos;
+  struct ClientActivity *cpos;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Stopping NAT test\n");
+  while (NULL != (cpos = tst->ca_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (tst->ca_head,
+                                tst->ca_tail,
+                                cpos);
+    GNUNET_MQ_destroy (cpos->mq);
+    GNUNET_free (cpos);
+  }
+  while (NULL != (pos = tst->na_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (tst->na_head,
+                                tst->na_tail,
+                                pos);
+    GNUNET_SCHEDULER_cancel (pos->rtask);
+    GNUNET_NETWORK_socket_close (pos->sock);
+    GNUNET_free (pos);
+  }
+  if (NULL != tst->ttask)
+  {
+    GNUNET_SCHEDULER_cancel (tst->ttask);
+    tst->ttask = NULL;
+  }
+  if (NULL != tst->ltask)
+  {
+    GNUNET_SCHEDULER_cancel (tst->ltask);
+    tst->ltask = NULL;
+  }
+  if (NULL != tst->lsock)
+  {
+    GNUNET_NETWORK_socket_close (tst->lsock);
+    tst->lsock = NULL;
+  }
+  if (NULL != tst->nat)
+  {
+    GNUNET_NAT_unregister (tst->nat);
+    tst->nat = NULL;
+  }
+  GNUNET_free (tst);
+}
+
+/* end of nat_test.c */
diff --git a/src/nat-auto/gnunet-nat-server.c b/src/nat-auto/gnunet-nat-server.c
new file mode 100644 (file)
index 0000000..dd08f8d
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2011 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file src/nat/gnunet-nat-server.c
+ * @brief Daemon to run on 'gnunet.org' to help test NAT traversal code
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_nat_service.h"
+#include "gnunet_protocols.h"
+#include "nat-auto.h"
+
+
+/**
+ * Our server.
+ */
+static struct GNUNET_SERVER_Handle *server;
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+
+/**
+ * Try contacting the peer using autonomous NAT traveral method.
+ *
+ * @param dst_ipv4 IPv4 address to send the fake ICMP message
+ * @param dport destination port to include in ICMP message
+ * @param is_tcp mark for TCP (#GNUNET_YES)  or UDP (#GNUNET_NO)
+ */
+static void
+try_anat (uint32_t dst_ipv4,
+          uint16_t dport,
+          int is_tcp)
+{
+  struct GNUNET_NAT_Handle *h;
+  struct sockaddr_in lsa;
+  struct sockaddr_in rsa;
+  socklen_t sa_len;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Asking for connection reversal with %x and code %u\n",
+              (unsigned int) dst_ipv4,
+              (unsigned int) dport);
+  memset (&lsa, 0, sizeof (lsa));
+  lsa.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  lsa.sin_len = sizeof (sa);
+#endif
+  lsa.sin_addr.s_addr = 0;
+  lsa.sin_port = htons (dport);
+  memset (&rsa, 0, sizeof (rsa));
+  rsa.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  rsa.sin_len = sizeof (sa);
+#endif
+  rsa.sin_addr.s_addr = dst_ipv4;
+  rsa.sin_port = htons (dport);
+  sa_len = sizeof (lsa);
+  h = GNUNET_NAT_register (cfg,
+                          "none",
+                           is_tcp ? IPPROTO_TCP : IPPROTO_UDP,
+                           1,
+                          (const struct sockaddr **) &lsa,
+                          &sa_len,
+                           NULL, NULL, NULL);
+  GNUNET_NAT_request_reversal (h,
+                              &lsa,
+                              &rsa);
+  GNUNET_NAT_unregister (h);
+}
+
+
+/**
+ * Closure for #tcp_send.
+ */
+struct TcpContext
+{
+  /**
+   * TCP  socket.
+   */
+  struct GNUNET_NETWORK_Handle *s;
+
+  /**
+   * Data to transmit.
+   */
+  uint16_t data;
+};
+
+
+/**
+ * Task called by the scheduler once we can do the TCP send
+ * (or once we failed to connect...).
+ *
+ * @param cls the `struct TcpContext`
+ */
+static void
+tcp_send (void *cls)
+{
+  struct TcpContext *ctx = cls;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  if ((NULL != tc->write_ready) &&
+      (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s)))
+  {
+    if (-1 ==
+        GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data)))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
+    }
+    GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
+  }
+  GNUNET_NETWORK_socket_close (ctx->s);
+  GNUNET_free (ctx);
+}
+
+
+/**
+ * Try to send @a data to the
+ * IP @a dst_ipv4' at port @a dport via TCP.
+ *
+ * @param dst_ipv4 target IP
+ * @param dport target port
+ * @param data data to send
+ */
+static void
+try_send_tcp (uint32_t dst_ipv4,
+              uint16_t dport,
+              uint16_t data)
+{
+  struct GNUNET_NETWORK_Handle *s;
+  struct sockaddr_in sa;
+  struct TcpContext *ctx;
+
+  s = GNUNET_NETWORK_socket_create (AF_INET,
+                                    SOCK_STREAM,
+                                    0);
+  if (NULL == s)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "socket");
+    return;
+  }
+  memset (&sa, 0, sizeof (sa));
+  sa.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa.sin_len = sizeof (sa);
+#endif
+  sa.sin_addr.s_addr = dst_ipv4;
+  sa.sin_port = htons (dport);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending TCP message to `%s'\n",
+              GNUNET_a2s ((struct sockaddr *) &sa,
+                          sizeof (sa)));
+  if ( (GNUNET_OK !=
+        GNUNET_NETWORK_socket_connect (s,
+                                       (const struct sockaddr *) &sa,
+                                       sizeof (sa))) &&
+       (errno != EINPROGRESS) )
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "connect");
+    GNUNET_NETWORK_socket_close (s);
+    return;
+  }
+  ctx = GNUNET_new (struct TcpContext);
+  ctx->s = s;
+  ctx->data = data;
+  GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS,
+                                  s,
+                                  &tcp_send,
+                                  ctx);
+}
+
+
+/**
+ * Try to send @a data to the
+ * IP @a dst_ipv4 at port @a dport via UDP.
+ *
+ * @param dst_ipv4 target IP
+ * @param dport target port
+ * @param data data to send
+ */
+static void
+try_send_udp (uint32_t dst_ipv4,
+              uint16_t dport,
+              uint16_t data)
+{
+  struct GNUNET_NETWORK_Handle *s;
+  struct sockaddr_in sa;
+
+  s = GNUNET_NETWORK_socket_create (AF_INET,
+                                    SOCK_DGRAM,
+                                    0);
+  if (NULL == s)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "socket");
+    return;
+  }
+  memset (&sa, 0, sizeof (sa));
+  sa.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa.sin_len = sizeof (sa);
+#endif
+  sa.sin_addr.s_addr = dst_ipv4;
+  sa.sin_port = htons (dport);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending UDP packet to `%s'\n",
+              GNUNET_a2s ((struct sockaddr *) &sa,
+                          sizeof (sa)));
+  if (-1 ==
+      GNUNET_NETWORK_socket_sendto (s,
+                                    &data,
+                                    sizeof (data),
+                                    (const struct sockaddr *) &sa,
+                                    sizeof (sa)))
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "sendto");
+  GNUNET_NETWORK_socket_close (s);
+}
+
+
+/**
+ * We've received a request to probe a NAT
+ * traversal. Do it.
+ *
+ * @param cls unused
+ * @param client handle to client (we always close)
+ * @param msg message with details about what to test
+ */
+static void
+test (void *cls,
+      struct GNUNET_SERVER_Client *client,
+      const struct GNUNET_MessageHeader *msg)
+{
+  const struct GNUNET_NAT_AUTO_TestMessage *tm;
+  uint16_t dport;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received test request\n");
+  tm = (const struct GNUNET_NAT_AUTO_TestMessage *) msg;
+  dport = ntohs (tm->dport);
+  if (0 == dport)
+    try_anat (tm->dst_ipv4,
+              ntohs (tm->data),
+              (int) ntohl (tm->is_tcp));
+  else if (GNUNET_YES == ntohl (tm->is_tcp))
+    try_send_tcp (tm->dst_ipv4,
+                  dport,
+                  tm->data);
+  else
+    try_send_udp (tm->dst_ipv4,
+                  dport,
+                  tm->data);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_NO);
+}
+
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ */
+static void
+shutdown_task (void *cls)
+{
+  GNUNET_SERVER_destroy (server);
+  server = NULL;
+}
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+    {&test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST,
+     sizeof (struct GNUNET_NAT_AUTO_TestMessage)},
+    {NULL, NULL, 0, 0}
+  };
+  unsigned int port;
+  struct sockaddr_in in4;
+  struct sockaddr_in6 in6;
+
+  socklen_t slen[] = {
+    sizeof (in4),
+    sizeof (in6),
+    0
+  };
+  struct sockaddr *sa[] = {
+    (struct sockaddr *) &in4,
+    (struct sockaddr *) &in6,
+    NULL
+  };
+
+  cfg = c;
+  if ( (NULL == args[0]) ||
+       (1 != SSCANF (args[0], "%u", &port)) ||
+       (0 == port) ||
+       (65536 <= port) )
+  {
+    FPRINTF (stderr,
+             _("Please pass valid port number as the first argument! (got `%s')\n"),
+             args[0]);
+    return;
+  }
+  memset (&in4, 0, sizeof (in4));
+  memset (&in6, 0, sizeof (in6));
+  in4.sin_family = AF_INET;
+  in4.sin_port = htons ((uint16_t) port);
+  in6.sin6_family = AF_INET6;
+  in6.sin6_port = htons ((uint16_t) port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  in4.sin_len = sizeof (in4);
+  in6.sin6_len = sizeof (in6);
+#endif
+  server = GNUNET_SERVER_create (NULL,
+                                NULL,
+                                (struct sockaddr * const *) sa,
+                                slen,
+                                GNUNET_TIME_UNIT_SECONDS,
+                                GNUNET_YES);
+  GNUNET_SERVER_add_handlers (server,
+                             handlers);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                NULL);
+}
+
+
+/**
+ * Main function of gnunet-nat-server.
+ *
+ * @param argc number of command-line arguments
+ * @param argv command line
+ * @return 0 on success, -1 on error
+ */
+int
+main (int argc, char *const argv[])
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_get_utf8_args (argc, argv,
+                                   &argc, &argv))
+    return 2;
+
+  if (GNUNET_OK !=
+      GNUNET_PROGRAM_run (argc,
+                         argv,
+                         "gnunet-nat-server [options] PORT",
+                          _("GNUnet NAT traversal test helper daemon"),
+                         options,
+                          &run,
+                         NULL))
+  {
+    GNUNET_free ((void*) argv);
+    return 1;
+  }
+  GNUNET_free ((void*) argv);
+  return 0;
+}
+
+
+/* end of gnunet-nat-server.c */
diff --git a/src/nat-auto/gnunet-service-nat-auto.c b/src/nat-auto/gnunet-service-nat-auto.c
new file mode 100644 (file)
index 0000000..ae570c3
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+  This file is part of GNUnet.
+  Copyright (C) 2016, 2017 GNUnet e.V.
+
+  GNUnet is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published
+  by the Free Software Foundation; either version 3, or (at your
+  option) any later version.
+
+  GNUnet is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with GNUnet; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file nat-auto/gnunet-service-nat-auto.c
+ * @brief NAT autoconfiguration service
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - merge client handle and autoconfig context
+ * - implement "more" autoconfig:
+ *   + re-work gnunet-nat-server & integrate!
+ *   + integrate "legacy" code
+ *   + test manually punched NAT (how?)
+ */
+#include "platform.h"
+#include <math.h>
+#include "gnunet_util_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+#include "gnunet_nat_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_resolver_service.h"
+#include "nat-auto.h"
+#include <gcrypt.h>
+
+
+/**
+ * How long do we wait until we forcefully terminate autoconfiguration?
+ */
+#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
+
+/**
+ * Internal data structure we track for each of our clients.
+ */
+struct ClientHandle
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct ClientHandle *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct ClientHandle *prev;
+
+  /**
+   * Underlying handle for this client with the service.
+   */
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * Message queue for communicating with the client.
+   */
+  struct GNUNET_MQ_Handle *mq;
+};
+
+
+/**
+ * Context for autoconfiguration operations.
+ */
+struct AutoconfigContext
+{
+  /**
+   * Kept in a DLL.
+   */
+  struct AutoconfigContext *prev;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct AutoconfigContext *next;
+
+  /**
+   * Which client asked the question.
+   */
+  struct ClientHandle *ch;
+
+  /**
+   * Configuration we are creating.
+   */
+  struct GNUNET_CONFIGURATION_Handle *c;
+
+  /**
+   * Original configuration (for diffing).
+   */
+  struct GNUNET_CONFIGURATION_Handle *orig;
+
+  /**
+   * Timeout task to force termination.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * #GNUNET_YES if upnpc should be used,
+   * #GNUNET_NO if upnpc should not be used,
+   * #GNUNET_SYSERR if we should simply not change the option.
+   */
+  int enable_upnpc;
+
+  /**
+   * Status code to return to the client.
+   */
+  enum GNUNET_NAT_StatusCode status_code;
+
+  /**
+   * NAT type to return to the client.
+   */
+  enum GNUNET_NAT_Type type;
+};
+
+
+/**
+ * Head of client DLL.
+ */
+static struct ClientHandle *ch_head;
+
+/**
+ * Tail of client DLL.
+ */
+static struct ClientHandle *ch_tail;
+
+/**
+ * DLL of our autoconfiguration operations.
+ */
+static struct AutoconfigContext *ac_head;
+
+/**
+ * DLL of our autoconfiguration operations.
+ */
+static struct AutoconfigContext *ac_tail;
+
+/**
+ * Handle to our current configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Handle to the statistics service.
+ */
+static struct GNUNET_STATISTICS_Handle *stats;
+
+
+/**
+ * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
+ * from client.
+ *
+ * @param cls client who sent the message
+ * @param message the message received
+ * @return #GNUNET_OK if message is well-formed
+ */
+static int
+check_autoconfig_request (void *cls,
+                         const struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *message)
+{
+  return GNUNET_OK;  /* checked later */
+}
+
+
+/**
+ * Stop all pending activities with respect to the @a ac
+ *
+ * @param ac autoconfiguration to terminate activities for
+ */
+static void
+terminate_ac_activities (struct AutoconfigContext *ac)
+{
+  if (NULL != ac->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (ac->timeout_task);
+    ac->timeout_task = NULL;
+  }
+}
+
+
+/**
+ * Finish handling the autoconfiguration request and send
+ * the response to the client.
+ *
+ * @param cls the `struct AutoconfigContext` to conclude
+ */
+static void
+conclude_autoconfig_request (void *cls)
+{
+  struct AutoconfigContext *ac = cls;
+  struct ClientHandle *ch = ac->ch;
+  struct GNUNET_NAT_AUTO_AutoconfigResultMessage *arm;
+  struct GNUNET_MQ_Envelope *env;
+  size_t c_size;
+  char *buf;
+  struct GNUNET_CONFIGURATION_Handle *diff;
+
+  ac->timeout_task = NULL;
+  terminate_ac_activities (ac);
+
+  /* Send back response */
+  diff = GNUNET_CONFIGURATION_get_diff (ac->orig,
+                                       ac->c);
+  buf = GNUNET_CONFIGURATION_serialize (diff,
+                                       &c_size);
+  GNUNET_CONFIGURATION_destroy (diff);
+  env = GNUNET_MQ_msg_extra (arm,
+                            c_size,
+                            GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT);
+  arm->status_code = htonl ((uint32_t) ac->status_code);
+  arm->type = htonl ((uint32_t) ac->type);
+  GNUNET_memcpy (&arm[1],
+                buf,
+                c_size);
+  GNUNET_free (buf);
+  GNUNET_MQ_send (ch->mq,
+                 env);
+
+  /* clean up */
+  GNUNET_CONFIGURATION_destroy (ac->orig);
+  GNUNET_CONFIGURATION_destroy (ac->c);
+  GNUNET_CONTAINER_DLL_remove (ac_head,
+                              ac_tail,
+                              ac);
+  GNUNET_free (ac);
+  GNUNET_SERVICE_client_continue (ch->client);
+}
+
+
+/**
+ * Check if all autoconfiguration operations have concluded,
+ * and if they have, send the result back to the client.
+ *
+ * @param ac autoconfiguation context to check
+ */
+static void
+check_autoconfig_finished (struct AutoconfigContext *ac)
+{
+  GNUNET_SCHEDULER_cancel (ac->timeout_task);
+  ac->timeout_task
+    = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request,
+                               ac);
+}
+
+
+/**
+ * Update ENABLE_UPNPC configuration option.
+ *
+ * @param ac autoconfiguration to update
+ */
+static void
+update_enable_upnpc_option (struct AutoconfigContext *ac)
+{
+  switch (ac->enable_upnpc)
+  {
+  case GNUNET_YES:
+    GNUNET_CONFIGURATION_set_value_string (ac->c,
+                                          "NAT",
+                                          "ENABLE_UPNP",
+                                          "YES");
+    break;
+  case GNUNET_NO:
+    GNUNET_CONFIGURATION_set_value_string (ac->c,
+                                          "NAT",
+                                          "ENABLE_UPNP",
+                                          "NO");
+    break;
+  case GNUNET_SYSERR:
+    /* We are unsure, do not change option */
+    break;
+  }
+}
+
+
+/**
+ * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
+ * client.
+ *
+ * @param cls client who sent the message
+ * @param message the message received
+ */
+static void
+handle_autoconfig_request (void *cls,
+                          const struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *message)
+{
+  struct ClientHandle *ch = cls;
+  size_t left = ntohs (message->header.size) - sizeof (*message);
+  struct AutoconfigContext *ac;
+
+  ac = GNUNET_new (struct AutoconfigContext);
+  ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
+  ac->ch = ch;
+  ac->c = GNUNET_CONFIGURATION_create ();
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_deserialize (ac->c,
+                                       (const char *) &message[1],
+                                       left,
+                                       GNUNET_NO))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (ch->client);
+    GNUNET_CONFIGURATION_destroy (ac->c);
+    GNUNET_free (ac);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Received REQUEST_AUTO_CONFIG message from client\n");
+
+  GNUNET_CONTAINER_DLL_insert (ac_head,
+                              ac_tail,
+                              ac);
+  ac->orig
+    = GNUNET_CONFIGURATION_dup (ac->c);
+  ac->timeout_task
+    = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT,
+                                   &conclude_autoconfig_request,
+                                   ac);
+  ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
+
+  /* Probe for upnpc */
+  if (GNUNET_SYSERR ==
+      GNUNET_OS_check_helper_binary ("upnpc",
+                                    GNUNET_NO,
+                                    NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               _("UPnP client `upnpc` command not found, disabling UPnP\n"));
+    ac->enable_upnpc = GNUNET_NO;
+  }
+  else
+  {
+    /* We might at some point be behind NAT, try upnpc */
+    ac->enable_upnpc = GNUNET_YES;
+  }
+  update_enable_upnpc_option (ac);
+
+  /* Finally, check if we are already done */
+  check_autoconfig_finished (ac);
+}
+
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ */
+static void
+shutdown_task (void *cls)
+{
+  struct AutoconfigContext *ac;
+
+  while (NULL != (ac = ac_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (ac_head,
+                                ac_tail,
+                                ac);
+    terminate_ac_activities (ac);
+    GNUNET_free (ac);
+  }
+  if (NULL != stats)
+  {
+    GNUNET_STATISTICS_destroy (stats,
+                              GNUNET_NO);
+    stats = NULL;
+  }
+}
+
+
+/**
+ * Setup NAT service.
+ *
+ * @param cls closure
+ * @param c configuration to use
+ * @param service the initialized service
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *c,
+     struct GNUNET_SERVICE_Handle *service)
+{
+  cfg = c;
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                NULL);
+  stats = GNUNET_STATISTICS_create ("nat-auto",
+                                   cfg);
+}
+
+
+/**
+ * Callback called when a client connects to the service.
+ *
+ * @param cls closure for the service
+ * @param c the new client that connected to the service
+ * @param mq the message queue used to send messages to the client
+ * @return a `struct ClientHandle`
+ */
+static void *
+client_connect_cb (void *cls,
+                  struct GNUNET_SERVICE_Client *c,
+                  struct GNUNET_MQ_Handle *mq)
+{
+  struct ClientHandle *ch;
+
+  ch = GNUNET_new (struct ClientHandle);
+  ch->mq = mq;
+  ch->client = c;
+  GNUNET_CONTAINER_DLL_insert (ch_head,
+                              ch_tail,
+                              ch);
+  return ch;
+}
+
+
+/**
+ * Callback called when a client disconnected from the service
+ *
+ * @param cls closure for the service
+ * @param c the client that disconnected
+ * @param internal_cls a `struct ClientHandle *`
+ */
+static void
+client_disconnect_cb (void *cls,
+                     struct GNUNET_SERVICE_Client *c,
+                     void *internal_cls)
+{
+  struct ClientHandle *ch = internal_cls;
+
+  GNUNET_CONTAINER_DLL_remove (ch_head,
+                              ch_tail,
+                              ch);
+  GNUNET_free (ch);
+}
+
+
+/**
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN
+("nat-auto",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_var_size (autoconfig_request,
+                       GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG,
+                       struct GNUNET_NAT_AUTO_AutoconfigRequestMessage,
+                       NULL),
+ GNUNET_MQ_handler_end ());
+
+
+#if defined(LINUX) && defined(__GLIBC__)
+#include <malloc.h>
+
+/**
+ * MINIMIZE heap size (way below 128k) since this process doesn't need much.
+ */
+void __attribute__ ((constructor))
+GNUNET_ARM_memory_init ()
+{
+  mallopt (M_TRIM_THRESHOLD, 4 * 1024);
+  mallopt (M_TOP_PAD, 1 * 1024);
+  malloc_trim (0);
+}
+#endif
+
+/* end of gnunet-service-nat.c */
diff --git a/src/nat-auto/gnunet-service-nat-auto_legacy.c b/src/nat-auto/gnunet-service-nat-auto_legacy.c
new file mode 100644 (file)
index 0000000..bcfa4b9
--- /dev/null
@@ -0,0 +1,1081 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2015 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file nat/nat_auto.c
+ * @brief functions for auto-configuration of the network
+ * @author Christian Grothoff
+ * @author Bruno Cabral
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_resolver_service.h"
+#include "gnunet_nat_lib.h"
+#include "nat.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
+
+
+/**
+ * How long do we wait for the NAT test to report success?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
+
+#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
+
+/**
+ * Phases of the auto configuration.
+ */
+enum AutoPhase
+{
+  /**
+   * Initial start value.
+   */
+  AUTO_INIT = 0,
+
+  /**
+   * Test our external IP.
+   */
+  AUTO_EXTERNAL_IP,
+
+  /**
+   * Test our external IP.
+   */
+   AUTO_STUN,
+
+  /**
+   * Test our internal IP.
+   */
+  AUTO_LOCAL_IP,
+
+  /**
+   * Test if NAT was punched.
+   */
+  AUTO_NAT_PUNCHED,
+
+  /**
+   * Test if UPnP is working.
+   */
+  AUTO_UPNPC,
+
+  /**
+   * Test if ICMP server works.
+   */
+  AUTO_ICMP_SERVER,
+
+  /**
+   * Test if ICMP client works.
+   */
+  AUTO_ICMP_CLIENT,
+
+  /**
+   * Last phase, we're done.
+   */
+  AUTO_DONE
+
+};
+
+
+/**
+ * Handle to auto-configuration in progress.
+ */
+struct GNUNET_NAT_AutoHandle
+{
+
+  /**
+   * Handle to the active NAT test.
+   */
+  struct GNUNET_NAT_Test *tst;
+
+  /**
+   * Function to call when done.
+   */
+  GNUNET_NAT_AutoResultCallback fin_cb;
+
+  /**
+   * Closure for @e fin_cb.
+   */
+  void *fin_cb_cls;
+
+  /**
+   * Handle for active 'GNUNET_NAT_mini_get_external_ipv4'-operation.
+   */
+  struct GNUNET_NAT_ExternalHandle *eh;
+
+  /**
+   * Current configuration (with updates from previous phases)
+   */
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Original configuration (used to calculate differences)
+   */
+  struct GNUNET_CONFIGURATION_Handle *initial_cfg;
+
+  /**
+   * Task identifier for the timeout.
+   */
+  struct GNUNET_SCHEDULER_Task *task;
+
+  /**
+   * Message queue to the gnunet-nat-server.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Where are we in the test?
+   */
+  enum AutoPhase phase;
+
+  /**
+   * Situation of the NAT
+   */
+  enum GNUNET_NAT_Type type;
+
+  /**
+   * Do we have IPv6?
+   */
+  int have_v6;
+
+  /**
+   * UPnP already set the external ip address ?
+   */
+  int upnp_set_external_address;
+
+  /**
+   * Did the external server connected back ?
+   */
+  int connected_back;
+
+  /**
+   * Address detected by STUN
+   */
+  char *stun_ip;
+
+  unsigned int stun_port;
+
+  /**
+   * Internal IP is the same as the public one ?
+   */
+  int internal_ip_is_public;
+
+  /**
+   * Error code for better debugging and user feedback
+   */
+  enum GNUNET_NAT_StatusCode ret;
+};
+
+
+/**
+ * The listen socket of the service for IPv4
+ */
+static struct GNUNET_NETWORK_Handle *lsock4;
+
+/**
+ * The listen task ID for IPv4
+ */
+static struct GNUNET_SCHEDULER_Task *ltask4;
+
+/**
+ * The port the test service is running on (default 7895)
+ */
+static unsigned long long port = 7895;
+
+static char *stun_server = "stun.ekiga.net";
+
+static unsigned int stun_port = 3478;
+
+
+/**
+ * Run the next phase of the auto test.
+ *
+ * @param ah auto test handle
+ */
+static void
+next_phase (struct GNUNET_NAT_AutoHandle *ah);
+
+
+static void
+process_stun_reply(struct sockaddr_in *answer,
+                   struct GNUNET_NAT_AutoHandle *ah)
+{
+  ah->stun_ip = inet_ntoa(answer->sin_addr);
+  ah->stun_port = ntohs (answer->sin_port);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "External IP is: %s , with port %u\n",
+              ah->stun_ip,
+              ah->stun_port);
+  next_phase (ah);
+}
+
+
+/**
+ * Function that terminates the test.
+ */
+static void
+stop_stun ()
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Stopping STUN and quitting...\n");
+  /* Clean task */
+  if (NULL != ltask4)
+  {
+    GNUNET_SCHEDULER_cancel (ltask4);
+    ltask4 = NULL;
+  }
+  /* Clean socket */
+  if (NULL != lsock4)
+  {
+    GNUNET_NETWORK_socket_close (lsock4);
+    lsock4 = NULL;
+  }
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls
+ */
+static void
+do_udp_read (void *cls)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+  unsigned char reply_buf[1024];
+  ssize_t rlen;
+  struct sockaddr_in answer;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                   lsock4)))
+  {
+    rlen = GNUNET_NETWORK_socket_recv (lsock4,
+                                      reply_buf,
+                                      sizeof (reply_buf));
+
+    //Lets handle the packet
+    memset (&answer, 0, sizeof(struct sockaddr_in));
+    if (ah->phase == AUTO_NAT_PUNCHED)
+    {
+      //Destroy the connection
+      GNUNET_NETWORK_socket_close (lsock4);
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "The external server was able to connect back");
+      ah->connected_back = GNUNET_YES;
+      next_phase (ah);
+    }
+    else
+    {
+      if (GNUNET_OK ==
+         GNUNET_NAT_stun_handle_packet (reply_buf, rlen, &answer))
+      {
+        //Process the answer
+        process_stun_reply (&answer, ah);
+      }
+      else
+      {
+        next_phase (ah);
+      }
+    }
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "TIMEOUT while waiting for an answer\n");
+    if (ah->phase == AUTO_NAT_PUNCHED)
+    {
+      stop_stun();
+    }
+
+    next_phase (ah);
+  }
+}
+
+
+/**
+ * Create an IPv4 listen socket bound to our port.
+ *
+ * @return NULL on error
+ */
+static struct GNUNET_NETWORK_Handle *
+bind_v4 ()
+{
+  struct GNUNET_NETWORK_Handle *ls;
+  struct sockaddr_in sa4;
+  int eno;
+
+  memset (&sa4, 0, sizeof (sa4));
+  sa4.sin_family = AF_INET;
+  sa4.sin_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    sa4.sin_len = sizeof (sa4);
+#endif
+  ls = GNUNET_NETWORK_socket_create (AF_INET,
+                                     SOCK_DGRAM,
+                                     0);
+  if (NULL == ls)
+    return NULL;
+  if (GNUNET_OK !=
+      GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4,
+                                  sizeof (sa4)))
+  {
+    eno = errno;
+    GNUNET_NETWORK_socket_close (ls);
+    errno = eno;
+    return NULL;
+  }
+  return ls;
+}
+
+
+static void
+request_callback (void *cls,
+                 enum GNUNET_NAT_StatusCode result)
+{
+  // struct GNUNET_NAT_AutoHandle *ah = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Request callback: stop and quit\n");
+  stop_stun ();
+
+  // next_phase (ah); FIXME this always will be NULL, as called in test_stun()
+}
+
+
+/**
+ * Function called by NAT to report the outcome of the nat-test.
+ * Clean up and update GUI.
+ *
+ * @param cls the auto handle
+ * @param success currently always #GNUNET_OK
+ * @param emsg NULL on success, otherwise an error message
+ */
+static void
+result_callback (void *cls,
+                 enum GNUNET_NAT_StatusCode ret)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+
+  if (GNUNET_NAT_ERROR_SUCCESS == ret)
+    GNUNET_NAT_test_stop (ah->tst);
+  ah->tst = NULL;
+  ah->ret = ret;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              GNUNET_NAT_ERROR_SUCCESS == ret
+             ? _("NAT traversal with ICMP Server succeeded.\n")
+             : _("NAT traversal with ICMP Server failed.\n"));
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_ICMP_SERVER",
+                                        GNUNET_NAT_ERROR_SUCCESS == ret ? "NO" : "YES");
+  next_phase (ah);
+}
+
+
+/**
+ * Main function for the connection reversal test.
+ *
+ * @param cls the `struct GNUNET_NAT_AutoHandle`
+ */
+static void
+reversal_test (void *cls)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+
+  ah->task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             _("Testing connection reversal with ICMP server.\n"));
+  GNUNET_RESOLVER_connect (ah->cfg);
+  ah->tst = GNUNET_NAT_test_start (ah->cfg, GNUNET_YES, 0, 0, TIMEOUT,
+                                  &result_callback, ah);
+}
+
+
+/**
+ * Set our external IPv4 address based on the UPnP.
+ *
+ *
+ * @param cls closure with our setup context
+ * @param addr the address, NULL on errors
+ * @param emsg NULL on success, otherwise an error message
+ */
+static void
+set_external_ipv4 (void *cls,
+                   const struct in_addr *addr,
+                   enum GNUNET_NAT_StatusCode ret)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+  char buf[INET_ADDRSTRLEN];
+
+  ah->eh = NULL;
+  ah->ret = ret;
+  if (GNUNET_NAT_ERROR_SUCCESS != ret)
+  {
+    next_phase (ah);
+    return;
+  }
+  /* enable 'behind nat' */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             _("Detected external IP `%s'\n"),
+             inet_ntop (AF_INET,
+                        addr,
+                        buf,
+                        sizeof (buf)));
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "BEHIND_NAT", "YES");
+
+  /* set external IP address */
+  if (NULL == inet_ntop (AF_INET, addr, buf, sizeof (buf)))
+  {
+    GNUNET_break (0);
+    /* actually, this should never happen, as the caller already executed just
+     * this check, but for consistency (eg: future changes in the caller)
+     * we still need to report this error...
+     */
+    ah->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID;
+    next_phase (ah);
+    return;
+  }
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS",
+                                        buf);
+  ah->upnp_set_external_address = GNUNET_YES;
+  next_phase (ah);
+}
+
+
+/**
+ * Determine our external IPv4 address.
+ *
+ * @param ah auto setup context
+ */
+static void
+test_external_ip (struct GNUNET_NAT_AutoHandle *ah)
+{
+  if (GNUNET_NAT_ERROR_SUCCESS != ah->ret)
+    next_phase (ah);
+
+  // FIXME: CPS?
+  /* try to detect external IP */
+  ah->eh = GNUNET_NAT_mini_get_external_ipv4 (TIMEOUT,
+                                             &set_external_ipv4, ah);
+}
+
+
+/**
+ * Determine our external IPv4 address and port using an external STUN server
+ *
+ * @param ah auto setup context
+ */
+static void
+test_stun (struct GNUNET_NAT_AutoHandle *ah)
+{
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running STUN test\n");
+
+  /* Get port from the configuration */
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (ah->cfg,
+                                             "transport-udp",
+                                             "PORT",
+                                             &port))
+  {
+    port = 2086;
+  }
+
+  //Lets create the socket
+  lsock4 = bind_v4 ();
+  if (NULL == lsock4)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
+    next_phase(ah);
+    return;
+  }
+  else
+  {
+    //Lets call our function now when it accepts
+    ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
+                                            lsock4,
+                                           &do_udp_read,
+                                           ah);
+  }
+
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "STUN service listens on port %u\n",
+              (unsigned int) port);
+  if (GNUNET_NO ==
+      GNUNET_NAT_stun_make_request (stun_server,
+                                    stun_port,
+                                   lsock4,
+                                   &request_callback,
+                                   NULL))
+  {
+    /*An error happened*/
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STUN error, stopping\n");
+    stop_stun ();
+    next_phase (ah);
+  }
+}
+
+
+/**
+ * Process list of local IP addresses.  Find and set the
+ * one of the default interface.
+ *
+ * @param cls our `struct GNUNET_NAT_AutoHandle`
+ * @param name name of the interface (can be NULL for unknown)
+ * @param isDefault is this presumably the default interface
+ * @param addr address of this interface (can be NULL for unknown or unassigned)
+ * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
+ * @param netmask the network mask (can be NULL for unknown or unassigned))
+ * @param addrlen length of the @a addr and @a broadcast_addr
+ * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
+ */
+static int
+process_if (void *cls,
+           const char *name,
+           int isDefault,
+           const struct sockaddr *addr,
+           const struct sockaddr *broadcast_addr,
+           const struct sockaddr *netmask,
+           socklen_t addrlen)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+  const struct sockaddr_in *in;
+  char buf[INET_ADDRSTRLEN];
+
+
+  if ( (sizeof (struct sockaddr_in6) == addrlen) &&
+       (0 != memcmp (&in6addr_loopback, &((const struct sockaddr_in6 *) addr)->sin6_addr,
+                    sizeof (struct in6_addr))) &&
+       (! IN6_IS_ADDR_LINKLOCAL(&((const struct sockaddr_in6 *) addr)->sin6_addr)) )
+  {
+    ah->have_v6 = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               _("This system has a global IPv6 address, setting IPv6 to supported.\n"));
+
+    return GNUNET_OK;
+  }
+  if (addrlen != sizeof (struct sockaddr_in))
+    return GNUNET_OK;
+  in = (const struct sockaddr_in *) addr;
+
+
+  /* set internal IP address */
+  if (NULL == inet_ntop (AF_INET, &in->sin_addr, buf, sizeof (buf)))
+  {
+    GNUNET_break (0);
+    return GNUNET_OK;
+  }
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS",
+                                        buf);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             _("Detected internal network address `%s'.\n"),
+             buf);
+
+
+  ah->ret = GNUNET_NAT_ERROR_SUCCESS;
+
+  /* Check if our internal IP is the same as the External detect by STUN*/
+  if(ah->stun_ip && (strcmp(buf, ah->stun_ip) == 0) )
+  {
+    ah->internal_ip_is_public = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,"A internal IP is the sameas the external");
+    /* No need to continue*/
+    return GNUNET_SYSERR;
+  }
+
+  /* no need to continue iteration if we found the default */
+  if (!isDefault)
+    return GNUNET_OK;
+  else
+    return GNUNET_SYSERR;
+}
+
+
+/**
+ * Determine our local IP addresses; detect internal IP & IPv6-support
+ *
+ * @param ah auto setup context
+ */
+static void
+test_local_ip (struct GNUNET_NAT_AutoHandle *ah)
+{
+  ah->have_v6 = GNUNET_NO;
+  ah->ret = GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO; // reset to success if any of the IFs in below iterator has a valid IP
+  GNUNET_OS_network_interfaces_list (&process_if, ah);
+
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "DISABLEV6",
+                                        (GNUNET_YES == ah->have_v6) ? "NO" : "YES");
+  next_phase (ah);
+}
+
+
+/**
+ * We got disconnected from the NAT server.  Stop
+ * waiting for a reply.
+ *
+ * @param cls the `struct GNUNET_NAT_AutoHandle`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+                  enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+
+  GNUNET_MQ_destroy (ah->mq);
+  ah->mq = NULL;
+  /* wait a bit first? */
+  next_phase (ah);
+}
+
+
+/**
+ * Test if NAT has been punched
+ *
+ * @param ah auto setup context
+ */
+static void
+test_nat_punched (struct GNUNET_NAT_AutoHandle *ah)
+{
+  struct GNUNET_NAT_TestMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  if (! ah->stun_ip)
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         "We don't have a STUN IP");
+    next_phase (ah);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Asking gnunet-nat-server to connect to `%s'\n",
+       ah->stun_ip);
+  ah->mq = GNUNET_CLIENT_connect (ah->cfg,
+                                  "gnunet-nat-server",
+                                  NULL,
+                                  &mq_error_handler,
+                                  ah);
+  if (NULL == ah->mq)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to connect to `gnunet-nat-server'\n"));
+    next_phase (ah);
+    return;
+  }
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_NAT_TEST);
+  msg->dst_ipv4 = inet_addr (ah->stun_ip);
+  msg->dport = htons (ah->stun_port);
+  msg->data = port;
+  msg->is_tcp = htonl ((uint32_t) GNUNET_NO);
+  GNUNET_MQ_send (ah->mq,
+                  env);
+  if (NULL != ltask4)
+  {
+    GNUNET_SCHEDULER_cancel (ltask4);
+    ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
+                                            lsock4,
+                                            &do_udp_read,
+                                            ah);
+  }
+}
+
+
+/**
+ * Test if UPnPC works.
+ *
+ * @param ah auto setup context
+ */
+static void
+test_upnpc (struct GNUNET_NAT_AutoHandle *ah)
+{
+
+  int have_upnpc;
+
+  if (GNUNET_NAT_ERROR_SUCCESS != ah->ret)
+    next_phase (ah);
+
+  // test if upnpc is available
+  have_upnpc = (GNUNET_SYSERR !=
+               GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL));
+  //FIXME: test if upnpc is actually working, that is, if transports start to work once we use UPnP
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             (have_upnpc)
+             ? _("upnpc found, enabling its use\n")
+             : _("upnpc not found\n"));
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_UPNP",
+                                        (GNUNET_YES == have_upnpc) ? "YES" : "NO");
+  next_phase (ah);
+
+}
+
+
+/**
+ * Test if ICMP server is working
+ *
+ * @param ah auto setup context
+ */
+static void
+test_icmp_server (struct GNUNET_NAT_AutoHandle *ah)
+{
+
+  int ext_ip;
+  int nated;
+  int binary;
+  char *tmp;
+  char *helper;
+  ext_ip = GNUNET_NO;
+  nated = GNUNET_NO;
+  binary = GNUNET_NO;
+
+  tmp = NULL;
+  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
+  if ( (GNUNET_OK ==
+        GNUNET_CONFIGURATION_get_value_string (ah->cfg,
+                                               "nat",
+                                               "EXTERNAL_ADDRESS",
+                                               &tmp)) &&
+       (0 < strlen (tmp)) )
+  {
+    ext_ip = GNUNET_OK;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("test_icmp_server not possible, as we have no public IPv4 address\n"));
+  }
+  else
+    goto err;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (ah->cfg,
+                                            "nat",
+                                            "BEHIND_NAT"))
+  {
+    nated = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("test_icmp_server not possible, as we are not behind NAT\n"));
+  }
+  else
+    goto err;
+
+  if (GNUNET_YES ==
+      GNUNET_OS_check_helper_binary (helper,
+                                     GNUNET_YES,
+                                     "-d 127.0.0.1" ))
+  {
+    binary = GNUNET_OK; // use localhost as source for that one udp-port, ok for testing
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("No working gnunet-helper-nat-server found\n"));
+  }
+err:
+  GNUNET_free_non_null (tmp);
+  GNUNET_free (helper);
+
+  if ( (GNUNET_OK == ext_ip) &&
+       (GNUNET_YES == nated) &&
+       (GNUNET_OK == binary) )
+    ah->task = GNUNET_SCHEDULER_add_now (&reversal_test,
+                                         ah);
+  else
+    next_phase (ah);
+}
+
+
+/**
+ * Test if ICMP client is working
+ *
+ * @param ah auto setup context
+ */
+static void
+test_icmp_client (struct GNUNET_NAT_AutoHandle *ah)
+{
+  char *tmp;
+  char *helper;
+
+  tmp = NULL;
+  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
+  if ( (GNUNET_OK ==
+        GNUNET_CONFIGURATION_get_value_string (ah->cfg,
+                                               "nat",
+                                               "INTERNAL_ADDRESS",
+                                               &tmp)) &&
+       (0 < strlen (tmp)) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("test_icmp_client not possible, as we have no internal IPv4 address\n"));
+  }
+  else
+    goto err;
+
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_yesno (ah->cfg,
+                                            "nat",
+                                            "BEHIND_NAT"))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               _("test_icmp_server not possible, as we are not behind NAT\n"));
+  }
+  else
+    goto err;
+
+  if (GNUNET_YES ==
+      GNUNET_OS_check_helper_binary (helper,
+                                     GNUNET_YES,
+                                     "-d 127.0.0.1 127.0.0.2 42"))
+  {
+    // none of these parameters are actually used in privilege testing mode
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               _("No working gnunet-helper-nat-server found\n"));
+  }
+err:
+  GNUNET_free_non_null (tmp);
+  GNUNET_free (helper);
+
+  next_phase (ah);
+}
+
+
+/**
+ * Run the next phase of the auto test.
+ */
+static void
+next_phase (struct GNUNET_NAT_AutoHandle *ah)
+{
+  struct GNUNET_CONFIGURATION_Handle *diff;
+
+  ah->phase++;
+  switch (ah->phase)
+  {
+  case AUTO_INIT:
+    GNUNET_assert (0);
+    break;
+  case AUTO_EXTERNAL_IP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_EXTERNAL_IP\n");
+    test_external_ip (ah);
+    break;
+  case AUTO_STUN:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_STUN\n");
+    test_stun (ah);
+    break;
+  case AUTO_LOCAL_IP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_LOCAL_IP\n");
+    test_local_ip (ah);
+    break;
+  case AUTO_NAT_PUNCHED:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_NAT_PUNCHED\n");
+    test_nat_punched (ah);
+    break;
+  case AUTO_UPNPC:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_UPNPC\n");
+    test_upnpc (ah);
+    break;
+  case AUTO_ICMP_SERVER:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_ICMP_SERVER\n");
+    test_icmp_server (ah);
+    break;
+  case AUTO_ICMP_CLIENT:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_ICMP_CLIENT\n");
+    test_icmp_client (ah);
+    break;
+  case AUTO_DONE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Done with tests\n");
+    if (!ah->internal_ip_is_public)
+    {
+      GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                             "nat",
+                                             "BEHIND_NAT",
+                                             "YES");
+
+      if (ah->connected_back)
+      {
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "PUNCHED_NAT",
+                                               "YES");
+      }
+      else
+      {
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "PUNCHED_NAT",
+                                               "NO");
+      }
+
+      if (ah->stun_ip)
+      {
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "EXTERNAL_ADDRESS",
+                                               ah->stun_ip);
+        if (ah->connected_back)
+        {
+          ah->type = GNUNET_NAT_TYPE_STUN_PUNCHED_NAT;
+          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                                 "nat",
+                                                 "USE_STUN",
+                                                 "YES");
+        }
+        else
+        {
+          ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT;
+          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                                 "nat",
+                                                 "USE_STUN",
+                                                 "NO");
+        }
+
+      }
+      if (0 != ah->stun_port)
+      {
+        GNUNET_CONFIGURATION_set_value_number (ah->cfg,
+                                               "transport-udp",
+                                               "ADVERTISED_PORT",
+                                               ah->stun_port);
+      }
+
+    }
+    else
+    {
+      //The internal IP is the same as public, but we didn't got a incoming connection
+      if (ah->connected_back)
+      {
+        ah->type = GNUNET_NAT_TYPE_NO_NAT;
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "BEHIND_NAT",
+                                               "NO");
+      }
+      else
+      {
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "BEHIND_NAT",
+                                               "YES");
+        ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT;
+        if (ah->stun_ip)
+        {
+          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                                 "nat",
+                                                 "EXTERNAL_ADDRESS",
+                                                 ah->stun_ip);
+        }
+        if (0 != ah->stun_port)
+        {
+          GNUNET_CONFIGURATION_set_value_number (ah->cfg,
+                                                 "transport-udp",
+                                                 "ADVERTISED_PORT",
+                                                 ah->stun_port);
+
+        }
+      }
+    }
+
+    diff = GNUNET_CONFIGURATION_get_diff (ah->initial_cfg,
+                                          ah->cfg);
+
+
+    ah->fin_cb (ah->fin_cb_cls,
+                diff,
+                ah->ret,
+                ah->type);
+    GNUNET_CONFIGURATION_destroy (diff);
+    GNUNET_NAT_autoconfig_cancel (ah);
+  }
+}
+
+
+/**
+ * Start auto-configuration routine.  The resolver service should
+ * be available when this function is called.
+ *
+ * @param cfg initial configuration
+ * @param cb function to call with autoconfiguration result
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel operation
+ */
+struct GNUNET_NAT_AutoHandle *
+GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                            GNUNET_NAT_AutoResultCallback cb,
+                            void *cb_cls)
+{
+  struct GNUNET_NAT_AutoHandle *ah;
+
+  ah = GNUNET_new (struct GNUNET_NAT_AutoHandle);
+  ah->fin_cb = cb;
+  ah->fin_cb_cls = cb_cls;
+  ah->ret = GNUNET_NAT_ERROR_SUCCESS;
+  ah->cfg = GNUNET_CONFIGURATION_dup (cfg);
+  ah->initial_cfg = GNUNET_CONFIGURATION_dup (cfg);
+
+  /* never use loopback addresses if user wanted autoconfiguration */
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                         "nat",
+                                        "USE_LOCALADDR",
+                                        "NO");
+
+  next_phase (ah);
+  return ah;
+}
+
+
+/**
+ * Abort autoconfiguration.
+ *
+ * @param ah handle for operation to abort
+ */
+void
+GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah)
+{
+  if (NULL != ah->tst)
+  {
+    GNUNET_NAT_test_stop (ah->tst);
+    ah->tst = NULL;
+  }
+  if (NULL != ah->eh)
+  {
+    GNUNET_NAT_mini_get_external_ipv4_cancel (ah->eh);
+    ah->eh = NULL;
+  }
+  if (NULL != ah->mq)
+  {
+    GNUNET_MQ_destroy (ah->mq);
+    ah->mq = NULL;
+  }
+  if (NULL != ah->task)
+  {
+    GNUNET_SCHEDULER_cancel (ah->task);
+    ah->task = NULL;
+  }
+  GNUNET_CONFIGURATION_destroy (ah->cfg);
+  GNUNET_CONFIGURATION_destroy (ah->initial_cfg);
+  GNUNET_free (ah);
+}
+
+
+/* end of nat_auto.c */
diff --git a/src/nat-auto/nat-auto.conf.in b/src/nat-auto/nat-auto.conf.in
new file mode 100644 (file)
index 0000000..9461ffc
--- /dev/null
@@ -0,0 +1,15 @@
+[nat-auto]
+AUTOSTART = @AUTOSTART@
+@UNIXONLY@ PORT = 2124
+HOSTNAME = localhost
+BINARY = gnunet-service-nat-auto
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nat-auto.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
+
+[gnunet-nat-server]
+HOSTNAME = gnunet.org
+PORT = 5724
+NOARMBIND = YES
diff --git a/src/nat-auto/nat-auto.h b/src/nat-auto/nat-auto.h
new file mode 100644 (file)
index 0000000..07b5a5b
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2011, 2016, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file src/nat-auto/nat-auto.h
+ * @brief Messages for interaction with gnunet-nat-auto-service
+ * @author Christian Grothoff
+ *
+ */
+#ifndef NAT_AUTO_H
+#define NAT_AUTO_H
+#include "gnunet_util_lib.h"
+
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Request to test NAT traversal, sent to the gnunet-nat-server
+ * (not the service!).
+ */
+struct GNUNET_NAT_AUTO_TestMessage
+{
+  /**
+   * Header with type #GNUNET_MESSAGE_TYPE_NAT_TEST
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * IPv4 target IP address
+   */
+  uint32_t dst_ipv4;
+
+  /**
+   * Port to use, 0 to send dummy ICMP response.
+   */
+  uint16_t dport;
+
+  /**
+   * Data to send OR advertised-port (in NBO) to use for dummy ICMP.
+   */
+  uint16_t data;
+
+  /**
+   * #GNUNET_YES for TCP, #GNUNET_NO for UDP.
+   */
+  int32_t is_tcp;
+
+};
+
+
+/**
+ * Client requesting automatic configuration.
+ */
+struct GNUNET_NAT_AUTO_AutoconfigRequestMessage
+{
+  /**
+   * Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG
+   */
+  struct GNUNET_MessageHeader header;
+
+  /* Followed by configuration (diff, serialized, compressed) */
+  
+};
+
+
+/**
+ * Service responding with proposed configuration.
+ */
+struct GNUNET_NAT_AUTO_AutoconfigResultMessage
+{
+  /**
+   * Header with type #GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+  
+  /**
+   * An `enum GNUNET_NAT_StatusCode` in NBO.
+   */
+  int32_t status_code GNUNET_PACKED;
+
+  /**
+   * An `enum GNUNET_NAT_Type` in NBO.
+   */
+  int32_t type GNUNET_PACKED;
+
+  /* Followed by configuration (diff, serialized, compressed) */
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/nat-auto/nat_auto_api.c b/src/nat-auto/nat_auto_api.c
new file mode 100644 (file)
index 0000000..a5b41ac
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2007-2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @author Christian Grothoff
+ * @author Milan Bouchet-Valat
+ *
+ * @file nat-auto/nat_auto_api.c
+ * Routines for NAT auto configuration.
+ */
+#include "platform.h"
+#include "gnunet_nat_service.h"
+#include "gnunet_nat_auto_service.h"
+#include "nat-auto.h"
+
+
+
+/**
+ * Handle to auto-configuration in progress.
+ */
+struct GNUNET_NAT_AUTO_AutoHandle
+{
+
+  /**
+   * Configuration we use.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+  
+  /**
+   * Message queue for communicating with the NAT service.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Function called with the result from the autoconfiguration.
+   */
+  GNUNET_NAT_AUTO_AutoResultCallback arc;
+
+  /**
+   * Closure for @e arc.
+   */
+  void *arc_cls;
+
+};
+
+
+/**
+ * Converts `enum GNUNET_NAT_StatusCode` to string
+ *
+ * @param err error code to resolve to a string
+ * @return point to a static string containing the error code
+ */
+const char *
+GNUNET_NAT_AUTO_status2string (enum GNUNET_NAT_StatusCode err)
+{
+  switch (err)
+  {
+  case GNUNET_NAT_ERROR_SUCCESS:
+    return _ ("Operation Successful");
+  case GNUNET_NAT_ERROR_IPC_FAILURE:
+    return _ ("IPC failure");
+  case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
+    return _ ("Failure in network subsystem, check permissions.");
+  case GNUNET_NAT_ERROR_TIMEOUT:
+    return _ ("Encountered timeout while performing operation");
+  case GNUNET_NAT_ERROR_NOT_ONLINE:
+    return _ ("detected that we are offline");
+  case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
+    return _ ("`upnpc` command not found");
+  case GNUNET_NAT_ERROR_UPNPC_FAILED:
+    return _ ("Failed to run `upnpc` command");
+  case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
+    return _ ("`upnpc' command took too long, process killed");
+  case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
+    return _ ("`upnpc' command failed to establish port mapping");
+  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
+    return _ ("`external-ip' command not found");
+  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
+    return _ ("Failed to run `external-ip` command");
+  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
+    return _ ("`external-ip' command output invalid");
+  case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
+    return _ ("no valid address was returned by `external-ip'");
+  case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
+    return _ ("Could not determine interface with internal/local network address");
+  case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
+    return _ ("No functioning gnunet-helper-nat-server installation found");
+  case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
+    return _ ("NAT test could not be initialized");
+  case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
+    return _ ("NAT test timeout reached");
+  case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
+    return _ ("could not register NAT");
+  case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
+    return _ ("No working gnunet-helper-nat-client installation found");
+  default:
+    return "unknown status code";
+  }
+}
+
+
+/**
+ * Check result from autoconfiguration attempt.
+ *
+ * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle`
+ * @param res the result
+ * @return #GNUNET_OK if @a res is well-formed (always for now)
+ */
+static int
+check_auto_result (void *cls,
+                  const struct GNUNET_NAT_AUTO_AutoconfigResultMessage *res)
+{
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle result from autoconfiguration attempt.
+ *
+ * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle`
+ * @param res the result
+ */
+static void
+handle_auto_result (void *cls,
+                   const struct GNUNET_NAT_AUTO_AutoconfigResultMessage *res)
+{
+  struct GNUNET_NAT_AUTO_AutoHandle *ah = cls;
+  size_t left;
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+  enum GNUNET_NAT_Type type
+    = (enum GNUNET_NAT_Type) ntohl (res->type);
+  enum GNUNET_NAT_StatusCode status
+    = (enum GNUNET_NAT_StatusCode) ntohl (res->status_code);
+
+  left = ntohs (res->header.size) - sizeof (*res);
+  cfg = GNUNET_CONFIGURATION_create ();
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_deserialize (cfg,
+                                       (const char *) &res[1],
+                                       left,
+                                       GNUNET_NO))
+  {
+    GNUNET_break (0);
+    ah->arc (ah->arc_cls,
+            NULL,
+            GNUNET_NAT_ERROR_IPC_FAILURE,
+            type);
+  }
+  else
+  {
+    ah->arc (ah->arc_cls,
+            cfg,
+            status,
+            type);
+  }
+  GNUNET_CONFIGURATION_destroy (cfg);
+  GNUNET_NAT_AUTO_autoconfig_cancel (ah);
+}
+
+
+/**
+ * Handle queue errors by reporting autoconfiguration failure.
+ *
+ * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle *`
+ * @param error details about the error
+ */
+static void
+ah_error_handler (void *cls,
+                 enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_NAT_AUTO_AutoHandle *ah = cls;
+
+  ah->arc (ah->arc_cls,
+          NULL,
+          GNUNET_NAT_ERROR_IPC_FAILURE,
+          GNUNET_NAT_TYPE_UNKNOWN);
+  GNUNET_NAT_AUTO_autoconfig_cancel (ah);
+}
+
+
+/**
+ * Start auto-configuration routine.  The transport adapters should
+ * be stopped while this function is called.
+ *
+ * @param cfg initial configuration
+ * @param cb function to call with autoconfiguration result
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel operation
+ */
+struct GNUNET_NAT_AUTO_AutoHandle *
+GNUNET_NAT_AUTO_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                            GNUNET_NAT_AUTO_AutoResultCallback cb,
+                            void *cb_cls)
+{
+  struct GNUNET_NAT_AUTO_AutoHandle *ah = GNUNET_new (struct GNUNET_NAT_AUTO_AutoHandle);
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_var_size (auto_result,
+                          GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT,
+                          struct GNUNET_NAT_AUTO_AutoconfigResultMessage,
+                          ah),
+    GNUNET_MQ_handler_end ()
+  };
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *req;
+  char *buf;
+  size_t size;
+
+  buf = GNUNET_CONFIGURATION_serialize (cfg,
+                                       &size);
+  if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*req))
+  {
+    GNUNET_break (0);
+    GNUNET_free (buf);
+    GNUNET_free (ah);
+    return NULL;
+  }
+  ah->arc = cb;
+  ah->arc_cls = cb_cls;
+  ah->mq = GNUNET_CLIENT_connect (cfg,
+                                 "nat",
+                                 handlers,
+                                 &ah_error_handler,
+                                 ah);
+  if (NULL == ah->mq)
+  {
+    GNUNET_break (0);
+    GNUNET_free (buf);
+    GNUNET_free (ah);
+    return NULL;
+  }
+  env = GNUNET_MQ_msg_extra (req,
+                            size,
+                            GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG);
+  GNUNET_memcpy (&req[1],
+                buf,
+                size);
+  GNUNET_free (buf);
+  GNUNET_MQ_send (ah->mq,
+                 env);
+  return ah;
+}
+
+
+/**
+ * Abort autoconfiguration.
+ *
+ * @param ah handle for operation to abort
+ */
+void
+GNUNET_NAT_AUTO_autoconfig_cancel (struct GNUNET_NAT_AUTO_AutoHandle *ah)
+{
+  GNUNET_MQ_destroy (ah->mq);
+  GNUNET_free (ah);
+}
+
+/* end of nat_api_auto.c */
diff --git a/src/nat-auto/nat_auto_api_test.c b/src/nat-auto/nat_auto_api_test.c
new file mode 100644 (file)
index 0000000..fb2bcd6
--- /dev/null
@@ -0,0 +1,644 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2011, 2016 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file nat/nat_auto_api_test.c
+ * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server)
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_nat_service.h"
+#include "gnunet_nat_auto_service.h"
+#include "nat-auto.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
+
+#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+
+/**
+ * Entry we keep for each incoming connection.
+ */
+struct NatActivity
+{
+  /**
+   * This is a doubly-linked list.
+   */
+  struct NatActivity *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct NatActivity *prev;
+
+  /**
+   * Socket of the incoming connection.
+   */
+  struct GNUNET_NETWORK_Handle *sock;
+
+  /**
+   * Handle of the master context.
+   */
+  struct GNUNET_NAT_AUTO_Test *h;
+
+  /**
+   * Task reading from the incoming connection.
+   */
+  struct GNUNET_SCHEDULER_Task *rtask;
+};
+
+
+/**
+ * Entry we keep for each connection to the gnunet-nat-service.
+ */
+struct ClientActivity
+{
+  /**
+   * This is a doubly-linked list.
+   */
+  struct ClientActivity *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct ClientActivity *prev;
+
+  /**
+   * Socket of the incoming connection.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Handle to overall NAT test.
+   */
+  struct GNUNET_NAT_AUTO_Test *h;
+
+};
+
+
+/**
+ * Handle to a NAT test.
+ */
+struct GNUNET_NAT_AUTO_Test
+{
+
+  /**
+   * Configuration used
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Function to call with success report
+   */
+  GNUNET_NAT_TestCallback report;
+
+  /**
+   * Closure for @e report.
+   */
+  void *report_cls;
+
+  /**
+   * Handle to NAT traversal in use
+   */
+  struct GNUNET_NAT_Handle *nat;
+
+  /**
+   * Handle to listen socket, or NULL
+   */
+  struct GNUNET_NETWORK_Handle *lsock;
+
+  /**
+   * Head of list of nat activities.
+   */
+  struct NatActivity *na_head;
+
+  /**
+   * Tail of list of nat activities.
+   */
+  struct NatActivity *na_tail;
+
+  /**
+   * Head of list of client activities.
+   */
+  struct ClientActivity *ca_head;
+
+  /**
+   * Tail of list of client activities.
+   */
+  struct ClientActivity *ca_tail;
+
+  /**
+   * Identity of task for the listen socket (if any)
+   */
+  struct GNUNET_SCHEDULER_Task *ltask;
+
+  /**
+   * Task identifier for the timeout (if any)
+   */
+  struct GNUNET_SCHEDULER_Task *ttask;
+
+  /**
+   * Section name of plugin to test.
+   */
+  char *section_name;
+
+  /**
+   * IPPROTO_TCP or IPPROTO_UDP.
+   */
+  int proto;
+
+  /**
+   * Data that should be transmitted or source-port.
+   */
+  uint16_t data;
+
+  /**
+   * Status code to be reported to the timeout/status call
+   */
+  enum GNUNET_NAT_StatusCode status;
+};
+
+
+/**
+ * Function called from #GNUNET_NAT_register whenever someone asks us
+ * to do connection reversal.
+ *
+ * @param cls closure, our `struct GNUNET_NAT_Handle`
+ * @param addr public IP address of the other peer
+ * @param addrlen actual lenght of the @a addr
+ */
+static void
+reversal_cb (void *cls,
+             const struct sockaddr *addr,
+             socklen_t addrlen)
+{
+  struct GNUNET_NAT_AUTO_Test *h = cls;
+  const struct sockaddr_in *sa;
+
+  if (sizeof (struct sockaddr_in) != addrlen)
+    return;
+  sa = (const struct sockaddr_in *) addr;
+  if (h->data != sa->sin_port)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Received connection reversal request for wrong port\n");
+    return;                     /* wrong port */
+  }
+  /* report success */
+  h->report (h->report_cls,
+             GNUNET_NAT_ERROR_SUCCESS);
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls the `struct GNUNET_NAT_AUTO_Test`
+ */
+static void
+do_udp_read (void *cls)
+{
+  struct GNUNET_NAT_AUTO_Test *tst = cls;
+  uint16_t data;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  tst->ltask =
+      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                     tst->lsock,
+                                     &do_udp_read,
+                                     tst);
+  if ((NULL != tc->write_ready) &&
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                   tst->lsock)) &&
+      (sizeof (data) ==
+       GNUNET_NETWORK_socket_recv (tst->lsock,
+                                   &data,
+                                   sizeof (data))))
+  {
+    if (data == tst->data)
+      tst->report (tst->report_cls,
+                   GNUNET_NAT_ERROR_SUCCESS);
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Received data mismatches expected value\n");
+  }
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Failed to receive data from inbound connection\n");
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls the `struct NatActivity`
+ */
+static void
+do_read (void *cls)
+{
+  struct NatActivity *na = cls;
+  struct GNUNET_NAT_AUTO_Test *tst;
+  uint16_t data;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  na->rtask = NULL;
+  tst = na->h;
+  GNUNET_CONTAINER_DLL_remove (tst->na_head,
+                              tst->na_tail,
+                              na);
+  if ((NULL != tc->write_ready) &&
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                   na->sock)) &&
+      (sizeof (data) ==
+       GNUNET_NETWORK_socket_recv (na->sock,
+                                   &data,
+                                   sizeof (data))))
+  {
+    if (data == tst->data)
+      tst->report (tst->report_cls,
+                   GNUNET_NAT_ERROR_SUCCESS);
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Received data does not match expected value\n");
+  }
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Failed to receive data from inbound connection\n");
+  GNUNET_NETWORK_socket_close (na->sock);
+  GNUNET_free (na);
+}
+
+
+/**
+ * Activity on our listen socket. Accept the
+ * incoming connection.
+ *
+ * @param cls the `struct GNUNET_NAT_AUTO_Test`
+ */
+static void
+do_accept (void *cls)
+{
+  struct GNUNET_NAT_AUTO_Test *tst = cls;
+  struct GNUNET_NETWORK_Handle *s;
+  struct NatActivity *wl;
+
+  tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                              tst->lsock,
+                                              &do_accept,
+                                              tst);
+  s = GNUNET_NETWORK_socket_accept (tst->lsock,
+                                    NULL,
+                                    NULL);
+  if (NULL == s)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
+                         "accept");
+    return;                     /* odd error */
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got an inbound connection, waiting for data\n");
+  wl = GNUNET_new (struct NatActivity);
+  wl->sock = s;
+  wl->h = tst;
+  wl->rtask =
+    GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                   wl->sock,
+                                   &do_read,
+                                   wl);
+  GNUNET_CONTAINER_DLL_insert (tst->na_head,
+                              tst->na_tail,
+                              wl);
+}
+
+
+/**
+ * We got disconnected from the NAT server.  Stop
+ * waiting for a reply.
+ *
+ * @param cls the `struct ClientActivity`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+                  enum GNUNET_MQ_Error error)
+{
+  struct ClientActivity *ca = cls;
+  struct GNUNET_NAT_AUTO_Test *tst = ca->h;
+
+  GNUNET_CONTAINER_DLL_remove (tst->ca_head,
+                               tst->ca_tail,
+                               ca);
+  GNUNET_MQ_destroy (ca->mq);
+  GNUNET_free (ca);
+}
+
+
+/**
+ * Address-callback, used to send message to gnunet-nat-server.
+ *
+ * @param cls closure
+ * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
+ *     the previous (now invalid) one
+ * @param ac address class the address belongs to
+ * @param addr either the previous or the new public IP address
+ * @param addrlen actual length of the @a addr
+ */
+static void
+addr_cb (void *cls,
+         int add_remove,
+         enum GNUNET_NAT_AddressClass ac,
+         const struct sockaddr *addr,
+         socklen_t addrlen)
+{
+  struct GNUNET_NAT_AUTO_Test *h = cls;
+  struct ClientActivity *ca;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_NAT_AUTO_TestMessage *msg;
+  const struct sockaddr_in *sa;
+
+  if (GNUNET_YES != add_remove)
+    return;
+  if (addrlen != sizeof (struct sockaddr_in))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "NAT test ignores IPv6 address `%s' returned from NAT library\n",
+        GNUNET_a2s (addr,
+                     addrlen));
+    return;                     /* ignore IPv6 here */
+  }
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Asking gnunet-nat-server to connect to `%s'\n",
+       GNUNET_a2s (addr,
+                   addrlen));
+
+  ca = GNUNET_new (struct ClientActivity);
+  ca->h = h;
+  ca->mq = GNUNET_CLIENT_connect (h->cfg,
+                                  "gnunet-nat-server",
+                                  NULL,
+                                  &mq_error_handler,
+                                  ca);
+  if (NULL == ca->mq)
+  {
+    GNUNET_free (ca);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to connect to `gnunet-nat-server'\n"));
+    return;
+  }
+  GNUNET_CONTAINER_DLL_insert (h->ca_head,
+                               h->ca_tail,
+                               ca);
+  sa = (const struct sockaddr_in *) addr;
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_NAT_TEST);
+  msg->dst_ipv4 = sa->sin_addr.s_addr;
+  msg->dport = sa->sin_port;
+  msg->data = h->data;
+  msg->is_tcp = htonl ((uint32_t) (h->proto == IPPROTO_TCP));
+  GNUNET_MQ_send (ca->mq,
+                  env);
+}
+
+
+/**
+ * Calls the report-callback reporting failure.
+ *
+ * Destroys the nat handle after the callback has been processed.
+ *
+ * @param cls handle to the timed out NAT test
+ */
+static void
+do_fail (void *cls)
+{
+  struct GNUNET_NAT_AUTO_Test *nh = cls;
+
+  nh->ttask = NULL;
+  nh->report (nh->report_cls,
+              nh->status);
+}
+
+
+/**
+ * Start testing if NAT traversal works using the given configuration.
+ *  The transport adapters should be down while using this function.
+ *
+ * @param cfg configuration for the NAT traversal
+ * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
+ * @param section_name configuration section to use for configuration
+ * @param report function to call with the result of the test
+ * @param report_cls closure for @a report
+ * @return handle to cancel NAT test
+ */
+struct GNUNET_NAT_AUTO_Test *
+GNUNET_NAT_AUTO_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                           uint8_t proto,
+                           const char *section_name,
+                           GNUNET_NAT_TestCallback report,
+                           void *report_cls)
+{
+  struct GNUNET_NAT_AUTO_Test *nh;
+  unsigned long long bnd_port;
+  struct sockaddr_in sa;
+  const struct sockaddr *addrs[] = {
+    (const struct sockaddr *) &sa
+  };
+  const socklen_t addrlens[] = {
+    sizeof (sa)
+  };
+
+  if ( (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_number (cfg,
+                                               section_name,
+                                               "PORT",
+                                               &bnd_port)) ||
+       (bnd_port > 65535) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to find valid PORT in section `%s'\n"),
+                section_name);
+    return NULL;
+  }
+
+  memset (&sa, 0, sizeof (sa));
+  sa.sin_family = AF_INET;
+  sa.sin_port = htons ((uint16_t) bnd_port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa.sin_len = sizeof (sa);
+#endif
+
+  nh = GNUNET_new (struct GNUNET_NAT_AUTO_Test);
+  nh->cfg = cfg;
+  nh->proto = proto;
+  nh->section_name = GNUNET_strdup (section_name);
+  nh->report = report;
+  nh->report_cls = report_cls;
+  nh->status = GNUNET_NAT_ERROR_SUCCESS;
+  if (0 == bnd_port)
+  {
+    nh->nat
+      = GNUNET_NAT_register (cfg,
+                             section_name,
+                             proto,
+                             0, NULL, NULL,
+                            &addr_cb,
+                             &reversal_cb,
+                             nh);
+  }
+  else
+  {
+    nh->lsock
+      = GNUNET_NETWORK_socket_create (AF_INET,
+                                      proto,
+                                      0);
+    if ( (NULL == nh->lsock) ||
+         (GNUNET_OK !=
+          GNUNET_NETWORK_socket_bind (nh->lsock,
+                                      (const struct sockaddr *) &sa,
+                                      sizeof (sa))))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
+                  GNUNET_a2s ((const struct sockaddr *) &sa,
+                              sizeof (sa)),
+                  STRERROR (errno));
+      if (NULL != nh->lsock)
+      {
+        GNUNET_NETWORK_socket_close (nh->lsock);
+        nh->lsock = NULL;
+      }
+      nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
+      nh->ttask = GNUNET_SCHEDULER_add_now (&do_fail,
+                                            nh);
+      return nh;
+    }
+    if (IPPROTO_TCP == proto)
+    {
+      GNUNET_break (GNUNET_OK ==
+                    GNUNET_NETWORK_socket_listen (nh->lsock,
+                                                  5));
+      nh->ltask =
+          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                         nh->lsock,
+                                        &do_accept,
+                                         nh);
+    }
+    else
+    {
+      nh->ltask =
+          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                         nh->lsock,
+                                        &do_udp_read,
+                                         nh);
+    }
+    LOG (GNUNET_ERROR_TYPE_INFO,
+        "NAT test listens on port %u (%s)\n",
+        bnd_port,
+        (IPPROTO_TCP == proto) ? "tcp" : "udp");
+    nh->nat = GNUNET_NAT_register (cfg,
+                                   section_name,
+                                   proto,
+                                   1,
+                                   addrs,
+                                   addrlens,
+                                   &addr_cb,
+                                   NULL,
+                                   nh);
+    if (NULL == nh->nat)
+    {
+      LOG (GNUNET_ERROR_TYPE_INFO,
+          _("NAT test failed to start NAT library\n"));
+      if (NULL != nh->ltask)
+      {
+        GNUNET_SCHEDULER_cancel (nh->ltask);
+        nh->ltask = NULL;
+      }
+      if (NULL != nh->lsock)
+      {
+        GNUNET_NETWORK_socket_close (nh->lsock);
+        nh->lsock = NULL;
+      }
+      nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
+      nh->ttask = GNUNET_SCHEDULER_add_now (&do_fail,
+                                            nh);
+      return nh;
+    }
+  }
+  return nh;
+}
+
+
+/**
+ * Stop an active NAT test.
+ *
+ * @param tst test to stop.
+ */
+void
+GNUNET_NAT_AUTO_test_stop (struct GNUNET_NAT_AUTO_Test *tst)
+{
+  struct NatActivity *pos;
+  struct ClientActivity *cpos;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Stopping NAT test\n");
+  while (NULL != (cpos = tst->ca_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (tst->ca_head,
+                                tst->ca_tail,
+                                cpos);
+    GNUNET_MQ_destroy (cpos->mq);
+    GNUNET_free (cpos);
+  }
+  while (NULL != (pos = tst->na_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (tst->na_head,
+                                tst->na_tail,
+                                pos);
+    GNUNET_SCHEDULER_cancel (pos->rtask);
+    GNUNET_NETWORK_socket_close (pos->sock);
+    GNUNET_free (pos);
+  }
+  if (NULL != tst->ttask)
+  {
+    GNUNET_SCHEDULER_cancel (tst->ttask);
+    tst->ttask = NULL;
+  }
+  if (NULL != tst->ltask)
+  {
+    GNUNET_SCHEDULER_cancel (tst->ltask);
+    tst->ltask = NULL;
+  }
+  if (NULL != tst->lsock)
+  {
+    GNUNET_NETWORK_socket_close (tst->lsock);
+    tst->lsock = NULL;
+  }
+  if (NULL != tst->nat)
+  {
+    GNUNET_NAT_unregister (tst->nat);
+    tst->nat = NULL;
+  }
+  GNUNET_free (tst->section_name);
+  GNUNET_free (tst);
+}
+
+/* end of nat_auto_api_test.c */
index 1dd8e44b9fa24b2e769f8cece75a3f5b5ba8eaba..3dc001dd79851e77cc5effa74f43b079b3390e1c 100644 (file)
@@ -34,7 +34,6 @@ install-exec-hook:
 endif
 
 bin_PROGRAMS = \
- gnunet-nat-server \
  gnunet-nat
 
 libexec_PROGRAMS = \
@@ -42,12 +41,6 @@ libexec_PROGRAMS = \
  gnunet-service-nat
 
 
-gnunet_nat_server_SOURCES = \
- gnunet-nat-server.c nat.h
-gnunet_nat_server_LDADD = \
-  libgnunetnat.la \
-  $(top_builddir)/src/util/libgnunetutil.la
-
 gnunet_helper_nat_server_SOURCES = \
  $(NATSERVER)
 
@@ -67,26 +60,11 @@ if USE_COVERAGE
 endif
 
 lib_LTLIBRARIES = \
-  libgnunetnat.la \
   libgnunetnatnew.la 
 
-libgnunetnat_la_SOURCES = \
-  nat.c nat.h \
-  nat_auto.c \
-  nat_test.c \
-  nat_mini.c \
-  nat_stun.c
-libgnunetnat_la_LIBADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(GN_LIBINTL) @EXT_LIBS@ 
-libgnunetnat_la_LDFLAGS = \
-  $(GN_LIB_LDFLAGS) $(WINFLAGS) \
-  -version-info 1:1:1
-
 libgnunetnatnew_la_SOURCES = \
   nat_api.c \
   nat_api_stun.c nat_stun.h \
-  nat_api_test.c \
   nat.h
 libgnunetnatnew_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
@@ -96,7 +74,8 @@ libgnunetnatnew_la_LDFLAGS = \
   -version-info 2:0:0
 
 gnunet_service_nat_SOURCES = \
- gnunet-service-nat.c \
+ gnunet-service-nat.c gnunet-service-nat.h \
+ gnunet-service-nat_externalip.c gnunet-service-nat_externalip.h \
  gnunet-service-nat_stun.c gnunet-service-nat_stun.h \
  gnunet-service-nat_mini.c gnunet-service-nat_mini.h \
  gnunet-service-nat_helper.c gnunet-service-nat_helper.h
@@ -107,40 +86,40 @@ gnunet_service_nat_LDADD = \
   -lgcrypt \
   $(GN_LIBINTL)
 
-check_PROGRAMS = \
-  test_nat \
-  test_nat_mini \
-  test_nat_test \
-  test_stun
+#check_PROGRAMS = \
+#  test_nat \
+#  test_nat_mini \
+#  test_nat_test \
+#  test_stun
 
 if ENABLE_TEST_RUN
  AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
  TESTS = $(check_PROGRAMS)
 endif
 
-test_nat_SOURCES = \
-  test_nat.c
-test_nat_LDADD = \
- libgnunetnat.la \
- $(top_builddir)/src/util/libgnunetutil.la 
-
-test_nat_mini_SOURCES = \
-  test_nat_mini.c
-test_nat_mini_LDADD = \
- libgnunetnat.la \
- $(top_builddir)/src/util/libgnunetutil.la 
-
-test_nat_test_SOURCES = \
-  test_nat_test.c
-test_nat_test_LDADD = \
- libgnunetnat.la \
- $(top_builddir)/src/util/libgnunetutil.la 
-
-test_stun_SOURCES = \
-  test_stun.c
-test_stun_LDADD = \
- libgnunetnat.la \
- $(top_builddir)/src/util/libgnunetutil.la 
+#test_nat_SOURCES = \
+#  test_nat.c
+#test_nat_LDADD = \
+# libgnunetnat.la \
+# $(top_builddir)/src/util/libgnunetutil.la 
+
+#test_nat_mini_SOURCES = \
+#  test_nat_mini.c
+#test_nat_mini_LDADD = \
+# libgnunetnat.la \
+# $(top_builddir)/src/util/libgnunetutil.la 
+
+#test_nat_test_SOURCES = \
+#  test_nat_test.c
+#test_nat_test_LDADD = \
+# libgnunetnat.la \
+# $(top_builddir)/src/util/libgnunetutil.la 
+
+#test_stun_SOURCES = \
+#  test_stun.c
+#test_stun_LDADD = \
+# libgnunetnat.la \
+# $(top_builddir)/src/util/libgnunetutil.la 
 
 EXTRA_DIST = \
  test_nat_data.conf \
diff --git a/src/nat/gnunet-nat-server.c b/src/nat/gnunet-nat-server.c
deleted file mode 100644 (file)
index 1692a8e..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2011 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file src/nat/gnunet-nat-server.c
- * @brief Daemon to run on 'gnunet.org' to help test NAT traversal code
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_nat_lib.h"
-#include "gnunet_protocols.h"
-#include "nat.h"
-
-
-/**
- * Our server.
- */
-static struct GNUNET_SERVER_Handle *server;
-
-/**
- * Our configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-
-/**
- * Try contacting the peer using autonomous NAT traveral method.
- *
- * @param dst_ipv4 IPv4 address to send the fake ICMP message
- * @param dport destination port to include in ICMP message
- * @param is_tcp mark for TCP (#GNUNET_YES)  or UDP (#GNUNET_NO)
- */
-static void
-try_anat (uint32_t dst_ipv4,
-          uint16_t dport,
-          int is_tcp)
-{
-  struct GNUNET_NAT_Handle *h;
-  struct sockaddr_in sa;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Asking for connection reversal with %x and code %u\n",
-              (unsigned int) dst_ipv4,
-              (unsigned int) dport);
-  h = GNUNET_NAT_register (cfg,
-                           is_tcp,
-                           dport,
-                           0,
-                           NULL, NULL, NULL, NULL, NULL, NULL);
-  memset (&sa, 0, sizeof (sa));
-  sa.sin_family = AF_INET;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  sa.sin_len = sizeof (sa);
-#endif
-  sa.sin_addr.s_addr = dst_ipv4;
-  GNUNET_NAT_run_client (h, &sa);
-  GNUNET_NAT_unregister (h);
-}
-
-
-/**
- * Closure for #tcp_send.
- */
-struct TcpContext
-{
-  /**
-   * TCP  socket.
-   */
-  struct GNUNET_NETWORK_Handle *s;
-
-  /**
-   * Data to transmit.
-   */
-  uint16_t data;
-};
-
-
-/**
- * Task called by the scheduler once we can do the TCP send
- * (or once we failed to connect...).
- *
- * @param cls the `struct TcpContext`
- */
-static void
-tcp_send (void *cls)
-{
-  struct TcpContext *ctx = cls;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  if ((NULL != tc->write_ready) &&
-      (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s)))
-  {
-    if (-1 ==
-        GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data)))
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
-    }
-    GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
-  }
-  GNUNET_NETWORK_socket_close (ctx->s);
-  GNUNET_free (ctx);
-}
-
-
-/**
- * Try to send @a data to the
- * IP @a dst_ipv4' at port @a dport via TCP.
- *
- * @param dst_ipv4 target IP
- * @param dport target port
- * @param data data to send
- */
-static void
-try_send_tcp (uint32_t dst_ipv4,
-              uint16_t dport,
-              uint16_t data)
-{
-  struct GNUNET_NETWORK_Handle *s;
-  struct sockaddr_in sa;
-  struct TcpContext *ctx;
-
-  s = GNUNET_NETWORK_socket_create (AF_INET,
-                                    SOCK_STREAM,
-                                    0);
-  if (NULL == s)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                         "socket");
-    return;
-  }
-  memset (&sa, 0, sizeof (sa));
-  sa.sin_family = AF_INET;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  sa.sin_len = sizeof (sa);
-#endif
-  sa.sin_addr.s_addr = dst_ipv4;
-  sa.sin_port = htons (dport);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending TCP message to `%s'\n",
-              GNUNET_a2s ((struct sockaddr *) &sa,
-                          sizeof (sa)));
-  if ( (GNUNET_OK !=
-        GNUNET_NETWORK_socket_connect (s,
-                                       (const struct sockaddr *) &sa,
-                                       sizeof (sa))) &&
-       (errno != EINPROGRESS) )
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                         "connect");
-    GNUNET_NETWORK_socket_close (s);
-    return;
-  }
-  ctx = GNUNET_new (struct TcpContext);
-  ctx->s = s;
-  ctx->data = data;
-  GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS,
-                                  s,
-                                  &tcp_send,
-                                  ctx);
-}
-
-
-/**
- * Try to send @a data to the
- * IP @a dst_ipv4 at port @a dport via UDP.
- *
- * @param dst_ipv4 target IP
- * @param dport target port
- * @param data data to send
- */
-static void
-try_send_udp (uint32_t dst_ipv4,
-              uint16_t dport,
-              uint16_t data)
-{
-  struct GNUNET_NETWORK_Handle *s;
-  struct sockaddr_in sa;
-
-  s = GNUNET_NETWORK_socket_create (AF_INET,
-                                    SOCK_DGRAM,
-                                    0);
-  if (NULL == s)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                         "socket");
-    return;
-  }
-  memset (&sa, 0, sizeof (sa));
-  sa.sin_family = AF_INET;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  sa.sin_len = sizeof (sa);
-#endif
-  sa.sin_addr.s_addr = dst_ipv4;
-  sa.sin_port = htons (dport);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending UDP packet to `%s'\n",
-              GNUNET_a2s ((struct sockaddr *) &sa,
-                          sizeof (sa)));
-  if (-1 ==
-      GNUNET_NETWORK_socket_sendto (s,
-                                    &data,
-                                    sizeof (data),
-                                    (const struct sockaddr *) &sa,
-                                    sizeof (sa)))
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                         "sendto");
-  GNUNET_NETWORK_socket_close (s);
-}
-
-
-/**
- * We've received a request to probe a NAT
- * traversal. Do it.
- *
- * @param cls unused
- * @param client handle to client (we always close)
- * @param msg message with details about what to test
- */
-static void
-test (void *cls,
-      struct GNUNET_SERVER_Client *client,
-      const struct GNUNET_MessageHeader *msg)
-{
-  const struct GNUNET_NAT_TestMessage *tm;
-  uint16_t dport;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received test request\n");
-  tm = (const struct GNUNET_NAT_TestMessage *) msg;
-  dport = ntohs (tm->dport);
-  if (0 == dport)
-    try_anat (tm->dst_ipv4,
-              ntohs (tm->data),
-              (int) ntohl (tm->is_tcp));
-  else if (GNUNET_YES == ntohl (tm->is_tcp))
-    try_send_tcp (tm->dst_ipv4,
-                  dport,
-                  tm->data);
-  else
-    try_send_udp (tm->dst_ipv4,
-                  dport,
-                  tm->data);
-  GNUNET_SERVER_receive_done (client,
-                              GNUNET_NO);
-}
-
-
-/**
- * Task run during shutdown.
- *
- * @param cls unused
- */
-static void
-shutdown_task (void *cls)
-{
-  GNUNET_SERVER_destroy (server);
-  server = NULL;
-}
-
-
-/**
- * Main function that will be run.
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL!)
- * @param c configuration
- */
-static void
-run (void *cls,
-     char *const *args,
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
-    {&test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST,
-     sizeof (struct GNUNET_NAT_TestMessage)},
-    {NULL, NULL, 0, 0}
-  };
-  unsigned int port;
-  struct sockaddr_in in4;
-  struct sockaddr_in6 in6;
-
-  socklen_t slen[] = {
-    sizeof (in4),
-    sizeof (in6),
-    0
-  };
-  struct sockaddr *sa[] = {
-    (struct sockaddr *) &in4,
-    (struct sockaddr *) &in6,
-    NULL
-  };
-
-  cfg = c;
-  if ( (NULL == args[0]) ||
-       (1 != SSCANF (args[0], "%u", &port)) ||
-       (0 == port) ||
-       (65536 <= port) )
-  {
-    FPRINTF (stderr,
-             _("Please pass valid port number as the first argument! (got `%s')\n"),
-             args[0]);
-    return;
-  }
-  memset (&in4, 0, sizeof (in4));
-  memset (&in6, 0, sizeof (in6));
-  in4.sin_family = AF_INET;
-  in4.sin_port = htons ((uint16_t) port);
-  in6.sin6_family = AF_INET6;
-  in6.sin6_port = htons ((uint16_t) port);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  in4.sin_len = sizeof (in4);
-  in6.sin6_len = sizeof (in6);
-#endif
-  server = GNUNET_SERVER_create (NULL,
-                                NULL,
-                                (struct sockaddr * const *) sa,
-                                slen,
-                                GNUNET_TIME_UNIT_SECONDS,
-                                GNUNET_YES);
-  GNUNET_SERVER_add_handlers (server,
-                             handlers);
-  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
-                                NULL);
-}
-
-
-/**
- * Main function of gnunet-nat-server.
- *
- * @param argc number of command-line arguments
- * @param argv command line
- * @return 0 on success, -1 on error
- */
-int
-main (int argc, char *const argv[])
-{
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-
-  if (GNUNET_OK !=
-      GNUNET_STRINGS_get_utf8_args (argc, argv,
-                                   &argc, &argv))
-    return 2;
-
-  if (GNUNET_OK !=
-      GNUNET_PROGRAM_run (argc,
-                         argv,
-                         "gnunet-nat-server [options] PORT",
-                          _("GNUnet NAT traversal test helper daemon"),
-                         options,
-                          &run,
-                         NULL))
-  {
-    GNUNET_free ((void*) argv);
-    return 1;
-  }
-  GNUNET_free ((void*) argv);
-  return 0;
-}
-
-
-/* end of gnunet-nat-server.c */
index 81e4549b5d2763c07e6c566a6ff8d200543a5895..f198adc0a4508ad2be5e3037922476b4c126d5c7 100644 (file)
 static int global_ret;
 
 /**
- * Handle to ongoing autoconfiguration.
- */
-static struct GNUNET_NAT_AutoHandle *ah;
-
-/**
- * External hostname and port, if user manually punched
- * the NAT.  
+ * Name of section in configuration file to use for 
+ * additional options.
  */ 
-static char *hole_external;
+static char *section_name;
 
 /**
  * Flag set to 1 if we use IPPROTO_UDP.
@@ -59,39 +54,11 @@ static int listen_reversal;
  */
 static int use_tcp;
 
-/**
- * If we do auto-configuration, should we write the result
- * to a file?
- */
-static int write_cfg;
-
-/**
- * Configuration filename.
- */ 
-static const char *cfg_file;
-
-/**
- * Original configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
 /**
  * Protocol to use.
  */
 static uint8_t proto;
 
-/**
- * Address we are bound to (in test), or should bind to
- * (if #do_stun is set).
- */
-static char *bind_addr;
-
-/**
- * External IP address and port to use for the test.
- * If not set, use #bind_addr.
- */
-static char *extern_addr;
-
 /**
  * Local address to use for connection reversal request.
  */
@@ -107,16 +74,6 @@ static char *remote_addr;
  */
 static unsigned int do_stun;
 
-/**
- * Should we run autoconfiguration?
- */
-static unsigned int do_auto;
-
-/**
- * Handle to a NAT test operation.
- */
-static struct GNUNET_NAT_Test *nt;
-
 /**
  * Handle to NAT operation.
  */
@@ -140,10 +97,6 @@ static struct GNUNET_SCHEDULER_Task *rtask;
 static void
 test_finished ()
 {
-  if (NULL != ah)
-    return;
-  if (NULL != nt)
-    return;
   if (NULL != nh)
     return;
   if (NULL != rtask)
@@ -152,160 +105,6 @@ test_finished ()
 }
 
 
-/**
- * Function to iterate over sugested changes options
- *
- * @param cls closure
- * @param section name of the section
- * @param option name of the option
- * @param value value of the option
- */
-static void
-auto_conf_iter (void *cls,
-                const char *section,
-                const char *option,
-                const char *value)
-{
-  struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
-  
-  PRINTF ("%s: %s\n",
-         option,
-         value);
-  if (NULL != new_cfg)
-    GNUNET_CONFIGURATION_set_value_string (new_cfg,
-                                          section,
-                                          option,
-                                          value);
-}
-
-
-/**
- * Function called with the result from the autoconfiguration.
- *
- * @param cls closure
- * @param diff minimal suggested changes to the original configuration
- *             to make it work (as best as we can)
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- * @param type what the situation of the NAT
- */
-static void
-auto_config_cb (void *cls,
-               const struct GNUNET_CONFIGURATION_Handle *diff,
-               enum GNUNET_NAT_StatusCode result,
-               enum GNUNET_NAT_Type type)
-{
-  const char *nat_type;
-  char unknown_type[64];
-  struct GNUNET_CONFIGURATION_Handle *new_cfg;
-
-  ah = NULL;
-  switch (type)
-  {
-  case GNUNET_NAT_TYPE_NO_NAT:
-    nat_type = "NO NAT";
-    break;
-  case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
-    nat_type = "NAT but we can traverse";
-    break;
-  case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
-    nat_type = "NAT but STUN is able to identify the correct information";
-    break;
-  case GNUNET_NAT_TYPE_UPNP_NAT:
-    nat_type = "NAT but UPNP opened the ports";
-    break;
-  default:
-    SPRINTF (unknown_type,
-            "NAT unknown, type %u",
-            type);
-    nat_type = unknown_type;
-    break;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-             "NAT status: %s/%s\n",
-             GNUNET_NAT_status2string (result),
-             nat_type);
-
-  /* Shortcut: if there are no changes suggested, bail out early. */
-  if (GNUNET_NO ==
-      GNUNET_CONFIGURATION_is_dirty (diff))
-  {
-    test_finished ();
-    return;
-  }
-
-  /* Apply diff to original configuration and show changes
-     to the user */
-  new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
-  
-  if (NULL != diff)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-               _("Suggested configuration changes:\n"));
-    GNUNET_CONFIGURATION_iterate_section_values (diff,
-                                                "nat",
-                                                &auto_conf_iter,
-                                                new_cfg);
-  }
-
-  /* If desired, write configuration to file; we write only the
-     changes to the defaults to keep things compact. */
-  if ( (write_cfg) &&
-       (NULL != diff) )
-  {
-    struct GNUNET_CONFIGURATION_Handle *def_cfg;
-
-    GNUNET_CONFIGURATION_set_value_string (new_cfg,
-                                          "ARM",
-                                          "CONFIG",
-                                          NULL);
-    def_cfg = GNUNET_CONFIGURATION_create ();
-    GNUNET_break (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_load (def_cfg,
-                                            NULL));
-    if (GNUNET_OK !=
-       GNUNET_CONFIGURATION_write_diffs (def_cfg,
-                                         new_cfg,
-                                         cfg_file))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                 _("Failed to write configuration to `%s'\n"),
-                 cfg_file);
-      global_ret = 1;
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                 _("Wrote updated configuration to `%s'\n"),
-                 cfg_file);
-    }
-    GNUNET_CONFIGURATION_destroy (def_cfg);
-  }
-
-  if (NULL != new_cfg)
-    GNUNET_CONFIGURATION_destroy (new_cfg);
-  test_finished ();
-}
-
-
-/**
- * Function called to report success or failure for
- * NAT configuration test.
- *
- * @param cls closure
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-static void
-test_report_cb (void *cls,
-               enum GNUNET_NAT_StatusCode result)
-{
-  nt = NULL;
-  PRINTF ("NAT test result: %s\n",
-         GNUNET_NAT_status2string (result));
-  test_finished ();
-}
-
-
 /**
  * Signature of the callback passed to #GNUNET_NAT_register() for
  * a function to call whenever our set of 'valid' addresses changes.
@@ -362,16 +161,6 @@ reversal_cb (void *cls,
 static void
 do_shutdown (void *cls)
 {
-  if (NULL != ah)
-  {
-    GNUNET_NAT_autoconfig_cancel (ah);
-    ah = NULL;
-  }
-  if (NULL != nt)
-  {
-    GNUNET_NAT_test_stop (nt);
-    nt = NULL;
-  }
   if (NULL != nh)
   {
     GNUNET_NAT_unregister (nh);
@@ -452,16 +241,11 @@ run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
   uint8_t af;
-  struct sockaddr_in bind_sa;
-  struct sockaddr_in extern_sa;
   struct sockaddr *local_sa;
   struct sockaddr *remote_sa;
   socklen_t local_len;
   size_t remote_len;
 
-  cfg_file = cfgfile;
-  cfg = c;
-  
   if (use_tcp && use_udp)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
@@ -478,50 +262,13 @@ run (void *cls,
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                 NULL);
 
-  if (do_auto)
-  {
-    ah = GNUNET_NAT_autoconfig_start (c,
-                                     &auto_config_cb,
-                                     NULL);
-  }
-
   if (0 == proto)
   {
-    if (do_auto)
-      return; /* all good, we just run auto config */
     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
                "Must specify either TCP or UDP\n");
     global_ret = 1;
     return;
   }
-  if (NULL != bind_addr)
-  {
-    if (GNUNET_OK !=
-       GNUNET_STRINGS_to_address_ipv4 (bind_addr,
-                                       strlen (bind_addr),
-                                       &bind_sa))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                 "Invalid socket address `%s'\n",
-                 bind_addr);
-      global_ret = 1;
-      return;
-    }
-  }
-  if (NULL != extern_addr)
-  {
-    if (GNUNET_OK !=
-       GNUNET_STRINGS_to_address_ipv4 (extern_addr,
-                                       strlen (extern_addr),
-                                       &extern_sa))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                 "Invalid socket address `%s'\n",
-                 extern_addr);
-      global_ret = 1;
-      return;
-    }
-  }
   if (NULL != local_addr)
   {
     local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
@@ -551,25 +298,13 @@ run (void *cls,
     }
   }
 
-  if (NULL != bind_addr)
-  {
-    if (NULL == extern_addr)
-      extern_sa = bind_sa;
-    nt = GNUNET_NAT_test_start (c,
-                               proto,
-                               bind_sa.sin_addr,
-                               ntohs (bind_sa.sin_port),
-                               extern_sa.sin_addr,
-                               ntohs (extern_sa.sin_port),
-                               &test_report_cb,
-                               NULL);
-  }
-
   if (NULL != local_addr)
   {
+    if (NULL == section_name)
+      section_name = GNUNET_strdup ("undefined");
     nh = GNUNET_NAT_register (c,
+                             section_name,
                              proto,
-                             hole_external,
                              1,
                              (const struct sockaddr **) &local_sa,
                              &local_len,
@@ -607,9 +342,11 @@ run (void *cls,
       GNUNET_SCHEDULER_shutdown ();
       return;
     }
+    GNUNET_assert (AF_INET == local_sa->sa_family);
+    GNUNET_assert (AF_INET == remote_sa->sa_family);
     ret = GNUNET_NAT_request_reversal (nh,
-                                      (const struct sockaddr_in *) &local_sa,
-                                      (const struct sockaddr_in *) &remote_sa);
+                                      (const struct sockaddr_in *) local_sa,
+                                      (const struct sockaddr_in *) remote_sa);
     switch (ret)
     {
     case GNUNET_SYSERR:
@@ -683,24 +420,15 @@ main (int argc,
       char *const argv[])
 {
   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'a', "auto", NULL,
-     gettext_noop ("run autoconfiguration"),
-     GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
-    {'b', "bind", "ADDRESS",
-     gettext_noop ("which IP and port are we bound to"),
-     GNUNET_YES, &GNUNET_GETOPT_set_string, &bind_addr },
-    {'e', "external", "ADDRESS",
-     gettext_noop ("which external IP and port should be used to test"),
-     GNUNET_YES, &GNUNET_GETOPT_set_string, &extern_addr },
     {'i', "in", "ADDRESS",
      gettext_noop ("which IP and port are we locally using to bind/listen to"),
      GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr },
     {'r', "remote", "ADDRESS",
      gettext_noop ("which remote IP and port should be asked for connection reversal"),
      GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr },
-    {'p', "punched", NULL,
-     gettext_noop ("external hostname and port of NAT, if punched manually; use AUTO for hostname for automatic determination of the external IP"),
-     GNUNET_YES, &GNUNET_GETOPT_set_string, &hole_external },
+    {'S', "section", NULL,
+     gettext_noop ("name of configuration section to find additional options, such as manual host punching data"),
+     GNUNET_YES, &GNUNET_GETOPT_set_string, &section_name },
     {'s', "stun", NULL,
      gettext_noop ("enable STUN processing"),
      GNUNET_NO, &GNUNET_GETOPT_set_one, &do_stun },
@@ -710,9 +438,6 @@ main (int argc,
     {'u', "udp", NULL,
      gettext_noop ("use UDP"),
      GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
-    {'w', "write", NULL,
-     gettext_noop ("write configuration file (for autoconfiguration)"),
-     GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
     {'W', "watch", NULL,
      gettext_noop ("watch for connection reversal requests"),
      GNUNET_NO, &GNUNET_GETOPT_set_one, &listen_reversal },
index e29f371083ba1055de1158d4fb882709766036ee..98d87262eb467591d9c241841e9e345a1c77f848 100644 (file)
  * @brief network address translation traversal service
  * @author Christian Grothoff
  *
- * The purpose of this service is to enable transports to 
+ * The purpose of this service is to enable transports to
  * traverse NAT routers, by providing traversal options and
  * knowledge about the local network topology.
  *
  * TODO:
- * - test and document (!) ICMP based NAT traversal
- * - implement manual hole punching support (incl. DNS
- *   lookup for DynDNS setups!)
- * - implement "more" autoconfig:
- *   re-work gnunet-nat-server & integrate!
- *   + test manually punched NAT (how?)
+ * - migrate test cases to new NAT service
+ * - add new traceroute-based logic for external IP detection
+ *
  * - implement & test STUN processing to classify NAT;
  *   basically, open port & try different methods.
- * - implement NEW logic for external IP detection
  */
 #include "platform.h"
 #include <math.h>
 #include "gnunet_protocols.h"
 #include "gnunet_signatures.h"
 #include "gnunet_statistics_service.h"
+#include "gnunet_resolver_service.h"
 #include "gnunet_nat_service.h"
+#include "gnunet-service-nat.h"
+#include "gnunet-service-nat_externalip.h"
 #include "gnunet-service-nat_stun.h"
 #include "gnunet-service-nat_mini.h"
 #include "gnunet-service-nat_helper.h"
 #define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
 
 /**
- * How long do we wait until we re-try running `external-ip` if the
- * command failed to terminate nicely?
- */
-#define EXTERN_IP_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
-
-/**
- * How long do we wait until we re-try running `external-ip` if the
- * command failed (but terminated)?
+ * How often do we scan for changes in how our external (dyndns) hostname resolves?
  */
-#define EXTERN_IP_RETRY_FAILURE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
-
-/**
- * How long do we wait until we re-try running `external-ip` if the
- * command succeeded?
- */
-#define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
+#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7)
 
 
 /**
- * Information we track per client address. 
+ * Information we track per client address.
  */
 struct ClientAddress
 {
@@ -98,7 +84,54 @@ struct ClientAddress
    * pending.
    */
   struct GNUNET_NAT_MiniHandle *mh;
-  
+
+};
+
+
+/**
+ * List of local addresses this system has.
+ */
+struct LocalAddressList
+{
+  /**
+   * This is a linked list.
+   */
+  struct LocalAddressList *next;
+
+  /**
+   * Previous entry.
+   */
+  struct LocalAddressList *prev;
+
+  /**
+   * Context for a gnunet-helper-nat-server used to listen
+   * for ICMP messages to this client for connection reversal.
+   */
+  struct HelperContext *hc;
+
+  /**
+   * The address itself (i.e. `struct sockaddr_in` or `struct
+   * sockaddr_in6`, in the respective byte order).
+   */
+  struct sockaddr_storage addr;
+
+  /**
+   * Address family. (FIXME: redundant, addr.ss_family! Remove!?)
+   */
+  int af;
+
+  /**
+   * #GNUNET_YES if we saw this one in the previous iteration,
+   * but not in the current iteration and thus might need to
+   * remove it at the end.
+   */
+  int old;
+
+  /**
+   * What type of address is this?
+   */
+  enum GNUNET_NAT_AddressClass ac;
+
 };
 
 
@@ -112,7 +145,7 @@ struct ClientHandle
    * Kept in a DLL.
    */
   struct ClientHandle *next;
-  
+
   /**
    * Kept in a DLL.
    */
@@ -120,7 +153,7 @@ struct ClientHandle
 
   /**
    * Underlying handle for this client with the service.
-   */ 
+   */
   struct GNUNET_SERVICE_Client *client;
 
   /**
@@ -136,74 +169,70 @@ struct ClientHandle
   /**
    * External DNS name and port given by user due to manual
    * hole punching.  Special DNS name 'AUTO' is used to indicate
-   * desire for automatic determination of the external IP 
-   * (instead of DNS or manual configuration, i.e. to be used 
+   * desire for automatic determination of the external IP
+   * (instead of DNS or manual configuration, i.e. to be used
    * if the IP keeps changing and we have no DynDNS, but we do
    * have a hole punched).
    */
   char *hole_external;
-  
+
   /**
-   * What does this client care about?
+   * Name of the configuration section this client cares about.
    */
-  enum GNUNET_NAT_RegisterFlags flags;
+  char *section_name;
 
   /**
-   * Is any of the @e caddrs in a reserved subnet for NAT?
+   * Task for periodically re-running the @e ext_dns DNS lookup.
    */
-  int natted_address;
-  
+  struct GNUNET_SCHEDULER_Task *ext_dns_task;
+
   /**
-   * Number of addresses that this service is bound to.
-   * Length of the @e caddrs array.
+   * Handle for (DYN)DNS lookup of our external IP as given in
+   * @e hole_external.
    */
-  uint16_t num_caddrs;
-  
+  struct GNUNET_RESOLVER_RequestHandle *ext_dns;
+
   /**
-   * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
+   * Handle for monitoring external IP changes.
    */
-  uint8_t proto;
-
-};
+  struct GN_ExternalIPMonitor *external_monitor;
 
+  /**
+   * DLL of external IP addresses as given in @e hole_external.
+   */
+  struct LocalAddressList *ext_addr_head;
 
-/**
- * List of local addresses this system has.
- */
-struct LocalAddressList
-{
   /**
-   * This is a linked list.
+   * DLL of external IP addresses as given in @e hole_external.
    */
-  struct LocalAddressList *next;
+  struct LocalAddressList *ext_addr_tail;
 
   /**
-   * Previous entry.
+   * Port number we found in @e hole_external.
    */
-  struct LocalAddressList *prev;
+  uint16_t ext_dns_port;
 
   /**
-   * Context for a gnunet-helper-nat-server used to listen
-   * for ICMP messages to this client for connection reversal.
+   * What does this client care about?
    */
-  struct HelperContext *hc;
-  
+  enum GNUNET_NAT_RegisterFlags flags;
+
   /**
-   * The address itself (i.e. `struct sockaddr_in` or `struct
-   * sockaddr_in6`, in the respective byte order).
+   * Is any of the @e caddrs in a reserved subnet for NAT?
    */
-  struct sockaddr_storage addr;
+  int natted_address;
 
   /**
-   * Address family.
+   * Number of addresses that this service is bound to.
+   * Length of the @e caddrs array.
    */
-  int af;
+  uint16_t num_caddrs;
 
   /**
-   * What type of address is this?
+   * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
    */
-  enum GNUNET_NAT_AddressClass ac;
-  
+  uint8_t proto;
+
 };
 
 
@@ -214,12 +243,12 @@ struct StunExternalIP
 {
   /**
    * Kept in a DLL.
-   */ 
+   */
   struct StunExternalIP *next;
 
   /**
    * Kept in a DLL.
-   */ 
+   */
   struct StunExternalIP *prev;
 
   /**
@@ -228,13 +257,13 @@ struct StunExternalIP
   struct GNUNET_SCHEDULER_Task *timeout_task;
 
   /**
-   * Our external IP address as reported by the 
+   * Our external IP address as reported by the
    * STUN server.
    */
   struct sockaddr_in external_addr;
 
   /**
-   * Address of the reporting STUN server.  Used to 
+   * Address of the reporting STUN server.  Used to
    * detect when a STUN server changes its opinion
    * to more quickly remove stale results.
    */
@@ -248,83 +277,14 @@ struct StunExternalIP
 
 
 /**
- * Context for autoconfiguration operations.
- */
-struct AutoconfigContext
-{
-  /**
-   * Kept in a DLL.
-   */
-  struct AutoconfigContext *prev;
-
-  /**
-   * Kept in a DLL.
-   */
-  struct AutoconfigContext *next;
-
-  /**
-   * Which client asked the question.
-   */
-  struct ClientHandle *ch;
-
-  /**
-   * Configuration we are creating.
-   */ 
-  struct GNUNET_CONFIGURATION_Handle *c;
-
-  /**
-   * Original configuration (for diffing).
-   */ 
-  struct GNUNET_CONFIGURATION_Handle *orig;
-
-  /**
-   * Timeout task to force termination.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * What type of system are we on?
-   */
-  char *system_type;
-
-  /**
-   * Handle to activity to probe for our external IP.
-   */
-  struct GNUNET_NAT_ExternalHandle *probe_external;
-
-  /**
-   * #GNUNET_YES if upnpc should be used,
-   * #GNUNET_NO if upnpc should not be used,
-   * #GNUNET_SYSERR if we should simply not change the option.
-   */
-  int enable_upnpc;
-
-  /**
-   * Status code to return to the client.
-   */
-  enum GNUNET_NAT_StatusCode status_code;
-
-  /**
-   * NAT type to return to the client.
-   */
-  enum GNUNET_NAT_Type type;
-};
-
-
-/**
- * DLL of our autoconfiguration operations.
- */
-static struct AutoconfigContext *ac_head;
-
-/**
- * DLL of our autoconfiguration operations.
+ * Timeout to use when STUN data is considered stale.
  */
-static struct AutoconfigContext *ac_tail;
+static struct GNUNET_TIME_Relative stun_stale_timeout;
 
 /**
- * Timeout to use when STUN data is considered stale.
+ * How often do we scan for changes in how our external (dyndns) hostname resolves?
  */
-static struct GNUNET_TIME_Relative stun_stale_timeout;
+static struct GNUNET_TIME_Relative dyndns_frequency;
 
 /**
  * Handle to our current configuration.
@@ -345,7 +305,7 @@ static struct GNUNET_SCHEDULER_Task *scan_task;
  * Head of client DLL.
  */
 static struct ClientHandle *ch_head;
-  
+
 /**
  * Tail of client DLL.
  */
@@ -363,36 +323,19 @@ static struct LocalAddressList *lal_tail;
 
 /**
  * Kept in a DLL.
- */ 
+ */
 static struct StunExternalIP *se_head;
 
 /**
  * Kept in a DLL.
- */ 
+ */
 static struct StunExternalIP *se_tail;
 
 /**
  * Is UPnP enabled? #GNUNET_YES if enabled, #GNUNET_NO if disabled,
  * #GNUNET_SYSERR if configuration enabled but binary is unavailable.
  */
-static int enable_upnp;
-
-/**
- * Task run to obtain our external IP (if #enable_upnp is set
- * and if we find we have a NATed IP address).
- */
-static struct GNUNET_SCHEDULER_Task *probe_external_ip_task;
-
-/**
- * Handle to our operation to run `external-ip`.
- */
-static struct GNUNET_NAT_ExternalHandle *probe_external_ip_op;
-
-/**
- * What is our external IP address as claimed by `external-ip`?
- * 0 for unknown.
- */
-static struct in_addr mini_external_ipv4;
+int enable_upnp;
 
 
 /**
@@ -422,7 +365,7 @@ free_lal (struct LocalAddressList *lal)
 
 /**
  * Free the DLL starting at #lal_head.
- */ 
+ */
 static void
 destroy_lal ()
 {
@@ -474,22 +417,22 @@ check_register (void *cls,
 #endif
     default:
       GNUNET_break (0);
-      return GNUNET_SYSERR;      
+      return GNUNET_SYSERR;
     }
     if (alen > left)
     {
       GNUNET_break (0);
-      return GNUNET_SYSERR;      
+      return GNUNET_SYSERR;
     }
     off += alen;
     left -= alen;
   }
-  if (left != ntohs (message->hole_external_len))
+  if (left != ntohs (message->str_len))
   {
     GNUNET_break (0);
-    return GNUNET_SYSERR;      
+    return GNUNET_SYSERR;
   }
-  return GNUNET_OK; 
+  return GNUNET_OK;
 }
 
 
@@ -535,7 +478,7 @@ match_ipv6 (const char *network,
   struct in6_addr net;
   struct in6_addr mask;
   unsigned int off;
-  
+
   if (0 == bits)
     return GNUNET_YES;
   GNUNET_assert (1 == inet_pton (AF_INET6,
@@ -607,7 +550,7 @@ is_nat_v6 (const struct in6_addr *ip)
 struct IfcProcContext
 {
 
-  /** 
+  /**
    * Head of DLL of local addresses.
    */
   struct LocalAddressList *lal_head;
@@ -718,7 +661,7 @@ notify_client (enum GNUNET_NAT_AddressClass ac,
 {
   struct GNUNET_MQ_Envelope *env;
   struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
-  
+
   env = GNUNET_MQ_msg_extra (msg,
                             addr_len,
                             GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
@@ -729,7 +672,7 @@ notify_client (enum GNUNET_NAT_AddressClass ac,
                 addr_len);
   GNUNET_MQ_send (ch->mq,
                  env);
-}                     
+}
 
 
 /**
@@ -748,7 +691,7 @@ check_notify_client (struct LocalAddressList *delta,
   size_t alen;
   struct sockaddr_in v4;
   struct sockaddr_in6 v6;
-  
+
   if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
     return;
   switch (delta->af)
@@ -758,14 +701,14 @@ check_notify_client (struct LocalAddressList *delta,
     GNUNET_memcpy (&v4,
                   &delta->addr,
                   alen);
-    
+
     /* Check for client notifications */
     for (unsigned int i=0;i<ch->num_caddrs;i++)
     {
       const struct sockaddr_in *c4;
 
       if (AF_INET != ch->caddrs[i].ss.ss_family)
-       return; /* IPv4 not relevant */
+       continue; /* IPv4 not relevant */
       c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
       if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) &&
           (0 != c4->sin_addr.s_addr) &&
@@ -806,9 +749,9 @@ check_notify_client (struct LocalAddressList *delta,
     for (unsigned int i=0;i<ch->num_caddrs;i++)
     {
       const struct sockaddr_in6 *c6;
-      
+
       if (AF_INET6 != ch->caddrs[i].ss.ss_family)
-       return; /* IPv4 not relevant */
+       continue; /* IPv4 not relevant */
       c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
       if ( match_ipv6 ("::1", &c6->sin6_addr, 128) &&
           (0 != memcmp (&c6->sin6_addr,
@@ -888,19 +831,40 @@ notify_clients (struct LocalAddressList *delta,
 /**
  * Tell relevant client about a change in our external
  * IPv4 address.
- * 
+ *
+ * @param cls client to check if it cares and possibly notify
  * @param v4 the external address that changed
- * @param ch client to check if it cares and possibly notify
  * @param add #GNUNET_YES to add, #GNUNET_NO to remove
  */
 static void
-check_notify_client_external_ipv4_change (const struct in_addr *v4,
-                                         struct ClientHandle *ch,
-                                         int add)
+notify_client_external_ipv4_change (void *cls,
+                                   const struct in_addr *v4,
+                                   int add)
 {
+  struct ClientHandle *ch = cls;
   struct sockaddr_in sa;
   int have_v4;
 
+  /* (0) check if this impacts 'hole_external' */
+  if ( (NULL != ch->hole_external) &&
+       (0 == strcasecmp (ch->hole_external,
+                        "AUTO")) )
+  {
+    struct LocalAddressList lal;
+    struct sockaddr_in *s4;
+
+    memset (&lal, 0, sizeof (lal));
+    s4 = (struct sockaddr_in *) &lal.addr;
+    s4->sin_family = AF_INET;
+    s4->sin_port = htons (ch->ext_dns_port);
+    s4->sin_addr = *v4;
+    lal.af = AF_INET;
+    lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
+    check_notify_client (&lal,
+                        ch,
+                        add);
+  }
+
   /* (1) check if client cares. */
   if (! ch->natted_address)
     return;
@@ -919,17 +883,17 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4,
   if (GNUNET_NO == have_v4)
     return; /* IPv6-only */
 
-  /* build address info */
+  /* (2) build address info */
   memset (&sa,
          0,
          sizeof (sa));
   sa.sin_family = AF_INET;
   sa.sin_addr = *v4;
   sa.sin_port = htons (0);
-  
+
   /* (3) notify client of change */
   notify_client (is_nat_v4 (v4)
-                ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN 
+                ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN
                 : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL,
                 ch,
                 add,
@@ -938,118 +902,12 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4,
 }
 
 
-/**
- * Tell relevant clients about a change in our external
- * IPv4 address.
- * 
- * @param add #GNUNET_YES to add, #GNUNET_NO to remove
- * @param v4 the external address that changed
- */
-static void
-notify_clients_external_ipv4_change (int add,
-                                    const struct in_addr *v4)
-{
-  for (struct ClientHandle *ch = ch_head;
-       NULL != ch;
-       ch = ch->next)
-    check_notify_client_external_ipv4_change (v4,
-                                             ch,
-                                             add);
-}
-
-
-/**
- * Task used to run `external-ip` to get our external IPv4
- * address and pass it to NATed clients if possible.
- *
- * @param cls NULL
- */
-static void
-run_external_ip (void *cls);
-
-
-/**
- * We learn our current external IP address.  If it changed,
- * notify all of our applicable clients. Also re-schedule
- * #run_external_ip with an appropriate timeout.
- * 
- * @param cls NULL
- * @param addr the address, NULL on errors
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-static void
-handle_external_ip (void *cls,
-                   const struct in_addr *addr,
-                   enum GNUNET_NAT_StatusCode result)
-{
-  char buf[INET_ADDRSTRLEN];
-  
-  probe_external_ip_op = NULL;
-  GNUNET_SCHEDULER_cancel (probe_external_ip_task);
-  probe_external_ip_task
-    = GNUNET_SCHEDULER_add_delayed ((NULL == addr)
-                                   ? EXTERN_IP_RETRY_FAILURE
-                                   : EXTERN_IP_RETRY_SUCCESS,
-                                   &run_external_ip,
-                                   NULL);
-  switch (result)
-  {
-  case GNUNET_NAT_ERROR_SUCCESS:
-    if (addr->s_addr == mini_external_ipv4.s_addr)
-      return; /* not change */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Our external IP is now %s\n",
-               inet_ntop (AF_INET,
-                          addr,
-                          buf,
-                          sizeof (buf)));
-    if (0 != mini_external_ipv4.s_addr)
-      notify_clients_external_ipv4_change (GNUNET_NO,
-                                          &mini_external_ipv4);
-    mini_external_ipv4 = *addr;
-    notify_clients_external_ipv4_change (GNUNET_YES,
-                                        &mini_external_ipv4);
-    break;
-  default:
-    if (0 != mini_external_ipv4.s_addr)
-      notify_clients_external_ipv4_change (GNUNET_NO,
-                                          &mini_external_ipv4);
-    mini_external_ipv4.s_addr = 0; 
-    break;
-  }
-}
-
-
-/**
- * Task used to run `external-ip` to get our external IPv4
- * address and pass it to NATed clients if possible.
- *
- * @param cls NULL
- */
-static void
-run_external_ip (void *cls)
-{
-  probe_external_ip_task
-    = GNUNET_SCHEDULER_add_delayed (EXTERN_IP_RETRY_TIMEOUT,
-                                   &run_external_ip,
-                                   NULL);
-  if (NULL != probe_external_ip_op)
-  {
-    GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
-    probe_external_ip_op = NULL;
-  }
-  probe_external_ip_op
-    = GNUNET_NAT_mini_get_external_ipv4_ (&handle_external_ip,
-                                         NULL);
-}
-
-
 /**
  * We got a connection reversal request from another peer.
  * Notify applicable clients.
  *
- * @param cls closure with the `struct LocalAddressList` 
- * @param ra IP address of the peer who wants us to connect to it 
+ * @param cls closure with the `struct LocalAddressList`
+ * @param ra IP address of the peer who wants us to connect to it
  */
 static void
 reversal_callback (void *cls,
@@ -1063,7 +921,7 @@ reversal_callback (void *cls,
   for (struct ClientHandle *ch = ch_head;
        NULL != ch;
        ch = ch->next)
-  {    
+  {
     struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm;
     struct GNUNET_MQ_Envelope *env;
     int match;
@@ -1077,7 +935,7 @@ reversal_callback (void *cls,
     {
       struct ClientAddress *ca = &ch->caddrs[i];
       const struct sockaddr_in *c4;
-      
+
       if (AF_INET != ca->ss.ss_family)
        continue;
       c4 = (const struct sockaddr_in *) &ca->ss;
@@ -1107,7 +965,7 @@ reversal_callback (void *cls,
  * Task we run periodically to scan for network interfaces.
  *
  * @param cls NULL
- */ 
+ */
 static void
 run_scan (void *cls)
 {
@@ -1115,7 +973,7 @@ run_scan (void *cls)
   int found;
   int have_nat;
   struct LocalAddressList *lnext;
-  
+
   scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
                                            &run_scan,
                                            NULL);
@@ -1194,8 +1052,8 @@ run_scan (void *cls)
       {
        const struct sockaddr_in *s4
          = (const struct sockaddr_in *) &pos->addr;
-       
-       GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+
+       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                    "Found NATed local address %s, starting NAT server\n",
                    GNUNET_a2s ((void *) &pos->addr, sizeof (*s4)));
        pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr,
@@ -1204,29 +1062,7 @@ run_scan (void *cls)
       }
     }
   }
-  if ( (GNUNET_YES == have_nat) &&
-       (GNUNET_YES == enable_upnp) &&
-       (NULL == probe_external_ip_task) &&
-       (NULL == probe_external_ip_op) )
-  {
-    probe_external_ip_task
-      = GNUNET_SCHEDULER_add_now (&run_external_ip,
-                                 NULL);
-  }
-  if ( (GNUNET_NO == have_nat) &&
-       (GNUNET_YES == enable_upnp) )
-  {
-    if (NULL != probe_external_ip_task)
-    {
-      GNUNET_SCHEDULER_cancel (probe_external_ip_task);
-      probe_external_ip_task = NULL;
-    }
-    if (NULL != probe_external_ip_op)
-    {
-      GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
-      probe_external_ip_op = NULL;
-    }
-  }
+  GN_nat_status_changed (have_nat);
 }
 
 
@@ -1267,6 +1103,10 @@ upnp_addr_change_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                "external-ip binary not found\n");
     return;
+  case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               "upnpc binary not found\n");
+    return;
   case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "external-ip binary could not be run\n");
@@ -1317,20 +1157,264 @@ upnp_addr_change_cb (void *cls,
 
 
 /**
- * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
- * We remember the client for updates upon future NAT events.
+ * Resolve the `hole_external` name to figure out our
+ * external address from a manually punched hole.  The
+ * port number has already been parsed, this task is
+ * responsible for periodically doing a DNS lookup.
  *
- * @param cls client who sent the message
- * @param message the message received
+ * @param ch client handle to act upon
  */
 static void
-handle_register (void *cls,
-                const struct GNUNET_NAT_RegisterMessage *message)
+dyndns_lookup (void *cls);
+
+
+/**
+ * Our (external) hostname was resolved.  Update lists of
+ * current external IPs (note that DNS may return multiple
+ * addresses!) and notify client accordingly.
+ *
+ * @param cls the `struct ClientHandle`
+ * @param addr NULL on error, otherwise result of DNS lookup
+ * @param addrlen number of bytes in @a addr
+ */
+static void
+process_external_ip (void *cls,
+                     const struct sockaddr *addr,
+                     socklen_t addrlen)
 {
   struct ClientHandle *ch = cls;
-  const char *off;
-  size_t left;
-
+  struct LocalAddressList *lal;
+  struct sockaddr_storage ss;
+  struct sockaddr_in *v4;
+  struct sockaddr_in6 *v6;
+
+  if (NULL == addr)
+  {
+    struct LocalAddressList *laln;
+
+    ch->ext_dns = NULL;
+    ch->ext_dns_task
+      = GNUNET_SCHEDULER_add_delayed (dyndns_frequency,
+                                     &dyndns_lookup,
+                                     ch);
+    /* Current iteration is over, remove 'old' IPs now */
+    for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
+    {
+      laln = lal->next;
+      if (GNUNET_YES == lal->old)
+      {
+       GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
+                                    ch->ext_addr_tail,
+                                    lal);
+       check_notify_client (lal,
+                            ch,
+                            GNUNET_NO);
+       GNUNET_free (lal);
+      }
+    }
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Got IP `%s' for external address `%s'\n",
+             GNUNET_a2s (addr,
+                         addrlen),
+             ch->hole_external);
+
+  /* build sockaddr storage with port number */
+  memset (&ss, 0, sizeof (ss));
+  memcpy (&ss, addr, addrlen);
+  switch (addr->sa_family)
+  {
+  case AF_INET:
+    v4 = (struct sockaddr_in *) &ss;
+    v4->sin_port = htons (ch->ext_dns_port);
+    break;
+  case AF_INET6:
+    v6 = (struct sockaddr_in6 *) &ss;
+    v6->sin6_port = htons (ch->ext_dns_port);
+    break;
+  default:
+    GNUNET_break (0);
+    return;
+  }
+  /* See if 'ss' matches any of our known addresses */
+  for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
+  {
+    if (GNUNET_NO == lal->old)
+      continue; /* already processed, skip */
+    if ( (addr->sa_family == lal->addr.ss_family) &&
+        (0 == memcmp (&ss,
+                      &lal->addr,
+                      addrlen)) )
+    {
+      /* Address unchanged, remember so we do not remove */
+      lal->old = GNUNET_NO;
+      return; /* done here */
+    }
+  }
+  /* notify client, and remember IP for later removal! */
+  lal = GNUNET_new (struct LocalAddressList);
+  lal->addr = ss;
+  lal->af = ss.ss_family;
+  lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
+  GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
+                              ch->ext_addr_tail,
+                              lal);
+  check_notify_client (lal,
+                      ch,
+                      GNUNET_YES);
+}
+
+
+/**
+ * Resolve the `hole_external` name to figure out our
+ * external address from a manually punched hole.  The
+ * port number has already been parsed, this task is
+ * responsible for periodically doing a DNS lookup.
+ *
+ * @param ch client handle to act upon
+ */
+static void
+dyndns_lookup (void *cls)
+{
+  struct ClientHandle *ch = cls;
+  struct LocalAddressList *lal;
+
+  for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
+    lal->old = GNUNET_YES;
+  ch->ext_dns_task = NULL;
+  ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external,
+                                       AF_UNSPEC,
+                                       GNUNET_TIME_UNIT_MINUTES,
+                                       &process_external_ip,
+                                       ch);
+}
+
+
+/**
+ * Resolve the `hole_external` name to figure out our
+ * external address from a manually punched hole.  The
+ * given name may be "AUTO" in which case we should use
+ * the IP address(es) we have from upnpc or other methods.
+ * The name can also be an IP address, in which case we
+ * do not need to do DNS resolution.  Finally, we also
+ * need to parse the port number.
+ *
+ * @param ch client handle to act upon
+ */
+static void
+lookup_hole_external (struct ClientHandle *ch)
+{
+  char *port;
+  unsigned int pnum;
+  struct sockaddr_in *s4;
+  struct LocalAddressList *lal;
+
+  port = strrchr (ch->hole_external, ':');
+  if (NULL == port)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               _("Malformed punched hole specification `%s' (lacks port)\n"),
+               ch->hole_external);
+    return;
+  }
+  if ( (1 != sscanf (port + 1,
+                    "%u",
+                    &pnum)) ||
+       (pnum > 65535) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               _("Invalid port number in punched hole specification `%s' (lacks port)\n"),
+               port + 1);
+    return;
+  }
+  ch->ext_dns_port = (uint16_t) pnum;
+  *port = '\0';
+
+  lal = GNUNET_new (struct LocalAddressList);
+  if ('[' == *ch->hole_external)
+  {
+    struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr;
+
+    s6->sin6_family = AF_INET6;
+    if (']' != (ch->hole_external[strlen(ch->hole_external)-1]))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Malformed punched hole specification `%s' (lacks `]')\n"),
+                 ch->hole_external);
+      GNUNET_free (lal);
+      return;
+    }
+    ch->hole_external[strlen(ch->hole_external)-1] = '\0';
+    if (1 != inet_pton (AF_INET6,
+                       ch->hole_external + 1,
+                       &s6->sin6_addr))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Malformed punched hole specification `%s' (IPv6 address invalid)"),
+                 ch->hole_external + 1);
+      GNUNET_free (lal);
+      return;
+    }
+    s6->sin6_port = htons (ch->ext_dns_port);
+    lal->af = AF_INET6;
+    lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
+    GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
+                                ch->ext_addr_tail,
+                                lal);
+    check_notify_client (lal,
+                        ch,
+                        GNUNET_YES);
+    return;
+  }
+
+  s4 = (struct sockaddr_in *) &lal->addr;
+  s4->sin_family = AF_INET;
+  if (1 == inet_pton (AF_INET,
+                     ch->hole_external,
+                     &s4->sin_addr))
+  {
+    s4->sin_port = htons (ch->ext_dns_port);
+    lal->af = AF_INET;
+    lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
+    GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
+                                ch->ext_addr_tail,
+                                lal);
+    check_notify_client (lal,
+                        ch,
+                        GNUNET_YES);
+    return;
+  }
+  if (0 == strcasecmp (ch->hole_external,
+                      "AUTO"))
+  {
+    /* handled in #notify_client_external_ipv4_change() */
+    GNUNET_free (lal);
+    return;
+  }
+  /* got a DNS name, trigger lookup! */
+  GNUNET_free (lal);
+  ch->ext_dns_task
+    = GNUNET_SCHEDULER_add_now (&dyndns_lookup,
+                               ch);
+}
+
+
+/**
+ * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
+ * We remember the client for updates upon future NAT events.
+ *
+ * @param cls client who sent the message
+ * @param message the message received
+ */
+static void
+handle_register (void *cls,
+                const struct GNUNET_NAT_RegisterMessage *message)
+{
+  struct ClientHandle *ch = cls;
+  const char *off;
+  size_t left;
+
   if ( (0 != ch->proto) ||
        (NULL != ch->caddrs) )
   {
@@ -1367,7 +1451,7 @@ handle_register (void *cls,
     case AF_INET:
       {
        const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa;
-       
+
        alen = sizeof (struct sockaddr_in);
        if (is_nat_v4 (&s4->sin_addr))
          is_nat = GNUNET_YES;
@@ -1377,7 +1461,7 @@ handle_register (void *cls,
     case AF_INET6:
       {
        const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa;
-       
+
        alen = sizeof (struct sockaddr_in6);
        if (is_nat_v6 (&s6->sin6_addr))
          is_nat = GNUNET_YES;
@@ -1393,14 +1477,14 @@ handle_register (void *cls,
     default:
       GNUNET_break (0);
       GNUNET_SERVICE_client_drop (ch->client);
-      return;      
+      return;
     }
     /* store address */
     GNUNET_assert (alen <= left);
     GNUNET_assert (alen <= sizeof (struct sockaddr_storage));
     GNUNET_memcpy (&ch->caddrs[i].ss,
                   sa,
-                  alen);    
+                  alen);
 
     /* If applicable, try UPNPC NAT punching */
     if ( (is_nat) &&
@@ -1419,10 +1503,16 @@ handle_register (void *cls,
     off += alen;
   }
 
-  ch->hole_external
+  ch->section_name
     = GNUNET_strndup (off,
-                     ntohs (message->hole_external_len));
-    
+                     ntohs (message->str_len));
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                            ch->section_name,
+                                            "HOLE_EXTERNAL",
+                                            &ch->hole_external))
+    lookup_hole_external (ch);
+
   /* Actually send IP address list to client */
   for (struct LocalAddressList *lal = lal_head;
        NULL != lal;
@@ -1433,12 +1523,9 @@ handle_register (void *cls,
                         GNUNET_YES);
   }
   /* Also consider IPv4 determined by `external-ip` */
-  if (0 != mini_external_ipv4.s_addr)
-  {
-    check_notify_client_external_ipv4_change (&mini_external_ipv4,
-                                             ch,
-                                             GNUNET_YES);
-  }
+  ch->external_monitor
+    = GN_external_ipv4_monitor_start (&notify_client_external_ipv4_change,
+                                     ch);
   GNUNET_SERVICE_client_continue (ch->client);
 }
 
@@ -1457,7 +1544,7 @@ check_stun (void *cls,
 {
   size_t sa_len = ntohs (message->sender_addr_size);
   size_t expect = sa_len + ntohs (message->payload_size);
-  
+
   if (ntohs (message->header.size) - sizeof (*message) != expect)
   {
     GNUNET_break (0);
@@ -1490,7 +1577,7 @@ notify_clients_stun_change (const struct sockaddr_in *ip,
     struct sockaddr_in v4;
     struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
     struct GNUNET_MQ_Envelope *env;
-    
+
     if (! ch->natted_address)
       continue;
     v4 = *ip;
@@ -1580,9 +1667,9 @@ handle_stun (void *cls,
       GNUNET_NAT_stun_handle_packet_ (payload,
                                      payload_size,
                                      &external_addr))
-  {     
+  {
     /* We now know that a server at "sa" claims that
-       we are visible at IP "external_addr". 
+       we are visible at IP "external_addr".
 
        We should (for some fixed period of time) tell
        all of our clients that listen to a NAT'ed address
@@ -1685,346 +1772,43 @@ handle_request_connection_reversal (void *cls,
   const char *buf = (const char *) &message[1];
   size_t local_sa_len = ntohs (message->local_addr_size);
   size_t remote_sa_len = ntohs (message->remote_addr_size);
-  const struct sockaddr *local_sa = (const struct sockaddr *) &buf[0];
-  const struct sockaddr *remote_sa = (const struct sockaddr *) &buf[local_sa_len];
-  const struct sockaddr_in *l4 = NULL;
-  const struct sockaddr_in *r4;
+  struct sockaddr_in l4;
+  struct sockaddr_in r4;
   int ret;
-  
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received REQUEST CONNECTION REVERSAL message from client\n");
-  switch (local_sa->sa_family)
+  if (local_sa_len != sizeof (struct sockaddr_in))
   {
-  case AF_INET:
-    if (local_sa_len != sizeof (struct sockaddr_in))
-    {
-      GNUNET_break (0);
-      GNUNET_SERVICE_client_drop (ch->client);
-      return;
-    }
-    l4 = (const struct sockaddr_in *) local_sa;    
-    break;
-  case AF_INET6:
-    if (local_sa_len != sizeof (struct sockaddr_in6))
-    {
-      GNUNET_break (0);
-      GNUNET_SERVICE_client_drop (ch->client);
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Connection reversal for IPv6 not supported yet\n"));
-    ret = GNUNET_SYSERR;
-    break;
-  default:
-    GNUNET_break (0);
+    GNUNET_break_op (0);
     GNUNET_SERVICE_client_drop (ch->client);
     return;
   }
-  switch (remote_sa->sa_family)
+  if (remote_sa_len != sizeof (struct sockaddr_in))
   {
-  case AF_INET:
-    if (remote_sa_len != sizeof (struct sockaddr_in))
-    {
-      GNUNET_break (0);
-      GNUNET_SERVICE_client_drop (ch->client);
-      return;
-    }
-    r4 = (const struct sockaddr_in *) remote_sa;
-    ret = GN_request_connection_reversal (&l4->sin_addr,
-                                         ntohs (l4->sin_port),
-                                         &r4->sin_addr);
-    break;
-  case AF_INET6:
-    if (remote_sa_len != sizeof (struct sockaddr_in6))
-    {
-      GNUNET_break (0);
-      GNUNET_SERVICE_client_drop (ch->client);
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Connection reversal for IPv6 not supported yet\n"));
-    ret = GNUNET_SYSERR;
-    break;
-  default:
-    GNUNET_break (0);
+    GNUNET_break_op (0);
     GNUNET_SERVICE_client_drop (ch->client);
     return;
   }
+  GNUNET_memcpy (&l4,
+                buf,
+                sizeof (struct sockaddr_in));
+  GNUNET_break_op (AF_INET == l4.sin_family);
+  buf += sizeof (struct sockaddr_in);
+  GNUNET_memcpy (&r4,
+                buf,
+                sizeof (struct sockaddr_in));
+  GNUNET_break_op (AF_INET == r4.sin_family);
+  ret = GN_request_connection_reversal (&l4.sin_addr,
+                                       ntohs (l4.sin_port),
+                                       &r4.sin_addr);
   if (GNUNET_OK != ret)
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-               _("Connection reversal request failed\n"));  
-  GNUNET_SERVICE_client_continue (ch->client);
-}
-
-
-/**
- * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
- * from client.
- *
- * @param cls client who sent the message
- * @param message the message received
- * @return #GNUNET_OK if message is well-formed
- */
-static int
-check_autoconfig_request (void *cls,
-                         const struct GNUNET_NAT_AutoconfigRequestMessage *message)
-{
-  return GNUNET_OK;  /* checked later */
-}
-
-
-/**
- * Stop all pending activities with respect to the @a ac
- *
- * @param ac autoconfiguration to terminate activities for
- */
-static void
-terminate_ac_activities (struct AutoconfigContext *ac)
-{
-  if (NULL != ac->probe_external)
-  {
-    GNUNET_NAT_mini_get_external_ipv4_cancel_ (ac->probe_external);
-    ac->probe_external = NULL;
-  }
-  if (NULL != ac->timeout_task)
-  {
-    GNUNET_SCHEDULER_cancel (ac->timeout_task);
-    ac->timeout_task = NULL;
-  }
-}
-
-
-/**
- * Finish handling the autoconfiguration request and send
- * the response to the client.
- *
- * @param cls the `struct AutoconfigContext` to conclude
- */
-static void
-conclude_autoconfig_request (void *cls)
-{
-  struct AutoconfigContext *ac = cls;
-  struct ClientHandle *ch = ac->ch;
-  struct GNUNET_NAT_AutoconfigResultMessage *arm;
-  struct GNUNET_MQ_Envelope *env;
-  size_t c_size;
-  char *buf;
-  struct GNUNET_CONFIGURATION_Handle *diff;
-  
-  ac->timeout_task = NULL;
-  terminate_ac_activities (ac);
-
-  /* Send back response */
-  diff = GNUNET_CONFIGURATION_get_diff (ac->orig,
-                                       ac->c);
-  buf = GNUNET_CONFIGURATION_serialize (diff,
-                                       &c_size);
-  GNUNET_CONFIGURATION_destroy (diff);
-  env = GNUNET_MQ_msg_extra (arm,
-                            c_size,
-                            GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT);
-  arm->status_code = htonl ((uint32_t) ac->status_code);
-  arm->type = htonl ((uint32_t) ac->type);
-  GNUNET_memcpy (&arm[1],
-                buf,
-                c_size);
-  GNUNET_free (buf);
-  GNUNET_MQ_send (ch->mq,
-                 env);
-
-  /* clean up */
-  GNUNET_free (ac->system_type);
-  GNUNET_CONFIGURATION_destroy (ac->orig);
-  GNUNET_CONFIGURATION_destroy (ac->c);
-  GNUNET_CONTAINER_DLL_remove (ac_head,
-                              ac_tail,
-                              ac);
-  GNUNET_free (ac);
+               _("Connection reversal request failed\n"));
   GNUNET_SERVICE_client_continue (ch->client);
 }
 
 
-/**
- * Check if all autoconfiguration operations have concluded,
- * and if they have, send the result back to the client.
- *
- * @param ac autoconfiguation context to check
- */
-static void
-check_autoconfig_finished (struct AutoconfigContext *ac)
-{
-  if (NULL != ac->probe_external)
-    return;
-  GNUNET_SCHEDULER_cancel (ac->timeout_task);
-  ac->timeout_task
-    = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request,
-                               ac);
-}
-
-
-/**
- * Update ENABLE_UPNPC configuration option.
- *
- * @param ac autoconfiguration to update
- */
-static void
-update_enable_upnpc_option (struct AutoconfigContext *ac)
-{
-  switch (ac->enable_upnpc)
-  {
-  case GNUNET_YES:
-    GNUNET_CONFIGURATION_set_value_string (ac->c,
-                                          "NAT",
-                                          "ENABLE_UPNP",
-                                          "YES");
-    break;
-  case GNUNET_NO:
-    GNUNET_CONFIGURATION_set_value_string (ac->c,
-                                          "NAT",
-                                          "ENABLE_UPNP",
-                                          "NO");
-    break;
-  case GNUNET_SYSERR:
-    /* We are unsure, do not change option */
-    break;
-  }
-}
-
-
-/**
- * Handle result from external IP address probe during
- * autoconfiguration.
- *
- * @param cls our `struct AutoconfigContext`
- * @param addr the address, NULL on errors
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-static void
-auto_external_result_cb (void *cls,
-                        const struct in_addr *addr,
-                        enum GNUNET_NAT_StatusCode result)
-{
-  struct AutoconfigContext *ac = cls;
-
-  ac->probe_external = NULL;
-  switch (result)
-  {
-  case GNUNET_NAT_ERROR_SUCCESS:
-    ac->enable_upnpc = GNUNET_YES;
-    break;
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
-  case GNUNET_NAT_ERROR_IPC_FAILURE:
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-               "Disabling UPNPC: %d\n",
-               (int) result);
-    ac->enable_upnpc = GNUNET_NO; /* did not work */
-    break;
-  default:
-    GNUNET_break (0); /* unexpected */
-    ac->enable_upnpc = GNUNET_SYSERR;
-    break;    
-  }
-  update_enable_upnpc_option (ac);
-  check_autoconfig_finished (ac);
-}
-
-
-/**
- * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
- * client.
- *
- * @param cls client who sent the message
- * @param message the message received
- */
-static void
-handle_autoconfig_request (void *cls,
-                          const struct GNUNET_NAT_AutoconfigRequestMessage *message)
-{
-  struct ClientHandle *ch = cls;
-  size_t left = ntohs (message->header.size) - sizeof (*message);
-  struct LocalAddressList *lal;
-  struct AutoconfigContext *ac;
-
-  ac = GNUNET_new (struct AutoconfigContext);
-  ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
-  ac->ch = ch;
-  ac->c = GNUNET_CONFIGURATION_create ();
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_deserialize (ac->c,
-                                       (const char *) &message[1],
-                                       left,
-                                       GNUNET_NO))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVICE_client_drop (ch->client);
-    GNUNET_CONFIGURATION_destroy (ac->c);
-    GNUNET_free (ac);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Received REQUEST_AUTO_CONFIG message from client\n");
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (ac->c,
-                                            "PEER",
-                                            "SYSTEM_TYPE",
-                                            &ac->system_type))
-    ac->system_type = GNUNET_strdup ("UNKNOWN");
-
-  GNUNET_CONTAINER_DLL_insert (ac_head,
-                              ac_tail,
-                              ac);
-  ac->orig
-    = GNUNET_CONFIGURATION_dup (ac->c);
-  ac->timeout_task
-    = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT,
-                                   &conclude_autoconfig_request,
-                                   ac);
-  ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
-  
-  /* Probe for upnpc */
-  if (GNUNET_SYSERR ==
-      GNUNET_OS_check_helper_binary ("upnpc",
-                                    GNUNET_NO,
-                                    NULL))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-               _("UPnP client `upnpc` command not found, disabling UPnP\n"));
-    ac->enable_upnpc = GNUNET_NO;
-  }
-  else
-  {
-    for (lal = lal_head; NULL != lal; lal = lal->next)
-      if (GNUNET_NAT_AC_LAN == (lal->ac & GNUNET_NAT_AC_LAN))
-       /* we are behind NAT, useful to try upnpc */
-       ac->enable_upnpc = GNUNET_YES;
-  }
-  if (GNUNET_YES == ac->enable_upnpc)
-  {
-    /* If we are a mobile device, always leave it on as the network
-       may change to one that supports UPnP anytime.  If we are
-       stationary, check if our network actually supports UPnP, and if
-       not, disable it. */
-    if ( (0 == strcasecmp (ac->system_type,
-                          "INFRASTRUCTURE")) ||
-        (0 == strcasecmp (ac->system_type,
-                          "DESKTOP")) )
-    {
-      /* Check if upnpc gives us an external IP */
-      ac->probe_external
-       = GNUNET_NAT_mini_get_external_ipv4_ (&auto_external_result_cb,
-                                             ac);
-    }
-  }
-  if (NULL == ac->probe_external)
-    update_enable_upnpc_option (ac);
-
-  /* Finally, check if we are already done */  
-  check_autoconfig_finished (ac);
-}
-
-
 /**
  * Task run during shutdown.
  *
@@ -2034,16 +1818,7 @@ static void
 shutdown_task (void *cls)
 {
   struct StunExternalIP *se;
-  struct AutoconfigContext *ac;
 
-  while (NULL != (ac = ac_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (ac_head,
-                                ac_tail,
-                                ac);
-    terminate_ac_activities (ac);
-    GNUNET_free (ac);
-  }
   while (NULL != (se = se_head))
   {
     GNUNET_CONTAINER_DLL_remove (se_head,
@@ -2052,16 +1827,7 @@ shutdown_task (void *cls)
     GNUNET_SCHEDULER_cancel (se->timeout_task);
     GNUNET_free (se);
   }
-  if (NULL != probe_external_ip_task)
-  {
-    GNUNET_SCHEDULER_cancel (probe_external_ip_task);
-    probe_external_ip_task = NULL;
-  }
-  if (NULL != probe_external_ip_op)
-  {
-    GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
-    probe_external_ip_op = NULL;
-  }
+  GN_nat_status_changed (GNUNET_NO);
   if (NULL != scan_task)
   {
     GNUNET_SCHEDULER_cancel (scan_task);
@@ -2098,7 +1864,7 @@ run (void *cls,
     stun_stale_timeout = GNUNET_TIME_UNIT_HOURS;
 
   /* Check for UPnP */
-  enable_upnp 
+  enable_upnp
     = GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                            "NAT",
                                            "ENABLE_UPNP");
@@ -2115,7 +1881,13 @@ run (void *cls,
       enable_upnp = GNUNET_SYSERR;
     }
   }
-  
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg,
+                                          "nat",
+                                          "DYNDNS_FREQUENCY",
+                                           &dyndns_frequency))
+    dyndns_frequency = DYNDNS_FREQUENCY;
+
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
                                 NULL);
   stats = GNUNET_STATISTICS_create ("nat",
@@ -2163,6 +1935,7 @@ client_disconnect_cb (void *cls,
                      void *internal_cls)
 {
   struct ClientHandle *ch = internal_cls;
+  struct LocalAddressList *lal;
 
   GNUNET_CONTAINER_DLL_remove (ch_head,
                               ch_tail,
@@ -2176,7 +1949,30 @@ client_disconnect_cb (void *cls,
     }
   }
   GNUNET_free_non_null (ch->caddrs);
-  GNUNET_free (ch->hole_external);
+  while (NULL != (lal = ch->ext_addr_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
+                                ch->ext_addr_tail,
+                                lal);
+    GNUNET_free (lal);
+  }
+  if (NULL != ch->ext_dns_task)
+  {
+    GNUNET_SCHEDULER_cancel (ch->ext_dns_task);
+    ch->ext_dns_task = NULL;
+  }
+  if (NULL != ch->external_monitor)
+  {
+    GN_external_ipv4_monitor_stop (ch->external_monitor);
+    ch->external_monitor = NULL;
+  }
+  if (NULL != ch->ext_dns)
+  {
+    GNUNET_RESOLVER_request_cancel (ch->ext_dns);
+    ch->ext_dns = NULL;
+  }
+  GNUNET_free_non_null (ch->hole_external);
+  GNUNET_free_non_null (ch->section_name);
   GNUNET_free (ch);
 }
 
@@ -2203,10 +1999,6 @@ GNUNET_SERVICE_MAIN
                        GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
                        struct GNUNET_NAT_RequestConnectionReversalMessage,
                        NULL),
- GNUNET_MQ_hd_var_size (autoconfig_request,
-                       GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG,
-                       struct GNUNET_NAT_AutoconfigRequestMessage,
-                       NULL),
  GNUNET_MQ_handler_end ());
 
 
diff --git a/src/nat/gnunet-service-nat.h b/src/nat/gnunet-service-nat.h
new file mode 100644 (file)
index 0000000..96eb9f7
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+  This file is part of GNUnet.
+  Copyright (C) 2016, 2017 GNUnet e.V.
+
+  GNUnet is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published
+  by the Free Software Foundation; either version 3, or (at your
+  option) any later version.
+
+  GNUnet is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with GNUnet; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file nat/gnunet-service-nat.h
+ * @brief network address translation traversal service
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SERVICE_NAT_H
+#define GNUNET_SERVICE_NAT_H
+
+/**
+ * Is UPnP enabled? #GNUNET_YES if enabled, #GNUNET_NO if disabled,
+ * #GNUNET_SYSERR if configuration enabled but binary is unavailable.
+ */
+extern int enable_upnp;
+
+#endif
diff --git a/src/nat/gnunet-service-nat_externalip.c b/src/nat/gnunet-service-nat_externalip.c
new file mode 100644 (file)
index 0000000..979d2f0
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009, 2015, 2016, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * Code to figure out what our external IPv4 address(es) might
+ * be (external IPv4s are what is seen on the rest of the Internet).
+ *
+ * This can be implemented using different methods, and we allow
+ * the main service to be notified about changes to what we believe
+ * is our external IPv4 address.  
+ *
+ * Note that this is explicitly only about NATed systems; if one
+ * of our network interfaces has a global IP address this does
+ * not count as "external".
+ *
+ * TODO:
+ * - implement NEW logic for external IP detection based on traceroute!
+ *
+ * @file nat/gnunet-service-nat_externalip.c
+ * @brief Functions for monitoring external IPv4 addresses
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <math.h>
+#include "gnunet_util_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_resolver_service.h"
+#include "gnunet_nat_service.h"
+#include "gnunet-service-nat.h"
+#include "gnunet-service-nat_externalip.h"
+#include "gnunet-service-nat_stun.h"
+#include "gnunet-service-nat_mini.h"
+#include "gnunet-service-nat_helper.h"
+#include "nat.h"
+#include <gcrypt.h>
+
+
+/**
+ * How long do we wait until we re-try running `external-ip` if the
+ * command failed to terminate nicely?
+ */
+#define EXTERN_IP_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
+
+/**
+ * How long do we wait until we re-try running `external-ip` if the
+ * command failed (but terminated)?
+ */
+#define EXTERN_IP_RETRY_FAILURE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
+
+/**
+ * How long do we wait until we re-try running `external-ip` if the
+ * command succeeded?
+ */
+#define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
+
+
+/**
+ * Handle to monitor for external IP changes.
+ */
+struct GN_ExternalIPMonitor
+{
+  /**
+   * Kept in DLL.
+   */
+  struct GN_ExternalIPMonitor *next;
+
+  /**
+   * Kept in DLL.
+   */
+  struct GN_ExternalIPMonitor *prev;
+  
+  /**
+   * Function to call when we believe our external IPv4 address changed.
+   */
+  GN_NotifyExternalIPv4Change cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+};
+
+
+/**
+ * List of monitors, kept in DLL.
+ */
+static struct GN_ExternalIPMonitor *mon_head;
+
+/**
+ * List of monitors, kept in DLL.
+ */
+static struct GN_ExternalIPMonitor *mon_tail;
+
+/**
+ * Task run to obtain our external IP (if #enable_upnp is set
+ * and if we find we have a NATed IP address).
+ */
+static struct GNUNET_SCHEDULER_Task *probe_external_ip_task;
+
+/**
+ * Handle to our operation to run `external-ip`.
+ */
+static struct GNUNET_NAT_ExternalHandle *probe_external_ip_op;
+
+/**
+ * What is our external IP address as claimed by `external-ip`?
+ * 0 for unknown.
+ */
+static struct in_addr mini_external_ipv4;
+
+
+/**
+ * Tell relevant clients about a change in our external
+ * IPv4 address.
+ * 
+ * @param add #GNUNET_YES to add, #GNUNET_NO to remove
+ * @param v4 the external address that changed
+ */
+static void
+notify_monitors_external_ipv4_change (int add,
+                                     const struct in_addr *v4)
+{
+  for (struct GN_ExternalIPMonitor *mon = mon_head;
+       NULL != mon;
+       mon = mon->next)
+    mon->cb (mon->cb_cls,
+            v4,
+            add);
+}
+
+
+/**
+ * Task used to run `external-ip` to get our external IPv4
+ * address and pass it to NATed clients if possible.
+ *
+ * @param cls NULL
+ */
+static void
+run_external_ip (void *cls);
+
+
+/**
+ * We learn our current external IP address.  If it changed,
+ * notify all of our applicable clients. Also re-schedule
+ * #run_external_ip with an appropriate timeout.
+ * 
+ * @param cls NULL
+ * @param addr the address, NULL on errors
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ */
+static void
+handle_external_ip (void *cls,
+                   const struct in_addr *addr,
+                   enum GNUNET_NAT_StatusCode result)
+{
+  char buf[INET_ADDRSTRLEN];
+  
+  probe_external_ip_op = NULL;
+  GNUNET_SCHEDULER_cancel (probe_external_ip_task);
+  probe_external_ip_task
+    = GNUNET_SCHEDULER_add_delayed ((NULL == addr)
+                                   ? EXTERN_IP_RETRY_FAILURE
+                                   : EXTERN_IP_RETRY_SUCCESS,
+                                   &run_external_ip,
+                                   NULL);
+  switch (result)
+  {
+  case GNUNET_NAT_ERROR_SUCCESS:
+    if (addr->s_addr == mini_external_ipv4.s_addr)
+      return; /* not change */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Our external IP is now %s\n",
+               inet_ntop (AF_INET,
+                          addr,
+                          buf,
+                          sizeof (buf)));
+    if (0 != mini_external_ipv4.s_addr)
+      notify_monitors_external_ipv4_change (GNUNET_NO,
+                                           &mini_external_ipv4);
+    mini_external_ipv4 = *addr;
+    notify_monitors_external_ipv4_change (GNUNET_YES,
+                                         &mini_external_ipv4);
+    break;
+  default:
+    if (0 != mini_external_ipv4.s_addr)
+      notify_monitors_external_ipv4_change (GNUNET_NO,
+                                           &mini_external_ipv4);
+    mini_external_ipv4.s_addr = 0; 
+    break;
+  }
+}
+
+
+/**
+ * Task used to run `external-ip` to get our external IPv4
+ * address and pass it to NATed clients if possible.
+ *
+ * @param cls NULL
+ */
+static void
+run_external_ip (void *cls)
+{
+  probe_external_ip_task
+    = GNUNET_SCHEDULER_add_delayed (EXTERN_IP_RETRY_TIMEOUT,
+                                   &run_external_ip,
+                                   NULL);
+  if (NULL != probe_external_ip_op)
+  {
+    GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
+    probe_external_ip_op = NULL;
+  }
+  probe_external_ip_op
+    = GNUNET_NAT_mini_get_external_ipv4_ (&handle_external_ip,
+                                         NULL);
+}
+
+
+/**
+ * We have changed our opinion about being NATed in the first
+ * place. Adapt our probing.
+ *
+ * @param have_nat #GNUNET_YES if we believe we are behind NAT
+ */
+void
+GN_nat_status_changed (int have_nat)
+{
+  if (GNUNET_YES != enable_upnp)
+    return;
+  if ( (GNUNET_YES == have_nat) &&
+       (NULL == probe_external_ip_task) &&
+       (NULL == probe_external_ip_op) )
+  {
+    probe_external_ip_task
+      = GNUNET_SCHEDULER_add_now (&run_external_ip,
+                                 NULL);
+    return;
+  }
+  if (GNUNET_NO == have_nat) 
+  {
+    if (NULL != probe_external_ip_task)
+    {
+      GNUNET_SCHEDULER_cancel (probe_external_ip_task);
+      probe_external_ip_task = NULL;
+    }
+    if (NULL != probe_external_ip_op)
+    {
+      GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
+      probe_external_ip_op = NULL;
+    }
+  }
+}
+
+
+/**
+ * Start monitoring external IPv4 addresses.
+ *
+ * @param cb function to call on changes
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel
+ */
+struct GN_ExternalIPMonitor *
+GN_external_ipv4_monitor_start (GN_NotifyExternalIPv4Change cb,
+                               void *cb_cls)
+{
+  struct GN_ExternalIPMonitor *mon;
+
+  mon = GNUNET_new (struct GN_ExternalIPMonitor);
+  mon->cb = cb;
+  mon->cb_cls = cb_cls;
+  GNUNET_CONTAINER_DLL_insert (mon_head,
+                              mon_tail,
+                              mon);
+  if (0 != mini_external_ipv4.s_addr)
+    cb (cb_cls,
+       &mini_external_ipv4,
+       GNUNET_YES);
+  return mon;
+}
+
+
+/**
+ * Stop calling monitor.
+ *
+ * @param mon monitor to call
+ */
+void
+GN_external_ipv4_monitor_stop (struct GN_ExternalIPMonitor *mon)
+{
+  GNUNET_CONTAINER_DLL_remove (mon_head,
+                              mon_tail,
+                              mon);
+  GNUNET_free (mon);
+}
+
+/* end of gnunet-service-nat_externalip.c */
diff --git a/src/nat/gnunet-service-nat_externalip.h b/src/nat/gnunet-service-nat_externalip.h
new file mode 100644 (file)
index 0000000..3191055
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009, 2015, 2016, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * Code to figure out what our external IPv4 address(es) might
+ * be (external IPv4s are what is seen on the rest of the Internet).
+ *
+ * This can be implemented using different methods, and we allow
+ * the main service to be notified about changes to what we believe
+ * is our external IPv4 address.  
+ *
+ * Note that this is explicitly only about NATed systems; if one
+ * of our network interfaces has a global IP address this does
+ * not count as "external".
+ *
+ * @file nat/gnunet-service-nat_externalip.h
+ * @brief Functions for monitoring external IPv4 addresses
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SERVICE_NAT_EXTERNALIP_H
+#define GNUNET_SERVICE_NAT_EXTERNALIP_H
+
+#include "platform.h"
+
+
+/**
+ * We have changed our opinion about being NATed in the first
+ * place. Adapt our probing.
+ *
+ * @param have_nat #GNUNET_YES if we believe we are behind NAT
+ */
+void
+GN_nat_status_changed (int have_nat);
+
+
+/**
+ * Function we call when we believe our external IPv4 address changed.
+ *
+ * @param cls closure
+ * @param ip address to add/remove
+ * @param add_remove #GNUNET_YES to add, #GNUNET_NO to remove
+ */
+typedef void
+(*GN_NotifyExternalIPv4Change)(void *cls,
+                              const struct in_addr *ip,
+                              int add_remove);
+
+
+/**
+ * Handle to monitor for external IP changes.
+ */
+struct GN_ExternalIPMonitor;
+
+
+/**
+ * Start monitoring external IPv4 addresses.
+ *
+ * @param cb function to call on changes
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel
+ */
+struct GN_ExternalIPMonitor *
+GN_external_ipv4_monitor_start (GN_NotifyExternalIPv4Change cb,
+                               void *cb_cls);
+
+
+/**
+ * Stop calling monitor.
+ *
+ * @param mon monitor to call
+ */
+void
+GN_external_ipv4_monitor_stop (struct GN_ExternalIPMonitor *mon);
+
+
+#endif
index 7e5051d6571305d43d1006c2912f4a78cf568077..e91f63beb3f39e6bd15980ced7872af26d018a80 100644 (file)
@@ -49,7 +49,7 @@ struct HelperContext
    * Closure for @e cb.
    */
   void *cb_cls;
-  
+
   /**
    * How long do we wait for restarting a crashed gnunet-helper-nat-server?
    */
@@ -126,7 +126,7 @@ nat_server_read (void *cls)
   memset (mybuf,
          0,
          sizeof (mybuf));
-  bytes 
+  bytes
     = GNUNET_DISK_file_read (h->server_stdout_handle,
                             mybuf,
                             sizeof (mybuf));
@@ -134,7 +134,7 @@ nat_server_read (void *cls)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Finished reading from server stdout with code: %d\n",
-               bytes);
+               (int) bytes);
     if (0 != GNUNET_OS_process_kill (h->server_proc,
                                     GNUNET_TERM_SIG))
       GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
@@ -185,7 +185,7 @@ nat_server_read (void *cls)
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("gnunet-helper-nat-server generated malformed address `%s'\n"),
                mybuf);
-    h->server_read_task 
+    h->server_read_task
       = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
                                         h->server_stdout_handle,
                                         &nat_server_read,
@@ -199,7 +199,7 @@ nat_server_read (void *cls)
              port);
   h->cb (h->cb_cls,
         &sin_addr);
-  h->server_read_task 
+  h->server_read_task
     = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
                                       h->server_stdout_handle,
                                      &nat_server_read,
@@ -219,9 +219,9 @@ restart_nat_server (void *cls)
   struct HelperContext *h = cls;
   char *binary;
   char ia[INET_ADDRSTRLEN];
-  
+
   h->server_read_task = NULL;
-  h->server_stdout 
+  h->server_stdout
     = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES,
                        GNUNET_NO, GNUNET_YES);
   if (NULL == h->server_stdout)
@@ -243,7 +243,7 @@ restart_nat_server (void *cls)
   /* Start the server process */
   binary
     = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
-  h->server_proc 
+  h->server_proc
     = GNUNET_OS_start_process (GNUNET_NO,
                               0,
                               NULL,
@@ -267,10 +267,10 @@ restart_nat_server (void *cls)
   /* Close the write end of the read pipe */
   GNUNET_DISK_pipe_close_end (h->server_stdout,
                              GNUNET_DISK_PIPE_END_WRITE);
-  h->server_stdout_handle 
+  h->server_stdout_handle
     = GNUNET_DISK_pipe_handle (h->server_stdout,
                               GNUNET_DISK_PIPE_END_READ);
-  h->server_read_task 
+  h->server_read_task
     = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
                                      h->server_stdout_handle,
                                      &nat_server_read,
@@ -316,7 +316,7 @@ GN_start_gnunet_nat_server_ (const struct in_addr *internal_address,
  */
 void
 GN_stop_gnunet_nat_server_ (struct HelperContext *h)
-{  
+{
   if (NULL != h->server_read_task)
   {
     GNUNET_SCHEDULER_cancel (h->server_read_task);
@@ -384,13 +384,13 @@ GN_request_connection_reversal (const struct in_addr *internal_address,
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
                         "inet_ntop");
     return GNUNET_SYSERR;
-  }  
+  }
   GNUNET_snprintf (port_as_string,
                    sizeof (port_as_string),
                    "%d",
                    internal_port);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             _("Running gnunet-helper-nat-client %s %s %u\n"),
+             "Running gnunet-helper-nat-client %s %s %u\n",
              intv4,
              remv4,
              internal_port);
index 2c0dd34458728899d25f06aadbb99ceec56cfb08..8a7af9bf10a525dd38f9db6bf2145b8134d02a0a 100644 (file)
@@ -55,7 +55,7 @@ struct GNUNET_NAT_ExternalHandle;
  */
 struct GNUNET_NAT_ExternalHandle *
 GNUNET_NAT_mini_get_external_ipv4_ (GNUNET_NAT_IPCallback cb,
-                                   void *cb_cls);
+                                    void *cb_cls);
 
 
 /**
diff --git a/src/nat/nat.c b/src/nat/nat.c
deleted file mode 100644 (file)
index 08dd5dd..0000000
+++ /dev/null
@@ -1,2054 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2009, 2010, 2011 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file nat/nat.c
- * @brief Library handling UPnP and NAT-PMP port forwarding and
- *     external IP address retrieval
- * @author Milan Bouchet-Valat
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_resolver_service.h"
-#include "gnunet_nat_lib.h"
-#include "nat.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
-
-/**
- * How often do we scan for changes in our IP address from our local
- * interfaces?
- */
-#define IFC_SCAN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
-
-/**
- * How often do we scan for changes in how our hostname resolves?
- */
-#define HOSTNAME_DNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 20)
-
-
-/**
- * How often do we scan for changes in how our external (dyndns) hostname resolves?
- */
-#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7)
-
-/**
- * How long until we give up trying to resolve our own hostname?
- */
-#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
-
-
-/**
- * How often do we check a STUN server ?
- */
-#define STUN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
-
-
-/**
- * Where did the given local address originate from?
- * To be used for debugging as well as in the future
- * to remove all addresses from a certain source when
- * we reevaluate the source.
- */
-enum LocalAddressSource
-{
-  /**
-   * Address was obtained by DNS resolution of the external hostname
-   * given in the configuration (i.e. hole-punched DynDNS setup).
-   */
-  LAL_EXTERNAL_IP,
-
-  /**
-   * Address was obtained by an external STUN server
-   */
-  LAL_EXTERNAL_STUN_IP,
-
-  /**
-   * Address was obtained by DNS resolution of the external hostname
-   * given in the configuration (i.e. hole-punched DynDNS setup)
-   * during the previous iteration (see #3213).
-   */
-  LAL_EXTERNAL_IP_OLD,
-
-  /**
-   * Address was obtained by looking up our own hostname in DNS.
-   */
-  LAL_HOSTNAME_DNS,
-
-  /**
-   * Address was obtained by scanning our hosts's network interfaces
-   * and taking their address (no DNS involved).
-   */
-  LAL_INTERFACE_ADDRESS,
-
-  /**
-   * Addresses we were explicitly bound to.
-   */
-  LAL_BINDTO_ADDRESS,
-
-  /**
-   * Addresses from UPnP or PMP
-   */
-  LAL_UPNP,
-
-  /**
-   * End of the list.
-   */
-  LAL_END
-};
-
-
-/**
- * List of local addresses that we currently deem valid.  Actual
- * struct is followed by the 'struct sockaddr'.  Note that the code
- * intentionally makes no attempt to ensure that a particular address
- * is only listed once (especially since it may come from different
- * sources, and the source is an "internal" construct).
- */
-struct LocalAddressList
-{
-  /**
-   * This is a linked list.
-   */
-  struct LocalAddressList *next;
-
-  /**
-   * Previous entry.
-   */
-  struct LocalAddressList *prev;
-
-  /**
-   * Number of bytes of address that follow.
-   */
-  socklen_t addrlen;
-
-  /**
-   * Origin of the local address.
-   */
-  enum LocalAddressSource source;
-};
-
-
-/**
- * Handle for miniupnp-based NAT traversal actions.
- */
-struct MiniList
-{
-
-  /**
-   * Doubly-linked list.
-   */
-  struct MiniList *next;
-
-  /**
-   * Doubly-linked list.
-   */
-  struct MiniList *prev;
-
-  /**
-   * Handle to mini-action.
-   */
-  struct GNUNET_NAT_MiniHandle *mini;
-
-  /**
-   * Local port number that was mapped.
-   */
-  uint16_t port;
-
-};
-
-
-/**
- * List of STUN servers
- */
-struct StunServerList
-{
-
-  /**
-   * Doubly-linked list.
-   */
-  struct StunServerList *next;
-
-  /**
-   * Doubly-linked list.
-   */
-  struct StunServerList *prev;
-
-  /**
-   * Address
-   */
-  char * address;
-
-  /**
-   * Server Port
-   */
-  uint16_t port;
-
-};
-
-
-/**
- * Handle for active NAT registrations.
- */
-struct GNUNET_NAT_Handle
-{
-
-  /**
-   * Configuration to use.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Function to call when we learn about a new address.
-   */
-  GNUNET_NAT_AddressCallback address_callback;
-
-  /**
-   * Function to call when we notice another peer asking for
-   * connection reversal.
-   */
-  GNUNET_NAT_ReversalCallback reversal_callback;
-
-  /**
-   * Closure for callbacks (@e address_callback and @e reversal_callback)
-   */
-  void *callback_cls;
-
-  /**
-   * Handle for (DYN)DNS lookup of our external IP.
-   */
-  struct GNUNET_RESOLVER_RequestHandle *ext_dns;
-
-  /**
-   * Handle for request of hostname resolution, non-NULL if pending.
-   */
-  struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
-
-  /**
-   * stdout pipe handle for the gnunet-helper-nat-server process
-   */
-  struct GNUNET_DISK_PipeHandle *server_stdout;
-
-  /**
-   * stdout file handle (for reading) for the gnunet-helper-nat-server process
-   */
-  const struct GNUNET_DISK_FileHandle *server_stdout_handle;
-
-  /**
-   * Linked list of currently valid addresses (head).
-   */
-  struct LocalAddressList *lal_head;
-
-  /**
-   * Linked list of currently valid addresses (tail).
-   */
-  struct LocalAddressList *lal_tail;
-
-  /**
-   * How long do we wait for restarting a crashed gnunet-helper-nat-server?
-   */
-  struct GNUNET_TIME_Relative server_retry_delay;
-
-  /**
-   * ID of select gnunet-helper-nat-server stdout read task
-   */
-  struct GNUNET_SCHEDULER_Task *server_read_task;
-
-  /**
-   * ID of interface IP-scan task
-   */
-  struct GNUNET_SCHEDULER_Task *ifc_task;
-
-  /**
-   * ID of hostname DNS lookup task
-   */
-  struct GNUNET_SCHEDULER_Task *hostname_task;
-
-  /**
-   * ID of DynDNS lookup task
-   */
-  struct GNUNET_SCHEDULER_Task *dns_task;
-
-  /**
-   * Active STUN request, if any.
-   */
-  struct GNUNET_NAT_STUN_Handle *stun_request;
-
-  /**
-   * How often do we scan for changes in our IP address from our local
-   * interfaces?
-   */
-  struct GNUNET_TIME_Relative ifc_scan_frequency;
-
-  /**
-   * How often do we scan for changes in how our hostname resolves?
-   */
-  struct GNUNET_TIME_Relative hostname_dns_frequency;
-
-  /**
-   * How often do we scan for changes in how our external (dyndns) hostname resolves?
-   */
-  struct GNUNET_TIME_Relative dyndns_frequency;
-
-  /**
-   * The process id of the server process (if behind NAT)
-   */
-  struct GNUNET_OS_Process *server_proc;
-
-  /**
-   * LAN address as passed by the caller (array).
-   */
-  struct sockaddr **local_addrs;
-
-  /**
-   * Length of the @e local_addrs.
-   */
-  socklen_t *local_addrlens;
-
-  /**
-   * List of handles for UPnP-traversal, one per local port (if
-   * not IPv6-only).
-   */
-  struct MiniList *mini_head;
-
-  /**
-   * List of handles for UPnP-traversal, one per local port (if
-   * not IPv6-only).
-   */
-  struct MiniList *mini_tail;
-
-  /**
-   * Number of entries in 'local_addrs' array.
-   */
-  unsigned int num_local_addrs;
-
-  /**
-   * Our external address (according to config, UPnP may disagree...),
-   * in dotted decimal notation, IPv4-only. Or NULL if not known.
-   */
-  char *external_address;
-
-  /**
-   * Presumably our internal address (according to config)
-   */
-  char *internal_address;
-
-  /**
-   * Is this transport configured to be behind a NAT?
-   */
-  int behind_nat;
-
-  /**
-   * Has the NAT been punched? (according to config)
-   */
-  int nat_punched;
-
-  /**
-   * Is this transport configured to allow connections to NAT'd peers?
-   */
-  int enable_nat_client;
-
-  /**
-   * Should we run the gnunet-helper-nat-server?
-   */
-  int enable_nat_server;
-
-  /**
-   * Are we allowed to try UPnP/PMP for NAT traversal?
-   */
-  int enable_upnp;
-
-  /**
-   * Should we use local addresses (loopback)? (according to config)
-   */
-  int use_localaddresses;
-
-  /**
-   * Should we return local addresses to clients
-   */
-  int return_localaddress;
-
-  /**
-   * Should we do a DNS lookup of our hostname to find out our own IP?
-   */
-  int use_hostname;
-
-  /**
-   * Is using IPv6 disabled?
-   */
-  int disable_ipv6;
-
-  /**
-   * Is this TCP or UDP?
-   */
-  int is_tcp;
-
-  /**
-   * Port we advertise to the outside.
-   */
-  uint16_t adv_port;
-
-  /**
-   * Should we use STUN ?
-   */
-  int use_stun;
-
-  /**
-   * How often should we check STUN ?
-   */
-  struct GNUNET_TIME_Relative stun_frequency;
-
-  /**
-   * STUN socket
-   */
-  struct GNUNET_NETWORK_Handle* socket;
-
-  /*
-   * Am I waiting for a STUN response ?
-   */
-  int waiting_stun;
-
-  /**
-   * STUN request task
-   */
-  struct GNUNET_SCHEDULER_Task *stun_task;
-
-  /**
-   * Head of List of STUN servers
-   */
-  struct StunServerList *stun_servers_head;
-
-  /**
-   * Tail of List of STUN servers
-   */
-  struct StunServerList *stun_servers_tail;
-
-  /**
-   * Actual STUN Server
-   */
-  struct StunServerList *actual_stun_server;
-
-};
-
-
-/**
- * Try to start the gnunet-helper-nat-server (if it is not
- * already running).
- *
- * @param h handle to NAT
- */
-static void
-start_gnunet_nat_server (struct GNUNET_NAT_Handle *h);
-
-
-/**
- * Remove all addresses from the list of 'local' addresses
- * that originated from the given source.
- *
- * @param h handle to NAT
- * @param src source that identifies addresses to remove
- */
-static void
-remove_from_address_list_by_source (struct GNUNET_NAT_Handle *h,
-                                    enum LocalAddressSource src)
-{
-  struct LocalAddressList *pos;
-  struct LocalAddressList *next;
-
-  next = h->lal_head;
-  while (NULL != (pos = next))
-  {
-    next = pos->next;
-    if (pos->source != src)
-      continue;
-    GNUNET_CONTAINER_DLL_remove (h->lal_head,
-                                 h->lal_tail,
-                                 pos);
-    if (NULL != h->address_callback)
-      h->address_callback (h->callback_cls,
-                           GNUNET_NO,
-                           (const struct sockaddr *) &pos[1],
-                           pos->addrlen);
-    GNUNET_free (pos);
-  }
-}
-
-
-/**
- * Add the given address to the list of 'local' addresses, thereby
- * making it a 'legal' address for this peer to have.
- *
- * @param h handle to NAT
- * @param src where did the local address originate from?
- * @param arg the address, some `struct sockaddr`
- * @param arg_size number of bytes in @a arg
- */
-static void
-add_to_address_list_as_is (struct GNUNET_NAT_Handle *h,
-                           enum LocalAddressSource src,
-                           const struct sockaddr *arg,
-                           socklen_t arg_size)
-{
-  struct LocalAddressList *lal;
-
-  lal = GNUNET_malloc (sizeof (struct LocalAddressList) + arg_size);
-  GNUNET_memcpy (&lal[1], arg, arg_size);
-  lal->addrlen = arg_size;
-  lal->source = src;
-  GNUNET_CONTAINER_DLL_insert (h->lal_head,
-                               h->lal_tail,
-                               lal);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Adding address `%s' from source %d\n",
-       GNUNET_a2s (arg, arg_size),
-       src);
-  if (NULL != h->address_callback)
-    h->address_callback (h->callback_cls,
-                         GNUNET_YES,
-                         arg,
-                         arg_size);
-}
-
-
-/**
- * Add the given address to the list of 'local' addresses, thereby
- * making it a 'legal' address for this peer to have.   Set the
- * port number in the process to the advertised port and possibly
- * also to zero (if we have the gnunet-helper-nat-server).
- *
- * @param h handle to NAT
- * @param src where did the local address originate from?
- * @param arg the address, some `struct sockaddr`
- * @param arg_size number of bytes in @a arg
- */
-static void
-add_to_address_list (struct GNUNET_NAT_Handle *h,
-                     enum LocalAddressSource src,
-                     const struct sockaddr *arg,
-                     socklen_t arg_size)
-{
-  struct sockaddr_in s4;
-  const struct sockaddr_in *in4;
-  struct sockaddr_in6 s6;
-  const struct sockaddr_in6 *in6;
-
-  if (arg_size == sizeof (struct sockaddr_in))
-  {
-    in4 = (const struct sockaddr_in *) arg;
-    s4 = *in4;
-    s4.sin_port = htons (h->adv_port);
-    add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4,
-                               sizeof (struct sockaddr_in));
-    if (GNUNET_YES == h->enable_nat_server)
-    {
-      /* also add with PORT = 0 to indicate NAT server is enabled */
-      s4.sin_port = htons (0);
-      add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4,
-                                 sizeof (struct sockaddr_in));
-    }
-  }
-  else if (arg_size == sizeof (struct sockaddr_in6))
-  {
-    if (GNUNET_YES != h->disable_ipv6)
-    {
-      in6 = (const struct sockaddr_in6 *) arg;
-      s6 = *in6;
-      s6.sin6_port = htons (h->adv_port);
-      add_to_address_list_as_is (h, src, (const struct sockaddr *) &s6,
-                                 sizeof (struct sockaddr_in6));
-    }
-  }
-  else
-  {
-    GNUNET_assert (0);
-  }
-}
-
-
-/**
- * Add the given IP address to the list of 'local' addresses, thereby
- * making it a 'legal' address for this peer to have.
- *
- * @param h handle to NAT
- * @param src where did the local address originate from?
- * @param addr the address, some `struct in_addr` or `struct in6_addr`
- * @param addrlen number of bytes in addr
- */
-static void
-add_ip_to_address_list (struct GNUNET_NAT_Handle *h,
-                        enum LocalAddressSource src,
-                       const void *addr,
-                        socklen_t addrlen)
-{
-  struct sockaddr_in s4;
-  const struct in_addr *in4;
-  struct sockaddr_in6 s6;
-  const struct in6_addr *in6;
-
-  if (addrlen == sizeof (struct in_addr))
-  {
-    in4 = (const struct in_addr *) addr;
-    memset (&s4, 0, sizeof (s4));
-    s4.sin_family = AF_INET;
-    s4.sin_port = 0;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-    s4.sin_len = (u_char) sizeof (struct sockaddr_in);
-#endif
-    s4.sin_addr = *in4;
-    add_to_address_list (h, src, (const struct sockaddr *) &s4,
-                         sizeof (struct sockaddr_in));
-    if (GNUNET_YES == h->enable_nat_server)
-    {
-      /* also add with PORT = 0 to indicate NAT server is enabled */
-      s4.sin_port = htons (0);
-      add_to_address_list (h, src, (const struct sockaddr *) &s4,
-                           sizeof (struct sockaddr_in));
-
-    }
-  }
-  else if (addrlen == sizeof (struct in6_addr))
-  {
-    if (GNUNET_YES != h->disable_ipv6)
-    {
-      in6 = (const struct in6_addr *) addr;
-      memset (&s6, 0, sizeof (s6));
-      s6.sin6_family = AF_INET6;
-      s6.sin6_port = htons (h->adv_port);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-      s6.sin6_len = (u_char) sizeof (struct sockaddr_in6);
-#endif
-      s6.sin6_addr = *in6;
-      add_to_address_list (h, src, (const struct sockaddr *) &s6,
-                           sizeof (struct sockaddr_in6));
-    }
-  }
-  else
-  {
-    GNUNET_assert (0);
-  }
-}
-
-
-/**
- * Task to do DNS lookup on our external hostname to
- * get DynDNS-IP addresses.
- *
- * @param cls the NAT handle
- */
-static void
-resolve_dns (void *cls);
-
-
-/**
- * Our (external) hostname was resolved and the configuration says that
- * the NAT was hole-punched.
- *
- * @param cls the `struct GNUNET_NAT_Handle`
- * @param addr NULL on error, otherwise result of DNS lookup
- * @param addrlen number of bytes in @a addr
- */
-static void
-process_external_ip (void *cls,
-                     const struct sockaddr *addr,
-                     socklen_t addrlen)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-  struct in_addr dummy;
-
-  if (NULL == addr)
-  {
-    h->ext_dns = NULL;
-    /* Current iteration is over, remove 'old' IPs now */
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Purging old IPs for external address\n");
-    remove_from_address_list_by_source (h,
-                                       LAL_EXTERNAL_IP_OLD);
-    if (1 == inet_pton (AF_INET,
-                        h->external_address,
-                        &dummy))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Got numeric IP for external address, not repeating lookup\n");
-      return;                   /* repated lookup pointless: was numeric! */
-    }
-    h->dns_task =
-      GNUNET_SCHEDULER_add_delayed (h->dyndns_frequency,
-                                    &resolve_dns, h);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Got IP `%s' for external address `%s'\n",
-       GNUNET_a2s (addr,
-                  addrlen),
-       h->external_address);
-  add_to_address_list (h,
-                      LAL_EXTERNAL_IP,
-                      addr,
-                      addrlen);
-}
-
-
-/**
- * Task to do a lookup on our hostname for IP addresses.
- *
- * @param cls the NAT handle
- */
-static void
-resolve_hostname (void *cls);
-
-
-/**
- * Function called by the resolver for each address obtained from DNS
- * for our own hostname.  Add the addresses to the list of our IP
- * addresses.
- *
- * @param cls closure
- * @param addr one of the addresses of the host, NULL for the last address
- * @param addrlen length of the @a addr
- */
-static void
-process_hostname_ip (void *cls,
-                     const struct sockaddr *addr,
-                     socklen_t addrlen)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-
-  if (NULL == addr)
-  {
-    h->hostname_dns = NULL;
-    h->hostname_task =
-        GNUNET_SCHEDULER_add_delayed (h->hostname_dns_frequency,
-                                      &resolve_hostname,
-                                     h);
-    return;
-  }
-  add_to_address_list (h,
-                      LAL_HOSTNAME_DNS,
-                      addr,
-                      addrlen);
-}
-
-
-/**
- * Length of the interface names returned from os_network.c.
- * (in that file, hardcoded at 11).
- */
-#define IF_NAME_LEN 11
-
-
-/**
- * Add the IP of our network interface to the list of
- * our IP addresses.
- *
- * @param cls the `struct GNUNET_NAT_Handle`
- * @param name name of the interface
- * @param isDefault do we think this may be our default interface
- * @param addr address of the interface
- * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
- * @param netmask the network mask (can be NULL for unknown or unassigned))
- * @param addrlen number of bytes in @a addr and @a broadcast_addr
- * @return #GNUNET_OK to continue iterating
- */
-static int
-process_interfaces (void *cls,
-                    const char *name,
-                    int isDefault,
-                    const struct sockaddr *addr,
-                    const struct sockaddr *broadcast_addr,
-                    const struct sockaddr *netmask,
-                    socklen_t addrlen)
-{
-  const static struct in6_addr any6 = IN6ADDR_ANY_INIT;
-  struct GNUNET_NAT_Handle *h = cls;
-  const struct sockaddr_in *s4;
-  const struct sockaddr_in6 *s6;
-  const void *ip;
-  char buf[INET6_ADDRSTRLEN];
-  unsigned int i;
-  int have_any;
-  char *tun_if;
-
-  /* skip virtual interfaces created by GNUnet-vpn */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (h->cfg,
-                                             "vpn",
-                                             "IFNAME",
-                                             &tun_if))
-  {
-    if (0 == strncasecmp (name,
-                          tun_if,
-                          IF_NAME_LEN))
-    {
-      GNUNET_free (tun_if);
-      return GNUNET_OK;
-    }
-    GNUNET_free (tun_if);
-  }
-  /* skip virtual interfaces created by GNUnet-dns */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (h->cfg,
-                                             "dns",
-                                             "IFNAME",
-                                             &tun_if))
-  {
-    if (0 == strncasecmp (name,
-                          tun_if,
-                          IF_NAME_LEN))
-    {
-      GNUNET_free (tun_if);
-      return GNUNET_OK;
-    }
-    GNUNET_free (tun_if);
-  }
-  /* skip virtual interfaces created by GNUnet-exit */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (h->cfg,
-                                             "exit",
-                                             "TUN_IFNAME",
-                                             &tun_if))
-  {
-    if (0 == strncasecmp (name,
-                          tun_if,
-                          IF_NAME_LEN))
-    {
-      GNUNET_free (tun_if);
-      return GNUNET_OK;
-    }
-    GNUNET_free (tun_if);
-  }
-
-  switch (addr->sa_family)
-  {
-  case AF_INET:
-    /* check if we're bound to the "ANY" IP address */
-    have_any = GNUNET_NO;
-    for (i=0;i<h->num_local_addrs;i++)
-      {
-       if (h->local_addrs[i]->sa_family != AF_INET)
-         continue;
-#ifndef INADDR_ANY
-#define INADDR_ANY 0
-#endif
-       if (INADDR_ANY == ((struct sockaddr_in*) h->local_addrs[i])->sin_addr.s_addr)
-         {
-           have_any = GNUNET_YES;
-           break;
-         }
-      }
-    if (GNUNET_NO == have_any)
-      return GNUNET_OK; /* not bound to IP 0.0.0.0 but to specific IP addresses,
-                          do not use those from interfaces */
-    s4 = (struct sockaddr_in *) addr;
-    ip = &s4->sin_addr;
-
-    /* Check if address is in 127.0.0.0/8 */
-    uint32_t address = ntohl ((uint32_t) (s4->sin_addr.s_addr));
-    uint32_t value = (address & 0xFF000000) ^ 0x7F000000;
-
-    if ((h->return_localaddress == GNUNET_NO) && (value == 0))
-    {
-      return GNUNET_OK;
-    }
-    if ((GNUNET_YES == h->use_localaddresses) || (value != 0))
-    {
-      add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s4->sin_addr,
-                              sizeof (struct in_addr));
-    }
-    break;
-  case AF_INET6:
-    /* check if we're bound to the "ANY" IP address */
-    have_any = GNUNET_NO;
-    for (i=0;i<h->num_local_addrs;i++)
-      {
-       if (h->local_addrs[i]->sa_family != AF_INET6)
-         continue;
-       if (0 == memcmp (&any6,
-                        &((struct sockaddr_in6*) h->local_addrs[i])->sin6_addr,
-                        sizeof (struct in6_addr)))
-         {
-           have_any = GNUNET_YES;
-           break;
-         }
-      }
-    if (GNUNET_NO == have_any)
-      return GNUNET_OK; /* not bound to "ANY" IP (::0) but to specific IP addresses,
-                          do not use those from interfaces */
-
-    s6 = (struct sockaddr_in6 *) addr;
-    if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
-    {
-      /* skip link local addresses */
-      return GNUNET_OK;
-    }
-    if ((h->return_localaddress == GNUNET_NO) &&
-        (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr)))
-    {
-      return GNUNET_OK;
-    }
-    ip = &s6->sin6_addr;
-    if (GNUNET_YES == h->use_localaddresses)
-    {
-      add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s6->sin6_addr,
-                              sizeof (struct in6_addr));
-    }
-    break;
-  default:
-    GNUNET_break (0);
-    return GNUNET_OK;
-  }
-  if ( (h->internal_address == NULL) &&
-       (h->server_proc == NULL) &&
-       (h->server_read_task == NULL) &&
-       (GNUNET_YES == isDefault) &&
-       ( (addr->sa_family == AF_INET) ||
-        (addr->sa_family == AF_INET6) ) )
-  {
-    /* no internal address configured, but we found a "default"
-     * interface, try using that as our 'internal' address */
-    h->internal_address =
-        GNUNET_strdup (inet_ntop (addr->sa_family, ip, buf, sizeof (buf)));
-    start_gnunet_nat_server (h);
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Task that restarts the gnunet-helper-nat-server process after a crash
- * after a certain delay.
- *
- * @param cls the `struct GNUNET_NAT_Handle`
- */
-static void
-restart_nat_server (void *cls)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-
-  h->server_read_task = NULL;
-  start_gnunet_nat_server (h);
-}
-
-
-/**
- * We have been notified that gnunet-helper-nat-server has written
- * something to stdout.  Handle the output, then reschedule this
- * function to be called again once more is available.
- *
- * @param cls the NAT handle
- */
-static void
-nat_server_read (void *cls)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-  char mybuf[40];
-  ssize_t bytes;
-  size_t i;
-  int port;
-  const char *port_start;
-  struct sockaddr_in sin_addr;
-
-  h->server_read_task = NULL;
-  memset (mybuf, 0, sizeof (mybuf));
-  bytes =
-    GNUNET_DISK_file_read (h->server_stdout_handle, mybuf, sizeof (mybuf));
-  if (bytes < 1)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Finished reading from server stdout with code: %d\n",
-         bytes);
-    if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG))
-      GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill");
-    GNUNET_OS_process_wait (h->server_proc);
-    GNUNET_OS_process_destroy (h->server_proc);
-    h->server_proc = NULL;
-    GNUNET_DISK_pipe_close (h->server_stdout);
-    h->server_stdout = NULL;
-    h->server_stdout_handle = NULL;
-    /* now try to restart it */
-    h->server_retry_delay = GNUNET_TIME_STD_BACKOFF (h->server_retry_delay);
-    h->server_read_task =
-        GNUNET_SCHEDULER_add_delayed (h->server_retry_delay,
-                                      &restart_nat_server, h);
-    return;
-  }
-
-  port_start = NULL;
-  for (i = 0; i < sizeof (mybuf); i++)
-  {
-    if (mybuf[i] == '\n')
-    {
-      mybuf[i] = '\0';
-      break;
-    }
-    if ((mybuf[i] == ':') && (i + 1 < sizeof (mybuf)))
-    {
-      mybuf[i] = '\0';
-      port_start = &mybuf[i + 1];
-    }
-  }
-
-  /* construct socket address of sender */
-  memset (&sin_addr, 0, sizeof (sin_addr));
-  sin_addr.sin_family = AF_INET;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  sin_addr.sin_len = sizeof (sin_addr);
-#endif
-  if ((NULL == port_start) || (1 != SSCANF (port_start, "%d", &port)) ||
-      (-1 == inet_pton (AF_INET, mybuf, &sin_addr.sin_addr)))
-  {
-    /* should we restart gnunet-helper-nat-server? */
-    LOG (GNUNET_ERROR_TYPE_WARNING, "nat",
-         _("gnunet-helper-nat-server generated malformed address `%s'\n"),
-         mybuf);
-    h->server_read_task =
-        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                        h->server_stdout_handle,
-                                        &nat_server_read, h);
-    return;
-  }
-  sin_addr.sin_port = htons ((uint16_t) port);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "gnunet-helper-nat-server read: %s:%d\n", mybuf,
-       port);
-  h->reversal_callback (h->callback_cls, (const struct sockaddr *) &sin_addr,
-                        sizeof (sin_addr));
-  h->server_read_task =
-      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      h->server_stdout_handle,
-                                     &nat_server_read,
-                                      h);
-}
-
-
-/**
- * Try to start the gnunet-helper-nat-server (if it is not
- * already running).
- *
- * @param h handle to NAT
- */
-static void
-start_gnunet_nat_server (struct GNUNET_NAT_Handle *h)
-{
-  char *binary;
-
-  if ((h->behind_nat == GNUNET_YES) && (h->enable_nat_server == GNUNET_YES) &&
-      (h->internal_address != NULL) &&
-      (NULL !=
-       (h->server_stdout =
-        GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES))))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Starting `%s' at `%s'\n",
-         "gnunet-helper-nat-server", h->internal_address);
-    /* Start the server process */
-    binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
-    h->server_proc =
-        GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout, NULL,
-                                 binary,
-                                 "gnunet-helper-nat-server",
-                                 h->internal_address, NULL);
-    GNUNET_free (binary);
-    if (h->server_proc == NULL)
-    {
-      LOG (GNUNET_ERROR_TYPE_WARNING, "nat", _("Failed to start %s\n"),
-           "gnunet-helper-nat-server");
-      GNUNET_DISK_pipe_close (h->server_stdout);
-      h->server_stdout = NULL;
-    }
-    else
-    {
-      /* Close the write end of the read pipe */
-      GNUNET_DISK_pipe_close_end (h->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
-      h->server_stdout_handle =
-          GNUNET_DISK_pipe_handle (h->server_stdout, GNUNET_DISK_PIPE_END_READ);
-      h->server_read_task =
-          GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                          h->server_stdout_handle,
-                                          &nat_server_read, h);
-    }
-  }
-}
-
-
-/**
- * Task to scan the local network interfaces for IP addresses.
- *
- * @param cls the NAT handle
- */
-static void
-list_interfaces (void *cls)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-
-  h->ifc_task = NULL;
-  remove_from_address_list_by_source (h, LAL_INTERFACE_ADDRESS);
-  GNUNET_OS_network_interfaces_list (&process_interfaces, h);
-  h->ifc_task =
-    GNUNET_SCHEDULER_add_delayed (h->ifc_scan_frequency,
-                                  &list_interfaces, h);
-}
-
-
-/**
- * Callback with the result from the STUN request.
- *
- * @param cls the NAT handle
- * @param result the status
- */
-static void
-stun_request_callback (void *cls,
-                       enum GNUNET_NAT_StatusCode result)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-
-  h->stun_request = NULL;
-  switch (result)
-  {
-  case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Failed to transmit STUN request\n");
-    break;
-  case GNUNET_NAT_ERROR_NOT_ONLINE:
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Failed to resolve STUN server (are we online?)\n");
-    break;
-  case GNUNET_NAT_ERROR_SUCCESS:
-    /* all good, STUN request active */
-    h->waiting_stun = GNUNET_YES;
-    break;
-  default:
-    /* unexpected error code for STUN */
-    GNUNET_break (0);
-  }
-}
-
-
-/**
- * CHECK if is a valid STUN packet sending to GNUNET_NAT_stun_handle_packet().
- * It also check if it can handle the packet based on the NAT handler.
- * You don't need to call anything else to check if the packet is valid,
- *
- * @param cls the NAT handle
- * @param data packet
- * @param len packet length
- * @return #GNUNET_NO if it can't decode, #GNUNET_YES if is a packet
- */
-int
-GNUNET_NAT_is_valid_stun_packet (void *cls,
-                                 const void *data,
-                                 size_t len)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-  struct sockaddr_in answer;
-
-  /* We are not expecting a STUN message */
-  if (GNUNET_YES != h->waiting_stun)
-    return GNUNET_NO;
-
-  /* We dont have STUN installed */
-  if (! h->use_stun)
-    return GNUNET_NO;
-
-  /* Empty the answer structure */
-  memset (&answer,
-          0,
-          sizeof(struct sockaddr_in));
-
-  /* Lets handle the packet*/
-  if (GNUNET_NO ==
-      GNUNET_NAT_stun_handle_packet (data,
-                                     len,
-                                     &answer))
-    return GNUNET_NO;
-
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "STUN server returned %s:%d\n",
-       inet_ntoa (answer.sin_addr),
-       ntohs (answer.sin_port));
-  /* Remove old IPs from previous STUN calls */
-  remove_from_address_list_by_source (h,
-                                      LAL_EXTERNAL_STUN_IP);
-  /* Add new IP from STUN packet */
-  add_to_address_list (h,
-                       LAL_EXTERNAL_STUN_IP,
-                       (const struct sockaddr *) &answer,
-                       sizeof (struct sockaddr_in));
-  h->waiting_stun = GNUNET_NO;
-  return GNUNET_YES;
-}
-
-
-/**
- * Task to do a STUN request
- *
- * @param cls the NAT handle
- */
-static void
-process_stun (void *cls)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-  struct StunServerList *elem = h->actual_stun_server;
-
-  h->stun_task = NULL;
-  /* Make the request */
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "I will request the stun server %s:%i\n",
-       elem->address,
-       elem->port);
-  if (NULL != h->stun_request)
-  {
-    GNUNET_NAT_stun_make_request_cancel (h->stun_request);
-    h->stun_request = NULL;
-  }
-  h->waiting_stun = GNUNET_NO;
-  h->stun_request
-    = GNUNET_NAT_stun_make_request (elem->address,
-                                    elem->port,
-                                    h->socket,
-                                    &stun_request_callback,
-                                    h);
-  if (NULL == h->stun_request)
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-         "STUN request to %s:%i failed\n",
-         elem->address,
-         elem->port);
-  }
-  h->stun_task =
-    GNUNET_SCHEDULER_add_delayed (h->stun_frequency,
-                                  &process_stun,
-                                  h);
-
-  /* Set actual Server*/
-  if (NULL != elem->next)
-  {
-    h->actual_stun_server = elem->next;
-  }
-  else
-  {
-    h->actual_stun_server = h->stun_servers_head;
-  }
-}
-
-
-/**
- * Task to do a lookup on our hostname for IP addresses.
- *
- * @param cls the NAT handle
- */
-static void
-resolve_hostname (void *cls)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-
-  h->hostname_task = NULL;
-  remove_from_address_list_by_source (h, LAL_HOSTNAME_DNS);
-  GNUNET_assert (NULL == h->hostname_dns);
-  h->hostname_dns =
-      GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC,
-                                       HOSTNAME_RESOLVE_TIMEOUT,
-                                        &process_hostname_ip,
-                                       h);
-}
-
-
-/**
- * Task to do DNS lookup on our external hostname to
- * get DynDNS-IP addresses.
- *
- * @param cls the NAT handle
- */
-static void
-resolve_dns (void *cls)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-  struct LocalAddressList *pos;
-
-  h->dns_task = NULL;
-  for (pos = h->lal_head; NULL != pos; pos = pos->next)
-    if (pos->source == LAL_EXTERNAL_IP)
-      pos->source = LAL_EXTERNAL_IP_OLD;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Resolving external address `%s'\n",
-       h->external_address);
-  GNUNET_assert (NULL == h->ext_dns);
-  h->ext_dns =
-      GNUNET_RESOLVER_ip_get (h->external_address,
-                             AF_INET,
-                              GNUNET_TIME_UNIT_MINUTES,
-                              &process_external_ip,
-                             h);
-}
-
-
-/**
- * Add or remove UPnP-mapped addresses.
- *
- * @param cls the `struct GNUNET_NAT_Handle`
- * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
- *     the previous (now invalid) one
- * @param addr either the previous or the new public IP address
- * @param addrlen actual lenght of @a addr
- * @param ret GNUNET_NAT_ERROR_SUCCESS on success, otherwise an error code
- */
-static void
-upnp_add (void *cls,
-          int add_remove,
-          const struct sockaddr *addr,
-          socklen_t addrlen,
-          enum GNUNET_NAT_StatusCode ret)
-{
-  struct GNUNET_NAT_Handle *h = cls;
-  struct LocalAddressList *pos;
-  struct LocalAddressList *next;
-
-
-  if (GNUNET_NAT_ERROR_SUCCESS != ret)
-  {
-    /* Error while running upnp client */
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-          _("Error while running upnp client:\n"));
-    //FIXME: convert error code to string
-    return;
-  }
-
-  if (GNUNET_YES == add_remove)
-  {
-    add_to_address_list (h,
-                         LAL_UPNP,
-                         addr,
-                         addrlen);
-    return;
-  }
-  else if (GNUNET_NO == add_remove)
-  {
-    /* remove address */
-    next = h->lal_head;
-    while (NULL != (pos = next))
-    {
-      next = pos->next;
-      if ((pos->source != LAL_UPNP) || (pos->addrlen != addrlen) ||
-          (0 != memcmp (&pos[1], addr, addrlen)))
-        continue;
-      GNUNET_CONTAINER_DLL_remove (h->lal_head,
-                                   h->lal_tail,
-                                   pos);
-      if (NULL != h->address_callback)
-        h->address_callback (h->callback_cls,
-                             GNUNET_NO,
-                             (const struct sockaddr *) &pos[1],
-                             pos->addrlen);
-      GNUNET_free (pos);
-      return;                     /* only remove once */
-    }
-    /* asked to remove address that does not exist */
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-         "Asked to remove unkown address `%s'\n",
-         GNUNET_a2s(addr, addrlen));
-    GNUNET_break (0);
-  }
-  else
-  {
-
-    GNUNET_break (0);
-  }
-}
-
-
-/**
- * Try to add a port mapping using UPnP.
- *
- * @param h overall NAT handle
- * @param port port to map with UPnP
- */
-static void
-add_minis (struct GNUNET_NAT_Handle *h,
-           uint16_t port)
-{
-  struct MiniList *ml;
-
-  ml = h->mini_head;
-  while (NULL != ml)
-  {
-    if (port == ml->port)
-      return;                   /* already got this port */
-    ml = ml->next;
-  }
-
-  ml = GNUNET_new (struct MiniList);
-  ml->port = port;
-  ml->mini = GNUNET_NAT_mini_map_start (port, h->is_tcp, &upnp_add, h);
-
-  if (NULL == ml->mini)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-        _("Failed to run upnp client for port %u\n"), ml->port);
-    GNUNET_free (ml);
-    return;
-  }
-
-  GNUNET_CONTAINER_DLL_insert (h->mini_head,
-                               h->mini_tail,
-                               ml);
-}
-
-
-/**
- * Task to add addresses from original bind to set of valid addrs.
- *
- * @param h the NAT handle
- */
-static void
-add_from_bind (struct GNUNET_NAT_Handle *h)
-{
-  static struct in6_addr any = IN6ADDR_ANY_INIT;
-
-  unsigned int i;
-  struct sockaddr *sa;
-  const struct sockaddr_in *v4;
-
-  for (i = 0; i < h->num_local_addrs; i++)
-  {
-    sa = h->local_addrs[i];
-    switch (sa->sa_family)
-    {
-    case AF_INET:
-      if (sizeof (struct sockaddr_in) != h->local_addrlens[i])
-      {
-        GNUNET_break (0);
-        break;
-      }
-      v4 = (const struct sockaddr_in *) sa;
-      if (0 != v4->sin_addr.s_addr)
-        add_to_address_list (h,
-                             LAL_BINDTO_ADDRESS, sa,
-                             sizeof (struct sockaddr_in));
-      if (h->enable_upnp)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "Running upnp client for address `%s'\n",
-                    GNUNET_a2s (sa,sizeof (struct sockaddr_in)));
-        add_minis (h, ntohs (v4->sin_port));
-      }
-      break;
-    case AF_INET6:
-      if (sizeof (struct sockaddr_in6) != h->local_addrlens[i])
-      {
-        GNUNET_break (0);
-        break;
-      }
-      if (0 !=
-          memcmp (&((const struct sockaddr_in6 *) sa)->sin6_addr,
-                  &any,
-                  sizeof (struct in6_addr)))
-        add_to_address_list (h,
-                             LAL_BINDTO_ADDRESS,
-                             sa,
-                             sizeof (struct sockaddr_in6));
-      break;
-    default:
-      break;
-    }
-  }
-}
-
-
-/**
- * Attempt to enable port redirection and detect public IP address contacting
- * UPnP or NAT-PMP routers on the local network. Use addr to specify to which
- * of the local host's addresses should the external port be mapped. The port
- * is taken from the corresponding sockaddr_in[6] field.
- *
- * @param cfg configuration to use
- * @param is_tcp #GNUNET_YES for TCP, #GNUNET_NO for UDP
- * @param adv_port advertised port (port we are either bound to or that our OS
- *                 locally performs redirection from to our bound port).
- * @param num_addrs number of addresses in @a addrs
- * @param addrs the local addresses packets should be redirected to
- * @param addrlens actual lengths of the addresses
- * @param address_callback function to call everytime the public IP address changes
- * @param reversal_callback function to call if someone wants connection reversal from us
- * @param callback_cls closure for callbacks
- * @param sock used socket
- * @return NULL on error, otherwise handle that can be used to unregister
- */
-struct GNUNET_NAT_Handle *
-GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                     int is_tcp,
-                     uint16_t adv_port,
-                     unsigned int num_addrs,
-                     const struct sockaddr **addrs,
-                     const socklen_t *addrlens,
-                     GNUNET_NAT_AddressCallback address_callback,
-                     GNUNET_NAT_ReversalCallback reversal_callback,
-                     void *callback_cls,
-                     struct GNUNET_NETWORK_Handle *sock)
-{
-  struct GNUNET_NAT_Handle *h;
-  struct in_addr in_addr;
-  unsigned int i;
-  char *binary;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Registered with NAT service at port %u with %u IP bound local addresses\n",
-       (unsigned int) adv_port, num_addrs);
-  h = GNUNET_new (struct GNUNET_NAT_Handle);
-  h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS;
-  h->cfg = cfg;
-  h->is_tcp = is_tcp;
-  h->address_callback = address_callback;
-  h->reversal_callback = reversal_callback;
-  h->callback_cls = callback_cls;
-  h->num_local_addrs = num_addrs;
-  h->adv_port = adv_port;
-  if (0 != num_addrs)
-  {
-    h->local_addrs = GNUNET_malloc (num_addrs * sizeof (struct sockaddr *));
-    h->local_addrlens = GNUNET_malloc (num_addrs * sizeof (socklen_t));
-    for (i = 0; i < num_addrs; i++)
-    {
-      GNUNET_assert (addrlens[i] > 0);
-      GNUNET_assert (addrs[i] != NULL);
-      h->local_addrlens[i] = addrlens[i];
-      h->local_addrs[i] = GNUNET_malloc (addrlens[i]);
-      GNUNET_memcpy (h->local_addrs[i], addrs[i], addrlens[i]);
-    }
-  }
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_have_value (cfg, "nat", "INTERNAL_ADDRESS"))
-  {
-    (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat",
-                                                  "INTERNAL_ADDRESS",
-                                                  &h->internal_address);
-  }
-  if ((h->internal_address != NULL) &&
-      (inet_pton (AF_INET, h->internal_address, &in_addr) != 1))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
-                              "nat", "INTERNAL_ADDRESS",
-                              _("malformed"));
-    GNUNET_free (h->internal_address);
-    h->internal_address = NULL;
-  }
-
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_have_value (cfg, "nat", "EXTERNAL_ADDRESS"))
-  {
-    (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat",
-                                                  "EXTERNAL_ADDRESS",
-                                                  &h->external_address);
-  }
-  h->behind_nat =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "BEHIND_NAT");
-  h->nat_punched =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "PUNCHED_NAT");
-  h->enable_nat_client =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_CLIENT");
-  h->enable_nat_server =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_SERVER");
-  h->enable_upnp =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_UPNP");
-  h->use_localaddresses =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_LOCALADDR");
-  h->return_localaddress =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat",
-                                            "RETURN_LOCAL_ADDRESSES");
-
-  h->use_hostname =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_HOSTNAME");
-  h->disable_ipv6 =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "DISABLEV6");
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "DYNDNS_FREQUENCY",
-                                           &h->dyndns_frequency))
-    h->dyndns_frequency = DYNDNS_FREQUENCY;
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "IFC_SCAN_FREQUENCY",
-                                           &h->ifc_scan_frequency))
-    h->ifc_scan_frequency = IFC_SCAN_FREQUENCY;
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "HOSTNAME_DNS_FREQUENCY",
-                                           &h->hostname_dns_frequency))
-    h->hostname_dns_frequency = HOSTNAME_DNS_FREQUENCY;
-
-  if (NULL == reversal_callback)
-    h->enable_nat_server = GNUNET_NO;
-
-  /* Check for UPnP client, disable immediately if not available */
-  if ( (GNUNET_YES == h->enable_upnp) &&
-       (GNUNET_SYSERR ==
-        GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)) )
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-        _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP \n"));
-    h->enable_upnp = GNUNET_NO;
-  }
-
-  /* STUN */
-  h->use_stun =
-    GNUNET_CONFIGURATION_get_value_yesno (cfg,
-                                          "nat",
-                                          "USE_STUN");
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg,
-                                           "nat",
-                                           "STUN_FREQUENCY",
-                                           &h->stun_frequency))
-    h->stun_frequency = STUN_FREQUENCY;
-
-
-  /* Check if NAT was hole-punched */
-  if ((NULL != h->address_callback) &&
-      (NULL != h->external_address) &&
-      (GNUNET_YES == h->nat_punched))
-  {
-    h->dns_task = GNUNET_SCHEDULER_add_now (&resolve_dns, h);
-    h->enable_nat_server = GNUNET_NO;
-    h->enable_upnp = GNUNET_NO;
-    h->use_stun = GNUNET_NO;
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "No external IP address given to add to our list of addresses\n");
-  }
-
-  /* ENABLE STUN ONLY ON UDP */
-  if( (! is_tcp) &&
-      (NULL != sock) &&
-      h->use_stun)
-  {
-    char *stun_servers;
-    size_t urls;
-    ssize_t pos;
-    size_t pos_port;
-
-    h->socket = sock;
-    stun_servers = NULL;
-    /* Lets process the servers*/
-    (void) GNUNET_CONFIGURATION_get_value_string (cfg,
-                                                  "nat",
-                                                  "STUN_SERVERS",
-                                                  &stun_servers);
-    urls = 0;
-    if ( (NULL != stun_servers) &&
-         (strlen (stun_servers) > 0) )
-    {
-      pos_port = 0;
-      for (pos = strlen (stun_servers) - 1;
-           pos >= 0;
-           pos--)
-      {
-        if (stun_servers[pos] == ':')
-        {
-          pos_port = pos + 1;
-          stun_servers[pos] = '\0';
-          continue;
-        }
-        if ((stun_servers[pos] == ' ') || (0 == pos))
-        {
-          struct StunServerList *ml;
-
-          /* Check if we do have a port */
-          if ((0 == pos_port) || (pos_port <= pos))
-          {
-            LOG (GNUNET_ERROR_TYPE_WARNING,
-                 "STUN server format mistake\n");
-            break;
-          }
-          urls++;
-          ml = GNUNET_new (struct StunServerList);
-          ml->port = atoi (&stun_servers[pos_port]);
-
-          /* Remove trailing space */
-          if (stun_servers[pos] == ' ')
-            ml->address = GNUNET_strdup (&stun_servers[pos + 1]);
-          else
-            ml->address = GNUNET_strdup (&stun_servers[pos]);
-          LOG (GNUNET_ERROR_TYPE_DEBUG,
-               "Found STUN server %s:%i\n",
-               ml->address,
-               ml->port);
-          GNUNET_CONTAINER_DLL_insert (h->stun_servers_head,
-                                       h->stun_servers_tail,
-                                       ml);
-         stun_servers[pos] = '\0';
-        }
-      }
-    }
-    if (0 == urls)
-    {
-      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
-                                 "nat",
-                                 "STUN_SERVERS");
-    }
-    else
-    {
-      /* Set the actual STUN server*/
-      h->actual_stun_server = h->stun_servers_head;
-    }
-    h->stun_task = GNUNET_SCHEDULER_add_now (&process_stun,
-                                             h);
-    GNUNET_free_non_null (stun_servers);
-  }
-
-
-  /* Test for SUID binaries */
-  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
-  if ( (GNUNET_YES == h->behind_nat) &&
-       (GNUNET_YES == h->enable_nat_server) &&
-       (GNUNET_YES !=
-        GNUNET_OS_check_helper_binary (binary,
-                                       GNUNET_YES,
-                                       "-d 127.0.0.1" )))
-  {
-    // use localhost as source for that one udp-port, ok for testing
-    h->enable_nat_server = GNUNET_NO;
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         _("Configuration requires `%s', but binary is not installed properly (SUID bit not set).  Option disabled.\n"),
-         "gnunet-helper-nat-server");
-  }
-  GNUNET_free (binary);
-  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
-  if ((GNUNET_YES == h->enable_nat_client) &&
-      (GNUNET_YES !=
-       GNUNET_OS_check_helper_binary (binary,
-                                      GNUNET_YES,
-                                      "-d 127.0.0.1 127.0.0.2 42"))) /* none of these parameters are actually used in privilege testing mode */
-  {
-    h->enable_nat_client = GNUNET_NO;
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         _("Configuration requires `%s', but binary is not installed properly (SUID bit not set).  Option disabled.\n"),
-         "gnunet-helper-nat-client");
-  }
-  GNUNET_free (binary);
-  start_gnunet_nat_server (h);
-
-  /* FIXME: add support for UPnP, etc */
-
-  if (NULL != h->address_callback)
-  {
-    h->ifc_task = GNUNET_SCHEDULER_add_now (&list_interfaces,
-                                            h);
-    if (GNUNET_YES == h->use_hostname)
-      h->hostname_task = GNUNET_SCHEDULER_add_now (&resolve_hostname,
-                                                   h);
-  }
-  add_from_bind (h);
-
-  return h;
-}
-
-
-/**
- * Stop port redirection and public IP address detection for the given handle.
- * This frees the handle, after having sent the needed commands to close open ports.
- *
- * @param h the handle to stop
- */
-void
-GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h)
-{
-  unsigned int i;
-  struct LocalAddressList *lal;
-  struct MiniList *ml;
-  struct StunServerList *ssl;
-  
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "NAT unregister called\n");
-  while (NULL != (ssl = h->stun_servers_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (h->stun_servers_head,
-                                 h->stun_servers_tail,
-                                 ssl);
-    GNUNET_free (ssl->address);
-    GNUNET_free (ssl);
-  }
-  while (NULL != (lal = h->lal_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (h->lal_head,
-                                 h->lal_tail,
-                                 lal);
-    if (NULL != h->address_callback)
-      h->address_callback (h->callback_cls,
-                           GNUNET_NO,
-                           (const struct sockaddr *) &lal[1],
-                           lal->addrlen);
-    GNUNET_free (lal);
-  }
-  while (NULL != (ml = h->mini_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (h->mini_head,
-                                 h->mini_tail,
-                                 ml);
-    if (NULL != ml->mini)
-      GNUNET_NAT_mini_map_stop (ml->mini);
-    GNUNET_free (ml);
-  }
-  if (NULL != h->ext_dns)
-  {
-    GNUNET_RESOLVER_request_cancel (h->ext_dns);
-    h->ext_dns = NULL;
-  }
-  if (NULL != h->hostname_dns)
-  {
-    GNUNET_RESOLVER_request_cancel (h->hostname_dns);
-    h->hostname_dns = NULL;
-  }
-  if (NULL != h->server_read_task)
-  {
-    GNUNET_SCHEDULER_cancel (h->server_read_task);
-    h->server_read_task = NULL;
-  }
-  if (NULL != h->ifc_task)
-  {
-    GNUNET_SCHEDULER_cancel (h->ifc_task);
-    h->ifc_task = NULL;
-  }
-  if (NULL != h->hostname_task)
-  {
-    GNUNET_SCHEDULER_cancel (h->hostname_task);
-    h->hostname_task = NULL;
-  }
-  if (NULL != h->dns_task)
-  {
-    GNUNET_SCHEDULER_cancel (h->dns_task);
-    h->dns_task = NULL;
-  }
-  if (NULL != h->stun_task)
-  {
-    GNUNET_SCHEDULER_cancel (h->stun_task);
-    h->stun_task = NULL;
-  }
-  if (NULL != h->stun_request)
-  {
-    GNUNET_NAT_stun_make_request_cancel (h->stun_request);
-    h->stun_request = NULL;
-  }
-  if (NULL != h->server_proc)
-  {
-    if (0 != GNUNET_OS_process_kill (h->server_proc,
-                                     GNUNET_TERM_SIG))
-      GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
-                                "nat",
-                                "kill");
-    GNUNET_OS_process_wait (h->server_proc);
-    GNUNET_OS_process_destroy (h->server_proc);
-    h->server_proc = NULL;
-    GNUNET_DISK_pipe_close (h->server_stdout);
-    h->server_stdout = NULL;
-    h->server_stdout_handle = NULL;
-  }
-  if (NULL != h->server_stdout)
-  {
-    GNUNET_DISK_pipe_close (h->server_stdout);
-    h->server_stdout = NULL;
-    h->server_stdout_handle = NULL;
-  }
-  for (i = 0; i < h->num_local_addrs; i++)
-    GNUNET_free (h->local_addrs[i]);
-  GNUNET_free_non_null (h->local_addrs);
-  GNUNET_free_non_null (h->local_addrlens);
-  GNUNET_free_non_null (h->external_address);
-  GNUNET_free_non_null (h->internal_address);
-  GNUNET_free (h);
-}
-
-
-/**
- * We learned about a peer (possibly behind NAT) so run the
- * gnunet-helper-nat-client to send dummy ICMP responses to cause
- * that peer to connect to us (connection reversal).
- *
- * @param h handle (used for configuration)
- * @param sa the address of the peer (IPv4-only)
- * @return #GNUNET_SYSERR on error, #GNUNET_NO if nat client is disabled,
- *         #GNUNET_OK otherwise
- */
-int
-GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h,
-                       const struct sockaddr_in *sa)
-
-
-{
-  char inet4[INET_ADDRSTRLEN];
-  char port_as_string[6];
-  struct GNUNET_OS_Process *proc;
-  char *binary;
-
-  if (GNUNET_YES != h->enable_nat_client)
-    return GNUNET_NO;                     /* not permitted / possible */
-
-  if (h->internal_address == NULL)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "nat",
-         _("Internal IP address not known, cannot use ICMP NAT traversal method\n"));
-    return GNUNET_SYSERR;
-  }
-  GNUNET_assert (sa->sin_family == AF_INET);
-  if (NULL == inet_ntop (AF_INET, &sa->sin_addr, inet4, INET_ADDRSTRLEN))
-  {
-    GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
-                              "nat",
-                              "inet_ntop");
-    return GNUNET_SYSERR;
-  }
-  GNUNET_snprintf (port_as_string,
-                   sizeof (port_as_string),
-                   "%d",
-                   h->adv_port);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       _("Running gnunet-helper-nat-client %s %s %u\n"),
-       h->internal_address,
-       inet4,
-       (unsigned int) h->adv_port);
-  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
-  proc =
-      GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL,
-                               binary,
-                               "gnunet-helper-nat-client",
-                               h->internal_address,
-                               inet4, port_as_string, NULL);
-  GNUNET_free (binary);
-  if (NULL == proc)
-    return GNUNET_SYSERR;
-  /* we know that the gnunet-helper-nat-client will terminate virtually
-   * instantly */
-  GNUNET_OS_process_wait (proc);
-  GNUNET_OS_process_destroy (proc);
-  return GNUNET_OK;
-}
-
-
-/**
- * Test if the given address is (currently) a plausible IP address for this peer.
- *
- * @param h the handle returned by register
- * @param addr IP address to test (IPv4 or IPv6)
- * @param addrlen number of bytes in @a addr
- * @return #GNUNET_YES if the address is plausible,
- *         #GNUNET_NO if the address is not plausible,
- *         #GNUNET_SYSERR if the address is malformed
- */
-int
-GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
-                         const void *addr,
-                         socklen_t addrlen)
-{
-  struct LocalAddressList *pos;
-  const struct sockaddr_in *in4;
-  const struct sockaddr_in6 *in6;
-  char pbuf[INET6_ADDRSTRLEN+1];
-
-  if ((addrlen != sizeof (struct in_addr)) &&
-      (addrlen != sizeof (struct in6_addr)))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  for (pos = h->lal_head; NULL != pos; pos = pos->next)
-  {
-    if (pos->addrlen == sizeof (struct sockaddr_in))
-    {
-      in4 = (struct sockaddr_in *) &pos[1];
-      if ((addrlen == sizeof (struct in_addr)) &&
-          (0 == memcmp (&in4->sin_addr, addr, sizeof (struct in_addr))))
-        return GNUNET_YES;
-    }
-    else if (pos->addrlen == sizeof (struct sockaddr_in6))
-    {
-      in6 = (struct sockaddr_in6 *) &pos[1];
-      if ((addrlen == sizeof (struct in6_addr)) &&
-          (0 == memcmp (&in6->sin6_addr, addr, sizeof (struct in6_addr))))
-        return GNUNET_YES;
-    }
-    else
-    {
-      GNUNET_assert (0);
-    }
-  }
-  LOG (GNUNET_ERROR_TYPE_WARNING,
-       "Asked to validate one of my addresses (%s) and validation failed!\n",
-       inet_ntop ((addrlen == sizeof(struct in_addr))
-                  ? AF_INET
-                  : AF_INET6,
-                  addr,
-                  pbuf, sizeof (pbuf)));
-  return GNUNET_NO;
-}
-
-/**
- * Converts enum GNUNET_NAT_StatusCode to a string
- *
- * @param err error code to resolve to a string
- * @return pointer to a static string containing the error code
- */
-const char *
-GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err)
-{
-  switch (err)
-  {
-  case GNUNET_NAT_ERROR_SUCCESS:
-    return _ ("Operation Successful");
-  case GNUNET_NAT_ERROR_IPC_FAILURE:
-    return _ ("Internal Failure (IPC, ...)");
-  case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
-    return _ ("Failure in network subsystem, check permissions.");
-  case GNUNET_NAT_ERROR_TIMEOUT:
-    return _ ("Encountered timeout while performing operation");
-  case GNUNET_NAT_ERROR_NOT_ONLINE:
-    return _ ("detected that we are offline");
-  case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
-    return _ ("`upnpc` command not found");
-  case GNUNET_NAT_ERROR_UPNPC_FAILED:
-    return _ ("Failed to run `upnpc` command");
-  case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
-    return _ ("`upnpc' command took too long, process killed");
-  case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
-    return _ ("`upnpc' command failed to establish port mapping");
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
-    return _ ("`external-ip' command not found");
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
-    return _ ("Failed to run `external-ip` command");
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
-    return _ ("`external-ip' command output invalid");
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
-    return _ ("no valid address was returned by `external-ip'");
-  case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
-    return _ ("Could not determine interface with internal/local network address");
-  case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
-    return _ ("No functioning gnunet-helper-nat-server installation found");
-  case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
-    return _ ("NAT test could not be initialized");
-  case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
-    return _ ("NAT test timeout reached");
-  case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
-    return _ ("could not register NAT");
-  case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
-    return _ ("No working gnunet-helper-nat-client installation found");
-/*  case:
-    return _ ("");*/
-  default:
-    return "unknown status code";
-  }
-}
-
-/* end of nat.c */
index 304db3c15318db1d7b60ac9c366af037e59ded54..87fe29d9cabf9b4edcd76974ecbab8daf5c73751 100644 (file)
@@ -9,42 +9,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nat.sock
 UNIX_MATCH_UID = YES
 UNIX_MATCH_GID = YES
 
-# Are we behind NAT?
-BEHIND_NAT = NO
-
-# Is the NAT hole-punched?
-PUNCHED_NAT = NO
-
 # Enable UPNP by default?
-ENABLE_UPNP = NO
-
-# Use addresses from the local network interfaces (inluding loopback, but also others)
-USE_LOCALADDR = YES
-
-# Use address obtained from a DNS lookup of our hostname
-USE_HOSTNAME = NO
-
-# External IP address of the NAT box (if known); IPv4 dotted-decimal ONLY at this time (should allow DynDNS!)
-# normal interface IP address for non-NATed peers; 
-# possibly auto-detected (using UPnP) if possible if not specified
-# EXTERNAL_ADDRESS = 
-
-# Should we use ICMP-based NAT traversal to try connect to NATed peers
-# or, if we are behind NAT, to allow connections to us?
-ENABLE_ICMP_CLIENT = NO
-ENABLE_ICMP_SERVER = NO
-
-# IP address of the interface connected to the NAT box; IPv4 dotted-decimal ONLY;
-# normal interface IP address for non-NATed peers; 
-# likely auto-detected (via interface list) if not specified (!)
-# INTERNAL_ADDRESS = 
+ENABLE_UPNP = YES
 
 # Disable IPv6 support
+# FIXME: move entirely to transport plugins!
 DISABLEV6 = NO
 
-# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
-RETURN_LOCAL_ADDRESSES = NO
-
 # How often do we query the DNS resolver
 # for our hostname (to get our own IP)
 HOSTNAME_DNS_FREQUENCY = 20 min
@@ -67,8 +38,3 @@ STUN_SERVERS = stun.gnunet.org stun.services.mozilla.com:3478 stun.ekiga.net:347
 # After how long do we consider STUN data stale?
 STUN_STALE = 60 min
 
-
-[gnunet-nat-server]
-HOSTNAME = gnunet.org
-PORT = 5724
-NOARMBIND = YES
index af418c7c248bc15b7fcd1de81b36f53b1f461fad..d34900bd191fdf729fffb79b526fdb6e8e1c473f 100644 (file)
@@ -29,6 +29,7 @@
 #include "gnunet_util_lib.h"
 
 
+
 GNUNET_NETWORK_STRUCT_BEGIN
 
 /**
@@ -111,10 +112,9 @@ struct GNUNET_NAT_RegisterMessage
 
   /**
    * Number of bytes in the string that follow which
-   * specify the hostname and port of a manually punched
-   * hole for this client.
+   * specifies a section name in the configuration.
    */
-  uint16_t hole_external_len GNUNET_PACKED;
+  uint16_t str_len GNUNET_PACKED;
 
   /**
    * Number of addresses that this service is bound to that follow.
@@ -126,8 +126,7 @@ struct GNUNET_NAT_RegisterMessage
   /* Followed by @e num_addrs addresses of type 'struct
      sockaddr' */
 
-  /* Followed by @e hole_external_len bytes giving a hostname
-     and port */
+  /* Followed by @e str_len section name to use for options */
   
 };
 
@@ -225,45 +224,6 @@ struct GNUNET_NAT_AddressChangeNotificationMessage
 };
 
 
-/**
- * Client requesting automatic configuration.
- */
-struct GNUNET_NAT_AutoconfigRequestMessage
-{
-  /**
-   * Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG
-   */
-  struct GNUNET_MessageHeader header;
-
-  /* Followed by configuration (diff, serialized, compressed) */
-  
-};
-
-
-/**
- * Service responding with proposed configuration.
- */
-struct GNUNET_NAT_AutoconfigResultMessage
-{
-  /**
-   * Header with type #GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
-   */
-  struct GNUNET_MessageHeader header;
-  
-  /**
-   * An `enum GNUNET_NAT_StatusCode` in NBO.
-   */
-  int32_t status_code GNUNET_PACKED;
-
-  /**
-   * An `enum GNUNET_NAT_Type` in NBO.
-   */
-  int32_t type GNUNET_PACKED;
-
-  /* Followed by configuration (diff, serialized, compressed) */
-};
-
-
 GNUNET_NETWORK_STRUCT_END
 
 #endif
index e4dfc1629e77ec6be1c50c785b1bf4815662234a..eec5d3968eb3d0fe64707ee10ee20ff869ba046b 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2007-2016 GNUnet e.V.
+     Copyright (C) 2007-2017 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -343,7 +343,7 @@ do_connect (void *cls)
   struct GNUNET_MQ_Envelope *env;
 
   nh->reconnect_task = NULL;
-  nh->mq = GNUNET_CLIENT_connecT (nh->cfg,
+  nh->mq = GNUNET_CLIENT_connect (nh->cfg,
                                  "nat",
                                  handlers,
                                  &mq_error_handler,
@@ -368,8 +368,8 @@ do_connect (void *cls)
  * address_callback for any 'plausible' external address.
  *
  * @param cfg configuration to use
+ * @param config_section name of the configuration section for optionsx
  * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
- * @param hole_external hostname and port of manually punched hole in NAT, otherwise NULL (or empty string)
  * @param num_addrs number of addresses in @a addrs
  * @param addrs list of local addresses packets should be redirected to
  * @param addrlens actual lengths of the addresses in @a addrs
@@ -381,8 +381,8 @@ do_connect (void *cls)
  */
 struct GNUNET_NAT_Handle *
 GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                     const char *config_section,
                      uint8_t proto,
-                     const char *hole_external,
                      unsigned int num_addrs,
                      const struct sockaddr **addrs,
                      const socklen_t *addrlens,
@@ -393,17 +393,14 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
   struct GNUNET_NAT_Handle *nh;
   struct GNUNET_NAT_RegisterMessage *rm;
   size_t len;
-  size_t hole_external_len;
+  size_t str_len;
   char *off;
   
   len = 0;
   for (unsigned int i=0;i<num_addrs;i++)
     len += addrlens[i];
-  hole_external_len
-    = (NULL == hole_external)
-    ? 0
-    : strlen (hole_external);
-  len += hole_external_len;
+  str_len = strlen (config_section) + 1;
+  len += str_len;
   if ( (len > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*rm)) ||
        (num_addrs > UINT16_MAX) )
   {
@@ -419,7 +416,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
   if (NULL != reversal_callback)
     rm->flags |= GNUNET_NAT_RF_REVERSAL;
   rm->proto = proto;
-  rm->hole_external_len = htons (hole_external_len);
+  rm->str_len = htons (str_len);
   rm->num_addrs = htons ((uint16_t) num_addrs);
   off = (char *) &rm[1];
   for (unsigned int i=0;i<num_addrs;i++)
@@ -459,8 +456,8 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
     off += addrlens[i];
   }
   GNUNET_memcpy (off,
-                hole_external,
-                hole_external_len);
+                config_section,
+                str_len);
 
   nh = GNUNET_new (struct GNUNET_NAT_Handle);
   nh->reg = &rm->header;
@@ -681,6 +678,8 @@ GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
 
   if (NULL == nh->mq)
     return GNUNET_SYSERR;
+  GNUNET_break (AF_INET == local_sa->sin_family);
+  GNUNET_break (AF_INET == remote_sa->sin_family);
   env = GNUNET_MQ_msg_extra (req,
                             2 * sizeof (struct sockaddr_in),
                             GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL);
@@ -710,249 +709,19 @@ GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
 void
 GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh)
 {
-  GNUNET_MQ_destroy (nh->mq);
-  GNUNET_free (nh->reg);
-  GNUNET_free (nh);
-}
-
-
-
-/**
- * Handle to auto-configuration in progress.
- */
-struct GNUNET_NAT_AutoHandle
-{
-
-  /**
-   * Configuration we use.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-  
-  /**
-   * Message queue for communicating with the NAT service.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Function called with the result from the autoconfiguration.
-   */
-  GNUNET_NAT_AutoResultCallback arc;
-
-  /**
-   * Closure for @e arc.
-   */
-  void *arc_cls;
-
-};
-
-
-/**
- * Converts `enum GNUNET_NAT_StatusCode` to string
- *
- * @param err error code to resolve to a string
- * @return point to a static string containing the error code
- */
-const char *
-GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err)
-{
-  switch (err)
-  {
-  case GNUNET_NAT_ERROR_SUCCESS:
-    return _ ("Operation Successful");
-  case GNUNET_NAT_ERROR_IPC_FAILURE:
-    return _ ("IPC failure");
-  case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
-    return _ ("Failure in network subsystem, check permissions.");
-  case GNUNET_NAT_ERROR_TIMEOUT:
-    return _ ("Encountered timeout while performing operation");
-  case GNUNET_NAT_ERROR_NOT_ONLINE:
-    return _ ("detected that we are offline");
-  case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
-    return _ ("`upnpc` command not found");
-  case GNUNET_NAT_ERROR_UPNPC_FAILED:
-    return _ ("Failed to run `upnpc` command");
-  case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
-    return _ ("`upnpc' command took too long, process killed");
-  case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
-    return _ ("`upnpc' command failed to establish port mapping");
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
-    return _ ("`external-ip' command not found");
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
-    return _ ("Failed to run `external-ip` command");
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
-    return _ ("`external-ip' command output invalid");
-  case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
-    return _ ("no valid address was returned by `external-ip'");
-  case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
-    return _ ("Could not determine interface with internal/local network address");
-  case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
-    return _ ("No functioning gnunet-helper-nat-server installation found");
-  case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
-    return _ ("NAT test could not be initialized");
-  case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
-    return _ ("NAT test timeout reached");
-  case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
-    return _ ("could not register NAT");
-  case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
-    return _ ("No working gnunet-helper-nat-client installation found");
-  default:
-    return "unknown status code";
-  }
-}
-
-
-/**
- * Check result from autoconfiguration attempt.
- *
- * @param cls the `struct GNUNET_NAT_AutoHandle`
- * @param res the result
- * @return #GNUNET_OK if @a res is well-formed (always for now)
- */
-static int
-check_auto_result (void *cls,
-                  const struct GNUNET_NAT_AutoconfigResultMessage *res)
-{
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle result from autoconfiguration attempt.
- *
- * @param cls the `struct GNUNET_NAT_AutoHandle`
- * @param res the result
- */
-static void
-handle_auto_result (void *cls,
-                   const struct GNUNET_NAT_AutoconfigResultMessage *res)
-{
-  struct GNUNET_NAT_AutoHandle *ah = cls;
-  size_t left;
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-  enum GNUNET_NAT_Type type
-    = (enum GNUNET_NAT_Type) ntohl (res->type);
-  enum GNUNET_NAT_StatusCode status
-    = (enum GNUNET_NAT_StatusCode) ntohl (res->status_code);
-
-  left = ntohs (res->header.size) - sizeof (*res);
-  cfg = GNUNET_CONFIGURATION_create ();
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_deserialize (cfg,
-                                       (const char *) &res[1],
-                                       left,
-                                       GNUNET_NO))
-  {
-    GNUNET_break (0);
-    ah->arc (ah->arc_cls,
-            NULL,
-            GNUNET_NAT_ERROR_IPC_FAILURE,
-            type);
-  }
-  else
-  {
-    ah->arc (ah->arc_cls,
-            cfg,
-            status,
-            type);
-  }
-  GNUNET_CONFIGURATION_destroy (cfg);
-  GNUNET_NAT_autoconfig_cancel (ah);
-}
-
-
-/**
- * Handle queue errors by reporting autoconfiguration failure.
- *
- * @param cls the `struct GNUNET_NAT_AutoHandle *`
- * @param error details about the error
- */
-static void
-ah_error_handler (void *cls,
-                 enum GNUNET_MQ_Error error)
-{
-  struct GNUNET_NAT_AutoHandle *ah = cls;
-
-  ah->arc (ah->arc_cls,
-          NULL,
-          GNUNET_NAT_ERROR_IPC_FAILURE,
-          GNUNET_NAT_TYPE_UNKNOWN);
-  GNUNET_NAT_autoconfig_cancel (ah);
-}
-
-
-/**
- * Start auto-configuration routine.  The transport adapters should
- * be stopped while this function is called.
- *
- * @param cfg initial configuration
- * @param cb function to call with autoconfiguration result
- * @param cb_cls closure for @a cb
- * @return handle to cancel operation
- */
-struct GNUNET_NAT_AutoHandle *
-GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                            GNUNET_NAT_AutoResultCallback cb,
-                            void *cb_cls)
-{
-  struct GNUNET_NAT_AutoHandle *ah = GNUNET_new (struct GNUNET_NAT_AutoHandle);
-  struct GNUNET_MQ_MessageHandler handlers[] = {
-    GNUNET_MQ_hd_var_size (auto_result,
-                          GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT,
-                          struct GNUNET_NAT_AutoconfigResultMessage,
-                          ah),
-    GNUNET_MQ_handler_end ()
-  };
-  struct GNUNET_MQ_Envelope *env;
-  struct GNUNET_NAT_AutoconfigRequestMessage *req;
-  char *buf;
-  size_t size;
-
-  buf = GNUNET_CONFIGURATION_serialize (cfg,
-                                       &size);
-  if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*req))
+  if (NULL != nh->mq)
   {
-    GNUNET_break (0);
-    GNUNET_free (buf);
-    GNUNET_free (ah);
-    return NULL;
+    GNUNET_MQ_destroy (nh->mq);
+    nh->mq = NULL;
   }
-  ah->arc = cb;
-  ah->arc_cls = cb_cls;
-  ah->mq = GNUNET_CLIENT_connecT (cfg,
-                                 "nat",
-                                 handlers,
-                                 &ah_error_handler,
-                                 ah);
-  if (NULL == ah->mq)
+  if (NULL != nh->reconnect_task)
   {
-    GNUNET_break (0);
-    GNUNET_free (buf);
-    GNUNET_free (ah);
-    return NULL;
+    GNUNET_SCHEDULER_cancel (nh->reconnect_task);
+    nh->reconnect_task = NULL;
   }
-  env = GNUNET_MQ_msg_extra (req,
-                            size,
-                            GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG);
-  GNUNET_memcpy (&req[1],
-                buf,
-                size);
-  GNUNET_free (buf);
-  GNUNET_MQ_send (ah->mq,
-                 env);
-  return ah;
+  GNUNET_free (nh->reg);
+  GNUNET_free (nh);
 }
 
 
-/**
- * Abort autoconfiguration.
- *
- * @param ah handle for operation to abort
- */
-void
-GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah)
-{
-  GNUNET_MQ_destroy (ah->mq);
-  GNUNET_free (ah);
-}
-
 /* end of nat_api.c */
index 7f2ef4eaff23fa4b0dd0a591d998a9582a3f8345..b1309fb538714e66f9fab0c9330febc54cd7d897 100644 (file)
@@ -38,7 +38,7 @@
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_resolver_service.h"
-#include "gnunet_nat_lib.h"
+#include "gnunet_nat_service.h"
 
 
 #include "nat_stun.h"
@@ -74,7 +74,7 @@ struct GNUNET_NAT_STUN_Handle
   /**
    * Function to call when a error occours
    */
-  GNUNET_NAT_STUN_ErrorCallback cb;
+  GNUNET_NAT_TestCallback cb;
 
   /**
    * Closure for @e cb.
@@ -199,7 +199,7 @@ stun_dns_callback (void *cls,
 
 /**
  * Make Generic STUN request. Sends a generic stun request to the
- * server specified using the specified socket.  
+ * server specified using the specified socket.
  *
  * @param server the address of the stun server
  * @param port port of the stun server, in host byte order
@@ -212,7 +212,7 @@ struct GNUNET_NAT_STUN_Handle *
 GNUNET_NAT_stun_make_request (const char *server,
                               uint16_t port,
                               struct GNUNET_NETWORK_Handle *sock,
-                              GNUNET_NAT_STUN_ErrorCallback cb,
+                              GNUNET_NAT_TestCallback cb,
                               void *cb_cls)
 {
   struct GNUNET_NAT_STUN_Handle *rh;
diff --git a/src/nat/nat_api_test.c b/src/nat/nat_api_test.c
deleted file mode 100644 (file)
index d47c140..0000000
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2011, 2016 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-/**
- * @file nat/nat_api_test.c
- * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server)
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_nat_lib.h"
-#include "nat.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
-
-#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
-
-/**
- * Entry we keep for each incoming connection.
- */
-struct NatActivity
-{
-  /**
-   * This is a doubly-linked list.
-   */
-  struct NatActivity *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct NatActivity *prev;
-
-  /**
-   * Socket of the incoming connection.
-   */
-  struct GNUNET_NETWORK_Handle *sock;
-
-  /**
-   * Handle of the master context.
-   */
-  struct GNUNET_NAT_Test *h;
-
-  /**
-   * Task reading from the incoming connection.
-   */
-  struct GNUNET_SCHEDULER_Task *rtask;
-};
-
-
-/**
- * Entry we keep for each connection to the gnunet-nat-service.
- */
-struct ClientActivity
-{
-  /**
-   * This is a doubly-linked list.
-   */
-  struct ClientActivity *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct ClientActivity *prev;
-
-  /**
-   * Socket of the incoming connection.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Handle to overall NAT test.
-   */
-  struct GNUNET_NAT_Test *h;
-
-};
-
-
-/**
- * Handle to a NAT test.
- */
-struct GNUNET_NAT_Test
-{
-
-  /**
-   * Configuration used
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Function to call with success report
-   */
-  GNUNET_NAT_TestCallback report;
-
-  /**
-   * Closure for @e report.
-   */
-  void *report_cls;
-
-  /**
-   * Handle to NAT traversal in use
-   */
-  struct GNUNET_NAT_Handle *nat;
-
-  /**
-   * Handle to listen socket, or NULL
-   */
-  struct GNUNET_NETWORK_Handle *lsock;
-
-  /**
-   * Head of list of nat activities.
-   */
-  struct NatActivity *na_head;
-
-  /**
-   * Tail of list of nat activities.
-   */
-  struct NatActivity *na_tail;
-
-  /**
-   * Head of list of client activities.
-   */
-  struct ClientActivity *ca_head;
-
-  /**
-   * Tail of list of client activities.
-   */
-  struct ClientActivity *ca_tail;
-
-  /**
-   * Identity of task for the listen socket (if any)
-   */
-  struct GNUNET_SCHEDULER_Task *ltask;
-
-  /**
-   * Task identifier for the timeout (if any)
-   */
-  struct GNUNET_SCHEDULER_Task *ttask;
-
-  /**
-   * #GNUNET_YES if we're testing TCP
-   */
-  int is_tcp;
-
-  /**
-   * Data that should be transmitted or source-port.
-   */
-  uint16_t data;
-
-  /**
-   * Advertised port to the other peer.
-   */
-  uint16_t adv_port;
-
-  /**
-   * Status code to be reported to the timeout/status call
-   */
-  enum GNUNET_NAT_StatusCode status;
-};
-
-
-/**
- * Function called from #GNUNET_NAT_register whenever someone asks us
- * to do connection reversal.
- *
- * @param cls closure, our `struct GNUNET_NAT_Handle`
- * @param addr public IP address of the other peer
- * @param addrlen actual lenght of the @a addr
- */
-static void
-reversal_cb (void *cls,
-             const struct sockaddr *addr,
-             socklen_t addrlen)
-{
-  struct GNUNET_NAT_Test *h = cls;
-  const struct sockaddr_in *sa;
-
-  if (sizeof (struct sockaddr_in) != addrlen)
-    return;
-  sa = (const struct sockaddr_in *) addr;
-  if (h->data != sa->sin_port)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Received connection reversal request for wrong port\n");
-    return;                     /* wrong port */
-  }
-  /* report success */
-  h->report (h->report_cls,
-             GNUNET_NAT_ERROR_SUCCESS);
-}
-
-
-/**
- * Activity on our incoming socket.  Read data from the
- * incoming connection.
- *
- * @param cls the `struct GNUNET_NAT_Test`
- */
-static void
-do_udp_read (void *cls)
-{
-  struct GNUNET_NAT_Test *tst = cls;
-  uint16_t data;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  tst->ltask =
-      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                     tst->lsock,
-                                     &do_udp_read,
-                                     tst);
-  if ((NULL != tc->write_ready) &&
-      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
-                                   tst->lsock)) &&
-      (sizeof (data) ==
-       GNUNET_NETWORK_socket_recv (tst->lsock,
-                                   &data,
-                                   sizeof (data))))
-  {
-    if (data == tst->data)
-      tst->report (tst->report_cls,
-                   GNUNET_NAT_ERROR_SUCCESS);
-    else
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Received data mismatches expected value\n");
-  }
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Failed to receive data from inbound connection\n");
-}
-
-
-/**
- * Activity on our incoming socket.  Read data from the
- * incoming connection.
- *
- * @param cls the `struct NatActivity`
- */
-static void
-do_read (void *cls)
-{
-  struct NatActivity *na = cls;
-  struct GNUNET_NAT_Test *tst;
-  uint16_t data;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  na->rtask = NULL;
-  tst = na->h;
-  GNUNET_CONTAINER_DLL_remove (tst->na_head,
-                              tst->na_tail,
-                              na);
-  if ((NULL != tc->write_ready) &&
-      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
-                                   na->sock)) &&
-      (sizeof (data) ==
-       GNUNET_NETWORK_socket_recv (na->sock,
-                                   &data,
-                                   sizeof (data))))
-  {
-    if (data == tst->data)
-      tst->report (tst->report_cls,
-                   GNUNET_NAT_ERROR_SUCCESS);
-    else
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Received data does not match expected value\n");
-  }
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Failed to receive data from inbound connection\n");
-  GNUNET_NETWORK_socket_close (na->sock);
-  GNUNET_free (na);
-}
-
-
-/**
- * Activity on our listen socket. Accept the
- * incoming connection.
- *
- * @param cls the `struct GNUNET_NAT_Test`
- */
-static void
-do_accept (void *cls)
-{
-  struct GNUNET_NAT_Test *tst = cls;
-  struct GNUNET_NETWORK_Handle *s;
-  struct NatActivity *wl;
-
-  tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                              tst->lsock,
-                                              &do_accept,
-                                              tst);
-  s = GNUNET_NETWORK_socket_accept (tst->lsock,
-                                    NULL,
-                                    NULL);
-  if (NULL == s)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
-                         "accept");
-    return;                     /* odd error */
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Got an inbound connection, waiting for data\n");
-  wl = GNUNET_new (struct NatActivity);
-  wl->sock = s;
-  wl->h = tst;
-  wl->rtask =
-    GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                   wl->sock,
-                                   &do_read,
-                                   wl);
-  GNUNET_CONTAINER_DLL_insert (tst->na_head,
-                              tst->na_tail,
-                              wl);
-}
-
-
-/**
- * We got disconnected from the NAT server.  Stop
- * waiting for a reply.
- *
- * @param cls the `struct ClientActivity`
- * @param error error code
- */
-static void
-mq_error_handler (void *cls,
-                  enum GNUNET_MQ_Error error)
-{
-  struct ClientActivity *ca = cls;
-  struct GNUNET_NAT_Test *tst = ca->h;
-
-  GNUNET_CONTAINER_DLL_remove (tst->ca_head,
-                               tst->ca_tail,
-                               ca);
-  GNUNET_MQ_destroy (ca->mq);
-  GNUNET_free (ca);
-}
-
-
-/**
- * Address-callback, used to send message to gnunet-nat-server.
- *
- * @param cls closure
- * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
- *     the previous (now invalid) one
- * @param addr either the previous or the new public IP address
- * @param addrlen actual length of the @a addr
- */
-static void
-addr_cb (void *cls,
-         int add_remove,
-         const struct sockaddr *addr,
-         socklen_t addrlen)
-{
-  struct GNUNET_NAT_Test *h = cls;
-  struct ClientActivity *ca;
-  struct GNUNET_MQ_Envelope *env;
-  struct GNUNET_NAT_TestMessage *msg;
-  const struct sockaddr_in *sa;
-
-  if (GNUNET_YES != add_remove)
-    return;
-  if (addrlen != sizeof (struct sockaddr_in))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "NAT test ignores IPv6 address `%s' returned from NAT library\n",
-        GNUNET_a2s (addr,
-                     addrlen));
-    return;                     /* ignore IPv6 here */
-  }
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "Asking gnunet-nat-server to connect to `%s'\n",
-       GNUNET_a2s (addr,
-                   addrlen));
-
-  ca = GNUNET_new (struct ClientActivity);
-  ca->h = h;
-  ca->mq = GNUNET_CLIENT_connecT (h->cfg,
-                                  "gnunet-nat-server",
-                                  NULL,
-                                  &mq_error_handler,
-                                  ca);
-  if (NULL == ca->mq)
-  {
-    GNUNET_free (ca);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Failed to connect to `gnunet-nat-server'\n"));
-    return;
-  }
-  GNUNET_CONTAINER_DLL_insert (h->ca_head,
-                               h->ca_tail,
-                               ca);
-  sa = (const struct sockaddr_in *) addr;
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_NAT_TEST);
-  msg->dst_ipv4 = sa->sin_addr.s_addr;
-  msg->dport = sa->sin_port;
-  msg->data = h->data;
-  msg->is_tcp = htonl ((uint32_t) h->is_tcp);
-  GNUNET_MQ_send (ca->mq,
-                  env);
-}
-
-
-/**
- * Timeout task for a nat test.
- * Calls the report-callback with a timeout return value
- *
- * Destroys the nat handle after the callback has been processed.
- *
- * @param cls handle to the timed out NAT test
- */
-static void
-do_timeout (void *cls)
-{
-  struct GNUNET_NAT_Test *nh = cls;
-
-  nh->ttask = NULL;
-  nh->report (nh->report_cls,
-              (GNUNET_NAT_ERROR_SUCCESS == nh->status)
-              ? GNUNET_NAT_ERROR_TIMEOUT
-              : nh->status);
-}
-
-
-/**
- * Start testing if NAT traversal works using the
- * given configuration (IPv4-only).
- *
- * ALL failures are reported directly to the report callback
- *
- * @param cfg configuration for the NAT traversal
- * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
- * @param bnd_port port to bind to, 0 for connection reversal
- * @param adv_port externally advertised port to use
- * @param timeout delay after which the test should be aborted
- * @param report function to call with the result of the test
- * @param report_cls closure for @a report
- * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback
- */
-struct GNUNET_NAT_Test *
-GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                       int is_tcp,
-                       uint16_t bnd_port,
-                       uint16_t adv_port,
-                       struct GNUNET_TIME_Relative timeout,
-                       GNUNET_NAT_TestCallback report,
-                       void *report_cls)
-{
-  struct GNUNET_NAT_Test *nh;
-  struct sockaddr_in sa;
-  const struct sockaddr *addrs[] = {
-    (const struct sockaddr *) &sa
-  };
-  const socklen_t addrlens[] = {
-    sizeof (sa)
-  };
-
-  memset (&sa, 0, sizeof (sa));
-  sa.sin_family = AF_INET;
-  sa.sin_port = htons (bnd_port);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  sa.sin_len = sizeof (sa);
-#endif
-
-  nh = GNUNET_new (struct GNUNET_NAT_Test);
-  nh->cfg = cfg;
-  nh->is_tcp = is_tcp;
-  nh->data = bnd_port;
-  nh->adv_port = adv_port;
-  nh->report = report;
-  nh->report_cls = report_cls;
-  nh->status = GNUNET_NAT_ERROR_SUCCESS;
-  if (0 == bnd_port)
-  {
-    nh->nat
-      = GNUNET_NAT_register (cfg,
-                             is_tcp,
-                             0,
-                             0,
-                            NULL,
-                             NULL,
-                            &addr_cb,
-                             &reversal_cb,
-                             nh,
-                             NULL);
-  }
-  else
-  {
-    nh->lsock =
-        GNUNET_NETWORK_socket_create (AF_INET,
-                                      (is_tcp ==
-                                       GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM,
-                                      0);
-    if ((nh->lsock == NULL) ||
-        (GNUNET_OK !=
-         GNUNET_NETWORK_socket_bind (nh->lsock,
-                                     (const struct sockaddr *) &sa,
-                                     sizeof (sa))))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
-                  GNUNET_a2s ((const struct sockaddr *) &sa,
-                              sizeof (sa)),
-                  STRERROR (errno));
-      if (NULL != nh->lsock)
-      {
-        GNUNET_NETWORK_socket_close (nh->lsock);
-        nh->lsock = NULL;
-      }
-      nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
-      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout,
-                                            nh);
-      return nh;
-    }
-    if (GNUNET_YES == is_tcp)
-    {
-      GNUNET_break (GNUNET_OK ==
-                    GNUNET_NETWORK_socket_listen (nh->lsock,
-                                                  5));
-      nh->ltask =
-          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                         nh->lsock,
-                                        &do_accept,
-                                         nh);
-    }
-    else
-    {
-      nh->ltask =
-          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                         nh->lsock,
-                                        &do_udp_read,
-                                         nh);
-    }
-    LOG (GNUNET_ERROR_TYPE_INFO,
-        "NAT test listens on port %u (%s)\n",
-        bnd_port,
-        (GNUNET_YES == is_tcp) ? "tcp" : "udp");
-    nh->nat = GNUNET_NAT_register (cfg,
-                                   is_tcp,
-                                   adv_port,
-                                   1,
-                                   addrs,
-                                   addrlens,
-                                   &addr_cb,
-                                   NULL,
-                                   nh,
-                                   NULL);
-    if (NULL == nh->nat)
-    {
-      LOG (GNUNET_ERROR_TYPE_INFO,
-          _("NAT test failed to start NAT library\n"));
-      if (NULL != nh->ltask)
-      {
-        GNUNET_SCHEDULER_cancel (nh->ltask);
-        nh->ltask = NULL;
-      }
-      if (NULL != nh->lsock)
-      {
-        GNUNET_NETWORK_socket_close (nh->lsock);
-        nh->lsock = NULL;
-      }
-      nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
-      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout,
-                                            nh);
-      return nh;
-    }
-  }
-  nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout,
-                                           &do_timeout,
-                                           nh);
-  return nh;
-}
-
-
-/**
- * Stop an active NAT test.
- *
- * @param tst test to stop.
- */
-void
-GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst)
-{
-  struct NatActivity *pos;
-  struct ClientActivity *cpos;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Stopping NAT test\n");
-  while (NULL != (cpos = tst->ca_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (tst->ca_head,
-                                tst->ca_tail,
-                                cpos);
-    GNUNET_MQ_destroy (cpos->mq);
-    GNUNET_free (cpos);
-  }
-  while (NULL != (pos = tst->na_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (tst->na_head,
-                                tst->na_tail,
-                                pos);
-    GNUNET_SCHEDULER_cancel (pos->rtask);
-    GNUNET_NETWORK_socket_close (pos->sock);
-    GNUNET_free (pos);
-  }
-  if (NULL != tst->ttask)
-  {
-    GNUNET_SCHEDULER_cancel (tst->ttask);
-    tst->ttask = NULL;
-  }
-  if (NULL != tst->ltask)
-  {
-    GNUNET_SCHEDULER_cancel (tst->ltask);
-    tst->ltask = NULL;
-  }
-  if (NULL != tst->lsock)
-  {
-    GNUNET_NETWORK_socket_close (tst->lsock);
-    tst->lsock = NULL;
-  }
-  if (NULL != tst->nat)
-  {
-    GNUNET_NAT_unregister (tst->nat);
-    tst->nat = NULL;
-  }
-  GNUNET_free (tst);
-}
-
-/* end of nat_test.c */
diff --git a/src/nat/nat_auto.c b/src/nat/nat_auto.c
deleted file mode 100644 (file)
index 061d0cb..0000000
+++ /dev/null
@@ -1,1081 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2015 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file nat/nat_auto.c
- * @brief functions for auto-configuration of the network
- * @author Christian Grothoff
- * @author Bruno Cabral
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_resolver_service.h"
-#include "gnunet_nat_lib.h"
-#include "nat.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
-
-
-/**
- * How long do we wait for the NAT test to report success?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
-
-#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
-
-/**
- * Phases of the auto configuration.
- */
-enum AutoPhase
-{
-  /**
-   * Initial start value.
-   */
-  AUTO_INIT = 0,
-
-  /**
-   * Test our external IP.
-   */
-  AUTO_EXTERNAL_IP,
-
-  /**
-   * Test our external IP.
-   */
-   AUTO_STUN,
-
-  /**
-   * Test our internal IP.
-   */
-  AUTO_LOCAL_IP,
-
-  /**
-   * Test if NAT was punched.
-   */
-  AUTO_NAT_PUNCHED,
-
-  /**
-   * Test if UPnP is working.
-   */
-  AUTO_UPNPC,
-
-  /**
-   * Test if ICMP server works.
-   */
-  AUTO_ICMP_SERVER,
-
-  /**
-   * Test if ICMP client works.
-   */
-  AUTO_ICMP_CLIENT,
-
-  /**
-   * Last phase, we're done.
-   */
-  AUTO_DONE
-
-};
-
-
-/**
- * Handle to auto-configuration in progress.
- */
-struct GNUNET_NAT_AutoHandle
-{
-
-  /**
-   * Handle to the active NAT test.
-   */
-  struct GNUNET_NAT_Test *tst;
-
-  /**
-   * Function to call when done.
-   */
-  GNUNET_NAT_AutoResultCallback fin_cb;
-
-  /**
-   * Closure for @e fin_cb.
-   */
-  void *fin_cb_cls;
-
-  /**
-   * Handle for active 'GNUNET_NAT_mini_get_external_ipv4'-operation.
-   */
-  struct GNUNET_NAT_ExternalHandle *eh;
-
-  /**
-   * Current configuration (with updates from previous phases)
-   */
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Original configuration (used to calculate differences)
-   */
-  struct GNUNET_CONFIGURATION_Handle *initial_cfg;
-
-  /**
-   * Task identifier for the timeout.
-   */
-  struct GNUNET_SCHEDULER_Task *task;
-
-  /**
-   * Message queue to the gnunet-nat-server.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Where are we in the test?
-   */
-  enum AutoPhase phase;
-
-  /**
-   * Situation of the NAT
-   */
-  enum GNUNET_NAT_Type type;
-
-  /**
-   * Do we have IPv6?
-   */
-  int have_v6;
-
-  /**
-   * UPnP already set the external ip address ?
-   */
-  int upnp_set_external_address;
-
-  /**
-   * Did the external server connected back ?
-   */
-  int connected_back;
-
-  /**
-   * Address detected by STUN
-   */
-  char *stun_ip;
-
-  unsigned int stun_port;
-
-  /**
-   * Internal IP is the same as the public one ?
-   */
-  int internal_ip_is_public;
-
-  /**
-   * Error code for better debugging and user feedback
-   */
-  enum GNUNET_NAT_StatusCode ret;
-};
-
-
-/**
- * The listen socket of the service for IPv4
- */
-static struct GNUNET_NETWORK_Handle *lsock4;
-
-/**
- * The listen task ID for IPv4
- */
-static struct GNUNET_SCHEDULER_Task *ltask4;
-
-/**
- * The port the test service is running on (default 7895)
- */
-static unsigned long long port = 7895;
-
-static char *stun_server = "stun.ekiga.net";
-
-static unsigned int stun_port = 3478;
-
-
-/**
- * Run the next phase of the auto test.
- *
- * @param ah auto test handle
- */
-static void
-next_phase (struct GNUNET_NAT_AutoHandle *ah);
-
-
-static void
-process_stun_reply(struct sockaddr_in *answer,
-                   struct GNUNET_NAT_AutoHandle *ah)
-{
-  ah->stun_ip = inet_ntoa(answer->sin_addr);
-  ah->stun_port = ntohs (answer->sin_port);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "External IP is: %s , with port %u\n",
-              ah->stun_ip,
-              ah->stun_port);
-  next_phase (ah);
-}
-
-
-/**
- * Function that terminates the test.
- */
-static void
-stop_stun ()
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Stopping STUN and quitting...\n");
-  /* Clean task */
-  if (NULL != ltask4)
-  {
-    GNUNET_SCHEDULER_cancel (ltask4);
-    ltask4 = NULL;
-  }
-  /* Clean socket */
-  if (NULL != lsock4)
-  {
-    GNUNET_NETWORK_socket_close (lsock4);
-    lsock4 = NULL;
-  }
-}
-
-
-/**
- * Activity on our incoming socket.  Read data from the
- * incoming connection.
- *
- * @param cls
- */
-static void
-do_udp_read (void *cls)
-{
-  struct GNUNET_NAT_AutoHandle *ah = cls;
-  unsigned char reply_buf[1024];
-  ssize_t rlen;
-  struct sockaddr_in answer;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
-      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
-                                   lsock4)))
-  {
-    rlen = GNUNET_NETWORK_socket_recv (lsock4,
-                                      reply_buf,
-                                      sizeof (reply_buf));
-
-    //Lets handle the packet
-    memset (&answer, 0, sizeof(struct sockaddr_in));
-    if (ah->phase == AUTO_NAT_PUNCHED)
-    {
-      //Destroy the connection
-      GNUNET_NETWORK_socket_close (lsock4);
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "The external server was able to connect back");
-      ah->connected_back = GNUNET_YES;
-      next_phase (ah);
-    }
-    else
-    {
-      if (GNUNET_OK ==
-         GNUNET_NAT_stun_handle_packet (reply_buf, rlen, &answer))
-      {
-        //Process the answer
-        process_stun_reply (&answer, ah);
-      }
-      else
-      {
-        next_phase (ah);
-      }
-    }
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "TIMEOUT while waiting for an answer\n");
-    if (ah->phase == AUTO_NAT_PUNCHED)
-    {
-      stop_stun();
-    }
-
-    next_phase (ah);
-  }
-}
-
-
-/**
- * Create an IPv4 listen socket bound to our port.
- *
- * @return NULL on error
- */
-static struct GNUNET_NETWORK_Handle *
-bind_v4 ()
-{
-  struct GNUNET_NETWORK_Handle *ls;
-  struct sockaddr_in sa4;
-  int eno;
-
-  memset (&sa4, 0, sizeof (sa4));
-  sa4.sin_family = AF_INET;
-  sa4.sin_port = htons (port);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-    sa4.sin_len = sizeof (sa4);
-#endif
-  ls = GNUNET_NETWORK_socket_create (AF_INET,
-                                     SOCK_DGRAM,
-                                     0);
-  if (NULL == ls)
-    return NULL;
-  if (GNUNET_OK !=
-      GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4,
-                                  sizeof (sa4)))
-  {
-    eno = errno;
-    GNUNET_NETWORK_socket_close (ls);
-    errno = eno;
-    return NULL;
-  }
-  return ls;
-}
-
-
-static void
-request_callback (void *cls,
-                 enum GNUNET_NAT_StatusCode result)
-{
-  // struct GNUNET_NAT_AutoHandle *ah = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Request callback: stop and quit\n");
-  stop_stun ();
-
-  // next_phase (ah); FIXME this always will be NULL, as called in test_stun()
-}
-
-
-/**
- * Function called by NAT to report the outcome of the nat-test.
- * Clean up and update GUI.
- *
- * @param cls the auto handle
- * @param success currently always #GNUNET_OK
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-result_callback (void *cls,
-                 enum GNUNET_NAT_StatusCode ret)
-{
-  struct GNUNET_NAT_AutoHandle *ah = cls;
-
-  if (GNUNET_NAT_ERROR_SUCCESS == ret)
-    GNUNET_NAT_test_stop (ah->tst);
-  ah->tst = NULL;
-  ah->ret = ret;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              GNUNET_NAT_ERROR_SUCCESS == ret
-             ? _("NAT traversal with ICMP Server succeeded.\n")
-             : _("NAT traversal with ICMP Server failed.\n"));
-  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_ICMP_SERVER",
-                                        GNUNET_NAT_ERROR_SUCCESS == ret ? "NO" : "YES");
-  next_phase (ah);
-}
-
-
-/**
- * Main function for the connection reversal test.
- *
- * @param cls the `struct GNUNET_NAT_AutoHandle`
- */
-static void
-reversal_test (void *cls)
-{
-  struct GNUNET_NAT_AutoHandle *ah = cls;
-
-  ah->task = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Testing connection reversal with ICMP server.\n"));
-  GNUNET_RESOLVER_connect (ah->cfg);
-  ah->tst = GNUNET_NAT_test_start (ah->cfg, GNUNET_YES, 0, 0, TIMEOUT,
-                                  &result_callback, ah);
-}
-
-
-/**
- * Set our external IPv4 address based on the UPnP.
- *
- *
- * @param cls closure with our setup context
- * @param addr the address, NULL on errors
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-set_external_ipv4 (void *cls,
-                   const struct in_addr *addr,
-                   enum GNUNET_NAT_StatusCode ret)
-{
-  struct GNUNET_NAT_AutoHandle *ah = cls;
-  char buf[INET_ADDRSTRLEN];
-
-  ah->eh = NULL;
-  ah->ret = ret;
-  if (GNUNET_NAT_ERROR_SUCCESS != ret)
-  {
-    next_phase (ah);
-    return;
-  }
-  /* enable 'behind nat' */
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Detected external IP `%s'\n"),
-             inet_ntop (AF_INET,
-                        addr,
-                        buf,
-                        sizeof (buf)));
-  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "BEHIND_NAT", "YES");
-
-  /* set external IP address */
-  if (NULL == inet_ntop (AF_INET, addr, buf, sizeof (buf)))
-  {
-    GNUNET_break (0);
-    /* actually, this should never happen, as the caller already executed just
-     * this check, but for consistency (eg: future changes in the caller)
-     * we still need to report this error...
-     */
-    ah->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID;
-    next_phase (ah);
-    return;
-  }
-  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS",
-                                        buf);
-  ah->upnp_set_external_address = GNUNET_YES;
-  next_phase (ah);
-}
-
-
-/**
- * Determine our external IPv4 address.
- *
- * @param ah auto setup context
- */
-static void
-test_external_ip (struct GNUNET_NAT_AutoHandle *ah)
-{
-  if (GNUNET_NAT_ERROR_SUCCESS != ah->ret)
-    next_phase (ah);
-
-  // FIXME: CPS?
-  /* try to detect external IP */
-  ah->eh = GNUNET_NAT_mini_get_external_ipv4 (TIMEOUT,
-                                             &set_external_ipv4, ah);
-}
-
-
-/**
- * Determine our external IPv4 address and port using an external STUN server
- *
- * @param ah auto setup context
- */
-static void
-test_stun (struct GNUNET_NAT_AutoHandle *ah)
-{
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running STUN test\n");
-
-  /* Get port from the configuration */
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (ah->cfg,
-                                             "transport-udp",
-                                             "PORT",
-                                             &port))
-  {
-    port = 2086;
-  }
-
-  //Lets create the socket
-  lsock4 = bind_v4 ();
-  if (NULL == lsock4)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
-    next_phase(ah);
-    return;
-  }
-  else
-  {
-    //Lets call our function now when it accepts
-    ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
-                                            lsock4,
-                                           &do_udp_read,
-                                           ah);
-  }
-
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "STUN service listens on port %u\n",
-              (unsigned int) port);
-  if (GNUNET_NO ==
-      GNUNET_NAT_stun_make_request (stun_server,
-                                    stun_port,
-                                   lsock4,
-                                   &request_callback,
-                                   NULL))
-  {
-    /*An error happened*/
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STUN error, stopping\n");
-    stop_stun ();
-    next_phase (ah);
-  }
-}
-
-
-/**
- * Process list of local IP addresses.  Find and set the
- * one of the default interface.
- *
- * @param cls our `struct GNUNET_NAT_AutoHandle`
- * @param name name of the interface (can be NULL for unknown)
- * @param isDefault is this presumably the default interface
- * @param addr address of this interface (can be NULL for unknown or unassigned)
- * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
- * @param netmask the network mask (can be NULL for unknown or unassigned))
- * @param addrlen length of the @a addr and @a broadcast_addr
- * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
- */
-static int
-process_if (void *cls,
-           const char *name,
-           int isDefault,
-           const struct sockaddr *addr,
-           const struct sockaddr *broadcast_addr,
-           const struct sockaddr *netmask,
-           socklen_t addrlen)
-{
-  struct GNUNET_NAT_AutoHandle *ah = cls;
-  const struct sockaddr_in *in;
-  char buf[INET_ADDRSTRLEN];
-
-
-  if ( (sizeof (struct sockaddr_in6) == addrlen) &&
-       (0 != memcmp (&in6addr_loopback, &((const struct sockaddr_in6 *) addr)->sin6_addr,
-                    sizeof (struct in6_addr))) &&
-       (! IN6_IS_ADDR_LINKLOCAL(&((const struct sockaddr_in6 *) addr)->sin6_addr)) )
-  {
-    ah->have_v6 = GNUNET_YES;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-               _("This system has a global IPv6 address, setting IPv6 to supported.\n"));
-
-    return GNUNET_OK;
-  }
-  if (addrlen != sizeof (struct sockaddr_in))
-    return GNUNET_OK;
-  in = (const struct sockaddr_in *) addr;
-
-
-  /* set internal IP address */
-  if (NULL == inet_ntop (AF_INET, &in->sin_addr, buf, sizeof (buf)))
-  {
-    GNUNET_break (0);
-    return GNUNET_OK;
-  }
-  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS",
-                                        buf);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Detected internal network address `%s'.\n"),
-             buf);
-
-
-  ah->ret = GNUNET_NAT_ERROR_SUCCESS;
-
-  /* Check if our internal IP is the same as the External detect by STUN*/
-  if(ah->stun_ip && (strcmp(buf, ah->stun_ip) == 0) )
-  {
-    ah->internal_ip_is_public = GNUNET_YES;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,"A internal IP is the sameas the external");
-    /* No need to continue*/
-    return GNUNET_SYSERR;
-  }
-
-  /* no need to continue iteration if we found the default */
-  if (!isDefault)
-    return GNUNET_OK;
-  else
-    return GNUNET_SYSERR;
-}
-
-
-/**
- * Determine our local IP addresses; detect internal IP & IPv6-support
- *
- * @param ah auto setup context
- */
-static void
-test_local_ip (struct GNUNET_NAT_AutoHandle *ah)
-{
-  ah->have_v6 = GNUNET_NO;
-  ah->ret = GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO; // reset to success if any of the IFs in below iterator has a valid IP
-  GNUNET_OS_network_interfaces_list (&process_if, ah);
-
-  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "DISABLEV6",
-                                        (GNUNET_YES == ah->have_v6) ? "NO" : "YES");
-  next_phase (ah);
-}
-
-
-/**
- * We got disconnected from the NAT server.  Stop
- * waiting for a reply.
- *
- * @param cls the `struct GNUNET_NAT_AutoHandle`
- * @param error error code
- */
-static void
-mq_error_handler (void *cls,
-                  enum GNUNET_MQ_Error error)
-{
-  struct GNUNET_NAT_AutoHandle *ah = cls;
-
-  GNUNET_MQ_destroy (ah->mq);
-  ah->mq = NULL;
-  /* wait a bit first? */
-  next_phase (ah);
-}
-
-
-/**
- * Test if NAT has been punched
- *
- * @param ah auto setup context
- */
-static void
-test_nat_punched (struct GNUNET_NAT_AutoHandle *ah)
-{
-  struct GNUNET_NAT_TestMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
-
-  if (! ah->stun_ip)
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO,
-         "We don't have a STUN IP");
-    next_phase (ah);
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "Asking gnunet-nat-server to connect to `%s'\n",
-       ah->stun_ip);
-  ah->mq = GNUNET_CLIENT_connecT (ah->cfg,
-                                  "gnunet-nat-server",
-                                  NULL,
-                                  &mq_error_handler,
-                                  ah);
-  if (NULL == ah->mq)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Failed to connect to `gnunet-nat-server'\n"));
-    next_phase (ah);
-    return;
-  }
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_NAT_TEST);
-  msg->dst_ipv4 = inet_addr (ah->stun_ip);
-  msg->dport = htons (ah->stun_port);
-  msg->data = port;
-  msg->is_tcp = htonl ((uint32_t) GNUNET_NO);
-  GNUNET_MQ_send (ah->mq,
-                  env);
-  if (NULL != ltask4)
-  {
-    GNUNET_SCHEDULER_cancel (ltask4);
-    ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
-                                            lsock4,
-                                            &do_udp_read,
-                                            ah);
-  }
-}
-
-
-/**
- * Test if UPnPC works.
- *
- * @param ah auto setup context
- */
-static void
-test_upnpc (struct GNUNET_NAT_AutoHandle *ah)
-{
-
-  int have_upnpc;
-
-  if (GNUNET_NAT_ERROR_SUCCESS != ah->ret)
-    next_phase (ah);
-
-  // test if upnpc is available
-  have_upnpc = (GNUNET_SYSERR !=
-               GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL));
-  //FIXME: test if upnpc is actually working, that is, if transports start to work once we use UPnP
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             (have_upnpc)
-             ? _("upnpc found, enabling its use\n")
-             : _("upnpc not found\n"));
-  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_UPNP",
-                                        (GNUNET_YES == have_upnpc) ? "YES" : "NO");
-  next_phase (ah);
-
-}
-
-
-/**
- * Test if ICMP server is working
- *
- * @param ah auto setup context
- */
-static void
-test_icmp_server (struct GNUNET_NAT_AutoHandle *ah)
-{
-
-  int ext_ip;
-  int nated;
-  int binary;
-  char *tmp;
-  char *helper;
-  ext_ip = GNUNET_NO;
-  nated = GNUNET_NO;
-  binary = GNUNET_NO;
-
-  tmp = NULL;
-  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
-  if ( (GNUNET_OK ==
-        GNUNET_CONFIGURATION_get_value_string (ah->cfg,
-                                               "nat",
-                                               "EXTERNAL_ADDRESS",
-                                               &tmp)) &&
-       (0 < strlen (tmp)) )
-  {
-    ext_ip = GNUNET_OK;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("test_icmp_server not possible, as we have no public IPv4 address\n"));
-  }
-  else
-    goto err;
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_yesno (ah->cfg,
-                                            "nat",
-                                            "BEHIND_NAT"))
-  {
-    nated = GNUNET_YES;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("test_icmp_server not possible, as we are not behind NAT\n"));
-  }
-  else
-    goto err;
-
-  if (GNUNET_YES ==
-      GNUNET_OS_check_helper_binary (helper,
-                                     GNUNET_YES,
-                                     "-d 127.0.0.1" ))
-  {
-    binary = GNUNET_OK; // use localhost as source for that one udp-port, ok for testing
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("No working gnunet-helper-nat-server found\n"));
-  }
-err:
-  GNUNET_free_non_null (tmp);
-  GNUNET_free (helper);
-
-  if ( (GNUNET_OK == ext_ip) &&
-       (GNUNET_YES == nated) &&
-       (GNUNET_OK == binary) )
-    ah->task = GNUNET_SCHEDULER_add_now (&reversal_test,
-                                         ah);
-  else
-    next_phase (ah);
-}
-
-
-/**
- * Test if ICMP client is working
- *
- * @param ah auto setup context
- */
-static void
-test_icmp_client (struct GNUNET_NAT_AutoHandle *ah)
-{
-  char *tmp;
-  char *helper;
-
-  tmp = NULL;
-  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
-  if ( (GNUNET_OK ==
-        GNUNET_CONFIGURATION_get_value_string (ah->cfg,
-                                               "nat",
-                                               "INTERNAL_ADDRESS",
-                                               &tmp)) &&
-       (0 < strlen (tmp)) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("test_icmp_client not possible, as we have no internal IPv4 address\n"));
-  }
-  else
-    goto err;
-
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_yesno (ah->cfg,
-                                            "nat",
-                                            "BEHIND_NAT"))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-               _("test_icmp_server not possible, as we are not behind NAT\n"));
-  }
-  else
-    goto err;
-
-  if (GNUNET_YES ==
-      GNUNET_OS_check_helper_binary (helper,
-                                     GNUNET_YES,
-                                     "-d 127.0.0.1 127.0.0.2 42"))
-  {
-    // none of these parameters are actually used in privilege testing mode
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-               _("No working gnunet-helper-nat-server found\n"));
-  }
-err:
-  GNUNET_free_non_null (tmp);
-  GNUNET_free (helper);
-
-  next_phase (ah);
-}
-
-
-/**
- * Run the next phase of the auto test.
- */
-static void
-next_phase (struct GNUNET_NAT_AutoHandle *ah)
-{
-  struct GNUNET_CONFIGURATION_Handle *diff;
-
-  ah->phase++;
-  switch (ah->phase)
-  {
-  case AUTO_INIT:
-    GNUNET_assert (0);
-    break;
-  case AUTO_EXTERNAL_IP:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Will run AUTO_EXTERNAL_IP\n");
-    test_external_ip (ah);
-    break;
-  case AUTO_STUN:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Will run AUTO_STUN\n");
-    test_stun (ah);
-    break;
-  case AUTO_LOCAL_IP:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Will run AUTO_LOCAL_IP\n");
-    test_local_ip (ah);
-    break;
-  case AUTO_NAT_PUNCHED:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Will run AUTO_NAT_PUNCHED\n");
-    test_nat_punched (ah);
-    break;
-  case AUTO_UPNPC:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Will run AUTO_UPNPC\n");
-    test_upnpc (ah);
-    break;
-  case AUTO_ICMP_SERVER:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Will run AUTO_ICMP_SERVER\n");
-    test_icmp_server (ah);
-    break;
-  case AUTO_ICMP_CLIENT:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Will run AUTO_ICMP_CLIENT\n");
-    test_icmp_client (ah);
-    break;
-  case AUTO_DONE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Done with tests\n");
-    if (!ah->internal_ip_is_public)
-    {
-      GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                             "nat",
-                                             "BEHIND_NAT",
-                                             "YES");
-
-      if (ah->connected_back)
-      {
-        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                               "nat",
-                                               "PUNCHED_NAT",
-                                               "YES");
-      }
-      else
-      {
-        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                               "nat",
-                                               "PUNCHED_NAT",
-                                               "NO");
-      }
-
-      if (ah->stun_ip)
-      {
-        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                               "nat",
-                                               "EXTERNAL_ADDRESS",
-                                               ah->stun_ip);
-        if (ah->connected_back)
-        {
-          ah->type = GNUNET_NAT_TYPE_STUN_PUNCHED_NAT;
-          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                                 "nat",
-                                                 "USE_STUN",
-                                                 "YES");
-        }
-        else
-        {
-          ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT;
-          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                                 "nat",
-                                                 "USE_STUN",
-                                                 "NO");
-        }
-
-      }
-      if (0 != ah->stun_port)
-      {
-        GNUNET_CONFIGURATION_set_value_number (ah->cfg,
-                                               "transport-udp",
-                                               "ADVERTISED_PORT",
-                                               ah->stun_port);
-      }
-
-    }
-    else
-    {
-      //The internal IP is the same as public, but we didn't got a incoming connection
-      if (ah->connected_back)
-      {
-        ah->type = GNUNET_NAT_TYPE_NO_NAT;
-        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                               "nat",
-                                               "BEHIND_NAT",
-                                               "NO");
-      }
-      else
-      {
-        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                               "nat",
-                                               "BEHIND_NAT",
-                                               "YES");
-        ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT;
-        if (ah->stun_ip)
-        {
-          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                                 "nat",
-                                                 "EXTERNAL_ADDRESS",
-                                                 ah->stun_ip);
-        }
-        if (0 != ah->stun_port)
-        {
-          GNUNET_CONFIGURATION_set_value_number (ah->cfg,
-                                                 "transport-udp",
-                                                 "ADVERTISED_PORT",
-                                                 ah->stun_port);
-
-        }
-      }
-    }
-
-    diff = GNUNET_CONFIGURATION_get_diff (ah->initial_cfg,
-                                          ah->cfg);
-
-
-    ah->fin_cb (ah->fin_cb_cls,
-                diff,
-                ah->ret,
-                ah->type);
-    GNUNET_CONFIGURATION_destroy (diff);
-    GNUNET_NAT_autoconfig_cancel (ah);
-  }
-}
-
-
-/**
- * Start auto-configuration routine.  The resolver service should
- * be available when this function is called.
- *
- * @param cfg initial configuration
- * @param cb function to call with autoconfiguration result
- * @param cb_cls closure for @a cb
- * @return handle to cancel operation
- */
-struct GNUNET_NAT_AutoHandle *
-GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                            GNUNET_NAT_AutoResultCallback cb,
-                            void *cb_cls)
-{
-  struct GNUNET_NAT_AutoHandle *ah;
-
-  ah = GNUNET_new (struct GNUNET_NAT_AutoHandle);
-  ah->fin_cb = cb;
-  ah->fin_cb_cls = cb_cls;
-  ah->ret = GNUNET_NAT_ERROR_SUCCESS;
-  ah->cfg = GNUNET_CONFIGURATION_dup (cfg);
-  ah->initial_cfg = GNUNET_CONFIGURATION_dup (cfg);
-
-  /* never use loopback addresses if user wanted autoconfiguration */
-  GNUNET_CONFIGURATION_set_value_string (ah->cfg,
-                                         "nat",
-                                        "USE_LOCALADDR",
-                                        "NO");
-
-  next_phase (ah);
-  return ah;
-}
-
-
-/**
- * Abort autoconfiguration.
- *
- * @param ah handle for operation to abort
- */
-void
-GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah)
-{
-  if (NULL != ah->tst)
-  {
-    GNUNET_NAT_test_stop (ah->tst);
-    ah->tst = NULL;
-  }
-  if (NULL != ah->eh)
-  {
-    GNUNET_NAT_mini_get_external_ipv4_cancel (ah->eh);
-    ah->eh = NULL;
-  }
-  if (NULL != ah->mq)
-  {
-    GNUNET_MQ_destroy (ah->mq);
-    ah->mq = NULL;
-  }
-  if (NULL != ah->task)
-  {
-    GNUNET_SCHEDULER_cancel (ah->task);
-    ah->task = NULL;
-  }
-  GNUNET_CONFIGURATION_destroy (ah->cfg);
-  GNUNET_CONFIGURATION_destroy (ah->initial_cfg);
-  GNUNET_free (ah);
-}
-
-
-/* end of nat_auto.c */
diff --git a/src/nat/nat_mini.c b/src/nat/nat_mini.c
deleted file mode 100644 (file)
index 915bcbd..0000000
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2011-2014 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file nat/nat_mini.c
- * @brief functions for interaction with miniupnp; tested with miniupnpc 1.5
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_nat_lib.h"
-#include "nat.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
-
-/**
- * How long do we give upnpc to create a mapping?
- */
-#define MAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
-
-/**
- * How long do we give upnpc to remove a mapping?
- */
-#define UNMAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
-
-/**
- * How often do we check for changes in the mapping?
- */
-#define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
-
-
-
-/**
- * Opaque handle to cancel "GNUNET_NAT_mini_get_external_ipv4" operation.
- */
-struct GNUNET_NAT_ExternalHandle
-{
-
-  /**
-   * Function to call with the result.
-   */
-  GNUNET_NAT_IPCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Read task.
-   */
-  struct GNUNET_SCHEDULER_Task * task;
-
-  /**
-   * Handle to 'external-ip' process.
-   */
-  struct GNUNET_OS_Process *eip;
-
-  /**
-   * Handle to stdout pipe of 'external-ip'.
-   */
-  struct GNUNET_DISK_PipeHandle *opipe;
-
-  /**
-   * Read handle of @e opipe.
-   */
-  const struct GNUNET_DISK_FileHandle *r;
-
-  /**
-   * When should this operation time out?
-   */
-  struct GNUNET_TIME_Absolute timeout;
-
-  /**
-   * Number of bytes in 'buf' that are valid.
-   */
-  size_t off;
-
-  /**
-   * Destination of our read operation (output of 'external-ip').
-   */
-  char buf[17];
-
-  /**
-   * Error code for better debugging and user feedback
-   */
-  enum GNUNET_NAT_StatusCode ret;
-};
-
-
-/**
- * Read the output of 'external-ip' into buf.  When complete, parse the
- * address and call our callback.
- *
- * @param cls the `struct GNUNET_NAT_ExternalHandle`
- */
-static void
-read_external_ipv4 (void *cls)
-{
-  struct GNUNET_NAT_ExternalHandle *eh = cls;
-  ssize_t ret;
-  struct in_addr addr;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-
-  eh->task = NULL;
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  if (GNUNET_YES ==
-      GNUNET_NETWORK_fdset_handle_isset (tc->read_ready, eh->r))
-  {
-    ret =
-        GNUNET_DISK_file_read (eh->r, &eh->buf[eh->off],
-                               sizeof (eh->buf) - eh->off);
-  }
-  else
-  {
-    eh->ret = GNUNET_NAT_ERROR_IPC_FAILURE;
-    ret = -1;                   /* error reading, timeout, etc. */
-  }
-  if (ret > 0)
-  {
-    /* try to read more */
-    eh->off += ret;
-    eh->task =
-        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
-                                        (eh->timeout), eh->r,
-                                        &read_external_ipv4, eh);
-    return;
-  }
-  eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID;
-  if ((eh->off > 7) && (eh->buf[eh->off - 1] == '\n'))
-  {
-    eh->buf[eh->off - 1] = '\0';
-    if (1 == inet_pton (AF_INET, eh->buf, &addr))
-    {
-      if (0 != addr.s_addr)
-        eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID;       /* got 0.0.0.0 */
-      else
-        eh->ret = GNUNET_NAT_ERROR_SUCCESS;
-    }
-  }
-  eh->cb (eh->cb_cls,
-          (GNUNET_NAT_ERROR_SUCCESS == eh->ret) ? &addr : NULL,
-          eh->ret);
-  GNUNET_NAT_mini_get_external_ipv4_cancel (eh);
-}
-
-
-/**
- * (Asynchronously) signal error invoking "external-ip" to client.
- *
- * @param cls the `struct GNUNET_NAT_ExternalHandle` (freed)
- */
-static void
-signal_external_ip_error (void *cls)
-{
-  struct GNUNET_NAT_ExternalHandle *eh = cls;
-
-  eh->task = NULL;
-  eh->cb (eh->cb_cls,
-          NULL,
-          eh->ret);
-  GNUNET_free (eh);
-}
-
-
-/**
- * Try to get the external IPv4 address of this peer.
- *
- * @param timeout when to fail
- * @param cb function to call with result
- * @param cb_cls closure for @a cb
- * @return handle for cancellation (can only be used until @a cb is called), never NULL
- */
-struct GNUNET_NAT_ExternalHandle *
-GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout,
-                                   GNUNET_NAT_IPCallback cb, void *cb_cls)
-{
-  struct GNUNET_NAT_ExternalHandle *eh;
-
-  eh = GNUNET_new (struct GNUNET_NAT_ExternalHandle);
-  eh->cb = cb;
-  eh->cb_cls = cb_cls;
-  eh->ret = GNUNET_NAT_ERROR_SUCCESS;
-  if (GNUNET_SYSERR ==
-      GNUNET_OS_check_helper_binary ("external-ip", GNUNET_NO, NULL))
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO,
-        _("`external-ip' command not found\n"));
-    eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND;
-    eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
-                                         eh);
-    return eh;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Running `external-ip' to determine our external IP\n");
-  eh->opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
-  if (NULL == eh->opipe)
-  {
-    eh->ret = GNUNET_NAT_ERROR_IPC_FAILURE;
-    eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
-                                         eh);
-    return eh;
-  }
-  eh->eip =
-      GNUNET_OS_start_process (GNUNET_NO, 0, NULL, eh->opipe, NULL,
-                               "external-ip", "external-ip",
-                               NULL);
-  if (NULL == eh->eip)
-  {
-    GNUNET_DISK_pipe_close (eh->opipe);
-    eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED;
-    eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
-                                         eh);
-    return eh;
-  }
-  GNUNET_DISK_pipe_close_end (eh->opipe, GNUNET_DISK_PIPE_END_WRITE);
-  eh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  eh->r = GNUNET_DISK_pipe_handle (eh->opipe, GNUNET_DISK_PIPE_END_READ);
-  eh->task =
-      GNUNET_SCHEDULER_add_read_file (timeout,
-                                      eh->r,
-                                      &read_external_ipv4, eh);
-  return eh;
-}
-
-
-/**
- * Cancel operation.
- *
- * @param eh operation to cancel
- */
-void
-GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh)
-{
-  if (NULL != eh->eip)
-  {
-    (void) GNUNET_OS_process_kill (eh->eip, SIGKILL);
-    GNUNET_OS_process_destroy (eh->eip);
-  }
-  if (NULL != eh->opipe)
-    GNUNET_DISK_pipe_close (eh->opipe);
-  if (NULL != eh->task)
-    GNUNET_SCHEDULER_cancel (eh->task);
-  GNUNET_free (eh);
-}
-
-
-/**
- * Handle to a mapping created with upnpc.
- */
-struct GNUNET_NAT_MiniHandle
-{
-
-  /**
-   * Function to call on mapping changes.
-   */
-  GNUNET_NAT_MiniAddressCallback ac;
-
-  /**
-   * Closure for @e ac.
-   */
-  void *ac_cls;
-
-  /**
-   * Command used to install the map.
-   */
-  struct GNUNET_OS_CommandHandle *map_cmd;
-
-  /**
-   * Command used to refresh our map information.
-   */
-  struct GNUNET_OS_CommandHandle *refresh_cmd;
-
-  /**
-   * Command used to remove the mapping.
-   */
-  struct GNUNET_OS_CommandHandle *unmap_cmd;
-
-  /**
-   * Our current external mapping (if we have one).
-   */
-  struct sockaddr_in current_addr;
-
-  /**
-   * We check the mapping periodically to see if it
-   * still works.  This task triggers the check.
-   */
-  struct GNUNET_SCHEDULER_Task * refresh_task;
-
-  /**
-   * Are we mapping TCP or UDP?
-   */
-  int is_tcp;
-
-  /**
-   * Did we succeed with creating a mapping?
-   */
-  int did_map;
-
-  /**
-   * Did we find our mapping during refresh scan?
-   */
-  int found;
-
-  /**
-   * Which port are we mapping?
-   */
-  uint16_t port;
-
-};
-
-
-/**
- * Run "upnpc -l" to find out if our mapping changed.
- *
- * @param cls the `struct GNUNET_NAT_MiniHandle`
- */
-static void
-do_refresh (void *cls);
-
-
-/**
- * Process the output from the "upnpc -r" command.
- *
- * @param cls the `struct GNUNET_NAT_MiniHandle`
- * @param line line of output, NULL at the end
- */
-static void
-process_map_output (void *cls, const char *line);
-
-
-/**
- * Run "upnpc -r" to map our internal port.
- *
- * @param mini our handle
- */
-static void
-run_upnpc_r (struct GNUNET_NAT_MiniHandle *mini)
-{
-  char pstr[6];
-
-  GNUNET_snprintf (pstr,
-                   sizeof (pstr),
-                   "%u",
-                   (unsigned int) mini->port);
-  mini->map_cmd =
-    GNUNET_OS_command_run (&process_map_output, mini, MAP_TIMEOUT,
-                           "upnpc", "upnpc", "-r", pstr,
-                           mini->is_tcp ? "tcp" : "udp", NULL);
-  if (NULL == mini->map_cmd)
-  {
-    mini->ac (mini->ac_cls,
-              GNUNET_SYSERR,
-              NULL, 0,
-              GNUNET_NAT_ERROR_UPNPC_FAILED);
-    return;
-  }
-}
-
-
-/**
- * Process the output from "upnpc -l" to see if our
- * external mapping changed.  If so, do the notifications.
- *
- * @param cls the `struct GNUNET_NAT_MiniHandle`
- * @param line line of output, NULL at the end
- */
-static void
-process_refresh_output (void *cls, const char *line)
-{
-  struct GNUNET_NAT_MiniHandle *mini = cls;
-  char pstr[9];
-  const char *s;
-  unsigned int nport;
-  struct in_addr exip;
-
-  if (NULL == line)
-  {
-    GNUNET_OS_command_stop (mini->refresh_cmd);
-    mini->refresh_cmd = NULL;
-    if (GNUNET_NO == mini->found)
-    {
-      /* mapping disappeared, try to re-create */
-      if (GNUNET_YES == mini->did_map)
-      {
-        mini->ac (mini->ac_cls,
-                  GNUNET_NO,
-                  (const struct sockaddr *) &mini->current_addr,
-                  sizeof (mini->current_addr),
-                  GNUNET_NAT_ERROR_SUCCESS);
-        mini->did_map = GNUNET_NO;
-      }
-      run_upnpc_r (mini);
-    }
-    return;
-  }
-  if (!mini->did_map)
-    return;                     /* never mapped, won't find our mapping anyway */
-
-  /* we're looking for output of the form:
-   * "ExternalIPAddress = 12.134.41.124" */
-
-  s = strstr (line, "ExternalIPAddress = ");
-  if (NULL != s)
-  {
-    s += strlen ("ExternalIPAddress = ");
-    if (1 != inet_pton (AF_INET, s, &exip))
-      return;                   /* skip */
-    if (exip.s_addr == mini->current_addr.sin_addr.s_addr)
-      return;                   /* no change */
-    /* update mapping */
-    mini->ac (mini->ac_cls, GNUNET_NO,
-              (const struct sockaddr *) &mini->current_addr,
-              sizeof (mini->current_addr),
-              GNUNET_NAT_ERROR_SUCCESS);
-    mini->current_addr.sin_addr = exip;
-    mini->ac (mini->ac_cls, GNUNET_YES,
-              (const struct sockaddr *) &mini->current_addr,
-              sizeof (mini->current_addr),
-              GNUNET_NAT_ERROR_SUCCESS);
-    return;
-  }
-  /*
-   * we're looking for output of the form:
-   *
-   * "0 TCP  3000->192.168.2.150:3000  'libminiupnpc' ''"
-   * "1 UDP  3001->192.168.2.150:3001  'libminiupnpc' ''"
-   *
-   * the pattern we look for is:
-   *
-   * "%s TCP  PORT->STRING:OURPORT *" or
-   * "%s UDP  PORT->STRING:OURPORT *"
-   */
-  GNUNET_snprintf (pstr, sizeof (pstr), ":%u ", mini->port);
-  if (NULL == (s = strstr (line, "->")))
-    return;                     /* skip */
-  if (NULL == strstr (s, pstr))
-    return;                     /* skip */
-  if (1 !=
-      SSCANF (line,
-              (mini->is_tcp) ? "%*u TCP  %u->%*s:%*u %*s" :
-              "%*u UDP  %u->%*s:%*u %*s", &nport))
-    return;                     /* skip */
-  mini->found = GNUNET_YES;
-  if (nport == ntohs (mini->current_addr.sin_port))
-    return;                     /* no change */
-
-  /* external port changed, update mapping */
-  mini->ac (mini->ac_cls, GNUNET_NO,
-            (const struct sockaddr *) &mini->current_addr,
-            sizeof (mini->current_addr),
-            GNUNET_NAT_ERROR_SUCCESS);
-  mini->current_addr.sin_port = htons ((uint16_t) nport);
-  mini->ac (mini->ac_cls, GNUNET_YES,
-            (const struct sockaddr *) &mini->current_addr,
-            sizeof (mini->current_addr),
-            GNUNET_NAT_ERROR_SUCCESS);
-}
-
-
-/**
- * Run "upnpc -l" to find out if our mapping changed.
- *
- * @param cls the 'struct GNUNET_NAT_MiniHandle'
- */
-static void
-do_refresh (void *cls)
-{
-  struct GNUNET_NAT_MiniHandle *mini = cls;
-  int ac;
-
-  mini->refresh_task =
-    GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
-                                  &do_refresh, mini);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Running `upnpc' to check if our mapping still exists\n");
-  mini->found = GNUNET_NO;
-  ac = GNUNET_NO;
-  if (NULL != mini->map_cmd)
-  {
-    /* took way too long, abort it! */
-    GNUNET_OS_command_stop (mini->map_cmd);
-    mini->map_cmd = NULL;
-    ac = GNUNET_YES;
-  }
-  if (NULL != mini->refresh_cmd)
-  {
-    /* took way too long, abort it! */
-    GNUNET_OS_command_stop (mini->refresh_cmd);
-    mini->refresh_cmd = NULL;
-    ac = GNUNET_YES;
-  }
-  mini->refresh_cmd =
-      GNUNET_OS_command_run (&process_refresh_output, mini, MAP_TIMEOUT,
-                             "upnpc", "upnpc", "-l", NULL);
-  if (GNUNET_YES == ac)
-    mini->ac (mini->ac_cls,
-              GNUNET_SYSERR,
-              NULL, 0,
-              GNUNET_NAT_ERROR_UPNPC_TIMEOUT);
-}
-
-
-/**
- * Process the output from the 'upnpc -r' command.
- *
- * @param cls the `struct GNUNET_NAT_MiniHandle`
- * @param line line of output, NULL at the end
- */
-static void
-process_map_output (void *cls,
-                    const char *line)
-{
-  struct GNUNET_NAT_MiniHandle *mini = cls;
-  const char *ipaddr;
-  char *ipa;
-  const char *pstr;
-  unsigned int port;
-
-  if (NULL == line)
-  {
-    GNUNET_OS_command_stop (mini->map_cmd);
-    mini->map_cmd = NULL;
-    if (GNUNET_YES != mini->did_map)
-      mini->ac (mini->ac_cls,
-                GNUNET_SYSERR,
-                NULL, 0,
-                GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED);
-    if (NULL == mini->refresh_task)
-      mini->refresh_task =
-        GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
-                                     &do_refresh,
-                                     mini);
-    return;
-  }
-  /*
-   * The upnpc output we're after looks like this:
-   *
-   * "external 87.123.42.204:3000 TCP is redirected to internal 192.168.2.150:3000"
-   */
-  if ((NULL == (ipaddr = strstr (line, " "))) ||
-      (NULL == (pstr = strstr (ipaddr, ":"))) ||
-      (1 != SSCANF (pstr + 1, "%u", &port)))
-  {
-    return;                     /* skip line */
-  }
-  ipa = GNUNET_strdup (ipaddr + 1);
-  strstr (ipa, ":")[0] = '\0';
-  if (1 != inet_pton (AF_INET, ipa, &mini->current_addr.sin_addr))
-  {
-    GNUNET_free (ipa);
-    return;                     /* skip line */
-  }
-  GNUNET_free (ipa);
-
-  mini->current_addr.sin_port = htons (port);
-  mini->current_addr.sin_family = AF_INET;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  mini->current_addr.sin_len = sizeof (struct sockaddr_in);
-#endif
-  mini->did_map = GNUNET_YES;
-  mini->ac (mini->ac_cls, GNUNET_YES,
-            (const struct sockaddr *) &mini->current_addr,
-            sizeof (mini->current_addr),
-            GNUNET_NAT_ERROR_SUCCESS);
-}
-
-
-/**
- * Start mapping the given port using (mini)upnpc.  This function
- * should typically not be used directly (it is used within the
- * general-purpose #GNUNET_NAT_register() code).  However, it can be
- * used if specifically UPnP-based NAT traversal is to be used or
- * tested.
- *
- * @param port port to map
- * @param is_tcp #GNUNET_YES to map TCP, #GNUNET_NO for UDP
- * @param ac function to call with mapping result
- * @param ac_cls closure for @a ac
- * @return NULL on error (no 'upnpc' installed)
- */
-struct GNUNET_NAT_MiniHandle *
-GNUNET_NAT_mini_map_start (uint16_t port,
-                           int is_tcp,
-                           GNUNET_NAT_MiniAddressCallback ac,
-                           void *ac_cls)
-{
-  struct GNUNET_NAT_MiniHandle *ret;
-
-  if (GNUNET_SYSERR ==
-      GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL))
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO,
-        _("`upnpc' command not found\n"));
-    ac (ac_cls,
-        GNUNET_SYSERR,
-        NULL, 0,
-        GNUNET_NAT_ERROR_UPNPC_NOT_FOUND);
-    return NULL;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Running `upnpc' to install mapping\n");
-  ret = GNUNET_new (struct GNUNET_NAT_MiniHandle);
-  ret->ac = ac;
-  ret->ac_cls = ac_cls;
-  ret->is_tcp = is_tcp;
-  ret->port = port;
-  ret->refresh_task =
-    GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
-                                 &do_refresh,
-                                 ret);
-  run_upnpc_r (ret);
-  return ret;
-}
-
-
-/**
- * Process output from our 'unmap' command.
- *
- * @param cls the `struct GNUNET_NAT_MiniHandle`
- * @param line line of output, NULL at the end
- */
-static void
-process_unmap_output (void *cls, const char *line)
-{
-  struct GNUNET_NAT_MiniHandle *mini = cls;
-
-  if (NULL == line)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "UPnP unmap done\n");
-    GNUNET_OS_command_stop (mini->unmap_cmd);
-    mini->unmap_cmd = NULL;
-    GNUNET_free (mini);
-    return;
-  }
-  /* we don't really care about the output... */
-}
-
-
-/**
- * Remove a mapping created with (mini)upnpc.  Calling
- * this function will give 'upnpc' 1s to remove tha mapping,
- * so while this function is non-blocking, a task will be
- * left with the scheduler for up to 1s past this call.
- *
- * @param mini the handle
- */
-void
-GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini)
-{
-  char pstr[6];
-
-  if (NULL != mini->refresh_task)
-  {
-    GNUNET_SCHEDULER_cancel (mini->refresh_task);
-    mini->refresh_task = NULL;
-  }
-  if (NULL != mini->refresh_cmd)
-  {
-    GNUNET_OS_command_stop (mini->refresh_cmd);
-    mini->refresh_cmd = NULL;
-  }
-  if (NULL != mini->map_cmd)
-  {
-    GNUNET_OS_command_stop (mini->map_cmd);
-    mini->map_cmd = NULL;
-  }
-  if (GNUNET_NO == mini->did_map)
-  {
-    GNUNET_free (mini);
-    return;
-  }
-  mini->ac (mini->ac_cls, GNUNET_NO,
-            (const struct sockaddr *) &mini->current_addr,
-            sizeof (mini->current_addr),
-            GNUNET_NAT_ERROR_SUCCESS);
-  /* Note: oddly enough, deletion uses the external port whereas
-   * addition uses the internal port; this rarely matters since they
-   * often are the same, but it might... */
-  GNUNET_snprintf (pstr,
-                   sizeof (pstr),
-                   "%u",
-                   (unsigned int) ntohs (mini->current_addr.sin_port));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Unmapping port %u with UPnP\n",
-       ntohs (mini->current_addr.sin_port));
-  mini->unmap_cmd =
-      GNUNET_OS_command_run (&process_unmap_output, mini, UNMAP_TIMEOUT,
-                             "upnpc", "upnpc", "-d", pstr,
-                             mini->is_tcp ? "tcp" : "udp", NULL);
-}
-
-
-/* end of nat_mini.c */
diff --git a/src/nat/nat_stun.c b/src/nat/nat_stun.c
deleted file mode 100644 (file)
index 62916ab..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2009, 2015 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-/**
- * This code provides some support for doing STUN transactions.
- * We send simplest possible packet ia REQUEST with BIND to a STUN server.
- *
- * All STUN packets start with a simple header made of a type,
- * length (excluding the header) and a 16-byte random transaction id.
- * Following the header we may have zero or more attributes, each
- * structured as a type, length and a value (whose format depends
- * on the type, but often contains addresses).
- * Of course all fields are in network format.
- *
- * This code was based on ministun.c.
- *
- * @file nat/nat_stun.c
- * @brief Functions for STUN functionality
- * @author Bruno Souza Cabral
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_resolver_service.h"
-#include "gnunet_nat_lib.h"
-
-
-#include "nat_stun.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__)
-
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
-
-
-/**
- * Handle to a request given to the resolver.  Can be used to cancel
- * the request prior to the timeout or successful execution.  Also
- * used to track our internal state for the request.
- */
-struct GNUNET_NAT_STUN_Handle
-{
-
-  /**
-   * Handle to a pending DNS lookup request.
-   */
-  struct GNUNET_RESOLVER_RequestHandle *dns_active;
-
-  /**
-   * Handle to the listen socket
-   */
-  struct GNUNET_NETWORK_Handle *sock;
-
-  /**
-   * Stun server address
-   */
-  char *stun_server;
-
-  /**
-   * Function to call when a error occours
-   */
-  GNUNET_NAT_STUN_ErrorCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Do we got a DNS resolution successfully?
-   */
-  int dns_success;
-
-  /**
-   * STUN port
-   */
-  uint16_t stun_port;
-
-};
-
-
-/**
- * here we store credentials extracted from a message
-*/
-struct StunState
-{
-    uint16_t attr;
-};
-
-
-/**
- * Encode a class and method to a compatible STUN format
- *
- * @param msg_class class to be converted
- * @param method method to be converted
- * @return message in a STUN compatible format
- */
-static int
-encode_message (enum StunClasses msg_class,
-                enum StunMethods method)
-{
-  return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) |
-    (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2);
-}
-
-
-/**
- * Fill the stun_header with a random request_id
- *
- * @param req, stun header to be filled
- */
-static void
-generate_request_id (struct stun_header *req)
-{
-  unsigned int x;
-
-  req->magic = htonl(STUN_MAGIC_COOKIE);
-  for (x = 0; x < 3; x++)
-    req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
-                                              UINT32_MAX);
-}
-
-
-/**
- * Extract the STUN_MAPPED_ADDRESS from the stun response.
- * This is used as a callback for stun_handle_response
- * when called from stun_request.
- *
- * @param st, pointer where we will set the type
- * @param attr , received stun attribute
- * @param arg , pointer to a sockaddr_in where we will set the reported IP and port
- * @param magic , Magic cookie
- *
- * @return 0 on success, other value otherwise
- */
-static int
-stun_get_mapped (struct StunState *st,
-                 struct stun_attr *attr,
-                 struct sockaddr_in *arg,
-                 unsigned int magic)
-{
-  struct stun_addr *returned_addr = (struct stun_addr *)(attr + 1);
-  struct sockaddr_in *sa = (struct sockaddr_in *)arg;
-  unsigned short type = ntohs(attr->attr);
-
-  switch (type)
-  {
-  case STUN_MAPPED_ADDRESS:
-    if (st->attr == STUN_XOR_MAPPED_ADDRESS ||
-        st->attr == STUN_MS_XOR_MAPPED_ADDRESS)
-      return 1;
-    magic = 0;
-    break;
-  case STUN_MS_XOR_MAPPED_ADDRESS:
-    if (st->attr == STUN_XOR_MAPPED_ADDRESS)
-      return 1;
-    break;
-  case STUN_XOR_MAPPED_ADDRESS:
-    break;
-  default:
-    return 1;
-  }
-  if ( (ntohs(attr->len) < 8) &&
-       (returned_addr->family != 1) )
-  {
-    return 1;
-  }
-  st->attr = type;
-  sa->sin_family = AF_INET;
-  sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16);
-  sa->sin_addr.s_addr = returned_addr->addr ^ magic;
-  return 0;
-}
-
-
-/**
- * Handle an incoming STUN message, Do some basic sanity checks on packet size and content,
- * try to extract a bit of information, and possibly reply.
- * At the moment this only processes BIND requests, and returns
- * the externally visible address of the request.
- * If a callback is specified, invoke it with the attribute.
- *
- * @param data the packet
- * @param len the length of the packet in @a data
- * @param[out] arg sockaddr_in where we will set our discovered address
- *
- * @return, #GNUNET_OK on OK, #GNUNET_NO if the packet is invalid (not a stun packet)
- */
-int
-GNUNET_NAT_stun_handle_packet (const void *data,
-                               size_t len,
-                               struct sockaddr_in *arg)
-{
-  const struct stun_header *hdr = (const struct stun_header *)data;
-  struct stun_attr *attr;
-  struct StunState st;
-  int ret = GNUNET_OK;
-  uint32_t advertised_message_size;
-  uint32_t message_magic_cookie;
-
-  /* On entry, 'len' is the length of the udp payload. After the
-   * initial checks it becomes the size of unprocessed options,
-   * while 'data' is advanced accordingly.
-   */
-  if (len < sizeof(struct stun_header))
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO,
-         "STUN packet too short (only %d, wanting at least %d)\n",
-         (int) len,
-         (int) sizeof(struct stun_header));
-    GNUNET_break_op (0);
-    return GNUNET_NO;
-  }
-  /* Skip header as it is already in hdr */
-  len -= sizeof(struct stun_header);
-  data += sizeof(struct stun_header);
-
-  /* len as advertised in the message */
-  advertised_message_size = ntohs(hdr->msglen);
-
-  message_magic_cookie = ntohl(hdr->magic);
-  /* Compare if the cookie match */
-  if (STUN_MAGIC_COOKIE != message_magic_cookie)
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO,
-         "Invalid magic cookie \n");
-    return GNUNET_NO;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "STUN Packet, msg %s (%04x), length: %d\n",
-       stun_msg2str(ntohs(hdr->msgtype)),
-       ntohs(hdr->msgtype),
-       advertised_message_size);
-  if (advertised_message_size > len)
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO,
-         "Scrambled STUN packet length (got %d, expecting %d)\n",
-         advertised_message_size,
-         (int)len);
-    return GNUNET_NO;
-  }
-  len = advertised_message_size;
-  memset (&st, 0, sizeof(st));
-
-  while (len > 0)
-  {
-    if (len < sizeof(struct stun_attr))
-    {
-      LOG (GNUNET_ERROR_TYPE_INFO,
-           "Attribute too short (got %d, expecting %d)\n",
-           (int)len,
-           (int) sizeof(struct stun_attr));
-      break;
-    }
-    attr = (struct stun_attr *)data;
-
-    /* compute total attribute length */
-    advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr);
-
-    /* Check if we still have space in our buffer */
-    if (advertised_message_size > len )
-    {
-      LOG (GNUNET_ERROR_TYPE_INFO,
-           "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n",
-           advertised_message_size,
-           (int)len);
-      break;
-    }
-    stun_get_mapped (&st,
-                     attr,
-                     arg,
-                     hdr->magic);
-    /* Clear attribute id: in case previous entry was a string,
-     * this will act as the terminator for the string.
-     */
-    attr->attr = 0;
-    data += advertised_message_size;
-    len -= advertised_message_size;
-    ret = GNUNET_OK;
-  }
-  return ret;
-}
-
-
-/**
- * Cancel active STUN request. Frees associated resources
- * and ensures that the callback is no longer invoked.
- *
- * @param rh request to cancel
- */
-void
-GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh)
-{
-  if (NULL != rh->dns_active)
-  {
-    GNUNET_RESOLVER_request_cancel (rh->dns_active);
-    rh->dns_active = NULL;
-  }
-  GNUNET_free (rh->stun_server);
-  GNUNET_free (rh);
-}
-
-
-/**
- * Try to establish a connection given the specified address.
- *
- * @param cls our `struct GNUNET_NAT_STUN_Handle *`
- * @param addr address to try, NULL for "last call"
- * @param addrlen length of @a addr
- */
-static void
-stun_dns_callback (void *cls,
-                   const struct sockaddr *addr,
-                   socklen_t addrlen)
-{
-  struct GNUNET_NAT_STUN_Handle *rh = cls;
-  struct stun_header *req;
-  uint8_t reqdata[1024];
-  int reqlen;
-  struct sockaddr_in server;
-
-  if (NULL == addr)
-  {
-    rh->dns_active = NULL;
-    if (GNUNET_NO == rh->dns_success)
-    {
-      LOG (GNUNET_ERROR_TYPE_INFO,
-           "Error resolving host %s\n",
-           rh->stun_server);
-      rh->cb (rh->cb_cls,
-              GNUNET_NAT_ERROR_NOT_ONLINE);
-    }
-    else if (GNUNET_SYSERR == rh->dns_success)
-    {
-      rh->cb (rh->cb_cls,
-             GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
-    }
-    else
-    {
-      rh->cb (rh->cb_cls,
-             GNUNET_NAT_ERROR_SUCCESS);
-    }
-    GNUNET_NAT_stun_make_request_cancel (rh);
-    return;
-  }
-
-  rh->dns_success = GNUNET_YES;
-  memset (&server,0, sizeof(server));
-  server.sin_family = AF_INET;
-  server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr;
-  server.sin_port = htons(rh->stun_port);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  server.sin_len = (u_char) sizeof (struct sockaddr_in);
-#endif
-
-  /*Craft the simplest possible STUN packet. A request binding*/
-  req = (struct stun_header *)reqdata;
-  generate_request_id (req);
-  reqlen = 0;
-  req->msgtype = 0;
-  req->msglen = 0;
-  req->msglen = htons (reqlen);
-  req->msgtype = htons (encode_message (STUN_REQUEST,
-                                       STUN_BINDING));
-
-  /* Send the packet */
-  if (-1 ==
-      GNUNET_NETWORK_socket_sendto (rh->sock,
-                                   req,
-                                   ntohs(req->msglen) + sizeof(*req),
-                                   (const struct sockaddr *) &server,
-                                   sizeof (server)))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
-                         "sendto");
-    rh->dns_success = GNUNET_SYSERR;
-    return;
-  }
-}
-
-
-/**
- * Make Generic STUN request. Sends a generic stun request to the
- * server specified using the specified socket, possibly waiting for
- * a reply and filling the 'reply' field with the externally visible
- * address.
- *
- * @param server the address of the stun server
- * @param port port of the stun server
- * @param sock the socket used to send the request
- * @param cb callback in case of error
- * @param cb_cls closure for @a cb
- * @return NULL on error
- */
-struct GNUNET_NAT_STUN_Handle *
-GNUNET_NAT_stun_make_request (const char *server,
-                              uint16_t port,
-                              struct GNUNET_NETWORK_Handle *sock,
-                              GNUNET_NAT_STUN_ErrorCallback cb,
-                              void *cb_cls)
-{
-  struct GNUNET_NAT_STUN_Handle *rh;
-
-  rh = GNUNET_new (struct GNUNET_NAT_STUN_Handle);
-  rh->sock = sock;
-  rh->cb = cb;
-  rh->cb_cls = cb_cls;
-  rh->stun_server = GNUNET_strdup (server);
-  rh->stun_port = port;
-  rh->dns_success = GNUNET_NO;
-  rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server,
-                                           AF_INET,
-                                           TIMEOUT,
-                                           &stun_dns_callback, rh);
-  if (NULL == rh->dns_active)
-  {
-    GNUNET_NAT_stun_make_request_cancel (rh);
-    return NULL;
-  }
-  return rh;
-}
-
-/* end of nat_stun.c */
diff --git a/src/nat/nat_test.c b/src/nat/nat_test.c
deleted file mode 100644 (file)
index 803ff23..0000000
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2011, 2016 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file nat/nat_test.c
- * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server)
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_nat_lib.h"
-#include "nat.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
-
-#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
-
-/**
- * Entry we keep for each incoming connection.
- */
-struct NatActivity
-{
-  /**
-   * This is a doubly-linked list.
-   */
-  struct NatActivity *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct NatActivity *prev;
-
-  /**
-   * Socket of the incoming connection.
-   */
-  struct GNUNET_NETWORK_Handle *sock;
-
-  /**
-   * Handle of the master context.
-   */
-  struct GNUNET_NAT_Test *h;
-
-  /**
-   * Task reading from the incoming connection.
-   */
-  struct GNUNET_SCHEDULER_Task *rtask;
-};
-
-
-/**
- * Entry we keep for each connection to the gnunet-nat-service.
- */
-struct ClientActivity
-{
-  /**
-   * This is a doubly-linked list.
-   */
-  struct ClientActivity *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct ClientActivity *prev;
-
-  /**
-   * Socket of the incoming connection.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Handle to overall NAT test.
-   */
-  struct GNUNET_NAT_Test *h;
-
-};
-
-
-/**
- * Handle to a NAT test.
- */
-struct GNUNET_NAT_Test
-{
-
-  /**
-   * Configuration used
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Function to call with success report
-   */
-  GNUNET_NAT_TestCallback report;
-
-  /**
-   * Closure for @e report.
-   */
-  void *report_cls;
-
-  /**
-   * Handle to NAT traversal in use
-   */
-  struct GNUNET_NAT_Handle *nat;
-
-  /**
-   * Handle to listen socket, or NULL
-   */
-  struct GNUNET_NETWORK_Handle *lsock;
-
-  /**
-   * Head of list of nat activities.
-   */
-  struct NatActivity *na_head;
-
-  /**
-   * Tail of list of nat activities.
-   */
-  struct NatActivity *na_tail;
-
-  /**
-   * Head of list of client activities.
-   */
-  struct ClientActivity *ca_head;
-
-  /**
-   * Tail of list of client activities.
-   */
-  struct ClientActivity *ca_tail;
-
-  /**
-   * Identity of task for the listen socket (if any)
-   */
-  struct GNUNET_SCHEDULER_Task *ltask;
-
-  /**
-   * Task identifier for the timeout (if any)
-   */
-  struct GNUNET_SCHEDULER_Task *ttask;
-
-  /**
-   * #GNUNET_YES if we're testing TCP
-   */
-  int is_tcp;
-
-  /**
-   * Data that should be transmitted or source-port.
-   */
-  uint16_t data;
-
-  /**
-   * Advertised port to the other peer.
-   */
-  uint16_t adv_port;
-
-  /**
-   * Status code to be reported to the timeout/status call
-   */
-  enum GNUNET_NAT_StatusCode status;
-};
-
-
-/**
- * Function called from #GNUNET_NAT_register whenever someone asks us
- * to do connection reversal.
- *
- * @param cls closure, our `struct GNUNET_NAT_Handle`
- * @param addr public IP address of the other peer
- * @param addrlen actual lenght of the @a addr
- */
-static void
-reversal_cb (void *cls,
-             const struct sockaddr *addr,
-             socklen_t addrlen)
-{
-  struct GNUNET_NAT_Test *h = cls;
-  const struct sockaddr_in *sa;
-
-  if (sizeof (struct sockaddr_in) != addrlen)
-    return;
-  sa = (const struct sockaddr_in *) addr;
-  if (h->data != sa->sin_port)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Received connection reversal request for wrong port\n");
-    return;                     /* wrong port */
-  }
-  /* report success */
-  h->report (h->report_cls,
-             GNUNET_NAT_ERROR_SUCCESS);
-}
-
-
-/**
- * Activity on our incoming socket.  Read data from the
- * incoming connection.
- *
- * @param cls the `struct GNUNET_NAT_Test`
- */
-static void
-do_udp_read (void *cls)
-{
-  struct GNUNET_NAT_Test *tst = cls;
-  uint16_t data;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  tst->ltask =
-      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                     tst->lsock,
-                                     &do_udp_read,
-                                     tst);
-  if ((NULL != tc->write_ready) &&
-      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
-                                   tst->lsock)) &&
-      (sizeof (data) ==
-       GNUNET_NETWORK_socket_recv (tst->lsock,
-                                   &data,
-                                   sizeof (data))))
-  {
-    if (data == tst->data)
-      tst->report (tst->report_cls,
-                   GNUNET_NAT_ERROR_SUCCESS);
-    else
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Received data mismatches expected value\n");
-  }
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Failed to receive data from inbound connection\n");
-}
-
-
-/**
- * Activity on our incoming socket.  Read data from the
- * incoming connection.
- *
- * @param cls the `struct NatActivity`
- */
-static void
-do_read (void *cls)
-{
-  struct NatActivity *na = cls;
-  struct GNUNET_NAT_Test *tst;
-  uint16_t data;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  na->rtask = NULL;
-  tst = na->h;
-  GNUNET_CONTAINER_DLL_remove (tst->na_head,
-                              tst->na_tail,
-                              na);
-  if ((NULL != tc->write_ready) &&
-      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
-                                   na->sock)) &&
-      (sizeof (data) ==
-       GNUNET_NETWORK_socket_recv (na->sock,
-                                   &data,
-                                   sizeof (data))))
-  {
-    if (data == tst->data)
-      tst->report (tst->report_cls,
-                   GNUNET_NAT_ERROR_SUCCESS);
-    else
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Received data does not match expected value\n");
-  }
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Failed to receive data from inbound connection\n");
-  GNUNET_NETWORK_socket_close (na->sock);
-  GNUNET_free (na);
-}
-
-
-/**
- * Activity on our listen socket. Accept the
- * incoming connection.
- *
- * @param cls the `struct GNUNET_NAT_Test`
- */
-static void
-do_accept (void *cls)
-{
-  struct GNUNET_NAT_Test *tst = cls;
-  struct GNUNET_NETWORK_Handle *s;
-  struct NatActivity *wl;
-
-  tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                              tst->lsock,
-                                              &do_accept,
-                                              tst);
-  s = GNUNET_NETWORK_socket_accept (tst->lsock,
-                                    NULL,
-                                    NULL);
-  if (NULL == s)
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
-                         "accept");
-    return;                     /* odd error */
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Got an inbound connection, waiting for data\n");
-  wl = GNUNET_new (struct NatActivity);
-  wl->sock = s;
-  wl->h = tst;
-  wl->rtask =
-    GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                   wl->sock,
-                                   &do_read,
-                                   wl);
-  GNUNET_CONTAINER_DLL_insert (tst->na_head,
-                              tst->na_tail,
-                              wl);
-}
-
-
-/**
- * We got disconnected from the NAT server.  Stop
- * waiting for a reply.
- *
- * @param cls the `struct ClientActivity`
- * @param error error code
- */
-static void
-mq_error_handler (void *cls,
-                  enum GNUNET_MQ_Error error)
-{
-  struct ClientActivity *ca = cls;
-  struct GNUNET_NAT_Test *tst = ca->h;
-
-  GNUNET_CONTAINER_DLL_remove (tst->ca_head,
-                               tst->ca_tail,
-                               ca);
-  GNUNET_MQ_destroy (ca->mq);
-  GNUNET_free (ca);
-}
-
-
-/**
- * Address-callback, used to send message to gnunet-nat-server.
- *
- * @param cls closure
- * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
- *     the previous (now invalid) one
- * @param addr either the previous or the new public IP address
- * @param addrlen actual length of the @a addr
- */
-static void
-addr_cb (void *cls,
-         int add_remove,
-         const struct sockaddr *addr,
-         socklen_t addrlen)
-{
-  struct GNUNET_NAT_Test *h = cls;
-  struct ClientActivity *ca;
-  struct GNUNET_MQ_Envelope *env;
-  struct GNUNET_NAT_TestMessage *msg;
-  const struct sockaddr_in *sa;
-
-  if (GNUNET_YES != add_remove)
-    return;
-  if (addrlen != sizeof (struct sockaddr_in))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "NAT test ignores IPv6 address `%s' returned from NAT library\n",
-        GNUNET_a2s (addr,
-                     addrlen));
-    return;                     /* ignore IPv6 here */
-  }
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "Asking gnunet-nat-server to connect to `%s'\n",
-       GNUNET_a2s (addr,
-                   addrlen));
-
-  ca = GNUNET_new (struct ClientActivity);
-  ca->h = h;
-  ca->mq = GNUNET_CLIENT_connecT (h->cfg,
-                                  "gnunet-nat-server",
-                                  NULL,
-                                  &mq_error_handler,
-                                  ca);
-  if (NULL == ca->mq)
-  {
-    GNUNET_free (ca);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Failed to connect to `gnunet-nat-server'\n"));
-    return;
-  }
-  GNUNET_CONTAINER_DLL_insert (h->ca_head,
-                               h->ca_tail,
-                               ca);
-  sa = (const struct sockaddr_in *) addr;
-  env = GNUNET_MQ_msg (msg,
-                       GNUNET_MESSAGE_TYPE_NAT_TEST);
-  msg->dst_ipv4 = sa->sin_addr.s_addr;
-  msg->dport = sa->sin_port;
-  msg->data = h->data;
-  msg->is_tcp = htonl ((uint32_t) h->is_tcp);
-  GNUNET_MQ_send (ca->mq,
-                  env);
-}
-
-
-/**
- * Timeout task for a nat test.
- * Calls the report-callback with a timeout return value
- *
- * Destroys the nat handle after the callback has been processed.
- *
- * @param cls handle to the timed out NAT test
- */
-static void
-do_timeout (void *cls)
-{
-  struct GNUNET_NAT_Test *nh = cls;
-
-  nh->ttask = NULL;
-  nh->report (nh->report_cls,
-              (GNUNET_NAT_ERROR_SUCCESS == nh->status)
-              ? GNUNET_NAT_ERROR_TIMEOUT
-              : nh->status);
-}
-
-
-/**
- * Start testing if NAT traversal works using the
- * given configuration (IPv4-only).
- *
- * ALL failures are reported directly to the report callback
- *
- * @param cfg configuration for the NAT traversal
- * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
- * @param bnd_port port to bind to, 0 for connection reversal
- * @param adv_port externally advertised port to use
- * @param timeout delay after which the test should be aborted
- * @param report function to call with the result of the test
- * @param report_cls closure for @a report
- * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback
- */
-struct GNUNET_NAT_Test *
-GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                       int is_tcp,
-                       uint16_t bnd_port,
-                       uint16_t adv_port,
-                       struct GNUNET_TIME_Relative timeout,
-                       GNUNET_NAT_TestCallback report,
-                       void *report_cls)
-{
-  struct GNUNET_NAT_Test *nh;
-  struct sockaddr_in sa;
-  const struct sockaddr *addrs[] = {
-    (const struct sockaddr *) &sa
-  };
-  const socklen_t addrlens[] = {
-    sizeof (sa)
-  };
-
-  memset (&sa, 0, sizeof (sa));
-  sa.sin_family = AF_INET;
-  sa.sin_port = htons (bnd_port);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  sa.sin_len = sizeof (sa);
-#endif
-
-  nh = GNUNET_new (struct GNUNET_NAT_Test);
-  nh->cfg = cfg;
-  nh->is_tcp = is_tcp;
-  nh->data = bnd_port;
-  nh->adv_port = adv_port;
-  nh->report = report;
-  nh->report_cls = report_cls;
-  nh->status = GNUNET_NAT_ERROR_SUCCESS;
-  if (0 == bnd_port)
-  {
-    nh->nat
-      = GNUNET_NAT_register (cfg,
-                             is_tcp,
-                             0,
-                             0,
-                            NULL,
-                             NULL,
-                            &addr_cb,
-                             &reversal_cb,
-                             nh,
-                             NULL);
-  }
-  else
-  {
-    nh->lsock =
-        GNUNET_NETWORK_socket_create (AF_INET,
-                                      (is_tcp ==
-                                       GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM,
-                                      0);
-    if ((nh->lsock == NULL) ||
-        (GNUNET_OK !=
-         GNUNET_NETWORK_socket_bind (nh->lsock,
-                                     (const struct sockaddr *) &sa,
-                                     sizeof (sa))))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
-                  GNUNET_a2s ((const struct sockaddr *) &sa,
-                              sizeof (sa)),
-                  STRERROR (errno));
-      if (NULL != nh->lsock)
-      {
-        GNUNET_NETWORK_socket_close (nh->lsock);
-        nh->lsock = NULL;
-      }
-      nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
-      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout,
-                                            nh);
-      return nh;
-    }
-    if (GNUNET_YES == is_tcp)
-    {
-      GNUNET_break (GNUNET_OK ==
-                    GNUNET_NETWORK_socket_listen (nh->lsock,
-                                                  5));
-      nh->ltask =
-          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                         nh->lsock,
-                                        &do_accept,
-                                         nh);
-    }
-    else
-    {
-      nh->ltask =
-          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                         nh->lsock,
-                                        &do_udp_read,
-                                         nh);
-    }
-    LOG (GNUNET_ERROR_TYPE_INFO,
-        "NAT test listens on port %u (%s)\n",
-        bnd_port,
-        (GNUNET_YES == is_tcp) ? "tcp" : "udp");
-    nh->nat = GNUNET_NAT_register (cfg,
-                                   is_tcp,
-                                   adv_port,
-                                   1,
-                                   addrs,
-                                   addrlens,
-                                   &addr_cb,
-                                   NULL,
-                                   nh,
-                                   NULL);
-    if (NULL == nh->nat)
-    {
-      LOG (GNUNET_ERROR_TYPE_INFO,
-          _("NAT test failed to start NAT library\n"));
-      if (NULL != nh->ltask)
-      {
-        GNUNET_SCHEDULER_cancel (nh->ltask);
-        nh->ltask = NULL;
-      }
-      if (NULL != nh->lsock)
-      {
-        GNUNET_NETWORK_socket_close (nh->lsock);
-        nh->lsock = NULL;
-      }
-      nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
-      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout,
-                                            nh);
-      return nh;
-    }
-  }
-  nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout,
-                                           &do_timeout,
-                                           nh);
-  return nh;
-}
-
-
-/**
- * Stop an active NAT test.
- *
- * @param tst test to stop.
- */
-void
-GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst)
-{
-  struct NatActivity *pos;
-  struct ClientActivity *cpos;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Stopping NAT test\n");
-  while (NULL != (cpos = tst->ca_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (tst->ca_head,
-                                tst->ca_tail,
-                                cpos);
-    GNUNET_MQ_destroy (cpos->mq);
-    GNUNET_free (cpos);
-  }
-  while (NULL != (pos = tst->na_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (tst->na_head,
-                                tst->na_tail,
-                                pos);
-    GNUNET_SCHEDULER_cancel (pos->rtask);
-    GNUNET_NETWORK_socket_close (pos->sock);
-    GNUNET_free (pos);
-  }
-  if (NULL != tst->ttask)
-  {
-    GNUNET_SCHEDULER_cancel (tst->ttask);
-    tst->ttask = NULL;
-  }
-  if (NULL != tst->ltask)
-  {
-    GNUNET_SCHEDULER_cancel (tst->ltask);
-    tst->ltask = NULL;
-  }
-  if (NULL != tst->lsock)
-  {
-    GNUNET_NETWORK_socket_close (tst->lsock);
-    tst->lsock = NULL;
-  }
-  if (NULL != tst->nat)
-  {
-    GNUNET_NAT_unregister (tst->nat);
-    tst->nat = NULL;
-  }
-  GNUNET_free (tst);
-}
-
-/* end of nat_test.c */
index 4e62576964df6702a9cc02dd1ab61a731132dc85..a2575673c8bfc90cd623a70be9e439ce39a9e225 100644 (file)
@@ -1,3 +1,5 @@
 gnunet-service-nse
 gnunet-nse
 gnunet-nse-profiler
+test_nse_api
+perf_kdf
index 511f95514737ae344fbb7e88b53e8bc6e3ab1519..4d54a740b626e397d54bc2994e817b39c4626a70 100644 (file)
@@ -1346,7 +1346,7 @@ shutdown_task (void *cls)
   }
   if (NULL != core_api)
   {
-    GNUNET_CORE_disconnecT (core_api);
+    GNUNET_CORE_disconnect (core_api);
     core_api = NULL;
   }
   if (NULL != stats)
@@ -1607,7 +1607,7 @@ run (void *cls,
                                                GNUNET_YES);
   nc = GNUNET_notification_context_create (1);
   /* Connect to core service and register core handlers */
-  core_api = GNUNET_CORE_connecT (cfg,   /* Main configuration */
+  core_api = GNUNET_CORE_connect (cfg,   /* Main configuration */
                                  NULL,       /* Closure passed to functions */
                                  &core_init,    /* Call core_init once connected */
                                  &handle_core_connect,  /* Handle connects */
index cfe5482ebe802ca04208ba005ccf3012afb8398d..d50b0214ac8efbe80ae177b6fddfa052bdae8302 100644 (file)
@@ -150,7 +150,7 @@ reconnect (void *cls)
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Connecting to network size estimation service.\n");
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "nse",
                                  handlers,
                                  &mq_error_handler,
index dc2209862a88a5367b9ff4708d2e1521d4370118..d4ed4f8011e7e14d90e31962e55a8c24fe051185 100644 (file)
@@ -1 +1,2 @@
 gnunet-peerinfo
+test_gnunet_peerinfo.py
index f22380a9e04073adcee0e82d0d7bda982bf0716d..c79c3ac6880ea19bd05905d78dd35ff9dcf90513 100644 (file)
@@ -19,7 +19,6 @@ gnunet_peerinfo_SOURCES = \
 
 gnunet_peerinfo_LDADD = \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
   $(top_builddir)/src/transport/libgnunettransport.la \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
index 950ed60a67dc9cc79fa19d0f3a2e74508b772332..e2a79a2119cc58c27ad26a4db5aaf5bde2b1054b 100644 (file)
@@ -1 +1,5 @@
 gnunet-service-peerinfo
+test_peerinfo_api
+test_peerinfo_api_friend_only
+test_peerinfo_api_notify_friend_only
+test_peerinfo_shipped_hellos
index 3080fb5036ebaeeaca1b9cab0492d16f586e9694..b75d4e2913259fc9583f99aa9226520c0df75371 100644 (file)
@@ -462,7 +462,7 @@ reconnect (struct GNUNET_PEERINFO_Handle *h)
     GNUNET_MQ_destroy (h->mq);
     h->mq = NULL;
   }
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "peerinfo",
                                  handlers,
                                  &mq_error_handler,
@@ -557,7 +557,7 @@ GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic)
 struct GNUNET_MQ_Envelope *
 GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h,
                           const struct GNUNET_HELLO_Message *hello,
-                         GNUNET_MQ_NotifyCallback cont,
+                         GNUNET_SCHEDULER_TaskCallback cont,
                          void *cont_cls)
 {
   struct GNUNET_MQ_Envelope *env;
index e707a911e8d5e1dd6fd1d37f5718aa346d0ec5b7..ce226d96e432b775a5a1431fe2b04c499f4c9146 100644 (file)
@@ -212,7 +212,7 @@ reconnect (void *cls)
   struct NotifyMessage *nm;
 
   nc->task = NULL;
-  nc->mq = GNUNET_CLIENT_connecT (nc->cfg,
+  nc->mq = GNUNET_CLIENT_connect (nc->cfg,
                                   "peerinfo",
                                   handlers,
                                   &mq_error_handler,
index a07db8a36affef967399511631e3032f1a44695a..33304d90b6c73e8fe8469729eaed2077adf65634 100644 (file)
@@ -1,2 +1,8 @@
 gnunet-service-peerstore
 gnunet-peerstore
+perf_peerstore_store
+test_peerstore_api_iterate
+test_peerstore_api_store
+test_peerstore_api_sync
+test_peerstore_api_watch
+test_plugin_peerstore_sqlite
index 47bf7775e73e246d7c7a922addb7c5a5432f7f3b..c9fcd17abf32ecd18528f64d088f5fbfab126e61 100644 (file)
@@ -829,7 +829,7 @@ reconnect (struct GNUNET_PEERSTORE_Handle *h)
     GNUNET_MQ_destroy (h->mq);
     h->mq = NULL;
   }
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "peerstore",
                                  mq_handlers,
                                  &handle_client_error,
diff --git a/src/pq/.gitignore b/src/pq/.gitignore
new file mode 100644 (file)
index 0000000..8de68dd
--- /dev/null
@@ -0,0 +1 @@
+test_pq
index 9769bb85374857c8a1b140044ccf841f8604d59c..c6544df3aeda2cf74284429fed5a6580a4d013af 100644 (file)
@@ -598,7 +598,7 @@ channel_disconnect (struct GNUNET_PSYC_Channel *chn,
     struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (chn->mq);
     if (NULL != env)
     {
-      GNUNET_MQ_notify_sent (env, (GNUNET_MQ_NotifyCallback) channel_cleanup, chn);
+      GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) channel_cleanup, chn);
     }
     else
     {
@@ -694,7 +694,7 @@ master_connect (struct GNUNET_PSYC_Master *mst)
     GNUNET_MQ_handler_end ()
   };
 
-  chn->mq = GNUNET_CLIENT_connecT (chn->cfg, "psyc",
+  chn->mq = GNUNET_CLIENT_connect (chn->cfg, "psyc",
                                    handlers, master_disconnected, mst);
   GNUNET_assert (NULL != chn->mq);
   chn->tmit = GNUNET_PSYC_transmit_create (chn->mq);
@@ -993,7 +993,7 @@ slave_connect (struct GNUNET_PSYC_Slave *slv)
     GNUNET_MQ_handler_end ()
   };
 
-  chn->mq = GNUNET_CLIENT_connecT (chn->cfg, "psyc",
+  chn->mq = GNUNET_CLIENT_connect (chn->cfg, "psyc",
                                    handlers, slave_disconnected, slv);
   GNUNET_assert (NULL != chn->mq);
   chn->tmit = GNUNET_PSYC_transmit_create (chn->mq);
index 573a58d5c64c3d45cbbbe0ab5efb265e8b095ed8..10c92a878d087e8a42e59d6049ca45c40dc54bc9 100644 (file)
@@ -198,8 +198,8 @@ send_fragment (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg,
   res->psycstore_flags = htonl (flags);
   GNUNET_memcpy (&res[1], msg, msg_size);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Sending fragment %ld to client\n",
-             GNUNET_ntohll (msg->fragment_id));
+             "Sending fragment %llu to client\n",
+             (unsigned long long) GNUNET_ntohll (msg->fragment_id));
   GNUNET_free (msg);
 
   GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (sc->client), env);
index 480d594fc969b8b48928bccb8ebed6e05bb61ade..40322662ea6eb84692b5e06b80cadb3061849612 100644 (file)
@@ -348,7 +348,7 @@ do_connect (struct GNUNET_PSYCSTORE_Handle *h)
 
   h->op = GNUNET_OP_create ();
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg, "psycstore",
+  h->mq = GNUNET_CLIENT_connect (h->cfg, "psycstore",
                                  handlers, disconnected, h);
   GNUNET_assert (NULL != h->mq);
 }
index 014e54347c94dc1c29752e5fee424cb3dc21a81e..39dc89c8832ede38056fabd3b26bac826e25775e 100644 (file)
@@ -3,3 +3,10 @@ gnunet-daemon-regexprofiler
 gnunet-regex-profiler
 gnunet-regex-simulation-profiler
 gnunet-service-regex
+test_graph.dot
+test_regex_api
+test_regex_eval_api
+test_regex_graph_api
+test_regex_integration
+test_regex_iterate_api
+test_regex_proofs
index 8fded96d2e7ae269f5b128f2509e056a5369a660..70bf34bc869b5e42323b802de1a1fdaf03e4bed4 100644 (file)
@@ -104,7 +104,7 @@ announce_reconnect (struct GNUNET_REGEX_Announcement *a)
   struct AnnounceMessage *am;
   size_t slen;
 
-  a->mq = GNUNET_CLIENT_connecT (a->cfg,
+  a->mq = GNUNET_CLIENT_connect (a->cfg,
                                  "regex",
                                  NULL,
                                  &announce_mq_error_handler,
index ff85f57485aa5d9f84ac941f6f279669cbda86c4..b7a015f87680f7fcf7fd178be169082f124faf6d 100644 (file)
@@ -167,7 +167,7 @@ search_reconnect (struct GNUNET_REGEX_Search *s)
   struct RegexSearchMessage *rsm;
 
   GNUNET_assert (NULL == s->mq);
-  s->mq = GNUNET_CLIENT_connecT (s->cfg,
+  s->mq = GNUNET_CLIENT_connect (s->cfg,
                                  "regex",
                                  handlers,
                                  &mq_error_handler,
index ad3253548e2391cc8843ea5995d11844dda7cbd4..2965808fa9b1916ce376aa814f0c42edd29b81e0 100644 (file)
@@ -670,7 +670,7 @@ shutdown_task (void *cls)
   }
   if (NULL != core_api)
   {
-    GNUNET_CORE_disconnecT (core_api);
+    GNUNET_CORE_disconnect (core_api);
     core_api = NULL;
   }
   if (NULL != stats)
@@ -894,7 +894,7 @@ run (void *cls,
   peers = GNUNET_CONTAINER_multipeermap_create (128,
                                                 GNUNET_YES);
   /* Connect to core service and register core handlers */
-  core_api = GNUNET_CORE_connecT (cfg,   /* Main configuration */
+  core_api = GNUNET_CORE_connect (cfg,   /* Main configuration */
                                  NULL,       /* Closure passed to functions */
                                  &core_init,    /* Call core_init once connected */
                                  &handle_core_connect,  /* Handle connects */
index 8c00ac2ae680bbef1d76647fe2291354fde7f25a..fde0296a4448e5f2d88f0698957f1d392ed232c3 100644 (file)
@@ -125,7 +125,7 @@ GNUNET_REVOCATION_query (const struct GNUNET_CONFIGURATION_Handle *cfg,
   struct QueryMessage *qm;
   struct GNUNET_MQ_Envelope *env;
 
-  q->mq = GNUNET_CLIENT_connecT (cfg,
+  q->mq = GNUNET_CLIENT_connect (cfg,
                                  "revocation",
                                  handlers,
                                  &query_mq_error_handler,
@@ -283,7 +283,7 @@ GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
     return NULL;
   }
 
-  h->mq = GNUNET_CLIENT_connecT (cfg,
+  h->mq = GNUNET_CLIENT_connect (cfg,
                                  "revocation",
                                  handlers,
                                  &revocation_mq_error_handler,
index ba659d9d85d5bc7732830d74621517ab8089914b..d3bbb879a80e44331575d0008f953b98b3928404 100644 (file)
@@ -337,7 +337,7 @@ core_connect_adapter (void *cls,
   struct TestPeer *me = cls;
 
   me->cfg = cfg;
-  me->ch = GNUNET_CORE_connecT (cfg,
+  me->ch = GNUNET_CORE_connect (cfg,
                                me,
                                NULL,
                                 &connect_cb,
@@ -356,7 +356,7 @@ core_disconnect_adapter (void *cls,
 {
   struct TestPeer *me = cls;
 
-  GNUNET_CORE_disconnecT (me->ch);
+  GNUNET_CORE_disconnect (me->ch);
   me->ch = NULL;
 }
 
index 3d2f3735981182a983245487c226b3938c7db442..504f28b92091aefecf905865707079f01a44c9b6 100644 (file)
@@ -286,7 +286,7 @@ reconnect (struct GNUNET_RPS_Handle *h)
 
   if (NULL != h->mq)
     GNUNET_MQ_destroy (h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "rps",
                                  mq_handlers,
                                  &mq_error_handler,
index 9606851c84007c252b7c4603bbc4ee7f00bc7b5e..df9f8d196c52e69ad7808e9ab4953de4650ed8cb 100644 (file)
@@ -256,7 +256,7 @@ GNUNET_SCALARPRODUCT_accept_computation (const struct GNUNET_CONFIGURATION_Handl
   h->response_proc = &process_status_message;
   h->cfg = cfg;
   h->key = *session_key;
-  h->mq = GNUNET_CLIENT_connecT (cfg,
+  h->mq = GNUNET_CLIENT_connect (cfg,
                                  "scalarproduct-bob",
                                  handlers,
                                  &mq_error_handler,
@@ -408,7 +408,7 @@ GNUNET_SCALARPRODUCT_start_computation (const struct GNUNET_CONFIGURATION_Handle
   if (GNUNET_SYSERR == check_unique (elements,
                                      element_count))
     return NULL;
-  h->mq = GNUNET_CLIENT_connecT (cfg,
+  h->mq = GNUNET_CLIENT_connect (cfg,
                                  "scalarproduct-alice",
                                  handlers,
                                  &mq_error_handler,
index 78167b671a5cf1cdb8ed8b70a726cbf5d2fbf20c..85df66c13b8f2692f8d0c930488e866d11c8e843 100644 (file)
@@ -261,7 +261,7 @@ GNUNET_SECRETSHARING_create_session (const struct GNUNET_CONFIGURATION_Handle *c
   struct GNUNET_MQ_Envelope *ev;
   struct GNUNET_SECRETSHARING_CreateMessage *msg;
 
-  s->mq = GNUNET_CLIENT_connecT (cfg,
+  s->mq = GNUNET_CLIENT_connect (cfg,
                                  "secretsharing",
                                  mq_handlers,
                                  &handle_session_client_error,
@@ -348,7 +348,7 @@ GNUNET_SECRETSHARING_decrypt (const struct GNUNET_CONFIGURATION_Handle *cfg,
 
   s->decrypt_cb = decrypt_cb;
   s->decrypt_cls = decrypt_cb_cls;
-  s->mq = GNUNET_CLIENT_connecT (cfg,
+  s->mq = GNUNET_CLIENT_connect (cfg,
                                  "secretsharing",
                                  mq_handlers,
                                  &handle_decrypt_client_error,
index 0142b1729ce40a4fd54ab903f0fd6f9bfde0ab5c..4d990479cb51e750fae8e8c26705b50c103993b1 100644 (file)
@@ -16,11 +16,13 @@ if USE_COVERAGE
   AM_CFLAGS = -fprofile-arcs -ftest-coverage
 endif
 
+if HAVE_TESTING
 bin_PROGRAMS = \
  gnunet-set-profiler
 
 noinst_PROGRAMS = \
  gnunet-set-ibf-profiler
+endif
 
 libexec_PROGRAMS = \
  gnunet-service-set
index 7a33b86eaeb8d210ada05c1ec7f1ff0db9d5fa25..7a7267a330c43075438d9599416bb17ff03058ff 100644 (file)
@@ -586,7 +586,7 @@ create_internal (const struct GNUNET_CONFIGURATION_Handle *cfg,
   struct GNUNET_SET_CopyLazyConnectMessage *copy_msg;
 
   set->cfg = cfg;
-  set->mq = GNUNET_CLIENT_connecT (cfg,
+  set->mq = GNUNET_CLIENT_connect (cfg,
                                    "set",
                                    mq_handlers,
                                    &handle_client_set_error,
@@ -914,7 +914,7 @@ listen_connect (void *cls)
 
   lh->reconnect_task = NULL;
   GNUNET_assert (NULL == lh->mq);
-  lh->mq = GNUNET_CLIENT_connecT (lh->cfg,
+  lh->mq = GNUNET_CLIENT_connect (lh->cfg,
                                   "set",
                                   mq_handlers,
                                   &handle_client_listener_error,
index afd06028c1a92ab27487dd563a20da12eb0794e8..6d72ca552453a01877be0589ea09140cd73673e9 100644 (file)
@@ -360,7 +360,7 @@ notify_data (void *cls, uint16_t *data_size, void *data)
 
   if (0 == tmit->size)
   {
-    if (op_host_announce || op_host_assign || op_guest_talk)
+    if ((op_host_announce || op_host_assign || op_guest_talk) && !opt_follow)
     {
       exit_success ();
     }
index f78cb9a85c52a2a8e547316837705349ce0bda83..a7fe0916f5609e743f39679279c1ffbbffdfcedb 100644 (file)
@@ -893,7 +893,7 @@ handle_guest_enter_decision (void *cls,
   struct GNUNET_SOCIAL_Guest *gst = cls;
 
   struct GNUNET_PSYC_Message *pmsg = NULL;
-  if (ntohs (dcsn->header.size) <= sizeof (*dcsn) + sizeof (*pmsg))
+  if (ntohs (dcsn->header.size) > sizeof (*dcsn))
     pmsg = (struct GNUNET_PSYC_Message *) GNUNET_MQ_extract_nested_mh (dcsn);
 
   if (NULL != gst->entry_dcsn_cb)
@@ -1087,7 +1087,7 @@ place_disconnect (struct GNUNET_SOCIAL_Place *plc,
     struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (plc->mq);
     if (NULL != env)
     {
-      GNUNET_MQ_notify_sent (env, (GNUNET_MQ_NotifyCallback) place_cleanup, plc);
+      GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) place_cleanup, plc);
     }
     else
     {
@@ -1195,7 +1195,7 @@ host_connect (struct GNUNET_SOCIAL_Host *hst)
     GNUNET_MQ_handler_end ()
   };
 
-  plc->mq = GNUNET_CLIENT_connecT (plc->cfg, "social",
+  plc->mq = GNUNET_CLIENT_connect (plc->cfg, "social",
                                    handlers, host_disconnected, hst);
   GNUNET_assert (NULL != plc->mq);
   plc->tmit = GNUNET_PSYC_transmit_create (plc->mq);
@@ -1697,7 +1697,7 @@ guest_connect (struct GNUNET_SOCIAL_Guest *gst)
     GNUNET_MQ_handler_end ()
   };
 
-  plc->mq = GNUNET_CLIENT_connecT (plc->cfg, "social",
+  plc->mq = GNUNET_CLIENT_connect (plc->cfg, "social",
                                    handlers, guest_disconnected, gst);
   GNUNET_assert (NULL != plc->mq);
   plc->tmit = GNUNET_PSYC_transmit_create (plc->mq);
@@ -2597,7 +2597,7 @@ app_connect (struct GNUNET_SOCIAL_App *app)
     GNUNET_MQ_handler_end ()
   };
 
-  app->mq = GNUNET_CLIENT_connecT (app->cfg, "social",
+  app->mq = GNUNET_CLIENT_connect (app->cfg, "social",
                                    handlers, app_disconnected, app);
   GNUNET_assert (NULL != app->mq);
   GNUNET_MQ_send_copy (app->mq, app->connect_env);
@@ -2701,7 +2701,7 @@ GNUNET_SOCIAL_app_disconnect (struct GNUNET_SOCIAL_App *app,
     struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (app->mq);
     if (NULL != env)
     {
-      GNUNET_MQ_notify_sent (env, (GNUNET_MQ_NotifyCallback) app_cleanup, app);
+      GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) app_cleanup, app);
     }
     else
     {
index 55f015bcef04015beb3f091dff4c7fe214d49ad6..f1f567149395d80b228337b2e25040e260ae39e6 100644 (file)
@@ -1,2 +1,7 @@
 gnunet-statistics
 gnunet-service-statistics
+test_gnunet_statistics.py
+test_statistics_api
+test_statistics_api_loop
+test_statistics_api_watch
+test_statistics_api_watch_zero_value
index bfa2da3b4d6cc33eab880299b7c6451ab068c7eb..ad4453b2a62a0e8515317e0d972bdd1c740aabab 100644 (file)
@@ -678,7 +678,7 @@ try_connect (struct GNUNET_STATISTICS_Handle *h)
     return GNUNET_NO;
   if (NULL != h->mq)
     return GNUNET_YES;
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "statistics",
                                  handlers,
                                  &mq_error_handler,
index 6e6ad861c1cf1c40aeefd3ae44e58638a9174af6..8ac4bacb5b639a3c467e5deaaf91b678ef0f269b 100644 (file)
@@ -1,2 +1,3 @@
 gnunet-template
 gnunet-service-template
+test_template_api
index eb2ed00b0c4de1255fec01bbc29f68cd5212e980..de0c2dcfe78d601bb5dd2cf3d20b2cc6176e72a9 100644 (file)
@@ -1 +1,2 @@
 gnunet-service-testbed-logger
+test_testbed_logger_api
index 19a5d9b501e88d2ac6c99168fbf5070305e24c8b..25494aed059e13794c5fbcca6b747bfb5bc0419b 100644 (file)
@@ -224,7 +224,7 @@ GNUNET_TESTBED_LOGGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
   struct GNUNET_TESTBED_LOGGER_Handle *h;
 
   h = GNUNET_new (struct GNUNET_TESTBED_LOGGER_Handle);
-  h->mq = GNUNET_CLIENT_connecT (cfg,
+  h->mq = GNUNET_CLIENT_connect (cfg,
                                  "testbed-logger",
                                  NULL,
                                  &mq_error_handler,
index acffa9b91ab44a6244c0618d35f76028b4ac8a42..f7cfb1e2355096bcc12d7aaf78b0c4a1d0ed5bc8 100644 (file)
@@ -5,3 +5,33 @@ gnunet-daemon-testbed-blacklist
 gnunet-daemon-testbed-underlay
 gnunet-helper-testbed
 gnunet-service-testbed
+gnunet-service-test-barriers
+test_gnunet_helper_testbed
+test_testbed_api
+test_testbed_api_2peers_1controller
+test_testbed_api_3peers_3controllers
+test_testbed_api_barriers
+test_testbed_api_controllerlink
+test_testbed_api_hosts
+test_testbed_api_operations
+test_testbed_api_peer_reconfiguration
+test_testbed_api_peers_manage_services
+test_testbed_api_sd
+test_testbed_api_statistics
+test_testbed_api_test
+test_testbed_api_test_timeout
+test_testbed_api_testbed_run
+test_testbed_api_testbed_run_topology2dtorus
+test_testbed_api_testbed_run_topologyclique
+test_testbed_api_testbed_run_topologyfromfile
+test_testbed_api_testbed_run_topologyline
+test_testbed_api_testbed_run_topologyrandom
+test_testbed_api_testbed_run_topologyring
+test_testbed_api_testbed_run_topologyscalefree
+test_testbed_api_testbed_run_topologysmallworld
+test_testbed_api_testbed_run_topologysmallworldring
+test_testbed_api_testbed_run_topologystar
+test_testbed_api_testbed_run_waitforever
+test_testbed_api_topology
+test_testbed_api_topology_clique
+test_testbed_underlay
index b0e369c6a3173b9c8f8f33afdbe078a9434248f8..6bc744ba876dec36f9e5143383fe3a205f45aaca 100644 (file)
@@ -623,12 +623,12 @@ core_peer_connect_cb (void *cls,
 
 
 /**
- * Function called after #GNUNET_CORE_connecT() has succeeded (or failed
+ * Function called after #GNUNET_CORE_connect() has succeeded (or failed
  * for good).  Note that the private key of the peer is intentionally
  * not exposed here; if you need it, your process should try to read
  * the private key file directly (which should work if you are
  * authorized...).  Implementations of this function must not call
- * #GNUNET_CORE_disconnecT() (other than by scheduling a new task to
+ * #GNUNET_CORE_disconnect() (other than by scheduling a new task to
  * do this later).
  *
  * @param cls the #PooledConnection object
@@ -675,7 +675,7 @@ opstart_get_handle_core (void *cls)
   LOG_DEBUG ("Opening a CORE connection to peer %u\n",
              entry->index);
   entry->handle_core
-    = GNUNET_CORE_connecT (entry->cfg,
+    = GNUNET_CORE_connect (entry->cfg,
                            entry,        /* closure */
                            &core_startup_cb, /* core startup notify */
                            &core_peer_connect_cb,    /* peer connect notify */
@@ -697,7 +697,7 @@ oprelease_get_handle_core (void *cls)
 
   if (NULL == entry->handle_core)
     return;
-  GNUNET_CORE_disconnecT (entry->handle_core);
+  GNUNET_CORE_disconnect (entry->handle_core);
   entry->handle_core = NULL;
   GNUNET_free_non_null (entry->peer_identity);
   entry->peer_identity = NULL;
index ae40948b3cf87d4be998a0f1d953c9ebd8d13731..0e0a5da9c9d4881ae3933f1e2daddfc9e2ed0fde 100644 (file)
@@ -1646,7 +1646,7 @@ GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
   controller->cc_cls = cc_cls;
   controller->event_mask = event_mask;
   controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
-  controller->mq = GNUNET_CLIENT_connecT (controller->cfg,
+  controller->mq = GNUNET_CLIENT_connect (controller->cfg,
                                           "testbed",
                                           handlers,
                                           &mq_error_handler,
index 1679756a1cb21138277d43feb9b23222e95cc594..93698d4b729ce0432e7744b944ece11bfa635b25 100644 (file)
@@ -215,7 +215,7 @@ GNUNET_TESTBED_barrier_wait (const char *name,
   h->name = GNUNET_strdup (name);
   h->cb = cb;
   h->cb_cls = cb_cls;
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "testbed-barrier",
                                  handlers,
                                  &mq_error_handler,
index 212ed2ad31d309f8389c7b01613662982e617696..f350da1f2726e2e4881b190769abf92f9e0a7d5c 100644 (file)
@@ -1,2 +1,7 @@
 list-keys
 gnunet-testing
+test_testing_peerstartup
+test_testing_peerstartup2
+test_testing_portreservation
+test_testing_servicestartup
+test_testing_sharedservices
index 9ac8c7c4778e25e6d92fc172abcb2c04e2e1d492..cfa95ec7ebd19c2f7f1d02ec355c4704f942189c 100644 (file)
@@ -1 +1,2 @@
 gnunet-daemon-topology
+test_gnunet_daemon_topology
index 69f01e0431ac9ed28a83c04b1822661b957ae58f..d48f07e719da09f813b200caa26979994c93ee3a 100644 (file)
@@ -902,7 +902,7 @@ process_peer (void *cls,
 
 
 /**
- * Function called after #GNUNET_CORE_connecT has succeeded
+ * Function called after #GNUNET_CORE_connect has succeeded
  * (or failed for good).
  *
  * @param cls closure
@@ -1101,7 +1101,7 @@ cleaning_task (void *cls)
   }
   if (NULL != handle)
   {
-    GNUNET_CORE_disconnecT (handle);
+    GNUNET_CORE_disconnect (handle);
     handle = NULL;
   }
   whitelist_peers ();
@@ -1189,7 +1189,7 @@ run (void *cls,
                                             &blacklist_check,
                                             NULL);
   ats = GNUNET_ATS_connectivity_init (cfg);
-  handle = GNUNET_CORE_connecT (cfg,
+  handle = GNUNET_CORE_connect (cfg,
                                NULL,
                                &core_init,
                                &connect_notify,
index eab8d31469f1ea8b145770c6240fbce15e76d8f5..d035b40116b0847f9fab14d2197acfc8711898e4 100644 (file)
@@ -7,3 +7,79 @@ gnunet-transport
 gnunet-transport-certificate-creation
 gnunet-transport-profiler
 gnunet-transport-wlan-receiver
+https_cert_qutoa_p2.crt
+https_key_quota_p2.key
+test_http_common
+test_plugin_bluetooth
+test_plugin_http_client
+test_plugin_http_server
+test_plugin_https_client
+test_plugin_https_server
+test_plugin_tcp
+test_plugin_udp
+test_plugin_unix
+test_plugin_wlan
+test_quota_compliance_bluetooth
+test_quota_compliance_bluetooth_asymmetric
+test_quota_compliance_http
+test_quota_compliance_http_asymmetric
+test_quota_compliance_https
+test_quota_compliance_https_asymmetric
+test_quota_compliance_tcp
+test_quota_compliance_tcp_asymmetric
+test_quota_compliance_udp
+test_quota_compliance_unix
+test_quota_compliance_unix_asymmetric
+test_quota_compliance_wlan
+test_quota_compliance_wlan_asymmetric
+test_transport_address_switch_http
+test_transport_address_switch_https
+test_transport_address_switch_tcp
+test_transport_address_switch_udp
+test_transport_api_blacklisting_tcp
+test_transport_api_bluetooth
+test_transport_api_disconnect_tcp
+test_transport_api_http
+test_transport_api_http_reverse
+test_transport_api_https
+test_transport_api_limited_sockets_tcp
+test_transport_api_manipulation_cfg
+test_transport_api_manipulation_recv_tcp
+test_transport_api_manipulation_send_tcp
+test_transport_api_monitor_peers
+test_transport_api_multi
+test_transport_api_reliability_bluetooth
+test_transport_api_reliability_http
+test_transport_api_reliability_http_xhr
+test_transport_api_reliability_https
+test_transport_api_reliability_https_xhr
+test_transport_api_reliability_tcp
+test_transport_api_reliability_tcp_nat
+test_transport_api_reliability_udp
+test_transport_api_reliability_unix
+test_transport_api_reliability_wlan
+test_transport_api_restart_1peer
+test_transport_api_restart_2peers
+test_transport_api_slow_ats
+test_transport_api_tcp
+test_transport_api_tcp_nat
+test_transport_api_timeout_bluetooth
+test_transport_api_timeout_http
+test_transport_api_timeout_https
+test_transport_api_timeout_tcp
+test_transport_api_timeout_udp
+test_transport_api_timeout_unix
+test_transport_api_timeout_wlan
+test_transport_api_udp
+test_transport_api_udp_nat
+test_transport_api_unix
+test_transport_api_unix_abstract
+test_transport_api_wlan
+test_transport_blacklisting_inbound_bl_full
+test_transport_blacklisting_inbound_bl_plugin
+test_transport_blacklisting_multiple_plugins
+test_transport_blacklisting_no_bl
+test_transport_blacklisting_outbound_bl_full
+test_transport_blacklisting_outbound_bl_plugin
+test_transport_testing_restart
+test_transport_testing_startstop
index 9fb4513839bcdc16c6bc9d5c8e7de08efbe9c3d1..0b523eecc465eb82cea96da1c005d93314b694fa 100644 (file)
@@ -235,7 +235,6 @@ gnunet_transport_profiler_SOURCES = \
  gnunet-transport-profiler.c
 gnunet_transport_profiler_LDADD = \
   libgnunettransport.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/ats/libgnunetats.la \
   $(top_builddir)/src/util/libgnunetutil.la \
@@ -245,7 +244,6 @@ gnunet_transport_SOURCES = \
  gnunet-transport.c
 gnunet_transport_LDADD = \
   libgnunettransport.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL)
@@ -268,7 +266,6 @@ gnunet_service_transport_LDADD = \
   $(top_builddir)/src/ats/libgnunetats.la \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_GLPK) \
@@ -299,7 +296,7 @@ libgnunet_plugin_transport_tcp_la_LIBADD = \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
+  $(top_builddir)/src/nat/libgnunetnatnew.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(LTLIBINTL)
 libgnunet_plugin_transport_tcp_la_LDFLAGS = \
@@ -347,7 +344,7 @@ libgnunet_plugin_transport_udp_la_LIBADD = \
   $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
+  $(top_builddir)/src/nat/libgnunetnatnew.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(LTLIBINTL)
 libgnunet_plugin_transport_udp_la_LDFLAGS = \
@@ -372,7 +369,6 @@ libgnunet_plugin_transport_http_client_la_LIBADD = \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
   $(LIB_GNURL) \
-  $(top_builddir)/src/nat/libgnunetnat.la \
   $(top_builddir)/src/util/libgnunetutil.la
 libgnunet_plugin_transport_http_client_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
@@ -388,7 +384,7 @@ libgnunet_plugin_transport_http_server_la_LIBADD = \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
+  $(top_builddir)/src/nat/libgnunetnatnew.la \
   $(top_builddir)/src/util/libgnunetutil.la
 libgnunet_plugin_transport_http_server_la_LDFLAGS = \
  $(GN_LIBMHD) \
@@ -403,7 +399,6 @@ libgnunet_plugin_transport_https_client_la_LIBADD = \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
   $(LIB_GNURL) \
-  $(top_builddir)/src/nat/libgnunetnat.la \
   $(top_builddir)/src/util/libgnunetutil.la
 libgnunet_plugin_transport_https_client_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
@@ -419,7 +414,7 @@ libgnunet_plugin_transport_https_server_la_LIBADD = \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
+  $(top_builddir)/src/nat/libgnunetnatnew.la \
   $(top_builddir)/src/util/libgnunetutil.la
 libgnunet_plugin_transport_https_server_la_LDFLAGS = \
  $(GN_LIBMHD) \
@@ -1176,7 +1171,6 @@ test_quota_compliance_wlan_asymmetric_LDADD = \
 test_quota_compliance_bluetooth_SOURCES = \
  test_quota_compliance.c
 test_quota_compliance_bluetooth_LDADD = \
- $(top_builddir)/src/nat/libgnunetnat.la \
  libgnunettransport.la \
  $(top_builddir)/src/hello/libgnunethello.la \
  $(top_builddir)/src/ats/libgnunetats.la \
index d82112e033b507f538e182f75063506dc87394fc..e1e4f56f801efe3b22247dd2172deedecc7707ae 100644 (file)
@@ -2236,6 +2236,14 @@ GST_neighbours_handle_session_syn (const struct GNUNET_MessageHeader *message,
   scm = (const struct TransportSynMessage *) message;
   GNUNET_break_op (0 == ntohl (scm->reserved));
   ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
+  if (0 ==
+      memcmp (&GST_my_identity,
+              peer,
+              sizeof (struct GNUNET_PeerIdentity)))
+  {
+    /* loopback connection-to-self, ignore */
+    return GNUNET_SYSERR;
+  }
   n = lookup_neighbour (peer);
   if (NULL == n)
   {
index e928cf6603ad4ee842d34ce23b5e56e288f31e37..fcfc94ac8e8b8c50c41f580d8753eafe5452ce40 100644 (file)
@@ -1,6 +1,6 @@
 /*
  This file is part of GNUnet.
- Copyright (C) 2011-2014, 2016 GNUnet e.V.
+ Copyright (C) 2011-2014, 2016, 2017 GNUnet e.V.
 
  GNUnet is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published
@@ -23,9 +23,6 @@
  * @brief Tool to help configure, measure and control the transport subsystem.
  * @author Christian Grothoff
  * @author Nathan Evans
- *
- * This utility can be used to test if a transport mechanism for
- * GNUnet is properly configured.
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_transport_service.h"
 #include "gnunet_transport_core_service.h"
-#include "gnunet_nat_lib.h"
-
-/**
- * How long do we wait for the NAT test to report success?
- * Should match NAT_SERVER_TIMEOUT in 'nat_test.c'.
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
 
 /**
  * Timeout for a name resolution
@@ -171,49 +161,6 @@ struct PeerResolutionContext
 };
 
 
-/**
- * Context for a plugin test.
- */
-struct TestContext
-{
-  /**
-   * Previous in DLL
-   */
-  struct TestContext *prev;
-
-  /**
-   * Next in DLL
-   */
-  struct TestContext *next;
-
-  /**
-   * Handle to the active NAT test.
-   */
-  struct GNUNET_NAT_Test *tst;
-
-  /**
-   * Task identifier for the timeout.
-   */
-  struct GNUNET_SCHEDULER_Task * tsk;
-
-  /**
-   * Name of plugin under test.
-   */
-  char *name;
-
-  /**
-   * Bound port
-   */
-  unsigned long long bnd_port;
-
-  /**
-   * Advertised ports
-   */
-  unsigned long long adv_port;
-
-};
-
-
 /**
  * Benchmarking block size in KB
  */
@@ -264,11 +211,6 @@ static int iterate_connections;
  */
 static int iterate_all;
 
-/**
- * Option -t.
- */
-static int test_configuration;
-
 /**
  * Option -c.
  */
@@ -365,16 +307,6 @@ struct GNUNET_OS_Process *resolver;
  */
 static unsigned int address_resolutions;
 
-/**
- * DLL for NAT Test Contexts: head
- */
-static struct TestContext *head;
-
-/**
- * DLL for NAT Test Contexts: tail
- */
-static struct TestContext *tail;
-
 /**
  * DLL: head of validation resolution entries
  */
@@ -553,11 +485,13 @@ operation_timeout (void *cls)
                _("Failed to resolve address for peer `%s'\n"),
                GNUNET_i2s (&cur->addrcp->peer));
 
-      GNUNET_CONTAINER_DLL_remove(rc_head, rc_tail, cur);
+      GNUNET_CONTAINER_DLL_remove(rc_head, 
+                                 rc_tail,
+                                 cur);
       GNUNET_TRANSPORT_address_to_string_cancel (cur->asc);
-      GNUNET_free(cur->transport);
-      GNUNET_free(cur->addrcp);
-      GNUNET_free(cur);
+      GNUNET_free (cur->transport);
+      GNUNET_free (cur->addrcp);
+      GNUNET_free (cur);
 
     }
     FPRINTF (stdout,
@@ -570,158 +504,6 @@ operation_timeout (void *cls)
 }
 
 
-static void
-run_nat_test (void);
-
-
-/**
- * Display the result of the test.
- *
- * @param tc test context
- * @param result #GNUNET_YES on success
- */
-static void
-display_test_result (struct TestContext *tc,
-                     enum GNUNET_NAT_StatusCode result)
-{
-  FPRINTF (stderr,
-           _("NAT plugin `%s' reports: %s\n"),
-           tc->name,
-           GNUNET_NAT_status2string (result));
-  if (NULL != tc->tsk)
-  {
-    GNUNET_SCHEDULER_cancel (tc->tsk);
-    tc->tsk = NULL;
-  }
-  if (NULL != tc->tst)
-  {
-    GNUNET_NAT_test_stop (tc->tst);
-    tc->tst = NULL;
-  }
-
-  GNUNET_CONTAINER_DLL_remove (head, tail, tc);
-  GNUNET_free (tc->name);
-  GNUNET_free (tc);
-
-  if ((NULL == head) && (NULL != resolver))
-  {
-    GNUNET_break (0 == GNUNET_OS_process_kill (resolver,
-                                               GNUNET_TERM_SIG));
-    GNUNET_OS_process_destroy (resolver);
-    resolver = NULL;
-  }
-  if (NULL != head)
-    run_nat_test ();
-}
-
-
-/**
- * Function called by NAT to report the outcome of the nat-test.
- * Clean up and update GUI.
- *
- * @param cls test context
- * @param result status code
- */
-static void
-result_callback (void *cls,
-                 enum GNUNET_NAT_StatusCode result)
-{
-  struct TestContext *tc = cls;
-
-  display_test_result (tc,
-                      result);
-}
-
-
-static void
-run_nat_test ()
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Running test for plugin `%s' using bind port %u and advertised port %u \n",
-              head->name,
-              (uint16_t) head->bnd_port,
-              (uint16_t) head->adv_port);
-
-  head->tst = GNUNET_NAT_test_start (cfg,
-                                    (0 == strcasecmp (head->name, "udp"))
-                                    ? GNUNET_NO : GNUNET_YES,
-                                    (uint16_t) head->bnd_port,
-                                    (uint16_t) head->adv_port,
-                                    TIMEOUT,
-                                    &result_callback, head);
-}
-
-
-/**
- * Test our plugin's configuration (NAT traversal, etc.).
- *
- * @param cfg configuration to test
- */
-static void
-do_test_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  char *plugins;
-  char *tok;
-  unsigned long long bnd_port;
-  unsigned long long adv_port;
-  struct TestContext *tc;
-  char *binary;
-
-  if (GNUNET_OK
-      != GNUNET_CONFIGURATION_get_value_string (cfg, "transport", "plugins",
-          &plugins))
-  {
-    FPRINTF (stderr, "%s", _
-    ("No transport plugins configured, peer will never communicate\n"));
-    ret = 4;
-    return;
-  }
-
-  for (tok = strtok (plugins, " "); tok != NULL ; tok = strtok (NULL, " "))
-  {
-    char section[12 + strlen (tok)];
-    GNUNET_snprintf (section, sizeof(section), "transport-%s", tok);
-    if (GNUNET_OK
-        != GNUNET_CONFIGURATION_get_value_number (cfg, section, "PORT",
-            &bnd_port))
-    {
-      FPRINTF (stderr,
-          _("No port configured for plugin `%s', cannot test it\n"), tok);
-      continue;
-    }
-    if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, section,
-            "ADVERTISED_PORT", &adv_port))
-      adv_port = bnd_port;
-
-    tc = GNUNET_new (struct TestContext);
-    tc->name = GNUNET_strdup (tok);
-    tc->adv_port = adv_port;
-    tc->bnd_port = bnd_port;
-    GNUNET_CONTAINER_DLL_insert_tail (head, tail, tc);
-  }
-  GNUNET_free(plugins);
-
-  if ((NULL != head) && (NULL == resolver))
-  {
-    binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
-    resolver = GNUNET_OS_start_process (GNUNET_YES,
-                                        GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                        NULL, NULL, NULL,
-                                        binary,
-                                        "gnunet-service-resolver", NULL);
-    if (NULL == resolver)
-    {
-      FPRINTF (stderr, _("Failed to start resolver!\n"));
-      return;
-    }
-
-    GNUNET_free(binary);
-    GNUNET_RESOLVER_connect (cfg);
-    run_nat_test ();
-  }
-}
-
-
 /**
  * Function called to notify a client about the socket
  * begin ready to queue more data.  Sends another message.
@@ -1041,7 +823,9 @@ process_peer_string (void *cls,
   }
   GNUNET_free (rc->transport);
   GNUNET_free (rc->addrcp);
-  GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, rc);
+  GNUNET_CONTAINER_DLL_remove (rc_head,
+                              rc_tail,
+                              rc);
   GNUNET_free (rc);
   if ((0 == address_resolutions) && (iterate_connections))
   {
@@ -1461,11 +1245,6 @@ run (void *cls,
   ret = 1;
 
   cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg;
-  if (test_configuration)
-  {
-    do_test_configuration (cfg);
-    return;
-  }
   if ( (NULL != cpid) &&
        (GNUNET_OK !=
         GNUNET_CRYPTO_eddsa_public_key_from_string (cpid,
@@ -1691,9 +1470,6 @@ main (int argc,
     { 's', "send", NULL, gettext_noop
       ("send data for benchmarking to the other peer (until CTRL-C)"), 0,
       &GNUNET_GETOPT_set_one, &benchmark_send },
-    { 't', "test", NULL,
-      gettext_noop ("test transport configuration (involves external server)"),
-      0, &GNUNET_GETOPT_set_one, &test_configuration },
     GNUNET_GETOPT_OPTION_VERBOSE (&verbosity),
     GNUNET_GETOPT_OPTION_END
   };
@@ -1706,7 +1482,7 @@ main (int argc,
                             gettext_noop ("Direct access to transport service."),
                             options,
                             &run, NULL);
-  GNUNET_free((void *) argv);
+  GNUNET_free ((void *) argv);
   if (GNUNET_OK == res)
     return ret;
   return 1;
index 5088f2e774e83fee43cc43bba1305f2c5279fce8..63c67b81c50b673f5041472ac28a7a7e4a09946e 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2002-2014 GNUnet e.V.
+     Copyright (C) 2002-2014, 2017 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -29,7 +29,7 @@
 #include "gnunet_util_lib.h"
 #include "gnunet_statistics_service.h"
 #include "gnunet_transport_plugin.h"
-#include "gnunet_nat_lib.h"
+#include "gnunet_nat_service.h"
 #include "plugin_transport_http_common.h"
 #include <microhttpd.h>
 #include <regex.h>
@@ -2473,12 +2473,14 @@ server_remove_address (void *cls,
  * @param cls closure, the 'struct LocalAddrList'
  * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
  *     the previous (now invalid) one
+ * @param ac address class the address belongs to
  * @param addr either the previous or the new public IP address
  * @param addrlen actual lenght of the address
  */
 static void
 server_nat_port_map_callback (void *cls,
                               int add_remove,
+                             enum GNUNET_NAT_AddressClass ac,
                               const struct sockaddr *addr,
                               socklen_t addrlen)
 {
@@ -2498,7 +2500,8 @@ server_nat_port_map_callback (void *cls,
 
     if ((NULL != plugin->server_addr_v4) &&
         (0 != memcmp (&plugin->server_addr_v4->sin_addr,
-                      &s4->sin_addr, sizeof (struct in_addr))))
+                      &s4->sin_addr,
+                     sizeof (struct in_addr))))
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG,
            "Skipping address `%s' (not bindto address)\n",
@@ -2754,14 +2757,16 @@ server_start_report_addresses (struct HTTP_Server_Plugin *plugin)
     return;
   }
 
-  plugin->nat =
-      GNUNET_NAT_register (plugin->env->cfg,
-                           GNUNET_YES,
-                           plugin->port,
+  plugin->nat 
+    = GNUNET_NAT_register (plugin->env->cfg,
+                          "transport-http_server",
+                          IPPROTO_TCP,
                            (unsigned int) res,
-                           (const struct sockaddr **) addrs, addrlens,
-                           &server_nat_port_map_callback, NULL,
-                          plugin, NULL);
+                           (const struct sockaddr **) addrs,
+                          addrlens,
+                           &server_nat_port_map_callback,
+                          NULL,
+                          plugin);
   while (res > 0)
   {
     res--;
index 79c70138f7d15cec8a0f1d360c14189899a9bb98..eca62a8cad704907ba486fc25d2d751e44604a03 100644 (file)
@@ -26,7 +26,7 @@
 #include "gnunet_hello_lib.h"
 #include "gnunet_constants.h"
 #include "gnunet_util_lib.h"
-#include "gnunet_nat_lib.h"
+#include "gnunet_nat_service.h"
 #include "gnunet_protocols.h"
 #include "gnunet_resolver_service.h"
 #include "gnunet_signatures.h"
@@ -945,13 +945,15 @@ notify_session_monitor (struct Plugin *plugin,
  * @param cls closure, the `struct Plugin`
  * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
  *     the previous (now invalid) one
+ * @param ac address class the address belongs to
  * @param addr either the previous or the new public IP address
  * @param addrlen actual length of @a addr
  */
 static void
 tcp_nat_port_map_callback (void *cls,
                            int add_remove,
-                           const struct sockaddr *addr,
+                          enum GNUNET_NAT_AddressClass ac,
+                          const struct sockaddr *addr,
                            socklen_t addrlen)
 {
   struct Plugin *plugin = cls;
@@ -961,10 +963,10 @@ tcp_nat_port_map_callback (void *cls,
   void *arg;
   size_t args;
 
-  LOG(GNUNET_ERROR_TYPE_INFO,
-      "NAT notification to %s address `%s'\n",
-      (GNUNET_YES == add_remove) ? "add" : "remove",
-      GNUNET_a2s (addr, addrlen));
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "NAT notification to %s address `%s'\n",
+       (GNUNET_YES == add_remove) ? "add" : "remove",
+       GNUNET_a2s (addr, addrlen));
   /* convert 'addr' to our internal format */
   switch (addr->sa_family)
   {
@@ -980,8 +982,9 @@ tcp_nat_port_map_callback (void *cls,
   case AF_INET6:
     GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
     memset (&t6, 0, sizeof(t6));
-    GNUNET_memcpy (&t6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
-        sizeof(struct in6_addr));
+    GNUNET_memcpy (&t6.ipv6_addr,
+                  &((struct sockaddr_in6 *) addr)->sin6_addr,
+                  sizeof(struct in6_addr));
     t6.options = htonl (plugin->myoptions);
     t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
     arg = &t6;
@@ -993,11 +996,17 @@ tcp_nat_port_map_callback (void *cls,
   }
   /* modify our published address list */
   GNUNET_assert ((args == sizeof (struct IPv4TcpAddress)) ||
-      (args == sizeof (struct IPv6TcpAddress)));
+                (args == sizeof (struct IPv6TcpAddress)));
+  /* TODO: use 'ac' here in the future... */
   address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
-      PLUGIN_NAME, arg, args, GNUNET_HELLO_ADDRESS_INFO_NONE);
-  plugin->env->notify_address (plugin->env->cls, add_remove, address);
-  GNUNET_HELLO_address_free(address);
+                                          PLUGIN_NAME,
+                                          arg,
+                                          args,
+                                          GNUNET_HELLO_ADDRESS_INFO_NONE);
+  plugin->env->notify_address (plugin->env->cls,
+                              add_remove,
+                              address);
+  GNUNET_HELLO_address_free (address);
 }
 
 
@@ -2068,6 +2077,8 @@ tcp_plugin_get_session (void *cls,
         GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
                                                 &address->peer)))
   {
+    struct sockaddr_in local_sa;
+    
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Found valid IPv4 NAT address (creating session)!\n");
     session = create_session (plugin,
@@ -2085,23 +2096,29 @@ tcp_plugin_get_session (void *cls,
                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Created NAT WAIT connection to `%4s' at `%s'\n",
+         "Created NAT WAIT connection to `%s' at `%s'\n",
          GNUNET_i2s (&session->target),
          GNUNET_a2s (sb, sbs));
-    if (GNUNET_OK == GNUNET_NAT_run_client (plugin->nat, &a4))
-    {
+    memset (&local_sa,
+           0,
+           sizeof (local_sa));
+    local_sa.sin_family = AF_INET;
+    local_sa.sin_port = htons (plugin->open_port);
+    /* We leave sin_address at 0, let the kernel figure it out,
+       even if our bind() is more specific.  (May want to reconsider
+       later.) */
+    if (GNUNET_OK ==
+       GNUNET_NAT_request_reversal (plugin->nat,
+                                    &local_sa,
+                                    &a4))
       return session;
-    }
-    else
-    {
-      LOG(GNUNET_ERROR_TYPE_DEBUG,
-          "Running NAT client for `%4s' at `%s' failed\n",
-          GNUNET_i2s (&session->target),
-          GNUNET_a2s (sb, sbs));
-      tcp_plugin_disconnect_session (plugin,
-                                     session);
-      return NULL;
-    }
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "Running NAT client for `%s' at `%s' failed\n",
+        GNUNET_i2s (&session->target),
+        GNUNET_a2s (sb, sbs));
+    tcp_plugin_disconnect_session (plugin,
+                                  session);
+    return NULL;
   }
 
   /* create new outbound session */
@@ -2395,27 +2412,6 @@ tcp_plugin_address_pretty_printer (void *cls,
 }
 
 
-/**
- * Check if the given port is plausible (must be either our listen
- * port or our advertised port), or any port if we are behind NAT
- * and do not have a port open.  If it is neither, we return
- * #GNUNET_SYSERR.
- *
- * @param plugin global variables
- * @param in_port port number to check
- * @return #GNUNET_OK if port is either open_port or adv_port
- */
-static int
-check_port (struct Plugin *plugin,
-           uint16_t in_port)
-{
-  if ( (in_port == plugin->adv_port) ||
-       (in_port == plugin->open_port) )
-    return GNUNET_OK;
-  return GNUNET_SYSERR;
-}
-
-
 /**
  * Function that will be called to check if a binary address for this
  * plugin is well-formed and corresponds to an address for THIS peer
@@ -2449,6 +2445,8 @@ tcp_plugin_check_address (void *cls,
 
   if (addrlen == sizeof(struct IPv4TcpAddress))
   {
+    struct sockaddr_in s4;
+    
     v4 = (const struct IPv4TcpAddress *) addr;
     if (0 != memcmp (&v4->options,
                      &plugin->myoptions,
@@ -2457,17 +2455,24 @@ tcp_plugin_check_address (void *cls,
       GNUNET_break (0);
       return GNUNET_SYSERR;
     }
-    if (GNUNET_OK != check_port (plugin,
-                                ntohs (v4->t4_port)))
-      return GNUNET_SYSERR;
+    memset (&s4, 0, sizeof (s4));
+    s4.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    s4.sin_len = sizeof (s4);
+#endif
+    s4.sin_port = v4->t4_port;
+    s4.sin_addr.s_addr = v4->ipv4_addr;
+    
     if (GNUNET_OK !=
        GNUNET_NAT_test_address (plugin->nat,
-                                &v4->ipv4_addr,
-                                sizeof (struct in_addr)))
+                                &s4,
+                                sizeof (struct sockaddr_in)))
       return GNUNET_SYSERR;
   }
   else
   {
+    struct sockaddr_in6 s6;
+    
     v6 = (const struct IPv6TcpAddress *) addr;
     if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
     {
@@ -2481,13 +2486,18 @@ tcp_plugin_check_address (void *cls,
       GNUNET_break (0);
       return GNUNET_SYSERR;
     }
-    if (GNUNET_OK != check_port (plugin,
-                                ntohs (v6->t6_port)))
-      return GNUNET_SYSERR;
+    memset (&s6, 0, sizeof (s6));
+    s6.sin6_family = AF_INET6;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    s6.sin6_len = sizeof (s6);
+#endif
+    s6.sin6_port = v6->t6_port;
+    s6.sin6_addr = v6->ipv6_addr;
+
     if (GNUNET_OK !=
        GNUNET_NAT_test_address (plugin->nat,
-                                &v6->ipv6_addr,
-                                sizeof(struct in6_addr)))
+                                &s6,
+                                sizeof(struct sockaddr_in6)))
       return GNUNET_SYSERR;
   }
   return GNUNET_OK;
@@ -3388,15 +3398,14 @@ libgnunet_plugin_transport_tcp_init (void *cls)
            GNUNET_a2s (addrs[ret], addrlens[ret]));
     plugin->nat
       = GNUNET_NAT_register (env->cfg,
-                             GNUNET_YES,
-                             aport,
+                            "transport-tcp",
+                            IPPROTO_TCP,
                              (unsigned int) ret_s,
                              (const struct sockaddr **) addrs,
                             addrlens,
                              &tcp_nat_port_map_callback,
                              &try_connection_reversal,
-                             plugin,
-                            NULL);
+                             plugin);
     for (ret = ret_s -1; ret >= 0; ret--)
       GNUNET_free (addrs[ret]);
     GNUNET_free_non_null (addrs);
@@ -3405,15 +3414,14 @@ libgnunet_plugin_transport_tcp_init (void *cls)
   else
   {
     plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
-                                       GNUNET_YES,
-                                       0,
+                                       "transport-tcp",
+                                      IPPROTO_TCP,
                                        0,
                                        NULL,
                                        NULL,
                                        NULL,
                                        &try_connection_reversal,
-                                       plugin,
-                                       NULL);
+                                       plugin);
   }
   api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
   api->cls = plugin;
index 35ae92460e7cf6ae8594608b94bcdb6b9aaea8d1..fd8493e5f5b7b1dedd34ff94f31571462852ef99 100644 (file)
@@ -1,6 +1,6 @@
 /*
  This file is part of GNUnet
- Copyright (C) 2010-2015 GNUnet e.V.
+ Copyright (C) 2010-2017 GNUnet e.V.
 
  GNUnet is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published
@@ -30,7 +30,7 @@
 #include "gnunet_hello_lib.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_fragmentation_lib.h"
-#include "gnunet_nat_lib.h"
+#include "gnunet_nat_service.h"
 #include "gnunet_protocols.h"
 #include "gnunet_resolver_service.h"
 #include "gnunet_signatures.h"
@@ -1245,31 +1245,48 @@ udp_plugin_check_address (void *cls,
 
   if (sizeof(struct IPv4UdpAddress) == addrlen)
   {
+    struct sockaddr_in s4;
+
     v4 = (const struct IPv4UdpAddress *) addr;
     if (GNUNET_OK != check_port (plugin,
                                  ntohs (v4->u4_port)))
       return GNUNET_SYSERR;
+    memset (&s4, 0, sizeof (s4));
+    s4.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    s4.sin_len = sizeof (s4);
+#endif
+    s4.sin_port = v4->u4_port;
+    s4.sin_addr.s_addr = v4->ipv4_addr;
+
     if (GNUNET_OK !=
-        GNUNET_NAT_test_address (plugin->nat,
-                                 &v4->ipv4_addr,
-                                 sizeof (struct in_addr)))
+       GNUNET_NAT_test_address (plugin->nat,
+                                &s4,
+                                sizeof (struct sockaddr_in)))
       return GNUNET_SYSERR;
   }
   else if (sizeof(struct IPv6UdpAddress) == addrlen)
   {
+    struct sockaddr_in6 s6;
+
     v6 = (const struct IPv6UdpAddress *) addr;
     if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
     {
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-    if (GNUNET_OK != check_port (plugin,
-                                 ntohs (v6->u6_port)))
-      return GNUNET_SYSERR;
+    memset (&s6, 0, sizeof (s6));
+    s6.sin6_family = AF_INET6;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    s6.sin6_len = sizeof (s6);
+#endif
+    s6.sin6_port = v6->u6_port;
+    s6.sin6_addr = v6->ipv6_addr;
+
     if (GNUNET_OK !=
-        GNUNET_NAT_test_address (plugin->nat,
-                                 &v6->ipv6_addr,
-                                 sizeof (struct in6_addr)))
+       GNUNET_NAT_test_address (plugin->nat,
+                                &s6,
+                                sizeof(struct sockaddr_in6)))
       return GNUNET_SYSERR;
   }
   else
@@ -1287,12 +1304,14 @@ udp_plugin_check_address (void *cls,
  * @param cls closure, the `struct Plugin`
  * @param add_remove #GNUNET_YES to mean the new public IP address,
  *                   #GNUNET_NO to mean the previous (now invalid) one
+ * @param ac address class the address belongs to
  * @param addr either the previous or the new public IP address
  * @param addrlen actual length of the @a addr
  */
 static void
 udp_nat_port_map_callback (void *cls,
                            int add_remove,
+                          enum GNUNET_NAT_AddressClass ac,
                            const struct sockaddr *addr,
                            socklen_t addrlen)
 {
@@ -1359,6 +1378,7 @@ udp_nat_port_map_callback (void *cls,
     return;
   }
   /* modify our published address list */
+  /* TODO: use 'ac' here in the future... */
   address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
                                            PLUGIN_NAME,
                                            arg,
@@ -3032,8 +3052,7 @@ read_process_fragment (struct Plugin *plugin,
                                           msg))
   {
     /* keep this 'rc' from expiring */
-    GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs,
-                                       d_ctx->hnode,
+    GNUNET_CONTAINER_heap_update_cost (d_ctx->hnode,
                                        (GNUNET_CONTAINER_HeapCostType) now.abs_value_us);
   }
   if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) >
@@ -3082,7 +3101,7 @@ udp_select_read (struct Plugin *plugin,
           sizeof(addr));
   size = GNUNET_NETWORK_socket_recvfrom (rsock,
                                          buf,
-                                         sizeof(buf),
+                                         sizeof (buf),
                                          (struct sockaddr *) &addr,
                                          &fromlen);
   sa = (const struct sockaddr *) &addr;
@@ -3111,9 +3130,12 @@ udp_select_read (struct Plugin *plugin,
   }
 
   /* Check if this is a STUN packet */
-  if (GNUNET_NAT_is_valid_stun_packet (plugin->nat,
-                                       (uint8_t *)buf,
-                                       size))
+  if (GNUNET_NO !=
+      GNUNET_NAT_stun_handle_packet (plugin->nat,
+                                    (const struct sockaddr *) &addr,
+                                    fromlen,
+                                    buf,
+                                    size))
     return; /* was STUN, do not process further */
 
   if (size < sizeof(struct GNUNET_MessageHeader))
@@ -3516,7 +3538,7 @@ udp_plugin_select_v4 (void *cls)
 {
   struct Plugin *plugin = cls;
   const struct GNUNET_SCHEDULER_TaskContext *tc;
-  
+
   plugin->select_task_v4 = NULL;
   if (NULL == plugin->sockv4)
     return;
@@ -3572,13 +3594,13 @@ udp_plugin_select_v6 (void *cls)
  * @param bind_v4 IPv4 address to bind to (can be NULL, for 'any')
  * @return number of sockets that were successfully bound
  */
-static int
+static unsigned int
 setup_sockets (struct Plugin *plugin,
                const struct sockaddr_in6 *bind_v6,
                const struct sockaddr_in *bind_v4)
 {
   int tries;
-  int sockets_created = 0;
+  unsigned int sockets_created = 0;
   struct sockaddr_in6 server_addrv6;
   struct sockaddr_in server_addrv4;
   const struct sockaddr *server_addr;
@@ -3788,15 +3810,14 @@ setup_sockets (struct Plugin *plugin,
   schedule_select_v4 (plugin);
   schedule_select_v6 (plugin);
   plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
-                                     GNUNET_NO,
-                                     plugin->port,
+                                    "transport-udp",
+                                    IPPROTO_UDP,
                                      sockets_created,
                                      addrs,
                                      addrlens,
                                      &udp_nat_port_map_callback,
                                      NULL,
-                                     plugin,
-                                     plugin->sockv4);
+                                     plugin);
   return sockets_created;
 }
 
@@ -3825,7 +3846,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
   struct GNUNET_TIME_Relative interval;
   struct sockaddr_in server_addrv4;
   struct sockaddr_in6 server_addrv6;
-  int res;
+  unsigned int res;
   int have_bind4;
   int have_bind6;
 
index c6799ba74f4615795d0e0fbc842e18446eff2a4e..152b16099c22914f05c261ecc2b5703fb2159777 100644 (file)
@@ -32,7 +32,6 @@
 #include "gnunet_hello_lib.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_fragmentation_lib.h"
-#include "gnunet_nat_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_resolver_service.h"
 #include "gnunet_signatures.h"
index 8ef001ddba1058be275f6320bc3fc42f3fb88439..a440830fd9450252a2749bad235779b701bc1981 100644 (file)
@@ -29,7 +29,6 @@
 #include "gnunet_hello_lib.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_fragmentation_lib.h"
-#include "gnunet_nat_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_resolver_service.h"
 #include "gnunet_signatures.h"
index 95e3f99446bebf025a84f7eed8e4927926e1f2d1..7b5413bbe6cf5f3f44bfe98d467ed5b0fadaeee5 100644 (file)
@@ -38,7 +38,17 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM;
 [transport-tcp]
 # Use 0 to ONLY advertise as a peer behind NAT (no port binding)
 PORT = 2086
+
+# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
 ADVERTISED_PORT = 2086
+
+# If we have a manually punched NAT, what is the external IP and port?
+# Can use DNS names for DynDNS-based detection of external IP.
+# Can use IPv6 addresses ([fefc::]:PORT).
+# Use "AUTO" for the hostname to automatically detect external IP.
+# Do not set if NAT is not manually punched.
+# HOLE_EXTERNAL = AUTO:2086
+
 TESTING_IGNORE_KEYS = ACCEPT_FROM;
 
 # Maximum number of open TCP connections allowed
@@ -55,6 +65,9 @@ MAX_CONNECTIONS = 128
 # Enable TCP stealth?
 TCP_STEALTH = NO
 
+# Configuration for manually punched holes in NAT.
+# HOLE_EXTERNAL = auto:2086
+
 [transport-udp]
 # Use PORT = 0 to autodetect a port available
 PORT = 2086
@@ -69,6 +82,14 @@ BROADCAST_INTERVAL = 30 s
 MAX_BPS = 1000000
 TESTING_IGNORE_KEYS = ACCEPT_FROM;
 
+# If we have a manually punched NAT, what is the external IP and port?
+# Can use DNS names for DynDNS-based detection of external IP.
+# Can use IPv6 addresses ([fefc::]:PORT).
+# Use "AUTO" for the hostname to automatically detect external IP.
+# Do not set if NAT is not manually punched.
+# HOLE_EXTERNAL = AUTO:2086
+
+
 [transport-http_client]
 MAX_CONNECTIONS = 128
 TESTING_IGNORE_KEYS = ACCEPT_FROM;
@@ -92,13 +113,27 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM;
 [transport-http_server]
 #EXTERNAL_HOSTNAME = <your hostname/path>
 PORT = 1080
+
+# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
 ADVERTISED_PORT = 1080
+
+# If we have a manually punched NAT, what is the external IP and port?
+# Can use DNS names for DynDNS-based detection of external IP.
+# Can use IPv6 addresses ([fefc::]:PORT).
+# Use "AUTO" for the hostname to automatically detect external IP.
+# Do not set if NAT is not manually punched.
+# HOLE_EXTERNAL = AUTO:2086
+
+
 MAX_CONNECTIONS = 128
 TESTING_IGNORE_KEYS = ACCEPT_FROM;
 
 # Enable TCP stealth?
 TCP_STEALTH = NO
 
+# Configuration for manually punched holes in NAT.
+# HOLE_EXTERNAL = auto:2086
+
 [transport-https_client]
 MAX_CONNECTIONS = 128
 TESTING_IGNORE_KEYS = ACCEPT_FROM;
@@ -130,7 +165,17 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM;
 # Does the external hostname use the same port?
 # EXTERNAL_HOSTNAME_USE_PORT = YES
 PORT = 4433
+
+# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
 ADVERTISED_PORT = 4433
+
+# If we have a manually punched NAT, what is the external IP and port?
+# Can use DNS names for DynDNS-based detection of external IP.
+# Can use IPv6 addresses ([fefc::]:PORT).
+# Use "AUTO" for the hostname to automatically detect external IP.
+# Do not set if NAT is not manually punched.
+# HOLE_EXTERNAL = AUTO:2086
+
 CRYPTO_INIT = NORMAL
 KEY_FILE = $GNUNET_DATA_HOME/transport/https.key
 CERT_FILE = $GNUNET_DATA_HOME/transport/https.cert
@@ -140,6 +185,10 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM;
 # Enable TCP stealth?
 TCP_STEALTH = NO
 
+# Configuration for manually punched holes in NAT.
+# HOLE_EXTERNAL = auto:2086
+
+
 [transport-wlan]
 # Name of the interface in monitor mode (typically monX)
 INTERFACE = mon0
index fd30230f751a3dda44e30f5d4d97e96736415091..b9c72dcb3d67229d85da236994c35c30e8c2c856 100644 (file)
@@ -210,7 +210,7 @@ GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle *cf
   }
   alc->cb = aluc;
   alc->cb_cls = aluc_cls;
-  alc->mq = GNUNET_CLIENT_connecT (cfg,
+  alc->mq = GNUNET_CLIENT_connect (cfg,
                                    "transport",
                                    handlers,
                                    &mq_error_handler,
index 4b758f9dc6cb08282cac1dfc8f0e1eac9d1dd9ac..7b1bf526e1931b646911cdc229dbd716b9235f89 100644 (file)
@@ -132,7 +132,7 @@ reconnect (struct GNUNET_TRANSPORT_Blacklist *br)
 
   if (NULL != br->mq)
     GNUNET_MQ_destroy (br->mq);
-  br->mq = GNUNET_CLIENT_connecT (br->cfg,
+  br->mq = GNUNET_CLIENT_connect (br->cfg,
                                   "transport",
                                   handlers,
                                   &mq_error_handler,
index de18a140cd7e19fcde3e3c1567d947c30beb2064..a693cb889ec08b2588d2b0deedd588a7ee82ad56 100644 (file)
@@ -805,7 +805,7 @@ reconnect (void *cls)
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Connecting to transport service.\n");
   GNUNET_assert (NULL == h->mq);
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "transport",
                                  handlers,
                                  &mq_error_handler,
index 9c3a3e7867f04846128232d66547ed828075f729..c53dd7a9a454233b0039c2bdf16ded2389602212 100644 (file)
@@ -182,7 +182,7 @@ reconnect (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Connecting to transport service.\n");
   GNUNET_assert (NULL == ghh->mq);
-  ghh->mq = GNUNET_CLIENT_connecT (ghh->cfg,
+  ghh->mq = GNUNET_CLIENT_connect (ghh->cfg,
                                    "transport",
                                    handlers,
                                    &mq_error_handler,
index 6325354cbe967bd2629e8208a2493eb2f51f9fb9..fd5849a7eed7a85394cf8c1b497bd1a67fac529f 100644 (file)
@@ -121,7 +121,7 @@ reconnect (void *cls)
        "Connecting to transport service.\n");
   GNUNET_assert (NULL == h->mq);
   h->reconnecting = GNUNET_NO;
-  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+  h->mq = GNUNET_CLIENT_connect (h->cfg,
                                  "transport",
                                  handlers,
                                  &mq_error_handler,
index 345f2ad6078c0b43404349674c61e1e0ea8e9449..38e6e0d7c20019828ff4beb159778463cbc5e2a1 100644 (file)
@@ -360,7 +360,7 @@ do_peer_connect (void *cls)
   struct GNUNET_MQ_Envelope *env;
 
   pal_ctx->reconnect_task = NULL;
-  pal_ctx->mq = GNUNET_CLIENT_connecT (pal_ctx->cfg,
+  pal_ctx->mq = GNUNET_CLIENT_connect (pal_ctx->cfg,
                                        "transport",
                                        handlers,
                                        &mq_error_handler,
index 7547a3402351fa425bb78f10b3977afed7ac36af..e81664c41f9b4235a8806235f732e1310c4b7112 100644 (file)
@@ -388,7 +388,7 @@ do_plugin_connect (void *cls)
   struct GNUNET_MQ_Envelope *env;
 
   pm->reconnect_task = NULL;
-  pm->mq = GNUNET_CLIENT_connecT (pm->cfg,
+  pm->mq = GNUNET_CLIENT_connect (pm->cfg,
                                   "transport",
                                   handlers,
                                   &mq_error_handler,
index 951ab9ba41ade8cca8b5096141fc6624fd4733f9..e1dca14e35fc47cc7d2cf26fc55034a142cefe63 100644 (file)
@@ -104,7 +104,7 @@ GNUNET_TRANSPORT_offer_hello (const struct GNUNET_CONFIGURATION_Handle *cfg,
     GNUNET_free (ohh);
     return NULL;
   }
-  ohh->mq = GNUNET_CLIENT_connecT (cfg,
+  ohh->mq = GNUNET_CLIENT_connect (cfg,
                                    "transport",
                                    NULL,
                                    NULL,
diff --git a/src/tun/.gitignore b/src/tun/.gitignore
new file mode 100644 (file)
index 0000000..b266855
--- /dev/null
@@ -0,0 +1,2 @@
+test_regex
+test_tun
index cbb349827f11062d0b660934601ecb6579efcb08..87b3797461a64a88486f39524c7c2ed61c2b03d2 100644 (file)
@@ -7,3 +7,58 @@ gnunet-resolver
 gnunet-scrypt
 gnunet-service-resolver
 gnunet-uri
+test_bio
+test_client.nc
+test_client_unix.nc
+test_common_allocation
+test_common_endian
+test_common_logging
+test_common_logging_runtime_loglevels
+test_configuration
+test_connection.nc
+test_connection_addressing.nc
+test_connection_receive_cancel.nc
+test_connection_timeout.nc
+test_connection_timeout_no_connect.nc
+test_connection_transmit_cancel.nc
+test_container_bloomfilter
+test_container_heap
+test_container_meta_data
+test_container_multihashmap
+test_container_multihashmap32
+test_container_multipeermap
+test_crypto_crc
+test_crypto_ecc_dlog
+test_crypto_ecdh_eddsa
+test_crypto_ecdhe
+test_crypto_ecdsa
+test_crypto_eddsa
+test_crypto_hash
+test_crypto_hash_context
+test_crypto_hkdf
+test_crypto_kdf
+test_crypto_paillier
+test_crypto_random
+test_crypto_rsa
+test_crypto_symmetric
+test_disk
+test_getopt
+test_mq
+test_os_network
+test_os_start_process
+test_peer
+test_plugin
+test_program
+test_resolver_api.nc
+test_scheduler
+test_scheduler_delay
+test_server.nc
+test_server_disconnect.nc
+test_server_mst_interrupt.nc
+test_server_with_client.nc
+test_server_with_client_unix
+test_service
+test_speedup
+test_strings
+test_strings_to_data
+test_time
index 65818640ced6bfdbce480fb1431911cf8e0115b1..f49aee17fa8a6cdc2d3d5e30b0c825ac627f8dfb 100644 (file)
@@ -59,7 +59,7 @@ test_common_logging_dummy_LDADD = \
 libgnunetutil_la_SOURCES = \
   bandwidth.c \
   bio.c \
-  client_new.c \
+  client.c \
   common_allocation.c \
   common_endian.c \
   common_logging.c \
@@ -70,6 +70,7 @@ libgnunetutil_la_SOURCES = \
   container_heap.c \
   container_meta_data.c \
   container_multihashmap.c \
+  container_multishortmap.c \
   container_multipeermap.c \
   container_multihashmap32.c \
   crypto_symmetric.c \
diff --git a/src/util/client.c b/src/util/client.c
new file mode 100644 (file)
index 0000000..4fd9710
--- /dev/null
@@ -0,0 +1,880 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2001-2016 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file util/client.c
+ * @brief code for access to services
+ * @author Christian Grothoff
+ *
+ * Generic TCP code for reliable, record-oriented TCP
+ * connections between clients and service providers.
+ */
+#include "platform.h"
+#include "gnunet_protocols.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_resolver_service.h"
+#include "gnunet_socks.h"
+
+
+#define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
+
+
+/**
+ * Internal state for a client connected to a GNUnet service.
+ */
+struct ClientState;
+
+
+/**
+ * During connect, we try multiple possible IP addresses
+ * to find out which one might work.
+ */
+struct AddressProbe
+{
+
+  /**
+   * This is a linked list.
+   */
+  struct AddressProbe *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct AddressProbe *prev;
+
+  /**
+   * The address; do not free (allocated at the end of this struct).
+   */
+  const struct sockaddr *addr;
+
+  /**
+   * Underlying OS's socket.
+   */
+  struct GNUNET_NETWORK_Handle *sock;
+
+  /**
+   * Connection for which we are probing.
+   */
+  struct ClientState *cstate;
+
+  /**
+   * Lenth of addr.
+   */
+  socklen_t addrlen;
+
+  /**
+   * Task waiting for the connection to finish connecting.
+   */
+  struct GNUNET_SCHEDULER_Task *task;
+};
+
+
+/**
+ * Internal state for a client connected to a GNUnet service.
+ */
+struct ClientState
+{
+
+  /**
+   * The connection handle, NULL if not live
+   */
+  struct GNUNET_NETWORK_Handle *sock;
+
+  /**
+   * Handle to a pending DNS lookup request, NULL if DNS is finished.
+   */
+  struct GNUNET_RESOLVER_RequestHandle *dns_active;
+
+  /**
+   * Our configuration.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Linked list of sockets we are currently trying out
+   * (during connect).
+   */
+  struct AddressProbe *ap_head;
+
+  /**
+   * Linked list of sockets we are currently trying out
+   * (during connect).
+   */
+  struct AddressProbe *ap_tail;
+
+  /**
+   * Name of the service we interact with.
+   */
+  char *service_name;
+
+  /**
+   * Hostname, if any.
+   */
+  char *hostname;
+
+  /**
+   * Next message to transmit to the service. NULL for none.
+   */
+  const struct GNUNET_MessageHeader *msg;
+
+  /**
+   * Task for trying to connect to the service.
+   */
+  struct GNUNET_SCHEDULER_Task *retry_task;
+
+  /**
+   * Task for sending messages to the service.
+   */
+  struct GNUNET_SCHEDULER_Task *send_task;
+
+  /**
+   * Task for sending messages to the service.
+   */
+  struct GNUNET_SCHEDULER_Task *recv_task;
+
+  /**
+   * Tokenizer for inbound messages.
+   */
+  struct GNUNET_MessageStreamTokenizer *mst;
+
+  /**
+   * Message queue under our control.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Timeout for receiving a response (absolute time).
+   */
+  struct GNUNET_TIME_Absolute receive_timeout;
+
+  /**
+   * Current value for our incremental back-off (for
+   * connect re-tries).
+   */
+  struct GNUNET_TIME_Relative back_off;
+
+  /**
+   * TCP port (0 for disabled).
+   */
+  unsigned long long port;
+
+  /**
+   * Offset in the message where we are for transmission.
+   */
+  size_t msg_off;
+
+  /**
+   * How often have we tried to connect?
+   */
+  unsigned int attempts;
+
+  /**
+   * Are we supposed to die?  #GNUNET_SYSERR if destruction must be
+   * deferred, #GNUNET_NO by default, #GNUNET_YES if destruction was
+   * deferred.
+   */
+  int in_destroy;
+
+};
+
+
+/**
+ * Try to connect to the service.
+ *
+ * @param cls the `struct ClientState` to try to connect to the service
+ */
+static void
+start_connect (void *cls);
+
+
+/**
+ * We've failed for good to establish a connection (timeout or
+ * no more addresses to try).
+ *
+ * @param cstate the connection we tried to establish
+ */
+static void
+connect_fail_continuation (struct ClientState *cstate)
+{
+  GNUNET_break (NULL == cstate->ap_head);
+  GNUNET_break (NULL == cstate->ap_tail);
+  GNUNET_break (NULL == cstate->dns_active);
+  GNUNET_break (NULL == cstate->sock);
+  GNUNET_assert (NULL == cstate->send_task);
+  GNUNET_assert (NULL == cstate->recv_task);
+  // GNUNET_assert (NULL == cstate->proxy_handshake);
+
+  cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Failed to establish connection to `%s', no further addresses to try, will try again in %s.\n",
+       cstate->service_name,
+       GNUNET_STRINGS_relative_time_to_string (cstate->back_off,
+                                               GNUNET_YES));
+  cstate->retry_task
+    = GNUNET_SCHEDULER_add_delayed (cstate->back_off,
+                                    &start_connect,
+                                    cstate);
+}
+
+
+/**
+ * We are ready to send a message to the service.
+ *
+ * @param cls the `struct ClientState` with the `msg` to transmit
+ */
+static void
+transmit_ready (void *cls)
+{
+  struct ClientState *cstate = cls;
+  ssize_t ret;
+  size_t len;
+  const char *pos;
+  int notify_in_flight;
+
+  cstate->send_task = NULL;
+  pos = (const char *) cstate->msg;
+  len = ntohs (cstate->msg->size);
+  GNUNET_assert (cstate->msg_off < len);
+ RETRY:
+  ret = GNUNET_NETWORK_socket_send (cstate->sock,
+                                    &pos[cstate->msg_off],
+                                    len - cstate->msg_off);
+  if (-1 == ret)
+  {
+    if (EINTR == errno)
+      goto RETRY;
+    GNUNET_MQ_inject_error (cstate->mq,
+                            GNUNET_MQ_ERROR_WRITE);
+    return;
+  }
+  notify_in_flight = (0 == cstate->msg_off);
+  cstate->msg_off += ret;
+  if (cstate->msg_off < len)
+  {
+    cstate->send_task
+      = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                        cstate->sock,
+                                        &transmit_ready,
+                                        cstate);
+    if (notify_in_flight)
+      GNUNET_MQ_impl_send_in_flight (cstate->mq);
+    return;
+  }
+  cstate->msg = NULL;
+  GNUNET_MQ_impl_send_continue (cstate->mq);
+}
+
+
+/**
+ * We have received a full message, pass to the MQ dispatcher.
+ * Called by the tokenizer via #receive_ready().
+ *
+ * @param cls the `struct ClientState`
+ * @param msg message we received.
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
+ */
+static int
+recv_message (void *cls,
+              const struct GNUNET_MessageHeader *msg)
+{
+  struct ClientState *cstate = cls;
+
+  if (GNUNET_YES == cstate->in_destroy)
+    return GNUNET_SYSERR;
+  GNUNET_MQ_inject_message (cstate->mq,
+                            msg);
+  if (GNUNET_YES == cstate->in_destroy)
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cancel all remaining connect attempts
+ *
+ * @param cstate handle of the client state to process
+ */
+static void
+cancel_aps (struct ClientState *cstate)
+{
+  struct AddressProbe *pos;
+
+  while (NULL != (pos = cstate->ap_head))
+  {
+    GNUNET_break (GNUNET_OK ==
+                  GNUNET_NETWORK_socket_close (pos->sock));
+    GNUNET_SCHEDULER_cancel (pos->task);
+    GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
+                                cstate->ap_tail,
+                                pos);
+    GNUNET_free (pos);
+  }
+}
+
+
+/**
+ * Implement the destruction of a message queue.  Implementations must
+ * not free @a mq, but should take care of @a impl_state.
+ *
+ * @param mq the message queue to destroy
+ * @param impl_state our `struct ClientState`
+ */
+static void
+connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
+                                void *impl_state)
+{
+  struct ClientState *cstate = impl_state;
+
+  if (GNUNET_SYSERR == cstate->in_destroy)
+  {
+    /* defer destruction */
+    cstate->in_destroy = GNUNET_YES;
+    cstate->mq = NULL;
+    return;
+  }
+  if (NULL != cstate->dns_active)
+    GNUNET_RESOLVER_request_cancel (cstate->dns_active);
+  if (NULL != cstate->send_task)
+    GNUNET_SCHEDULER_cancel (cstate->send_task);
+  if (NULL != cstate->recv_task)
+    GNUNET_SCHEDULER_cancel (cstate->recv_task);
+  if (NULL != cstate->retry_task)
+    GNUNET_SCHEDULER_cancel (cstate->retry_task);
+  if (NULL != cstate->sock)
+    GNUNET_NETWORK_socket_close (cstate->sock);
+  cancel_aps (cstate);
+  GNUNET_free (cstate->service_name);
+  GNUNET_free_non_null (cstate->hostname);
+  GNUNET_MST_destroy (cstate->mst);
+  GNUNET_free (cstate);
+}
+
+
+/**
+ * This function is called once we have data ready to read.
+ *
+ * @param cls `struct ClientState` with connection to read from
+ */
+static void
+receive_ready (void *cls)
+{
+  struct ClientState *cstate = cls;
+  int ret;
+
+  cstate->recv_task = NULL;
+  cstate->in_destroy = GNUNET_SYSERR;
+  ret = GNUNET_MST_read (cstate->mst,
+                         cstate->sock,
+                         GNUNET_NO,
+                         GNUNET_NO);
+  if (GNUNET_SYSERR == ret)
+  {
+    if (NULL != cstate->mq)
+      GNUNET_MQ_inject_error (cstate->mq,
+                             GNUNET_MQ_ERROR_READ);
+    if (GNUNET_YES == cstate->in_destroy)
+      connection_client_destroy_impl (cstate->mq,
+                                     cstate);
+    return;
+  }
+  if (GNUNET_YES == cstate->in_destroy)
+  {
+    connection_client_destroy_impl (cstate->mq,
+                                    cstate);
+    return;
+  }
+  cstate->in_destroy = GNUNET_NO;
+  cstate->recv_task
+    = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                     cstate->sock,
+                                     &receive_ready,
+                                     cstate);
+}
+
+
+/**
+ * We've succeeded in establishing a connection.
+ *
+ * @param cstate the connection we tried to establish
+ */
+static void
+connect_success_continuation (struct ClientState *cstate)
+{
+  GNUNET_assert (NULL == cstate->recv_task);
+  cstate->recv_task
+    = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                     cstate->sock,
+                                     &receive_ready,
+                                     cstate);
+  if (NULL != cstate->msg)
+  {
+    GNUNET_assert (NULL == cstate->send_task);
+    cstate->send_task
+      = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                        cstate->sock,
+                                        &transmit_ready,
+                                        cstate);
+  }
+}
+
+
+/**
+ * Try connecting to the server using UNIX domain sockets.
+ *
+ * @param service_name name of service to connect to
+ * @param cfg configuration to use
+ * @return NULL on error, socket connected to UNIX otherwise
+ */
+static struct GNUNET_NETWORK_Handle *
+try_unixpath (const char *service_name,
+             const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+#if AF_UNIX
+  struct GNUNET_NETWORK_Handle *sock;
+  char *unixpath;
+  struct sockaddr_un s_un;
+
+  unixpath = NULL;
+  if ((GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                service_name,
+                                                "UNIXPATH",
+                                                &unixpath)) &&
+      (0 < strlen (unixpath)))
+  {
+    /* We have a non-NULL unixpath, need to validate it */
+    if (strlen (unixpath) >= sizeof (s_un.sun_path))
+    {
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+          _("UNIXPATH `%s' too long, maximum length is %llu\n"),
+           unixpath,
+          (unsigned long long) sizeof (s_un.sun_path));
+      unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
+      LOG (GNUNET_ERROR_TYPE_INFO,
+          _("Using `%s' instead\n"),
+           unixpath);
+      if (NULL == unixpath)
+       return NULL;
+    }
+    memset (&s_un,
+            0,
+            sizeof (s_un));
+    s_un.sun_family = AF_UNIX;
+    strncpy (s_un.sun_path,
+             unixpath,
+             sizeof (s_un.sun_path) - 1);
+#ifdef LINUX
+    {
+      int abstract;
+
+      abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                                       "TESTING",
+                                                       "USE_ABSTRACT_SOCKETS");
+      if (GNUNET_YES == abstract)
+        s_un.sun_path[0] = '\0';
+    }
+#endif
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    un.sun_len = (u_char) sizeof (struct sockaddr_un);
+#endif
+    sock = GNUNET_NETWORK_socket_create (AF_UNIX,
+                                         SOCK_STREAM,
+                                         0);
+    if ( (NULL != sock) &&
+         ( (GNUNET_OK ==
+            GNUNET_NETWORK_socket_connect (sock,
+                                           (struct sockaddr *) &s_un,
+                                           sizeof (s_un))) ||
+           (EINPROGRESS == errno) ) )
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Successfully connected to unixpath `%s'!\n",
+          unixpath);
+      GNUNET_free (unixpath);
+      return sock;
+    }
+  }
+  GNUNET_free_non_null (unixpath);
+#endif
+  return NULL;
+}
+
+
+/**
+ * Scheduler let us know that we're either ready to write on the
+ * socket OR connect timed out.  Do the right thing.
+ *
+ * @param cls the `struct AddressProbe *` with the address that we are probing
+ */
+static void
+connect_probe_continuation (void *cls)
+{
+  struct AddressProbe *ap = cls;
+  struct ClientState *cstate = ap->cstate;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+  int error;
+  socklen_t len;
+
+  ap->task = NULL;
+  GNUNET_assert (NULL != ap->sock);
+  GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
+                              cstate->ap_tail,
+                              ap);
+  len = sizeof (error);
+  error = 0;
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
+       (GNUNET_OK !=
+       GNUNET_NETWORK_socket_getsockopt (ap->sock,
+                                         SOL_SOCKET,
+                                         SO_ERROR,
+                                         &error,
+                                         &len)) ||
+       (0 != error) )
+  {
+    GNUNET_break (GNUNET_OK ==
+                 GNUNET_NETWORK_socket_close (ap->sock));
+    GNUNET_free (ap);
+    if ( (NULL == cstate->ap_head) &&
+         //     (NULL == cstate->proxy_handshake) &&
+        (NULL == cstate->dns_active) )
+      connect_fail_continuation (cstate);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Connection to `%s' succeeded!\n",
+       cstate->service_name);
+  /* trigger jobs that waited for the connection */
+  GNUNET_assert (NULL == cstate->sock);
+  cstate->sock = ap->sock;
+  GNUNET_free (ap);
+  cancel_aps (cstate);
+  connect_success_continuation (cstate);
+}
+
+
+/**
+ * Try to establish a connection given the specified address.
+ * This function is called by the resolver once we have a DNS reply.
+ *
+ * @param cls our `struct ClientState *`
+ * @param addr address to try, NULL for "last call"
+ * @param addrlen length of @a addr
+ */
+static void
+try_connect_using_address (void *cls,
+                           const struct sockaddr *addr,
+                           socklen_t addrlen)
+{
+  struct ClientState *cstate = cls;
+  struct AddressProbe *ap;
+
+  if (NULL == addr)
+  {
+    cstate->dns_active = NULL;
+    if ( (NULL == cstate->ap_head) &&
+         //  (NULL == cstate->proxy_handshake) &&
+         (NULL == cstate->sock) )
+      connect_fail_continuation (cstate);
+    return;
+  }
+  if (NULL != cstate->sock)
+    return;                     /* already connected */
+  /* try to connect */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Trying to connect using address `%s:%u'\n",
+       GNUNET_a2s (addr,
+                   addrlen),
+       cstate->port);
+  ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
+  ap->addr = (const struct sockaddr *) &ap[1];
+  GNUNET_memcpy (&ap[1],
+                 addr,
+                 addrlen);
+  ap->addrlen = addrlen;
+  ap->cstate = cstate;
+
+  switch (ap->addr->sa_family)
+  {
+  case AF_INET:
+    ((struct sockaddr_in *) ap->addr)->sin_port = htons (cstate->port);
+    break;
+  case AF_INET6:
+    ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (cstate->port);
+    break;
+  default:
+    GNUNET_break (0);
+    GNUNET_free (ap);
+    return;                     /* not supported by us */
+  }
+  ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family,
+                                          SOCK_STREAM,
+                                           0);
+  if (NULL == ap->sock)
+  {
+    GNUNET_free (ap);
+    return;                     /* not supported by OS */
+  }
+  if ( (GNUNET_OK !=
+        GNUNET_NETWORK_socket_connect (ap->sock,
+                                       ap->addr,
+                                       ap->addrlen)) &&
+       (EINPROGRESS != errno) )
+  {
+    /* maybe refused / unsupported address, try next */
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
+                         "connect");
+    GNUNET_break (GNUNET_OK ==
+                  GNUNET_NETWORK_socket_close (ap->sock));
+    GNUNET_free (ap);
+    return;
+  }
+  GNUNET_CONTAINER_DLL_insert (cstate->ap_head,
+                               cstate->ap_tail,
+                               ap);
+  ap->task = GNUNET_SCHEDULER_add_write_net (GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
+                                            ap->sock,
+                                            &connect_probe_continuation,
+                                            ap);
+}
+
+
+/**
+ * Test whether the configuration has proper values for connection
+ * (UNIXPATH || (PORT && HOSTNAME)).
+ *
+ * @param service_name name of service to connect to
+ * @param cfg configuration to use
+ * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not
+ */
+static int
+test_service_configuration (const char *service_name,
+                           const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  int ret = GNUNET_SYSERR;
+  char *hostname = NULL;
+  unsigned long long port;
+#if AF_UNIX
+  char *unixpath = NULL;
+
+  if ((GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                service_name,
+                                                "UNIXPATH",
+                                                &unixpath)) &&
+      (0 < strlen (unixpath)))
+    ret = GNUNET_OK;
+  GNUNET_free_non_null (unixpath);
+#endif
+
+  if ( (GNUNET_YES ==
+       GNUNET_CONFIGURATION_have_value (cfg,
+                                         service_name,
+                                         "PORT")) &&
+       (GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_number (cfg,
+                                               service_name,
+                                               "PORT",
+                                               &port)) &&
+       (port <= 65535) &&
+       (0 != port) &&
+       (GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_string (cfg,
+                                               service_name,
+                                               "HOSTNAME",
+                                              &hostname)) &&
+       (0 != strlen (hostname)) )
+    ret = GNUNET_OK;
+  GNUNET_free_non_null (hostname);
+  return ret;
+}
+
+
+/**
+ * Try to connect to the service.
+ *
+ * @param cls the `struct ClientState` to try to connect to the service
+ */
+static void
+start_connect (void *cls)
+{
+  struct ClientState *cstate = cls;
+
+  cstate->retry_task = NULL;
+#if 0
+  /* Never use a local source if a proxy is configured */
+  if (GNUNET_YES ==
+      GNUNET_SOCKS_check_service (cstate->service_name,
+                                  cstate->cfg))
+  {
+    socks_connect (cstate);
+    return;
+  }
+#endif
+
+  if ( (0 == (cstate->attempts++ % 2)) ||
+       (0 == cstate->port) ||
+       (NULL == cstate->hostname) )
+  {
+    /* on even rounds, try UNIX first, or always
+       if we do not have a DNS name and TCP port. */
+    cstate->sock = try_unixpath (cstate->service_name,
+                                 cstate->cfg);
+    if (NULL != cstate->sock)
+    {
+      connect_success_continuation (cstate);
+      return;
+    }
+  }
+  if ( (NULL == cstate->hostname) ||
+       (0 == cstate->port) )
+  {
+    /* All options failed. Boo! */
+    connect_fail_continuation (cstate);
+    return;
+  }
+  cstate->dns_active
+    = GNUNET_RESOLVER_ip_get (cstate->hostname,
+                             AF_UNSPEC,
+                              GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
+                              &try_connect_using_address,
+                             cstate);
+}
+
+
+/**
+ * Implements the transmission functionality of a message queue.
+ *
+ * @param mq the message queue
+ * @param msg the message to send
+ * @param impl_state our `struct ClientState`
+ */
+static void
+connection_client_send_impl (struct GNUNET_MQ_Handle *mq,
+                             const struct GNUNET_MessageHeader *msg,
+                             void *impl_state)
+{
+  struct ClientState *cstate = impl_state;
+
+  /* only one message at a time allowed */
+  GNUNET_assert (NULL == cstate->msg);
+  GNUNET_assert (NULL == cstate->send_task);
+  cstate->msg = msg;
+  cstate->msg_off = 0;
+  if (NULL == cstate->sock)
+    return; /* still waiting for connection */
+  cstate->send_task
+    = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      cstate->sock,
+                                      &transmit_ready,
+                                      cstate);
+}
+
+
+/**
+ * Cancel the currently sent message.
+ *
+ * @param mq message queue
+ * @param impl_state our `struct ClientState`
+ */
+static void
+connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
+                               void *impl_state)
+{
+  struct ClientState *cstate = impl_state;
+
+  GNUNET_assert (NULL != cstate->msg);
+  GNUNET_assert (0 == cstate->msg_off);
+  cstate->msg = NULL;
+  if (NULL != cstate->send_task)
+  {
+    GNUNET_SCHEDULER_cancel (cstate->send_task);
+    cstate->send_task = NULL;
+  }
+}
+
+
+/**
+ * Create a message queue to connect to a GNUnet service.
+ * If handlers are specfied, receive messages from the connection.
+ *
+ * @param cfg our configuration
+ * @param service_name name of the service to connect to
+ * @param handlers handlers for receiving messages, can be NULL
+ * @param error_handler error handler
+ * @param error_handler_cls closure for the @a error_handler
+ * @return the message queue, NULL on error
+ */
+struct GNUNET_MQ_Handle *
+GNUNET_CLIENT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                      const char *service_name,
+                      const struct GNUNET_MQ_MessageHandler *handlers,
+                      GNUNET_MQ_ErrorHandler error_handler,
+                      void *error_handler_cls)
+{
+  struct ClientState *cstate;
+
+  if (GNUNET_OK !=
+      test_service_configuration (service_name,
+                                 cfg))
+    return NULL;
+  cstate = GNUNET_new (struct ClientState);
+  cstate->service_name = GNUNET_strdup (service_name);
+  cstate->cfg = cfg;
+  cstate->retry_task = GNUNET_SCHEDULER_add_now (&start_connect,
+                                                 cstate);
+  cstate->mst = GNUNET_MST_create (&recv_message,
+                                   cstate);
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_have_value (cfg,
+                                       service_name,
+                                       "PORT"))
+  {
+    if (! ( (GNUNET_OK !=
+            GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                   service_name,
+                                                   "PORT",
+                                                   &cstate->port)) ||
+           (cstate->port > 65535) ||
+           (GNUNET_OK !=
+            GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                   service_name,
+                                                   "HOSTNAME",
+                                                   &cstate->hostname)) ) &&
+       (0 == strlen (cstate->hostname)) )
+    {
+      GNUNET_free (cstate->hostname);
+      cstate->hostname = NULL;
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+          _("Need a non-empty hostname for service `%s'.\n"),
+          service_name);
+    }
+  }
+  cstate->mq = GNUNET_MQ_queue_for_callbacks (&connection_client_send_impl,
+                                             &connection_client_destroy_impl,
+                                             &connection_client_cancel_impl,
+                                             cstate,
+                                             handlers,
+                                             error_handler,
+                                             error_handler_cls);
+  return cstate->mq;
+}
+
+/* end of client_new.c */
diff --git a/src/util/client_new.c b/src/util/client_new.c
deleted file mode 100644 (file)
index 337d067..0000000
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2001-2016 GNUnet e.V.
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file util/client.c
- * @brief code for access to services
- * @author Christian Grothoff
- *
- * Generic TCP code for reliable, record-oriented TCP
- * connections between clients and service providers.
- */
-#include "platform.h"
-#include "gnunet_protocols.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_resolver_service.h"
-#include "gnunet_socks.h"
-
-
-#define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
-
-
-/**
- * Internal state for a client connected to a GNUnet service.
- */
-struct ClientState;
-
-
-/**
- * During connect, we try multiple possible IP addresses
- * to find out which one might work.
- */
-struct AddressProbe
-{
-
-  /**
-   * This is a linked list.
-   */
-  struct AddressProbe *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct AddressProbe *prev;
-
-  /**
-   * The address; do not free (allocated at the end of this struct).
-   */
-  const struct sockaddr *addr;
-
-  /**
-   * Underlying OS's socket.
-   */
-  struct GNUNET_NETWORK_Handle *sock;
-
-  /**
-   * Connection for which we are probing.
-   */
-  struct ClientState *cstate;
-
-  /**
-   * Lenth of addr.
-   */
-  socklen_t addrlen;
-
-  /**
-   * Task waiting for the connection to finish connecting.
-   */
-  struct GNUNET_SCHEDULER_Task *task;
-};
-
-
-/**
- * Internal state for a client connected to a GNUnet service.
- */
-struct ClientState
-{
-
-  /**
-   * The connection handle, NULL if not live
-   */
-  struct GNUNET_NETWORK_Handle *sock;
-
-  /**
-   * Handle to a pending DNS lookup request, NULL if DNS is finished.
-   */
-  struct GNUNET_RESOLVER_RequestHandle *dns_active;
-
-  /**
-   * Our configuration.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Linked list of sockets we are currently trying out
-   * (during connect).
-   */
-  struct AddressProbe *ap_head;
-
-  /**
-   * Linked list of sockets we are currently trying out
-   * (during connect).
-   */
-  struct AddressProbe *ap_tail;
-
-  /**
-   * Name of the service we interact with.
-   */
-  char *service_name;
-
-  /**
-   * Hostname, if any.
-   */
-  char *hostname;
-
-  /**
-   * Next message to transmit to the service. NULL for none.
-   */
-  const struct GNUNET_MessageHeader *msg;
-
-  /**
-   * Task for trying to connect to the service.
-   */
-  struct GNUNET_SCHEDULER_Task *retry_task;
-
-  /**
-   * Task for sending messages to the service.
-   */
-  struct GNUNET_SCHEDULER_Task *send_task;
-
-  /**
-   * Task for sending messages to the service.
-   */
-  struct GNUNET_SCHEDULER_Task *recv_task;
-
-  /**
-   * Tokenizer for inbound messages.
-   */
-  struct GNUNET_MessageStreamTokenizer *mst;
-
-  /**
-   * Message queue under our control.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Timeout for receiving a response (absolute time).
-   */
-  struct GNUNET_TIME_Absolute receive_timeout;
-
-  /**
-   * Current value for our incremental back-off (for
-   * connect re-tries).
-   */
-  struct GNUNET_TIME_Relative back_off;
-
-  /**
-   * TCP port (0 for disabled).
-   */
-  unsigned long long port;
-
-  /**
-   * Offset in the message where we are for transmission.
-   */
-  size_t msg_off;
-
-  /**
-   * How often have we tried to connect?
-   */
-  unsigned int attempts;
-
-  /**
-   * Are we supposed to die?  #GNUNET_SYSERR if destruction must be
-   * deferred, #GNUNET_NO by default, #GNUNET_YES if destruction was
-   * deferred.
-   */
-  int in_destroy;
-
-};
-
-
-/**
- * Try to connect to the service.
- *
- * @param cls the `struct ClientState` to try to connect to the service
- */
-static void
-start_connect (void *cls);
-
-
-/**
- * We've failed for good to establish a connection (timeout or
- * no more addresses to try).
- *
- * @param cstate the connection we tried to establish
- */
-static void
-connect_fail_continuation (struct ClientState *cstate)
-{
-  LOG (GNUNET_ERROR_TYPE_WARNING,
-       "Failed to establish connection to `%s', no further addresses to try.\n",
-       cstate->service_name);
-  GNUNET_break (NULL == cstate->ap_head);
-  GNUNET_break (NULL == cstate->ap_tail);
-  GNUNET_break (NULL == cstate->dns_active);
-  GNUNET_break (NULL == cstate->sock);
-  GNUNET_assert (NULL == cstate->send_task);
-  GNUNET_assert (NULL == cstate->recv_task);
-  // GNUNET_assert (NULL == cstate->proxy_handshake);
-
-  cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off);
-  cstate->retry_task
-    = GNUNET_SCHEDULER_add_delayed (cstate->back_off,
-                                    &start_connect,
-                                    cstate);
-}
-
-
-/**
- * We are ready to send a message to the service.
- *
- * @param cls the `struct ClientState` with the `msg` to transmit
- */
-static void
-transmit_ready (void *cls)
-{
-  struct ClientState *cstate = cls;
-  ssize_t ret;
-  size_t len;
-  const char *pos;
-  int notify_in_flight;
-
-  cstate->send_task = NULL;
-  pos = (const char *) cstate->msg;
-  len = ntohs (cstate->msg->size);
-  GNUNET_assert (cstate->msg_off < len);
- RETRY:
-  ret = GNUNET_NETWORK_socket_send (cstate->sock,
-                                    &pos[cstate->msg_off],
-                                    len - cstate->msg_off);
-  if (-1 == ret)
-  {
-    if (EINTR == errno)
-      goto RETRY;
-    GNUNET_MQ_inject_error (cstate->mq,
-                            GNUNET_MQ_ERROR_WRITE);
-    return;
-  }
-  notify_in_flight = (0 == cstate->msg_off);
-  cstate->msg_off += ret;
-  if (cstate->msg_off < len)
-  {
-    cstate->send_task
-      = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                        cstate->sock,
-                                        &transmit_ready,
-                                        cstate);
-    if (notify_in_flight) 
-      GNUNET_MQ_impl_send_in_flight (cstate->mq);
-    return;
-  }
-  cstate->msg = NULL;
-  GNUNET_MQ_impl_send_continue (cstate->mq);
-}
-
-
-/**
- * We have received a full message, pass to the MQ dispatcher.
- * Called by the tokenizer via #receive_ready().
- *
- * @param cls the `struct ClientState`
- * @param msg message we received.
- * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
- */
-static int
-recv_message (void *cls,
-              const struct GNUNET_MessageHeader *msg)
-{
-  struct ClientState *cstate = cls;
-
-  if (GNUNET_YES == cstate->in_destroy)
-    return GNUNET_SYSERR;
-  GNUNET_MQ_inject_message (cstate->mq,
-                            msg);
-  if (GNUNET_YES == cstate->in_destroy)
-    return GNUNET_SYSERR;
-  return GNUNET_OK;
-}
-
-
-/**
- * Cancel all remaining connect attempts
- *
- * @param cstate handle of the client state to process
- */
-static void
-cancel_aps (struct ClientState *cstate)
-{
-  struct AddressProbe *pos;
-
-  while (NULL != (pos = cstate->ap_head))
-  {
-    GNUNET_break (GNUNET_OK ==
-                  GNUNET_NETWORK_socket_close (pos->sock));
-    GNUNET_SCHEDULER_cancel (pos->task);
-    GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
-                                cstate->ap_tail,
-                                pos);
-    GNUNET_free (pos);
-  }
-}
-
-
-/**
- * Implement the destruction of a message queue.  Implementations must
- * not free @a mq, but should take care of @a impl_state.
- *
- * @param mq the message queue to destroy
- * @param impl_state our `struct ClientState`
- */
-static void
-connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
-                                void *impl_state)
-{
-  struct ClientState *cstate = impl_state;
-
-  if (GNUNET_SYSERR == cstate->in_destroy)
-  {
-    /* defer destruction */
-    cstate->in_destroy = GNUNET_YES;
-    cstate->mq = NULL;
-    return;
-  }
-  if (NULL != cstate->dns_active)
-    GNUNET_RESOLVER_request_cancel (cstate->dns_active);
-  if (NULL != cstate->send_task)
-    GNUNET_SCHEDULER_cancel (cstate->send_task);
-  if (NULL != cstate->recv_task)
-    GNUNET_SCHEDULER_cancel (cstate->recv_task);
-  if (NULL != cstate->retry_task)
-    GNUNET_SCHEDULER_cancel (cstate->retry_task);
-  if (NULL != cstate->sock)
-    GNUNET_NETWORK_socket_close (cstate->sock);
-  cancel_aps (cstate);
-  GNUNET_free (cstate->service_name);
-  GNUNET_free_non_null (cstate->hostname);
-  GNUNET_MST_destroy (cstate->mst);
-  GNUNET_free (cstate);
-}
-
-
-/**
- * This function is called once we have data ready to read.
- *
- * @param cls `struct ClientState` with connection to read from
- */
-static void
-receive_ready (void *cls)
-{
-  struct ClientState *cstate = cls;
-  int ret;
-
-  cstate->recv_task = NULL;
-  cstate->in_destroy = GNUNET_SYSERR;
-  ret = GNUNET_MST_read (cstate->mst,
-                         cstate->sock,
-                         GNUNET_NO,
-                         GNUNET_NO);
-  if (GNUNET_SYSERR == ret)
-  {
-    if (NULL != cstate->mq)
-      GNUNET_MQ_inject_error (cstate->mq,
-                             GNUNET_MQ_ERROR_READ);
-    if (GNUNET_YES == cstate->in_destroy)
-      connection_client_destroy_impl (cstate->mq,
-                                     cstate);
-    return;
-  }
-  if (GNUNET_YES == cstate->in_destroy)
-  {
-    connection_client_destroy_impl (cstate->mq,
-                                    cstate);
-    return;
-  }
-  cstate->in_destroy = GNUNET_NO;
-  cstate->recv_task
-    = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                     cstate->sock,
-                                     &receive_ready,
-                                     cstate);
-}
-
-
-/**
- * We've succeeded in establishing a connection.
- *
- * @param cstate the connection we tried to establish
- */
-static void
-connect_success_continuation (struct ClientState *cstate)
-{
-  GNUNET_assert (NULL == cstate->recv_task);
-  cstate->recv_task
-    = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                     cstate->sock,
-                                     &receive_ready,
-                                     cstate);
-  if (NULL != cstate->msg)
-  {
-    GNUNET_assert (NULL == cstate->send_task);
-    cstate->send_task
-      = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                        cstate->sock,
-                                        &transmit_ready,
-                                        cstate);
-  }
-}
-
-
-/**
- * Try connecting to the server using UNIX domain sockets.
- *
- * @param service_name name of service to connect to
- * @param cfg configuration to use
- * @return NULL on error, socket connected to UNIX otherwise
- */
-static struct GNUNET_NETWORK_Handle *
-try_unixpath (const char *service_name,
-             const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-#if AF_UNIX
-  struct GNUNET_NETWORK_Handle *sock;
-  char *unixpath;
-  struct sockaddr_un s_un;
-
-  unixpath = NULL;
-  if ((GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                                service_name,
-                                                "UNIXPATH",
-                                                &unixpath)) &&
-      (0 < strlen (unixpath)))
-  {
-    /* We have a non-NULL unixpath, need to validate it */
-    if (strlen (unixpath) >= sizeof (s_un.sun_path))
-    {
-      LOG (GNUNET_ERROR_TYPE_WARNING,
-          _("UNIXPATH `%s' too long, maximum length is %llu\n"),
-           unixpath,
-          (unsigned long long) sizeof (s_un.sun_path));
-      unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
-      LOG (GNUNET_ERROR_TYPE_INFO,
-          _("Using `%s' instead\n"),
-           unixpath);
-      if (NULL == unixpath)
-       return NULL;
-    }
-    memset (&s_un,
-            0,
-            sizeof (s_un));
-    s_un.sun_family = AF_UNIX;
-    strncpy (s_un.sun_path,
-             unixpath,
-             sizeof (s_un.sun_path) - 1);
-#ifdef LINUX
-    {
-      int abstract;
-
-      abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
-                                                       "TESTING",
-                                                       "USE_ABSTRACT_SOCKETS");
-      if (GNUNET_YES == abstract)
-        s_un.sun_path[0] = '\0';
-    }
-#endif
-#if HAVE_SOCKADDR_IN_SIN_LEN
-    un.sun_len = (u_char) sizeof (struct sockaddr_un);
-#endif
-    sock = GNUNET_NETWORK_socket_create (AF_UNIX,
-                                         SOCK_STREAM,
-                                         0);
-    if ( (NULL != sock) &&
-         ( (GNUNET_OK ==
-            GNUNET_NETWORK_socket_connect (sock,
-                                           (struct sockaddr *) &s_un,
-                                           sizeof (s_un))) ||
-           (EINPROGRESS == errno) ) )
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Successfully connected to unixpath `%s'!\n",
-          unixpath);
-      GNUNET_free (unixpath);
-      return sock;
-    }
-  }
-  GNUNET_free_non_null (unixpath);
-#endif
-  return NULL;
-}
-
-
-/**
- * Scheduler let us know that we're either ready to write on the
- * socket OR connect timed out.  Do the right thing.
- *
- * @param cls the `struct AddressProbe *` with the address that we are probing
- */
-static void
-connect_probe_continuation (void *cls)
-{
-  struct AddressProbe *ap = cls;
-  struct ClientState *cstate = ap->cstate;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-  int error;
-  socklen_t len;
-
-  ap->task = NULL;
-  GNUNET_assert (NULL != ap->sock);
-  GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
-                              cstate->ap_tail,
-                              ap);
-  len = sizeof (error);
-  error = 0;
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
-       (GNUNET_OK !=
-       GNUNET_NETWORK_socket_getsockopt (ap->sock,
-                                         SOL_SOCKET,
-                                         SO_ERROR,
-                                         &error,
-                                         &len)) ||
-       (0 != error) )
-  {
-    GNUNET_break (GNUNET_OK ==
-                 GNUNET_NETWORK_socket_close (ap->sock));
-    GNUNET_free (ap);
-    if ( (NULL == cstate->ap_head) &&
-         //     (NULL == cstate->proxy_handshake) &&
-        (NULL == cstate->dns_active) )
-      connect_fail_continuation (cstate);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Connection to `%s' succeeded!\n",
-       cstate->service_name);
-  /* trigger jobs that waited for the connection */
-  GNUNET_assert (NULL == cstate->sock);
-  cstate->sock = ap->sock;
-  GNUNET_free (ap);
-  cancel_aps (cstate);
-  connect_success_continuation (cstate);
-}
-
-
-/**
- * Try to establish a connection given the specified address.
- * This function is called by the resolver once we have a DNS reply.
- *
- * @param cls our `struct ClientState *`
- * @param addr address to try, NULL for "last call"
- * @param addrlen length of @a addr
- */
-static void
-try_connect_using_address (void *cls,
-                           const struct sockaddr *addr,
-                           socklen_t addrlen)
-{
-  struct ClientState *cstate = cls;
-  struct AddressProbe *ap;
-  
-  if (NULL == addr)
-  {
-    cstate->dns_active = NULL;
-    if ( (NULL == cstate->ap_head) &&
-         //  (NULL == cstate->proxy_handshake) &&
-         (NULL == cstate->sock) )
-      connect_fail_continuation (cstate);
-    return;
-  }
-  if (NULL != cstate->sock)
-    return;                     /* already connected */
-  /* try to connect */
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Trying to connect using address `%s:%u'\n",
-       GNUNET_a2s (addr,
-                   addrlen),
-       cstate->port);
-  ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
-  ap->addr = (const struct sockaddr *) &ap[1];
-  GNUNET_memcpy (&ap[1],
-                 addr,
-                 addrlen);
-  ap->addrlen = addrlen;
-  ap->cstate = cstate;
-
-  switch (ap->addr->sa_family)
-  {
-  case AF_INET:
-    ((struct sockaddr_in *) ap->addr)->sin_port = htons (cstate->port);
-    break;
-  case AF_INET6:
-    ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (cstate->port);
-    break;
-  default:
-    GNUNET_break (0);
-    GNUNET_free (ap);
-    return;                     /* not supported by us */
-  }
-  ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family,
-                                          SOCK_STREAM,
-                                           0);
-  if (NULL == ap->sock)
-  {
-    GNUNET_free (ap);
-    return;                     /* not supported by OS */
-  }
-  if ( (GNUNET_OK !=
-        GNUNET_NETWORK_socket_connect (ap->sock,
-                                       ap->addr,
-                                       ap->addrlen)) &&
-       (EINPROGRESS != errno) )
-  {
-    /* maybe refused / unsupported address, try next */
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
-                         "connect");
-    GNUNET_break (GNUNET_OK ==
-                  GNUNET_NETWORK_socket_close (ap->sock));
-    GNUNET_free (ap);
-    return;
-  }
-  GNUNET_CONTAINER_DLL_insert (cstate->ap_head,
-                               cstate->ap_tail,
-                               ap);
-  ap->task = GNUNET_SCHEDULER_add_write_net (GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
-                                            ap->sock,
-                                            &connect_probe_continuation,
-                                            ap);
-}
-
-
-/**
- * Test whether the configuration has proper values for connection
- * (UNIXPATH || (PORT && HOSTNAME)).
- *
- * @param service_name name of service to connect to
- * @param cfg configuration to use
- * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not
- */
-static int
-test_service_configuration (const char *service_name,
-                           const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  int ret = GNUNET_SYSERR;
-  char *hostname = NULL;
-  unsigned long long port;
-#if AF_UNIX
-  char *unixpath = NULL;
-
-  if ((GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                                service_name,
-                                                "UNIXPATH",
-                                                &unixpath)) &&
-      (0 < strlen (unixpath)))
-    ret = GNUNET_OK;
-  GNUNET_free_non_null (unixpath);
-#endif
-
-  if ( (GNUNET_YES ==
-       GNUNET_CONFIGURATION_have_value (cfg,
-                                         service_name,
-                                         "PORT")) &&
-       (GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_number (cfg,
-                                               service_name,
-                                               "PORT",
-                                               &port)) &&
-       (port <= 65535) &&
-       (0 != port) &&
-       (GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_string (cfg,
-                                               service_name,
-                                               "HOSTNAME",
-                                              &hostname)) &&
-       (0 != strlen (hostname)) )
-    ret = GNUNET_OK;
-  GNUNET_free_non_null (hostname);
-  return ret;
-}
-
-
-/**
- * Try to connect to the service.
- *
- * @param cls the `struct ClientState` to try to connect to the service
- */
-static void
-start_connect (void *cls)
-{
-  struct ClientState *cstate = cls;
-
-  cstate->retry_task = NULL;
-#if 0
-  /* Never use a local source if a proxy is configured */
-  if (GNUNET_YES ==
-      GNUNET_SOCKS_check_service (cstate->service_name,
-                                  cstate->cfg))
-  {
-    socks_connect (cstate);
-    return;
-  }
-#endif
-
-  if ( (0 == (cstate->attempts++ % 2)) ||
-       (0 == cstate->port) ||
-       (NULL == cstate->hostname) )
-  {
-    /* on even rounds, try UNIX first, or always
-       if we do not have a DNS name and TCP port. */
-    cstate->sock = try_unixpath (cstate->service_name,
-                                 cstate->cfg);
-    if (NULL != cstate->sock)
-    {
-      connect_success_continuation (cstate);
-      return;
-    }    
-  }
-  if ( (NULL == cstate->hostname) ||
-       (0 == cstate->port) )
-  {
-    /* All options failed. Boo! */
-    connect_fail_continuation (cstate);
-    return;
-  }
-  cstate->dns_active
-    = GNUNET_RESOLVER_ip_get (cstate->hostname,
-                             AF_UNSPEC,
-                              GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
-                              &try_connect_using_address,
-                             cstate);
-}
-
-
-/**
- * Implements the transmission functionality of a message queue.
- *
- * @param mq the message queue
- * @param msg the message to send
- * @param impl_state our `struct ClientState`
- */
-static void
-connection_client_send_impl (struct GNUNET_MQ_Handle *mq,
-                             const struct GNUNET_MessageHeader *msg,
-                             void *impl_state)
-{
-  struct ClientState *cstate = impl_state;
-
-  /* only one message at a time allowed */
-  GNUNET_assert (NULL == cstate->msg);
-  GNUNET_assert (NULL == cstate->send_task);
-  cstate->msg = msg;
-  cstate->msg_off = 0;
-  if (NULL == cstate->sock)
-    return; /* still waiting for connection */
-  cstate->send_task
-    = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      cstate->sock,
-                                      &transmit_ready,
-                                      cstate);
-}
-
-
-/**
- * Cancel the currently sent message.
- *
- * @param mq message queue
- * @param impl_state our `struct ClientState`
- */
-static void
-connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
-                               void *impl_state)
-{
-  struct ClientState *cstate = impl_state;
-
-  GNUNET_assert (NULL != cstate->msg);
-  GNUNET_assert (0 == cstate->msg_off);
-  cstate->msg = NULL;
-  if (NULL != cstate->send_task)
-  {
-    GNUNET_SCHEDULER_cancel (cstate->send_task);
-    cstate->send_task = NULL;
-  }
-}
-
-
-/**
- * Create a message queue to connect to a GNUnet service.
- * If handlers are specfied, receive messages from the connection.
- *
- * @param cfg our configuration
- * @param service_name name of the service to connect to
- * @param handlers handlers for receiving messages, can be NULL
- * @param error_handler error handler
- * @param error_handler_cls closure for the @a error_handler
- * @return the message queue, NULL on error
- */
-struct GNUNET_MQ_Handle *
-GNUNET_CLIENT_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                      const char *service_name,
-                      const struct GNUNET_MQ_MessageHandler *handlers,
-                      GNUNET_MQ_ErrorHandler error_handler,
-                      void *error_handler_cls)
-{
-  struct ClientState *cstate;
-
-  if (GNUNET_OK !=
-      test_service_configuration (service_name,
-                                 cfg))
-    return NULL;
-  cstate = GNUNET_new (struct ClientState);
-  cstate->service_name = GNUNET_strdup (service_name);
-  cstate->cfg = cfg;
-  cstate->retry_task = GNUNET_SCHEDULER_add_now (&start_connect,
-                                                 cstate);
-  cstate->mst = GNUNET_MST_create (&recv_message,
-                                   cstate);
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_have_value (cfg,
-                                       service_name,
-                                       "PORT"))
-  {
-    if (! ( (GNUNET_OK !=
-            GNUNET_CONFIGURATION_get_value_number (cfg,
-                                                   service_name,
-                                                   "PORT",
-                                                   &cstate->port)) ||
-           (cstate->port > 65535) ||
-           (GNUNET_OK !=
-            GNUNET_CONFIGURATION_get_value_string (cfg,
-                                                   service_name,
-                                                   "HOSTNAME",
-                                                   &cstate->hostname)) ) &&
-       (0 == strlen (cstate->hostname)) )
-    {
-      GNUNET_free (cstate->hostname);
-      cstate->hostname = NULL;
-      LOG (GNUNET_ERROR_TYPE_WARNING,
-          _("Need a non-empty hostname for service `%s'.\n"),
-          service_name);
-    }
-  }
-  cstate->mq = GNUNET_MQ_queue_for_callbacks (&connection_client_send_impl,
-                                             &connection_client_destroy_impl,
-                                             &connection_client_cancel_impl,
-                                             cstate,
-                                             handlers,
-                                             error_handler,
-                                             error_handler_cls);
-  return cstate->mq;
-}
-
-/* end of client_new.c */
index 5989db00cf2f717fc1b6dfe3609dde4e71709c62..ce229826ef4b1829a69a4589dc9db2c7595a3894 100644 (file)
@@ -1152,6 +1152,29 @@ GNUNET_h2s (const struct GNUNET_HashCode * hc)
 }
 
 
+/**
+ * @ingroup logging
+ * Convert a short hash value to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant!
+ *
+ * @param shc the hash code
+ * @return string
+ */
+const char *
+GNUNET_sh2s (const struct GNUNET_ShortHashCode *shc)
+{
+  static char buf[32];
+
+  GNUNET_STRINGS_data_to_string (shc,
+                                 sizeof (*shc),
+                                 buf,
+                                 sizeof (buf));
+  buf[6] = '\0';
+  return (const char *) buf;
+}
+
+
 /**
  * Convert a hash to a string (for printing debug messages).
  * This is one of the very few calls in the entire API that is
index 4f82fb076cb3704aa1e8b4bf69378b2969368e9d..1ead5ec6d79879bfcd585352210373628c496433 100644 (file)
@@ -541,36 +541,23 @@ GNUNET_CONTAINER_heap_remove_node (struct GNUNET_CONTAINER_HeapNode *node)
 /**
  * Updates the cost of any node in the tree
  *
- * @param heap heap to modify
  * @param node node for which the cost is to be changed
  * @param new_cost new cost for the node
  */
 void
-GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_Heap *heap,
-                                   struct GNUNET_CONTAINER_HeapNode *node,
+GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_HeapNode *node,
                                    GNUNET_CONTAINER_HeapCostType new_cost)
 {
-#if EXTRA_CHECKS
-  GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) ||
-                 (heap->size == heap->root->tree_size + 1));
-  CHECK (heap->root);
-#endif
+  struct GNUNET_CONTAINER_Heap *heap = node->heap;
+
   remove_node (node);
-#if EXTRA_CHECKS
-  CHECK (heap->root);
-  GNUNET_assert (((heap->size == 1) && (heap->root == NULL)) ||
-                 (heap->size == heap->root->tree_size + 2));
-#endif
   node->cost = new_cost;
-  if (heap->root == NULL)
+  if (NULL == heap->root)
     heap->root = node;
   else
-    insert_node (heap, heap->root, node);
-#if EXTRA_CHECKS
-  CHECK (heap->root);
-  GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) ||
-                 (heap->size == heap->root->tree_size + 1));
-#endif
+    insert_node (heap,
+                 heap->root,
+                 node);
 }
 
 
diff --git a/src/util/container_multishortmap.c b/src/util/container_multishortmap.c
new file mode 100644 (file)
index 0000000..5e8a47b
--- /dev/null
@@ -0,0 +1,965 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2008, 2012 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file util/container_multishortmap.c
+ * @brief hash map where the same key may be present multiple times
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+
+/**
+ * An entry in the hash map with the full key.
+ */
+struct BigMapEntry
+{
+
+  /**
+   * Value of the entry.
+   */
+  void *value;
+
+  /**
+   * If there is a hash collision, we create a linked list.
+   */
+  struct BigMapEntry *next;
+
+  /**
+   * Key for the entry.
+   */
+  struct GNUNET_ShortHashCode key;
+
+};
+
+
+/**
+ * An entry in the hash map with just a pointer to the key.
+ */
+struct SmallMapEntry
+{
+
+  /**
+   * Value of the entry.
+   */
+  void *value;
+
+  /**
+   * If there is a hash collision, we create a linked list.
+   */
+  struct SmallMapEntry *next;
+
+  /**
+   * Key for the entry.
+   */
+  const struct GNUNET_ShortHashCode *key;
+
+};
+
+
+/**
+ * Entry in the map.
+ */
+union MapEntry
+{
+  /**
+   * Variant used if map entries only contain a pointer to the key.
+   */
+  struct SmallMapEntry *sme;
+
+  /**
+   * Variant used if map entries contain the full key.
+   */
+  struct BigMapEntry *bme;
+};
+
+
+/**
+ * Internal representation of the hash map.
+ */
+struct GNUNET_CONTAINER_MultiShortmap
+{
+  /**
+   * All of our buckets.
+   */
+  union MapEntry *map;
+
+  /**
+   * Number of entries in the map.
+   */
+  unsigned int size;
+
+  /**
+   * Length of the "map" array.
+   */
+  unsigned int map_length;
+
+  /**
+   * GNUNET_NO if the map entries are of type 'struct BigMapEntry',
+   * GNUNET_YES if the map entries are of type 'struct SmallMapEntry'.
+   */
+  int use_small_entries;
+
+  /**
+   * Counts the destructive modifications (grow, remove)
+   * to the map, so that iterators can check if they are still valid.
+   */
+  unsigned int modification_counter;
+};
+
+
+/**
+ * Cursor into a multishortmap.
+ * Allows to enumerate elements asynchronously.
+ */
+struct GNUNET_CONTAINER_MultiShortmapIterator
+{
+  /**
+   * Position in the bucket 'idx'
+   */
+  union MapEntry me;
+
+  /**
+   * Current bucket index.
+   */
+  unsigned int idx;
+
+  /**
+   * Modification counter as observed on the map when the iterator
+   * was created.
+   */
+  unsigned int modification_counter;
+
+  /**
+   * Map that we are iterating over.
+   */
+  const struct GNUNET_CONTAINER_MultiShortmap *map;
+};
+
+
+/**
+ * Create a multi hash map.
+ *
+ * @param len initial size (map will grow as needed)
+ * @param do_not_copy_keys GNUNET_NO is always safe and should be used by default;
+ *                         GNUNET_YES means that on 'put', the 'key' does not have
+ *                         to be copied as the destination of the pointer is
+ *                         guaranteed to be life as long as the value is stored in
+ *                         the hashmap.  This can significantly reduce memory
+ *                         consumption, but of course is also a recipie for
+ *                         heap corruption if the assumption is not true.  Only
+ *                         use this if (1) memory use is important in this case and
+ *                         (2) you have triple-checked that the invariant holds
+ * @return NULL on error
+ */
+struct GNUNET_CONTAINER_MultiShortmap *
+GNUNET_CONTAINER_multishortmap_create (unsigned int len,
+                                     int do_not_copy_keys)
+{
+  struct GNUNET_CONTAINER_MultiShortmap *map;
+
+  GNUNET_assert (len > 0);
+  map = GNUNET_new (struct GNUNET_CONTAINER_MultiShortmap);
+  map->map = GNUNET_malloc (len * sizeof (union MapEntry));
+  map->map_length = len;
+  map->use_small_entries = do_not_copy_keys;
+  return map;
+}
+
+
+/**
+ * Destroy a hash map.  Will not free any values
+ * stored in the hash map!
+ *
+ * @param map the map
+ */
+void
+GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap
+                                       *map)
+{
+  unsigned int i;
+  union MapEntry me;
+
+  for (i = 0; i < map->map_length; i++)
+  {
+    me = map->map[i];
+    if (map->use_small_entries)
+    {
+      struct SmallMapEntry *sme;
+      struct SmallMapEntry *nxt;
+
+      nxt = me.sme;
+      while (NULL != (sme = nxt))
+      {
+       nxt = sme->next;
+       GNUNET_free (sme);
+      }
+      me.sme = NULL;
+    }
+    else
+    {
+      struct BigMapEntry *bme;
+      struct BigMapEntry *nxt;
+
+      nxt = me.bme;
+      while (NULL != (bme = nxt))
+      {
+       nxt = bme->next;
+       GNUNET_free (bme);
+      }
+      me.bme = NULL;
+    }
+  }
+  GNUNET_free (map->map);
+  GNUNET_free (map);
+}
+
+
+/**
+ * Compute the index of the bucket for the given key.
+ *
+ * @param map hash map for which to compute the index
+ * @param key what key should the index be computed for
+ * @return offset into the "map" array of "map"
+ */
+static unsigned int
+idx_of (const struct GNUNET_CONTAINER_MultiShortmap *map,
+        const struct GNUNET_ShortHashCode *key)
+{
+  unsigned int kx;
+
+  GNUNET_assert (NULL != map);
+  GNUNET_memcpy (&kx, key, sizeof (kx));
+  return kx % map->map_length;
+}
+
+
+/**
+ * Get the number of key-value pairs in the map.
+ *
+ * @param map the map
+ * @return the number of key value pairs
+ */
+unsigned int
+GNUNET_CONTAINER_multishortmap_size (const struct GNUNET_CONTAINER_MultiShortmap *map)
+{
+  return map->size;
+}
+
+
+/**
+ * Given a key find a value in the map matching the key.
+ *
+ * @param map the map
+ * @param key what to look for
+ * @return NULL if no value was found; note that
+ *   this is indistinguishable from values that just
+ *   happen to be NULL; use "contains" to test for
+ *   key-value pairs with value NULL
+ */
+void *
+GNUNET_CONTAINER_multishortmap_get (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                    const struct GNUNET_ShortHashCode *key)
+{
+  union MapEntry me;
+
+  me = map->map[idx_of (map, key)];
+  if (map->use_small_entries)
+  {
+    struct SmallMapEntry *sme;
+
+    for (sme = me.sme; NULL != sme; sme = sme->next)
+      if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
+       return sme->value;
+  }
+  else
+  {
+    struct BigMapEntry *bme;
+
+    for (bme = me.bme; NULL != bme; bme = bme->next)
+      if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
+       return bme->value;
+  }
+  return NULL;
+}
+
+
+/**
+ * Iterate over all entries in the map.
+ *
+ * @param map the map
+ * @param it function to call on each entry
+ * @param it_cls extra argument to @a it
+ * @return the number of key value pairs processed,
+ *         #GNUNET_SYSERR if it aborted iteration
+ */
+int
+GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                       GNUNET_CONTAINER_ShortmapIterator it,
+                                       void *it_cls)
+{
+  int count;
+  unsigned int i;
+  union MapEntry me;
+  struct GNUNET_ShortHashCode kc;
+
+  count = 0;
+  GNUNET_assert (NULL != map);
+  for (i = 0; i < map->map_length; i++)
+  {
+    me = map->map[i];
+    if (map->use_small_entries)
+    {
+      struct SmallMapEntry *sme;
+      struct SmallMapEntry *nxt;
+
+      nxt = me.sme;
+      while (NULL != (sme = nxt))
+      {
+       nxt = sme->next;
+       if (NULL != it)
+       {
+         if (GNUNET_OK != it (it_cls, sme->key, sme->value))
+           return GNUNET_SYSERR;
+       }
+       count++;
+      }
+    }
+    else
+    {
+      struct BigMapEntry *bme;
+      struct BigMapEntry *nxt;
+
+      nxt = me.bme;
+      while (NULL != (bme = nxt))
+      {
+       nxt = bme->next;
+       if (NULL != it)
+       {
+         kc = bme->key;
+         if (GNUNET_OK != it (it_cls, &kc, bme->value))
+           return GNUNET_SYSERR;
+       }
+       count++;
+      }
+    }
+  }
+  return count;
+}
+
+
+/**
+ * Remove the given key-value pair from the map.  Note that if the
+ * key-value pair is in the map multiple times, only one of the pairs
+ * will be removed.
+ *
+ * @param map the map
+ * @param key key of the key-value pair
+ * @param value value of the key-value pair
+ * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair
+ *  is not in the map
+ */
+int
+GNUNET_CONTAINER_multishortmap_remove (struct GNUNET_CONTAINER_MultiShortmap *map,
+                                       const struct GNUNET_ShortHashCode *key,
+                                       const void *value)
+{
+  union MapEntry me;
+  unsigned int i;
+
+  map->modification_counter++;
+
+  i = idx_of (map, key);
+  me = map->map[i];
+  if (map->use_small_entries)
+  {
+    struct SmallMapEntry *sme;
+    struct SmallMapEntry *p;
+
+    p = NULL;
+    for (sme = me.sme; NULL != sme; sme = sme->next)
+    {
+      if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) &&
+         (value == sme->value))
+      {
+       if (NULL == p)
+         map->map[i].sme = sme->next;
+       else
+         p->next = sme->next;
+       GNUNET_free (sme);
+       map->size--;
+       return GNUNET_YES;
+      }
+      p = sme;
+    }
+  }
+  else
+  {
+    struct BigMapEntry *bme;
+    struct BigMapEntry *p;
+
+    p = NULL;
+    for (bme = me.bme; NULL != bme; bme = bme->next)
+    {
+      if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) &&
+         (value == bme->value))
+      {
+       if (NULL == p)
+         map->map[i].bme = bme->next;
+       else
+         p->next = bme->next;
+       GNUNET_free (bme);
+       map->size--;
+       return GNUNET_YES;
+      }
+      p = bme;
+    }
+  }
+  return GNUNET_NO;
+}
+
+
+/**
+ * Remove all entries for the given key from the map.
+ * Note that the values would not be "freed".
+ *
+ * @param map the map
+ * @param key identifies values to be removed
+ * @return number of values removed
+ */
+int
+GNUNET_CONTAINER_multishortmap_remove_all (struct GNUNET_CONTAINER_MultiShortmap *map,
+                                           const struct GNUNET_ShortHashCode *key)
+{
+  union MapEntry me;
+  unsigned int i;
+  int ret;
+
+  map->modification_counter++;
+
+  ret = 0;
+  i = idx_of (map, key);
+  me = map->map[i];
+  if (map->use_small_entries)
+  {
+    struct SmallMapEntry *sme;
+    struct SmallMapEntry *p;
+
+    p = NULL;
+    sme = me.sme;
+    while (NULL != sme)
+    {
+      if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
+      {
+       if (NULL == p)
+         map->map[i].sme = sme->next;
+       else
+         p->next = sme->next;
+       GNUNET_free (sme);
+       map->size--;
+       if (NULL == p)
+         sme = map->map[i].sme;
+       else
+         sme = p->next;
+       ret++;
+      }
+      else
+      {
+       p = sme;
+       sme = sme->next;
+      }
+    }
+  }
+  else
+  {
+    struct BigMapEntry *bme;
+    struct BigMapEntry *p;
+
+    p = NULL;
+    bme = me.bme;
+    while (NULL != bme)
+    {
+      if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
+      {
+       if (NULL == p)
+         map->map[i].bme = bme->next;
+       else
+         p->next = bme->next;
+       GNUNET_free (bme);
+       map->size--;
+       if (NULL == p)
+         bme = map->map[i].bme;
+       else
+         bme = p->next;
+       ret++;
+      }
+      else
+      {
+       p = bme;
+       bme = bme->next;
+      }
+    }
+  }
+  return ret;
+}
+
+
+/**
+ * Check if the map contains any value under the given
+ * key (including values that are NULL).
+ *
+ * @param map the map
+ * @param key the key to test if a value exists for it
+ * @return #GNUNET_YES if such a value exists,
+ *         #GNUNET_NO if not
+ */
+int
+GNUNET_CONTAINER_multishortmap_contains (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                         const struct GNUNET_ShortHashCode *key)
+{
+  union MapEntry me;
+
+  me = map->map[idx_of (map, key)];
+  if (map->use_small_entries)
+  {
+    struct SmallMapEntry *sme;
+
+    for (sme = me.sme; NULL != sme; sme = sme->next)
+      if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
+       return GNUNET_YES;
+  }
+  else
+  {
+    struct BigMapEntry *bme;
+
+    for (bme = me.bme; NULL != bme; bme = bme->next)
+      if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
+       return GNUNET_YES;
+  }
+  return GNUNET_NO;
+}
+
+
+/**
+ * Check if the map contains the given value under the given
+ * key.
+ *
+ * @param map the map
+ * @param key the key to test if a value exists for it
+ * @param value value to test for
+ * @return #GNUNET_YES if such a value exists,
+ *         #GNUNET_NO if not
+ */
+int
+GNUNET_CONTAINER_multishortmap_contains_value (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                               const struct GNUNET_ShortHashCode *key,
+                                               const void *value)
+{
+  union MapEntry me;
+
+  me = map->map[idx_of (map, key)];
+  if (map->use_small_entries)
+  {
+    struct SmallMapEntry *sme;
+
+    for (sme = me.sme; NULL != sme; sme = sme->next)
+      if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) &&
+          (sme->value == value) )
+       return GNUNET_YES;
+  }
+  else
+  {
+    struct BigMapEntry *bme;
+
+    for (bme = me.bme; NULL != bme; bme = bme->next)
+      if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) &&
+          (bme->value == value) )
+       return GNUNET_YES;
+  }
+  return GNUNET_NO;
+}
+
+
+/**
+ * Grow the given map to a more appropriate size.
+ *
+ * @param map the hash map to grow
+ */
+static void
+grow (struct GNUNET_CONTAINER_MultiShortmap *map)
+{
+  union MapEntry *old_map;
+  union MapEntry *new_map;
+  unsigned int old_len;
+  unsigned int new_len;
+  unsigned int idx;
+  unsigned int i;
+
+  map->modification_counter++;
+
+  old_map = map->map;
+  old_len = map->map_length;
+  new_len = old_len * 2;
+  new_map = GNUNET_malloc (sizeof (union MapEntry) * new_len);
+  map->map_length = new_len;
+  map->map = new_map;
+  for (i = 0; i < old_len; i++)
+  {
+    if (map->use_small_entries)
+    {
+      struct SmallMapEntry *sme;
+
+      while (NULL != (sme = old_map[i].sme))
+      {
+       old_map[i].sme = sme->next;
+       idx = idx_of (map, sme->key);
+       sme->next = new_map[idx].sme;
+       new_map[idx].sme = sme;
+      }
+    }
+    else
+    {
+      struct BigMapEntry *bme;
+
+      while (NULL != (bme = old_map[i].bme))
+      {
+       old_map[i].bme = bme->next;
+       idx = idx_of (map, &bme->key);
+       bme->next = new_map[idx].bme;
+       new_map[idx].bme = bme;
+      }
+    }
+  }
+  GNUNET_free (old_map);
+}
+
+
+/**
+ * Store a key-value pair in the map.
+ *
+ * @param map the map
+ * @param key key to use
+ * @param value value to use
+ * @param opt options for put
+ * @return #GNUNET_OK on success,
+ *         #GNUNET_NO if a value was replaced (with REPLACE)
+ *         #GNUNET_SYSERR if GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the
+ *                       value already exists
+ */
+int
+GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map,
+                                    const struct GNUNET_ShortHashCode *key,
+                                    void *value,
+                                    enum GNUNET_CONTAINER_MultiHashMapOption opt)
+{
+  union MapEntry me;
+  unsigned int i;
+
+  i = idx_of (map, key);
+  if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) &&
+      (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+  {
+    me = map->map[i];
+    if (map->use_small_entries)
+    {
+      struct SmallMapEntry *sme;
+
+      for (sme = me.sme; NULL != sme; sme = sme->next)
+       if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
+       {
+         if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)
+           return GNUNET_SYSERR;
+         sme->value = value;
+         return GNUNET_NO;
+       }
+    }
+    else
+    {
+      struct BigMapEntry *bme;
+
+      for (bme = me.bme; NULL != bme; bme = bme->next)
+       if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
+       {
+         if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)
+           return GNUNET_SYSERR;
+         bme->value = value;
+         return GNUNET_NO;
+       }
+    }
+  }
+  if (map->size / 3 >= map->map_length / 4)
+  {
+    grow (map);
+    i = idx_of (map, key);
+  }
+  if (map->use_small_entries)
+  {
+    struct SmallMapEntry *sme;
+
+    sme = GNUNET_new (struct SmallMapEntry);
+    sme->key = key;
+    sme->value = value;
+    sme->next = map->map[i].sme;
+    map->map[i].sme = sme;
+  }
+  else
+  {
+    struct BigMapEntry *bme;
+
+    bme = GNUNET_new (struct BigMapEntry);
+    bme->key = *key;
+    bme->value = value;
+    bme->next = map->map[i].bme;
+    map->map[i].bme = bme;
+  }
+  map->size++;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Iterate over all entries in the map that match a particular key.
+ *
+ * @param map the map
+ * @param key key that the entries must correspond to
+ * @param it function to call on each entry
+ * @param it_cls extra argument to @a it
+ * @return the number of key value pairs processed,
+ *         #GNUNET_SYSERR if it aborted iteration
+ */
+int
+GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                             const struct GNUNET_ShortHashCode *key,
+                                             GNUNET_CONTAINER_ShortmapIterator it,
+                                             void *it_cls)
+{
+  int count;
+  union MapEntry me;
+
+  count = 0;
+  me = map->map[idx_of (map, key)];
+  if (map->use_small_entries)
+  {
+    struct SmallMapEntry *sme;
+    struct SmallMapEntry *nxt;
+
+    nxt = me.sme;
+    while (NULL != (sme = nxt))
+    {
+      nxt = sme->next;
+      if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
+       continue;
+      if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value)))
+       return GNUNET_SYSERR;
+      count++;
+    }
+  }
+  else
+  {
+    struct BigMapEntry *bme;
+    struct BigMapEntry *nxt;
+
+    nxt = me.bme;
+    while (NULL != (bme = nxt))
+    {
+      nxt = bme->next;
+      if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
+       continue;
+      if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value)))
+       return GNUNET_SYSERR;
+      count++;
+    }
+  }
+  return count;
+}
+
+
+/**
+ * @ingroup hashmap
+ * Call @a it on a random value from the map, or not at all
+ * if the map is empty.  Note that this function has linear
+ * complexity (in the size of the map).
+ *
+ * @param map the map
+ * @param it function to call on a random entry
+ * @param it_cls extra argument to @a it
+ * @return the number of key value pairs processed, zero or one.
+ */
+unsigned int
+GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiShortmap *map,
+                                          GNUNET_CONTAINER_ShortmapIterator it,
+                                          void *it_cls)
+{
+  unsigned int off;
+  unsigned int idx;
+  union MapEntry me;
+
+  if (0 == map->size)
+    return 0;
+  if (NULL == it)
+    return 1;
+  off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                  map->size);
+  for (idx = 0; idx < map->map_length; idx++)
+  {
+    me = map->map[idx];
+    if (map->use_small_entries)
+    {
+      struct SmallMapEntry *sme;
+      struct SmallMapEntry *nxt;
+
+      nxt = me.sme;
+      while (NULL != (sme = nxt))
+      {
+        nxt = sme->next;
+        if (0 == off)
+        {
+          if (GNUNET_OK != it (it_cls,
+                               sme->key,
+                               sme->value))
+            return GNUNET_SYSERR;
+          return 1;
+        }
+        off--;
+      }
+    }
+    else
+    {
+      struct BigMapEntry *bme;
+      struct BigMapEntry *nxt;
+
+      nxt = me.bme;
+      while (NULL != (bme = nxt))
+      {
+        nxt = bme->next;
+        if (0 == off)
+        {
+          if (GNUNET_OK != it (it_cls,
+                               &bme->key, bme->value))
+            return GNUNET_SYSERR;
+          return 1;
+        }
+        off--;
+      }
+    }
+  }
+  GNUNET_break (0);
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Create an iterator for a multishortmap.
+ * The iterator can be used to retrieve all the elements in the multishortmap
+ * one by one, without having to handle all elements at once (in contrast to
+ * #GNUNET_CONTAINER_multishortmap_iterate).  Note that the iterator can not be
+ * used anymore if elements have been removed from 'map' after the creation of
+ * the iterator, or 'map' has been destroyed.  Adding elements to 'map' may
+ * result in skipped or repeated elements.
+ *
+ * @param map the map to create an iterator for
+ * @return an iterator over the given multishortmap 'map'
+ */
+struct GNUNET_CONTAINER_MultiShortmapIterator *
+GNUNET_CONTAINER_multishortmap_iterator_create (const struct GNUNET_CONTAINER_MultiShortmap *map)
+{
+  struct GNUNET_CONTAINER_MultiShortmapIterator *iter;
+
+  iter = GNUNET_new (struct GNUNET_CONTAINER_MultiShortmapIterator);
+  iter->map = map;
+  iter->modification_counter = map->modification_counter;
+  iter->me = map->map[0];
+  return iter;
+}
+
+
+/**
+ * Retrieve the next element from the hash map at the iterator's position.
+ * If there are no elements left, GNUNET_NO is returned, and 'key' and 'value'
+ * are not modified.
+ * This operation is only allowed if no elements have been removed from the
+ * multishortmap since the creation of 'iter', and the map has not been destroyed.
+ * Adding elements may result in repeating or skipping elements.
+ *
+ * @param iter the iterator to get the next element from
+ * @param key pointer to store the key in, can be NULL
+ * @param value pointer to store the value in, can be NULL
+ * @return #GNUNET_YES we returned an element,
+ *         #GNUNET_NO if we are out of elements
+ */
+int
+GNUNET_CONTAINER_multishortmap_iterator_next (struct GNUNET_CONTAINER_MultiShortmapIterator *iter,
+                                              struct GNUNET_ShortHashCode *key,
+                                              const void **value)
+{
+  /* make sure the map has not been modified */
+  GNUNET_assert (iter->modification_counter == iter->map->modification_counter);
+
+  /* look for the next entry, skipping empty buckets */
+  while (1)
+  {
+    if (iter->idx >= iter->map->map_length)
+      return GNUNET_NO;
+    if (GNUNET_YES == iter->map->use_small_entries)
+    {
+      if (NULL != iter->me.sme)
+      {
+        if (NULL != key)
+          *key = *iter->me.sme->key;
+        if (NULL != value)
+          *value = iter->me.sme->value;
+        iter->me.sme = iter->me.sme->next;
+        return GNUNET_YES;
+      }
+    }
+    else
+    {
+      if (NULL != iter->me.bme)
+      {
+        if (NULL != key)
+          *key = iter->me.bme->key;
+        if (NULL != value)
+          *value = iter->me.bme->value;
+        iter->me.bme = iter->me.bme->next;
+        return GNUNET_YES;
+      }
+    }
+    iter->idx += 1;
+    if (iter->idx < iter->map->map_length)
+      iter->me = iter->map->map[iter->idx];
+  }
+}
+
+
+/**
+ * Destroy a multishortmap iterator.
+ *
+ * @param iter the iterator to destroy
+ */
+void
+GNUNET_CONTAINER_multishortmap_iterator_destroy (struct GNUNET_CONTAINER_MultiShortmapIterator *iter)
+{
+  GNUNET_free (iter);
+}
+
+
+/* end of container_multishortmap.c */
index ae13ff60156c2408ef3afc5a6ba1b83c8df52b15..985e8633120d815f55c33daf830e49289106e6d0 100644 (file)
@@ -58,7 +58,7 @@ struct GNUNET_MQ_Envelope
   /**
    * Called after the message was sent irrevocably.
    */
-  GNUNET_MQ_NotifyCallback sent_cb;
+  GNUNET_SCHEDULER_TaskCallback sent_cb;
 
   /**
    * Closure for @e send_cb
@@ -128,10 +128,10 @@ struct GNUNET_MQ_Handle
   void *error_handler_cls;
 
   /**
-   * Task to asynchronously run #impl_send_continue(). 
+   * Task to asynchronously run #impl_send_continue().
    */
   struct GNUNET_SCHEDULER_Task *send_task;
-  
+
   /**
    * Linked list of messages pending to be sent
    */
@@ -414,7 +414,7 @@ static void
 impl_send_continue (void *cls)
 {
   struct GNUNET_MQ_Handle *mq = cls;
-  
+
   mq->send_task = NULL;
   /* call is only valid if we're actually currently sending
    * a message */
@@ -441,8 +441,8 @@ void
 GNUNET_MQ_impl_send_continue (struct GNUNET_MQ_Handle *mq)
 {
   struct GNUNET_MQ_Envelope *current_envelope;
-  GNUNET_MQ_NotifyCallback cb;
-  
+  GNUNET_SCHEDULER_TaskCallback cb;
+
   GNUNET_assert (0 < mq->queue_length);
   mq->queue_length--;
   mq->in_flight = GNUNET_NO;
@@ -456,7 +456,7 @@ GNUNET_MQ_impl_send_continue (struct GNUNET_MQ_Handle *mq)
   {
     current_envelope->sent_cb = NULL;
     cb (current_envelope->sent_cls);
-  }  
+  }
   GNUNET_free (current_envelope);
 }
 
@@ -475,8 +475,8 @@ void
 GNUNET_MQ_impl_send_in_flight (struct GNUNET_MQ_Handle *mq)
 {
   struct GNUNET_MQ_Envelope *current_envelope;
-  GNUNET_MQ_NotifyCallback cb;
-  
+  GNUNET_SCHEDULER_TaskCallback cb;
+
   mq->in_flight = GNUNET_YES;
   /* call is only valid if we're actually currently sending
    * a message */
@@ -812,7 +812,7 @@ GNUNET_MQ_assoc_remove (struct GNUNET_MQ_Handle *mq,
  */
 void
 GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *mqm,
-                       GNUNET_MQ_NotifyCallback cb,
+                       GNUNET_SCHEDULER_TaskCallback cb,
                        void *cb_cls)
 {
   mqm->sent_cb = cb;
@@ -953,7 +953,7 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev)
 
   GNUNET_assert (NULL != mq);
   GNUNET_assert (NULL != mq->cancel_impl);
-  
+
   mq->evacuate_called = GNUNET_NO;
 
   if (mq->current_envelope == ev)
index 481e99157ed641e5ffd46699a4390f32d644ae3c..fdeaed0065347d646b5caa00b92605643b3212c7 100644 (file)
@@ -735,7 +735,7 @@ reconnect_task (void *cls)
     return;                     /* no work pending */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Trying to connect to DNS service\n");
-  mq = GNUNET_CLIENT_connecT (resolver_cfg,
+  mq = GNUNET_CLIENT_connect (resolver_cfg,
                               "resolver",
                               handlers,
                               &mq_error_handler,
index aa4d8449534717b0532abb6487b6d7ffcf4afef2..f60e5b7f7513a9f55b932ff9cf874d37f353d768 100644 (file)
@@ -98,12 +98,12 @@ task (void *cls,
 
   /* test that ill-configured client fails instantly */
   GNUNET_assert (NULL ==
-                GNUNET_CLIENT_connecT (cfg,
+                GNUNET_CLIENT_connect (cfg,
                                        "invalid-service",
                                        NULL,
                                        &mq_error_handler,
                                        NULL));
-  client_mq = GNUNET_CLIENT_connecT (cfg,
+  client_mq = GNUNET_CLIENT_connect (cfg,
                                     "test_client",
                                     chandlers,
                                     &mq_error_handler,
index f115159bf8561eb8ba410c184d3e22a29b2aa726..82b0e9523809077269b912eebfc65e80dad149b5 100644 (file)
@@ -28,7 +28,8 @@
 #include "gnunet_util_lib.h"
 
 static int
-iterator_callback (void *cls, struct GNUNET_CONTAINER_HeapNode *node,
+iterator_callback (void *cls,
+                   struct GNUNET_CONTAINER_HeapNode *node,
                    void *element, GNUNET_CONTAINER_HeapCostType cost)
 {
   return GNUNET_OK;
@@ -93,12 +94,12 @@ check ()
   GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL);
 
   n3 = GNUNET_CONTAINER_heap_insert (myHeap, "15", 5);
-  GNUNET_CONTAINER_heap_update_cost (myHeap, n3, 15);
+  GNUNET_CONTAINER_heap_update_cost (n3, 15);
   GNUNET_assert (2 == GNUNET_CONTAINER_heap_get_size (myHeap));
   GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL);
 
   n4 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50);
-  GNUNET_CONTAINER_heap_update_cost (myHeap, n4, 50);
+  GNUNET_CONTAINER_heap_update_cost (n4, 50);
   GNUNET_assert (3 == GNUNET_CONTAINER_heap_get_size (myHeap));
   GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL);
 
@@ -109,7 +110,7 @@ check ()
   r = GNUNET_CONTAINER_heap_remove_root (myHeap);       /* n1 */
   GNUNET_assert (NULL != r);
   GNUNET_assert (0 == strcmp ("11", r));
-  GNUNET_CONTAINER_heap_update_cost (myHeap, n6, 200);
+  GNUNET_CONTAINER_heap_update_cost (n6, 200);
   GNUNET_CONTAINER_heap_remove_node (n3);
   r = GNUNET_CONTAINER_heap_remove_root (myHeap);       /* n4 */
   GNUNET_assert (NULL != r);
@@ -128,7 +129,7 @@ check ()
   myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
 
   n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10);
-  GNUNET_CONTAINER_heap_update_cost (myHeap, n1, 15);
+  GNUNET_CONTAINER_heap_update_cost (n1, 15);
 
   r = GNUNET_CONTAINER_heap_remove_node (n1);
   GNUNET_assert (NULL != r);
@@ -213,7 +214,7 @@ check ()
   myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX);
 
   n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10);
-  GNUNET_CONTAINER_heap_update_cost (myHeap, n1, 15);
+  GNUNET_CONTAINER_heap_update_cost (n1, 15);
 
   GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1)));
 
index eac45fc6979184bc6b92f73cff89707d7a08161e..8003adbf4c3a7bcb24fc9b413c7d688dc01aa0a6 100644 (file)
@@ -267,7 +267,7 @@ task (void *cls)
                                          "resolver",
                                          "HOSTNAME",
                                          "localhost");
-  mq = GNUNET_CLIENT_connecT (cfg,
+  mq = GNUNET_CLIENT_connect (cfg,
                               "test-server",
                               chandlers,
                               &mq_error_handler,
index de9c4722d63d59eeaabfb8194528ebaa2a5ded7d..c3d003e9099180bffed0ae52e8aa9edce9cfad27 100644 (file)
@@ -125,7 +125,7 @@ task (void *cls)
                                          "localhost");
   GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME",
                                          "localhost");
-  mq = GNUNET_CLIENT_connecT (cfg,
+  mq = GNUNET_CLIENT_connect (cfg,
                               "test-server",
                               NULL,
                               NULL,
index 59f9b6afd05530e4ceae172d5386c53c9406c4bb..63bfda00cf6c288fa21457b4524031dd81c16dfc 100644 (file)
@@ -166,7 +166,7 @@ task (void *cls)
   GNUNET_CONFIGURATION_set_value_string (cfg, "test", "HOSTNAME", "localhost");
   GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME",
                                          "localhost");
-  mq = GNUNET_CLIENT_connecT (cfg,
+  mq = GNUNET_CLIENT_connect (cfg,
                               "test",
                               NULL,
                               NULL,
index ef48aabcec9a04dd2b0d1ce54409d01c71facc9f..d240f1a88a751d39d2618595a6c26bd463a7e38f 100644 (file)
@@ -144,7 +144,7 @@ task (void *cls)
   GNUNET_CONFIGURATION_set_value_string (cfg, "test", "UNIXPATH", unixpath);
   GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME",
                                          "localhost");
-  mq = GNUNET_CLIENT_connecT (cfg,
+  mq = GNUNET_CLIENT_connect (cfg,
                               "test",
                               NULL,
                               NULL,
index dc9d16ed999bf2fdcbad188811d3f0a78ef619bd..d2136b42f0a8881a89a175e506e79e26ec6eda7b 100644 (file)
@@ -107,7 +107,7 @@ service_init (void *cls,
   struct GNUNET_MQ_Envelope *env;
   struct GNUNET_MessageHeader *msg;
   
-  mq = GNUNET_CLIENT_connecT (cfg,
+  mq = GNUNET_CLIENT_connect (cfg,
                               service_name,
                               NULL,
                               NULL,
index 416f32f62ca4dd3cc06953e96e22275100f61be3..cb70f916fb86b52680ce25f229d044d22d944fdc 100644 (file)
@@ -160,7 +160,7 @@ task (void *cls)
   handlers[0].callback_cls = cls;
   handlers[1].callback_cls = cls;
   GNUNET_SERVER_add_handlers (server, handlers);
-  mq = GNUNET_CLIENT_connecT (cfg,
+  mq = GNUNET_CLIENT_connect (cfg,
                               MYNAME,
                               chandlers,
                               &mq_error_handler,
index 4c0978d5c93838fa6f0015078ddc142926eaaa3e..c66023c8572098b3c352f58b98e1335e56353831 100644 (file)
@@ -1129,8 +1129,7 @@ route_packet (struct DestinationEntry *destination,
   }
   else
   {
-    GNUNET_CONTAINER_heap_update_cost (channel_heap,
-                                      ts->heap_node,
+    GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
                                       GNUNET_TIME_absolute_get ().abs_value_us);
   }
   if (NULL == ts->channel)
@@ -2062,8 +2061,7 @@ receive_icmp_back (void *cls,
   default:
     GNUNET_assert (0);
   }
-  GNUNET_CONTAINER_heap_update_cost (channel_heap,
-                                    ts->heap_node,
+  GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
                                     GNUNET_TIME_absolute_get ().abs_value_us);
   GNUNET_CADET_receive_done (channel);
   return GNUNET_OK;
@@ -2218,8 +2216,7 @@ receive_udp_back (void *cls,
   default:
     GNUNET_assert (0);
   }
-  GNUNET_CONTAINER_heap_update_cost (channel_heap,
-                                    ts->heap_node,
+  GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
                                     GNUNET_TIME_absolute_get ().abs_value_us);
   GNUNET_CADET_receive_done (channel);
   return GNUNET_OK;
@@ -2361,8 +2358,7 @@ receive_tcp_back (void *cls,
     }
     break;
   }
-  GNUNET_CONTAINER_heap_update_cost (channel_heap,
-                                    ts->heap_node,
+  GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
                                     GNUNET_TIME_absolute_get ().abs_value_us);
   GNUNET_CADET_receive_done (channel);
   return GNUNET_OK;
index 000300084401d3df6326e11e3ee8cb1273e307e8..58513155463c2a4badba5b90b9647afc355f83ab 100644 (file)
@@ -6,7 +6,7 @@ BINARY = gnunet-service-vpn
 ACCEPT_FROM = 127.0.0.1;
 ACCEPT_FROM6 = ::1;
 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn.sock
-UNIX_MATCH_UID = YES
+UNIX_MATCH_UID = NO
 UNIX_MATCH_GID = YES
 
 IPV6ADDR = 1234::1
index 4add41ce4d58e5ca4ecaaf326cd80c55fab614db..bc77865a89d0e17799ab2f52079d94a8f494646f 100644 (file)
@@ -324,7 +324,7 @@ connect_task (void *cls)
   struct GNUNET_VPN_RedirectionRequest *rr;
 
   vh->rt = NULL;
-  vh->mq = GNUNET_CLIENT_connecT (vh->cfg,
+  vh->mq = GNUNET_CLIENT_connect (vh->cfg,
                                   "vpn",
                                   handlers,
                                   &mq_error_handler,
diff --git a/src/zonemaster/.gitignore b/src/zonemaster/.gitignore
new file mode 100644 (file)
index 0000000..1a0e22b
--- /dev/null
@@ -0,0 +1 @@
+gnunet-service-zonemaster
diff --git a/src/zonemaster/Makefile.am b/src/zonemaster/Makefile.am
new file mode 100644 (file)
index 0000000..21f9864
--- /dev/null
@@ -0,0 +1,35 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include 
+
+plugindir = $(libdir)/gnunet
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfg_DATA = \
+   zonemaster.conf
+
+if MINGW
+  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIBS = -lgcov
+endif
+
+libexec_PROGRAMS = \
+ gnunet-service-zonemaster
+
+gnunet_service_zonemaster_SOURCES = \
+ gnunet-service-zonemaster.c
+
+gnunet_service_zonemaster_LDADD = \
+  $(top_builddir)/src/dht/libgnunetdht.la \
+  $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/namestore/libgnunetnamestore.la \
+  $(GN_LIBINTL)
+
diff --git a/src/zonemaster/gnunet-service-zonemaster.c b/src/zonemaster/gnunet-service-zonemaster.c
new file mode 100644 (file)
index 0000000..08a09de
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012, 2013, 2014, 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file zonemaster/gnunet-service-zonemaster.c
+ * @brief publish records from namestore to GNUnet name system
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_dht_service.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_namestore_plugin.h"
+#include "gnunet_signatures.h"
+
+
+#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
+
+
+
+/**
+ * The initial interval in milliseconds btween puts in
+ * a zone iteration
+ */
+#define INITIAL_PUT_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS
+
+/**
+ * The lower bound for the zone iteration interval
+ */
+#define MINIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_SECONDS
+
+/**
+ * The upper bound for the zone iteration interval
+ */
+#define MAXIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
+
+/**
+ * The default put interval for the zone iteration. In case
+ * no option is found
+ */
+#define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
+
+/**
+ * The factor the current zone iteration interval is divided by for each
+ * additional new record
+ */
+#define LATE_ITERATION_SPEEDUP_FACTOR 2
+
+/**
+ * How long until a DHT PUT attempt should time out?
+ */
+#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
+
+/**
+ * What replication level do we use for DHT PUT operations?
+ */
+#define DHT_GNS_REPLICATION_LEVEL 5
+
+
+/**
+ * Handle for DHT PUT activity triggered from the namestore monitor.
+ */
+struct MonitorActivity
+{
+  /**
+   * Kept in a DLL.
+   */
+  struct MonitorActivity *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct MonitorActivity *prev;
+
+  /**
+   * Handle for the DHT PUT operation.
+   */
+  struct GNUNET_DHT_PutHandle *ph;
+};
+
+
+/**
+ * Handle to the statistics service
+ */
+static struct GNUNET_STATISTICS_Handle *statistics;
+
+/**
+ * Our handle to the DHT
+ */
+static struct GNUNET_DHT_Handle *dht_handle;
+
+/**
+ * Active DHT put operation (or NULL)
+ */
+static struct GNUNET_DHT_PutHandle *active_put;
+
+/**
+ * Our handle to the namestore service
+ */
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+/**
+ * Handle to iterate over our authoritative zone in namestore
+ */
+static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
+
+/**
+ * Handle to monitor namestore changes to instant propagation.
+ */
+static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
+
+/**
+ * Head of monitor activities; kept in a DLL.
+ */
+static struct MonitorActivity *ma_head;
+
+/**
+ * Tail of monitor activities; kept in a DLL.
+ */
+static struct MonitorActivity *ma_tail;
+
+/**
+ * Useful for zone update for DHT put
+ */
+static unsigned long long num_public_records;
+
+/**
+ * Last seen record count
+ */
+static unsigned long long last_num_public_records;
+
+/**
+ * Minimum relative expiration time of records seem during the current
+ * zone iteration.
+ */
+static struct GNUNET_TIME_Relative min_relative_record_time;
+
+/**
+ * Zone iteration PUT interval.
+ */
+static struct GNUNET_TIME_Relative put_interval;
+
+/**
+ * Default time window for zone iteration
+ */
+static struct GNUNET_TIME_Relative zone_publish_time_window_default;
+
+/**
+ * Time window for zone iteration, adjusted based on relative record
+ * expiration times in our zone.
+ */
+static struct GNUNET_TIME_Relative zone_publish_time_window;
+
+/**
+ * zone publish task
+ */
+static struct GNUNET_SCHEDULER_Task *zone_publish_task;
+
+/**
+ * #GNUNET_YES if zone has never been published before
+ */
+static int first_zone_iteration;
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+shutdown_task (void *cls)
+{
+  struct MonitorActivity *ma;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Shutting down!\n");
+  while (NULL != (ma = ma_head))
+  {
+    GNUNET_DHT_put_cancel (ma->ph);
+    GNUNET_CONTAINER_DLL_remove (ma_head,
+                                 ma_tail,
+                                 ma);
+    GNUNET_free (ma);
+  }
+  if (NULL != statistics)
+  {
+    GNUNET_STATISTICS_destroy (statistics,
+                               GNUNET_NO);
+    statistics = NULL;
+  }
+  if (NULL != zone_publish_task)
+  {
+    GNUNET_SCHEDULER_cancel (zone_publish_task);
+    zone_publish_task = NULL;
+  }
+  if (NULL != namestore_iter)
+  {
+    GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
+    namestore_iter = NULL;
+  }
+  if (NULL != zmon)
+  {
+    GNUNET_NAMESTORE_zone_monitor_stop (zmon);
+    zmon = NULL;
+  }
+  if (NULL != namestore_handle)
+  {
+    GNUNET_NAMESTORE_disconnect (namestore_handle);
+    namestore_handle = NULL;
+  }
+  if (NULL != active_put)
+  {
+    GNUNET_DHT_put_cancel (active_put);
+    active_put = NULL;
+  }
+  if (NULL != dht_handle)
+  {
+    GNUNET_DHT_disconnect (dht_handle);
+    dht_handle = NULL;
+  }
+}
+
+
+/**
+ * Method called periodically that triggers iteration over authoritative records
+ *
+ * @param cls closure
+ */
+static void
+publish_zone_dht_next (void *cls)
+{
+  zone_publish_task = NULL;
+  GNUNET_assert (NULL != namestore_iter);
+  GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
+}
+
+
+/**
+ * Periodically iterate over our zone and store everything in dht
+ *
+ * @param cls NULL
+ */
+static void
+publish_zone_dht_start (void *cls);
+
+
+/**
+ * Continuation called from DHT once the PUT operation is done.
+ *
+ * @param cls closure, NULL if called from regular iteration,
+ *        `struct MonitorActivity` if called from #handle_monitor_event.
+ * @param success #GNUNET_OK on success
+ */
+static void
+dht_put_continuation (void *cls,
+                      int success)
+{
+  struct MonitorActivity *ma = cls;
+  struct GNUNET_TIME_Relative next_put_interval;
+
+  num_public_records++;
+  if (NULL == ma)
+  {
+    active_put = NULL;
+    if ( (num_public_records > last_num_public_records) &&
+         (GNUNET_NO == first_zone_iteration) )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Last record count was lower than current record count.  Reducing interval.\n");
+      put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
+                                                  num_public_records);
+      next_put_interval = GNUNET_TIME_relative_divide (put_interval,
+                                                       LATE_ITERATION_SPEEDUP_FACTOR);
+    }
+    else
+      next_put_interval = put_interval;
+    next_put_interval = GNUNET_TIME_relative_min (next_put_interval,
+                                                  MAXIMUM_ZONE_ITERATION_INTERVAL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "PUT complete, next PUT in %s!\n",
+                GNUNET_STRINGS_relative_time_to_string (next_put_interval,
+                                                        GNUNET_YES));
+
+    GNUNET_STATISTICS_set (statistics,
+                           "Current zone iteration interval (ms)",
+                           next_put_interval.rel_value_us / 1000LL,
+                           GNUNET_NO);
+    GNUNET_assert (NULL == zone_publish_task);
+    zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval,
+                                                      &publish_zone_dht_next,
+                                                      NULL);
+  }
+  else
+  {
+    GNUNET_CONTAINER_DLL_remove (ma_head,
+                                 ma_tail,
+                                 ma);
+    GNUNET_free (ma);
+  }
+}
+
+
+/**
+ * Convert namestore records from the internal format to that
+ * suitable for publication (removes private records, converts
+ * to absolute expiration time).
+ *
+ * @param rd input records
+ * @param rd_count size of the @a rd and @a rd_public arrays
+ * @param rd_public where to write the converted records
+ * @return number of records written to @a rd_public
+ */
+static unsigned int
+convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
+                            unsigned int rd_count,
+                            struct GNUNET_GNSRECORD_Data *rd_public)
+{
+  struct GNUNET_TIME_Absolute now;
+  unsigned int rd_public_count;
+  unsigned int i;
+
+  rd_public_count = 0;
+  now = GNUNET_TIME_absolute_get ();
+  for (i=0;i<rd_count;i++)
+    if (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
+    {
+      rd_public[rd_public_count] = rd[i];
+      if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
+      {
+        /* GNUNET_GNSRECORD_block_create will convert to absolute time;
+           we just need to adjust our iteration frequency */
+        min_relative_record_time.rel_value_us =
+          GNUNET_MIN (rd_public[rd_public_count].expiration_time,
+                      min_relative_record_time.rel_value_us);
+      }
+      else if (rd_public[rd_public_count].expiration_time < now.abs_value_us)
+      {
+        /* record already expired, skip it */
+        continue;
+      }
+      rd_public_count++;
+    }
+  return rd_public_count;
+}
+
+
+/**
+ * Store GNS records in the DHT.
+ *
+ * @param key key of the zone
+ * @param label label to store under
+ * @param rd_public public record data
+ * @param rd_public_count number of records in @a rd_public
+ * @param pc_arg closure argument to pass to the #dht_put_continuation
+ * @return DHT PUT handle, NULL on error
+ */
+static struct GNUNET_DHT_PutHandle *
+perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
+                 const char *label,
+                 const struct GNUNET_GNSRECORD_Data *rd_public,
+                 unsigned int rd_public_count,
+                 void *pc_arg)
+{
+  struct GNUNET_GNSRECORD_Block *block;
+  struct GNUNET_HashCode query;
+  struct GNUNET_TIME_Absolute expire;
+  size_t block_size;
+  struct GNUNET_DHT_PutHandle *ret;
+
+  expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
+                                                        rd_public);
+  block = GNUNET_GNSRECORD_block_create (key,
+                                         expire,
+                                         label,
+                                         rd_public,
+                                         rd_public_count);
+  if (NULL == block)
+    return NULL; /* whoops */
+  block_size = ntohl (block->purpose.size)
+    + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)
+    + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
+  GNUNET_GNSRECORD_query_from_private_key (key,
+                                           label,
+                                           &query);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n",
+              rd_public_count,
+              label,
+              GNUNET_STRINGS_absolute_time_to_string (expire),
+              GNUNET_h2s (&query));
+  ret = GNUNET_DHT_put (dht_handle,
+                        &query,
+                        DHT_GNS_REPLICATION_LEVEL,
+                        GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
+                        GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+                        block_size,
+                        block,
+                        expire,
+                        &dht_put_continuation,
+                        pc_arg);
+  GNUNET_free (block);
+  return ret;
+}
+
+
+/**
+ * We encountered an error in our zone iteration.
+ */
+static void
+zone_iteration_error (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got disconnected from namestore database, retrying.\n");
+  namestore_iter = NULL;
+  /* We end up here on error/disconnect/shutdown, so potentially
+     while a zone publish task or a DHT put is still running; hence
+     we need to cancel those. */
+  if (NULL != zone_publish_task)
+  {
+    GNUNET_SCHEDULER_cancel (zone_publish_task);
+    zone_publish_task = NULL;
+  }
+  if (NULL != active_put)
+  {
+    GNUNET_DHT_put_cancel (active_put);
+    active_put = NULL;
+  }
+  zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
+                                                NULL);
+}
+
+
+/**
+ * Zone iteration is completed.
+ */
+static void
+zone_iteration_finished (void *cls)
+{
+  /* we're done with one iteration, calculate when to do the next one */
+  namestore_iter = NULL;
+  last_num_public_records = num_public_records;
+  first_zone_iteration = GNUNET_NO;
+  if (0 == num_public_records)
+  {
+    /**
+     * If no records are known (startup) or none present
+     * we can safely set the interval to the value for a single
+     * record
+     */
+    put_interval = zone_publish_time_window;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+                "No records in namestore database.\n");
+  }
+  else
+  {
+    /* If records are present, next publication is based on the minimum
+     * relative expiration time of the records published divided by 4
+     */
+    zone_publish_time_window
+      = GNUNET_TIME_relative_min (GNUNET_TIME_relative_divide (min_relative_record_time, 4),
+                                  zone_publish_time_window_default);
+    put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
+                                                num_public_records);
+  }
+  /* reset for next iteration */
+  min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL;
+  put_interval = GNUNET_TIME_relative_max (MINIMUM_ZONE_ITERATION_INTERVAL,
+                                           put_interval);
+  put_interval = GNUNET_TIME_relative_min (put_interval,
+                                           MAXIMUM_ZONE_ITERATION_INTERVAL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Zone iteration finished. Adjusted zone iteration interval to %s\n",
+              GNUNET_STRINGS_relative_time_to_string (put_interval,
+                                                      GNUNET_YES));
+  GNUNET_STATISTICS_set (statistics,
+                         "Current zone iteration interval (in ms)",
+                         put_interval.rel_value_us / 1000LL,
+                         GNUNET_NO);
+  GNUNET_STATISTICS_update (statistics,
+                            "Number of zone iterations",
+                            1,
+                            GNUNET_NO);
+  GNUNET_STATISTICS_set (statistics,
+                         "Number of public records in DHT",
+                         last_num_public_records,
+                         GNUNET_NO);
+  GNUNET_assert (NULL == zone_publish_task);
+  if (0 == num_public_records)
+    zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval,
+                                                      &publish_zone_dht_start,
+                                                      NULL);
+  else
+    zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
+                                                  NULL);
+}
+
+
+/**
+ * Function used to put all records successively into the DHT.
+ *
+ * @param cls the closure (NULL)
+ * @param key the private key of the authority (ours)
+ * @param label the name of the records, NULL once the iteration is done
+ * @param rd_count the number of records in @a rd
+ * @param rd the record data
+ */
+static void
+put_gns_record (void *cls,
+                const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
+                const char *label,
+                unsigned int rd_count,
+                const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct GNUNET_GNSRECORD_Data rd_public[rd_count];
+  unsigned int rd_public_count;
+
+  rd_public_count = convert_records_for_export (rd,
+                                                rd_count,
+                                                rd_public);
+
+  if (0 == rd_public_count)
+  {
+    GNUNET_assert (NULL == zone_publish_task);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Record set empty, moving to next record set\n");
+    zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next,
+                                                  NULL);
+    return;
+  }
+  /* We got a set of records to publish */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting DHT PUT\n");
+  active_put = perform_dht_put (key,
+                                label,
+                                rd_public,
+                                rd_public_count,
+                                NULL);
+  if (NULL == active_put)
+  {
+    GNUNET_break (0);
+    dht_put_continuation (NULL, GNUNET_NO);
+  }
+}
+
+
+/**
+ * Periodically iterate over all zones and store everything in DHT
+ *
+ * @param cls NULL
+ */
+static void
+publish_zone_dht_start (void *cls)
+{
+  zone_publish_task = NULL;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting DHT zone update!\n");
+  /* start counting again */
+  num_public_records = 0;
+  GNUNET_assert (NULL == namestore_iter);
+  namestore_iter
+    = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
+                                             NULL, /* All zones */
+                                             &zone_iteration_error,
+                                             NULL,
+                                             &put_gns_record,
+                                             NULL,
+                                             &zone_iteration_finished,
+                                             NULL);
+}
+
+
+/**
+ * Process a record that was stored in the namestore
+ * (invoked by the monitor).
+ *
+ * @param cls closure, NULL
+ * @param zone private key of the zone; NULL on disconnect
+ * @param label label of the records; NULL on disconnect
+ * @param rd_count number of entries in @a rd array, 0 if label was deleted
+ * @param rd array of records with data to store
+ */
+static void
+handle_monitor_event (void *cls,
+                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                      const char *label,
+                      unsigned int rd_count,
+                      const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct GNUNET_GNSRECORD_Data rd_public[rd_count];
+  unsigned int rd_public_count;
+  struct MonitorActivity *ma;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received %u records for label `%s' via namestore monitor\n",
+              rd_count,
+              label);
+  /* filter out records that are not public, and convert to
+     absolute expiration time. */
+  rd_public_count = convert_records_for_export (rd,
+                                                rd_count,
+                                                rd_public);
+  if (0 == rd_public_count)
+    return; /* nothing to do */
+  ma = GNUNET_new (struct MonitorActivity);
+  ma->ph = perform_dht_put (zone,
+                            label,
+                            rd,
+                            rd_count,
+                            ma);
+  if (NULL == ma->ph)
+  {
+    /* PUT failed, do not remember operation */
+    GNUNET_free (ma);
+    return;
+  }
+  GNUNET_CONTAINER_DLL_insert (ma_head,
+                               ma_tail,
+                               ma);
+}
+
+
+/**
+ * The zone monitor is now in SYNC with the current state of the
+ * name store.  Start to perform periodic iterations.
+ *
+ * @param cls NULL
+ */
+static void
+monitor_sync_event (void *cls)
+{
+  GNUNET_assert (NULL == zone_publish_task);
+  zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
+                                                NULL);
+}
+
+
+/**
+ * The zone monitor is now in SYNC with the current state of the
+ * name store.  Start to perform periodic iterations.
+ *
+ * @param cls NULL
+ */
+static void
+handle_monitor_error (void *cls)
+{
+  if (NULL != zone_publish_task)
+  {
+    GNUNET_SCHEDULER_cancel (zone_publish_task);
+    zone_publish_task = NULL;
+  }
+  if (NULL != namestore_iter)
+  {
+    GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
+    namestore_iter = NULL;
+  }
+  if (NULL != active_put)
+  {
+    GNUNET_DHT_put_cancel (active_put);
+    active_put = NULL;
+  }
+  zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
+                                                NULL);
+}
+
+
+/**
+ * Performe zonemaster duties: watch namestore, publish records.
+ *
+ * @param cls closure
+ * @param server the initialized server
+ * @param c configuration to use
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *c,
+     struct GNUNET_SERVICE_Handle *service)
+{
+  unsigned long long max_parallel_bg_queries = 128;
+
+  min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL;
+  namestore_handle = GNUNET_NAMESTORE_connect (c);
+  if (NULL == namestore_handle)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to connect to the namestore!\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  put_interval = INITIAL_PUT_INTERVAL;
+  zone_publish_time_window_default = DEFAULT_ZONE_PUBLISH_TIME_WINDOW;
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_time (c,
+                                          "zonemaster",
+                                           "ZONE_PUBLISH_TIME_WINDOW",
+                                           &zone_publish_time_window_default))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Time window for zone iteration: %s\n",
+                GNUNET_STRINGS_relative_time_to_string (zone_publish_time_window,
+                                                        GNUNET_YES));
+  }
+  zone_publish_time_window = zone_publish_time_window_default;
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_number (c,
+                                            "zonemaster",
+                                             "MAX_PARALLEL_BACKGROUND_QUERIES",
+                                             &max_parallel_bg_queries))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Number of allowed parallel background queries: %llu\n",
+                max_parallel_bg_queries);
+  }
+  if (0 == max_parallel_bg_queries)
+    max_parallel_bg_queries = 1;         
+  dht_handle = GNUNET_DHT_connect (c,
+                                   (unsigned int) max_parallel_bg_queries);
+  if (NULL == dht_handle)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Could not connect to DHT!\n"));
+    GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+    return;
+  }
+
+  /* Schedule periodic put for our records. */
+  first_zone_iteration = GNUNET_YES;\
+  statistics = GNUNET_STATISTICS_create ("zonemaster", c);
+  zmon = GNUNET_NAMESTORE_zone_monitor_start (c,
+                                              NULL,
+                                              GNUNET_NO,
+                                              &handle_monitor_error,
+                                              NULL,
+                                              &handle_monitor_event,
+                                              NULL,
+                                              &monitor_sync_event,
+                                              NULL);
+  GNUNET_break (NULL != zmon);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+}
+
+
+/**
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN
+("zonemaster",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ NULL,
+ NULL,
+ NULL,
+ GNUNET_MQ_handler_end());
+
+
+/* end of gnunet-service-zonemaster.c */
diff --git a/src/zonemaster/zonemaster.conf.in b/src/zonemaster/zonemaster.conf.in
new file mode 100644 (file)
index 0000000..871eb9c
--- /dev/null
@@ -0,0 +1,25 @@
+[zonemaster]
+AUTOSTART = @AUTOSTART@
+FORCESTART = YES
+HOSTNAME = localhost
+BINARY = gnunet-service-zonemaster
+UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster.sock
+@JAVAPORT@PORT = 2123
+
+# Do we require users that want to access GNS to run this process
+# (usually not a good idea)
+UNIX_MATCH_UID = NO
+
+# Do we require users that want to access GNS to be in the 'gnunet' group?
+UNIX_MATCH_GID = NO
+
+# How many queries is GNS allowed to perform in the background at the same time?
+MAX_PARALLEL_BACKGROUND_QUERIES = 1000
+
+# How frequently do we try to publish our full zone?
+ZONE_PUBLISH_TIME_WINDOW = 4 h
+
+# Using caching or always ask DHT
+# USE_CACHE = YES
+
+# PREFIX = valgrind --leak-check=full --track-origins=yes