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>
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
+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
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/.
$ 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
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
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
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
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
pydiffer.py
terminate.py
timeout_watchdog
+gnunet_pyexpect.py
+gnunet_pyexpect.pyc
[gns]
FORCESTART = NO
+
+[zonemaster]
+FORCESTART = NO
\ No newline at end of file
--- /dev/null
+# ~/.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
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
gnunet-namestore.1 \
gnunet-namestore-fcfsd.1 \
gnunet-nat.1 \
+ gnunet-nat-auto.1 \
gnunet-nat-server.1 \
gnunet-peerinfo.1 \
gnunet-publish.1 \
--- /dev/null
+.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)
as attempting auto\-configuration.
.SH OPTIONS
-.B
-.IP "\-a, \-\-auto"
-Attempt auto\-configuration for NAT traversal.
.B
.IP "\-b ADDRESS, \-\-bind=ADDRESS"
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"
.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.
\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
# 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>
\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
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];
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
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
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
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
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
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"
#: 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 ""
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
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
"%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 ""
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"
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"
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"
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 ""
"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
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 ""
#: 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"
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 ""
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 ""
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"
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"
"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 ""
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"
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 ""
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"
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"
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 ""
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"
#: 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 ""
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"
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 ""
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"
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 ""
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"
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"
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"
#: 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 ""
"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"
"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
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
"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 ""
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"
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"
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"
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"
"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
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)"
#: 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"
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"
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»"
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"
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"
"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"
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"
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)"
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"
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"
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."
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 "
"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, "
"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"
"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."
#: 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 ""
"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"
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"
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 "
"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 "
"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"
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"
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"
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"
#~ "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 "
#~ 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"
#~ 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"
#~ 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"
#~ "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 "
#~ "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 "
#~ 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"
#~ 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"
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"
#: 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 ""
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
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
"%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 ""
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 ""
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 ""
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"
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 ""
"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
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 ""
#: 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"
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 ""
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 ""
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 ""
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 ""
"\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 ""
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 ""
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 ""
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 ""
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"
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 ""
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 ""
#: 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 ""
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 ""
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 ""
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 ""
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 ""
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 ""
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"
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"
#: 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"
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
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
"%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 ""
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"
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"
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"
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 ""
"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
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."
#: 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"
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"
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"
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"
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"
"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 ""
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 ""
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 ""
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"
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: "
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."
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."
#: 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 ""
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 ""
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"
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"
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 ""
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"
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"
#~ 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"
#~ 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"
#~ 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"
#~ 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:"
#~ msgid "Save configuration?"
#~ msgstr "GNUnet-konfiguration"
-#, fuzzy
-#~ msgid "GNUnet Configuration"
-#~ msgstr "GNUnet-konfiguration"
-
#~ msgid "Back"
#~ msgstr "Tillbaka"
#~ 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!"
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"
#: 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"
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
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
"%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 ""
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"
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"
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"
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 ""
"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
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."
#: 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"
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"
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"
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"
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"
"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 ""
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"
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 ""
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"
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"
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."
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."
#: 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 ""
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"
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"
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"
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 ""
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"
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"
#~ 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"
#~ 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 ""
#~ "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)?"
#~ 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"
#~ 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"
#~ 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"
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"
#: 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"
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
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
"%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 ""
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"
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"
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"
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 ""
"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
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 ""
#: 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"
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 的最大连接数"
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 ""
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 ""
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 ""
"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 ""
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 ""
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 ""
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"
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"
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 ""
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."
#: 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 ""
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 ""
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"
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"
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 ""
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"
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"
#~ 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 "保存配置失败。"
#~ "量。如果您的网速很平稳,您可以将该限制设置为网速的最大值。您不应该使用超过"
#~ "实际连接速度极限的值。"
-#~ msgid "Quota configuration"
-#~ msgstr "配额配置"
-
#~ msgid "What is the maximum size of the datastore in MB?"
#~ msgstr "数据仓库的最大尺寸是多少(MB)?"
#~ msgid "Save configuration?"
#~ msgstr "保存配置?"
-#~ msgid "GNUnet Configuration"
-#~ msgstr "GNUnet 配置"
-
#~ msgid "Back"
#~ 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"
TESTBED = testbed-logger testbed
CONSENSUS = consensus
SECRETSHARING = secretsharing
+ ATS_TESTS = ats-tests
endif
if HAVE_EXPERIMENTAL
endif
endif
+if HAVE_JSON
+ AUCTION_DIR = auction
+endif
+
if TALER_ONLY
SUBDIRS = \
include \
template \
ats \
nat \
+ nat-auto \
fragmentation \
transport \
ats-tool \
peerinfo-tool \
core \
$(TESTBED) \
- ats-tests \
+ $(ATS_TESTS) \
nse \
dht \
hostlist \
vpn \
gns \
credential \
+ zonemaster \
$(CONVERSATION_DIR) \
fs \
exit \
psycstore \
psyc \
social \
+ $(AUCTION_DIR) \
$(EXP_DIR) \
$(PROVIDER_DIR)
mockup-service
gnunet-arm
gnunet-service-arm
+test_arm_api
+test_exponential_backoff
+test_gnunet_arm.py
+test_gnunet_service_arm
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,
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,
/**
* 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?
*/
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);
}
+/**
+ * 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.
*
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);
}
*
* @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)
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;
}
GNUNET_free (shutdown_ctx);
return;
}
- shutdown_ctx->mq = GNUNET_CLIENT_connecT (cfg,
+ shutdown_ctx->mq = GNUNET_CLIENT_connect (cfg,
SERVICE,
handlers,
&mq_error_handler,
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
/*
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
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) )
{
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);
"%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);
}
GNUNET_MQ_handler_end ()
};
- me->ch = GNUNET_CORE_connecT (cfg,
+ me->ch = GNUNET_CORE_connect (cfg,
me,
NULL,
&comm_connect_cb,
{
struct BenchmarkPeer *me = cls;
- GNUNET_CORE_disconnecT (me->ch);
+ GNUNET_CORE_disconnect (me->ch);
me->ch = NULL;
}
*/
struct BenchmarkPeer *dest;
- /**
- * Core transmit handles
- */
- struct GNUNET_CORE_TransmitHandle *cth;
-
/**
* Message queue handle.
*/
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;
gnunet-service-ats
+test_ats_api_proportional
+test_ats_reservation_api_proportional
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,
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,
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,
--- /dev/null
+gnunet-auction-create
+gnunet-auction-info
+gnunet-auction-join
+gnunet-service-auction
+test_auction_api
--- /dev/null
+# 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
--- /dev/null
+[auction]
+AUTOSTART = NO
+BINARY = gnunet-service-auction
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-auction.sock
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+#! /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
AM_CLFAGS = -g
libexec_PROGRAMS = \
- gnunet-service-cadet $(EXP_LIBEXEC)
+ gnunet-service-cadet \
+ gnunet-service-cadet-new \
+ $(EXP_LIBEXEC)
bin_PROGRAMS = \
gnunet-cadet
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 \
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 \
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 = \
#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>
/************************** 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 ******************************/
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.
*/
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
* 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;
};
/**
* ID of the channel
*/
- uint32_t id GNUNET_PACKED;
+ struct GNUNET_CADET_ClientChannelNumber id;
/**
* Payload follows
/**
* ID of the channel allowed to send more data.
*/
- CADET_ChannelNumber channel_id GNUNET_PACKED;
+ struct GNUNET_CADET_ClientChannelNumber channel_id;
};
/**
* 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).
* (each path ends in destination) */
};
+
/**
* Message to inform the client about one of the tunnels in the service.
*/
*/
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] */
};
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.
*
* @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
/*
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
*/
/**
* @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.
*/
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;
/**
*/
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
*/
struct GNUNET_CADET_Peer
{
- /**
- * ID of the peer in short form
- */
+ /**
+ * ID of the peer in short form
+ */
GNUNET_PEER_Id id;
/**
*/
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;
/**
*/
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;
};
/**
* 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;
}
* @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
}
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) )
if (0 != ch->peer)
GNUNET_PEER_change_rc (ch->peer, -1);
GNUNET_free (ch);
- return;
+
}
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);
}
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);
}
*/
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;
{
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);
}
return GNUNET_SYSERR;
}
- ch = retrieve_channel (h, ntohl (message->id));
+ ch = retrieve_channel (h,
+ message->id);
if (NULL == ch)
{
GNUNET_break_op (0);
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));
{
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)
{
{
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));
}
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);
(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;
}
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));
}
{
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,
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 ()
};
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,
/******************************************************************************/
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;
}
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;
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;
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:
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;
}
}
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);
{
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
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");
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;
}
}
+
+/**
+ * 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))) );
}
}
-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.
*
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
* 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
/**
* 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;
/**
* ID of the connection.
*/
- struct GNUNET_CADET_Hash cid;
+ struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
};
/**
* 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;
/**
* ID of the connection.
*/
- struct GNUNET_CADET_Hash cid;
+ struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
/**
* ID of the endpoint
/**
* Message to destroy a connection.
*/
-struct GNUNET_CADET_ConnectionDestroy
+struct GNUNET_CADET_ConnectionDestroyMessage
{
/**
* Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
/**
* 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.
*/
/**
* 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;
/**
* ID of the connection.
*/
- struct GNUNET_CADET_Hash cid;
+ struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
/**
* Sender's ephemeral public ECC key encoded in a
* 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 ****************/
};
+/**
+ * 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;
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,
/**
* 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
/**
* 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
/**
* 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
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)
{
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));
}
GNUNET_SCHEDULER_shutdown ();
return;
}
- GNUNET_CADET_get_tunnel (mh, &pid, tunnel_callback, NULL);
+ GNUNET_CADET_get_tunnel (mh,
+ &pid,
+ &tunnel_callback,
+ NULL);
}
--- /dev/null
+/*
+ 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 */
--- /dev/null
+
+/*
+ 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
--- /dev/null
+
+/*
+ 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 */
--- /dev/null
+
+/*
+ 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
--- /dev/null
+
+/*
+ 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 */
--- /dev/null
+
+/*
+ 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
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+
+/*
+ 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 */
--- /dev/null
+
+/*
+ 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
--- /dev/null
+
+/*
+ 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 */
--- /dev/null
+
+/*
+ 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
--- /dev/null
+
+/*
+ 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 */
--- /dev/null
+
+/*
+ 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
/**
* Connection confirmed, ready to carry traffic.
*/
- CADET_CHANNEL_READY,
+ CADET_CHANNEL_READY
};
*/
struct GNUNET_TIME_Absolute timestamp;
- /* struct GNUNET_CADET_Data with payload */
+ /* struct GNUNET_CADET_ChannelAppDataMessage with payload */
};
/**
* 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.
* @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;
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 (©[1], msg, size);
return copy;
* @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;
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
*/
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);
}
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));
}
*/
static void
send_client_data (struct CadetChannel *ch,
- const struct GNUNET_CADET_Data *msg,
+ const struct GNUNET_CADET_ChannelAppDataMessage *msg,
int fwd)
{
if (fwd)
{
if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable)
{
- struct GNUNET_CADET_Data *msg = (struct GNUNET_CADET_Data *) ©[1];
+ struct GNUNET_CADET_ChannelAppDataMessage *msg = (struct GNUNET_CADET_ChannelAppDataMessage *) ©[1];
LOG (GNUNET_ERROR_TYPE_DEBUG, " have %u! now expecting %u\n",
copy->mid, rel->mid_recv + 1);
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;
return;
}
- payload = (struct GNUNET_CADET_Data *) ©[1];
+ payload = (struct GNUNET_CADET_ChannelAppDataMessage *) ©[1];
fwd = (rel == ch->root_rel);
/* Message not found in the queue that we are going to use. */
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 ();
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);
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));
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);
}
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));
}
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);
}
*/
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;
static struct CadetChannel *
channel_new (struct CadetTunnel *t,
struct CadetClient *owner,
- CADET_ChannelNumber lid_root)
+ struct GNUNET_CADET_ClientChannelNumber lid_root)
{
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;
*
* @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;
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;
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));
{
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);
* @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;
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);
*/
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))
*/
void
GCCH_handle_data (struct CadetChannel *ch,
- const struct GNUNET_CADET_Data *msg,
+ const struct GNUNET_CADET_ChannelAppDataMessage *msg,
int fwd)
{
struct CadetChannelReliability *rel;
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);
}
}
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);
}
*/
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;
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)
*/
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;
}
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))
{
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);
*/
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'. */
*/
void
GCCH_handle_destroy (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelManage *msg,
+ const struct GNUNET_CADET_ChannelManageMessage *msg,
int fwd)
{
struct CadetChannelReliability *rel;
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);
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:
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);
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;
}
}
+ 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;
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;
}
*
* @return ID used to identify the channel with the remote peer.
*/
-CADET_ChannelNumber
+struct GNUNET_CADET_ChannelTunnelNumber
GCCH_get_id (const 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.
*/
void
GCCH_handle_data (struct CadetChannel *ch,
- const struct GNUNET_CADET_Data *msg,
+ const struct GNUNET_CADET_ChannelAppDataMessage *msg,
int fwd);
*/
void
GCCH_handle_data_ack (struct CadetChannel *ch,
- const struct GNUNET_CADET_DataACK *msg,
+ const struct GNUNET_CADET_ChannelDataAckMessage *msg,
int fwd);
*/
struct CadetChannel *
GCCH_handle_create (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelCreate *msg);
+ const struct GNUNET_CADET_ChannelOpenMessage *msg);
/**
*/
void
GCCH_handle_ack (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelManage *msg,
+ const struct GNUNET_CADET_ChannelManageMessage *msg,
int fwd);
*/
void
GCCH_handle_destroy (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelManage *msg,
+ const struct GNUNET_CADET_ChannelManageMessage *msg,
int fwd);
GCCH_2s (const struct CadetChannel *ch);
+
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
/**
* 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:
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.
/**
* 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
/**
* 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.
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",
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;
* @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);
}
* @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 ();
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 ();
/* 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);
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 ();
*/
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)
{
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. */
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. */
}
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;
}
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);
{
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)
{
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;
*/
static int
check_connection (void *cls,
- const struct GNUNET_HashCode *key,
+ const struct GNUNET_ShortHashCode *key,
void *value)
{
struct CadetConnection *c = value;
return;
if (NULL == connections)
return;
- GNUNET_CONTAINER_multihashmap_iterate (connections,
- &check_connection,
- NULL);
+ GNUNET_CONTAINER_multishortmap_iterate (connections,
+ &check_connection,
+ NULL);
}
* @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));
}
* @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;
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;
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);
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 ();
}
* @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);
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 ();
}
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,
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;
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 ();
}
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;
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 = "==";
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);
}
/******************************************************************************/
*/
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;
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);
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 ();
*/
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;
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 ();
*/
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;
}
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);
}
*/
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;
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)
*/
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 ();
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);
*/
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 ();
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,
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);
*/
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;
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,
/* 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)
*/
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;
cid,
c,
peer,
- 0);
+ zero);
/* If something went wrong, discard message. */
if (GNUNET_SYSERR == fwd)
/* 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 ();
}
*/
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);
/* If something went wrong, discard message. */
if (GNUNET_SYSERR == fwd)
{
- GNUNET_break_op (0);
GCC_check_connections ();
return;
}
/* 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 ();
}
}
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);
}
*/
static int
shutdown_iterator (void *cls,
- const struct GNUNET_HashCode *key,
+ const struct GNUNET_ShortHashCode *key,
void *value)
{
struct CadetConnection *c = value;
{
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;
}
* 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)
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;
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",
*
* @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.
*
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));
}
*
* @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;
}
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);
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;
*/
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)
{
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);
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--;
}
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;
}
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);
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);
}
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;
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 ();
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);
}
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);
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);
*/
void
GCC_handle_create (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionCreate *msg);
+ const struct GNUNET_CADET_ConnectionCreateMessage *msg);
/**
*/
void
GCC_handle_confirm (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionACK *msg);
+ const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg);
/**
*/
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.
*/
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.
*/
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.
*/
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).
*/
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).
*/
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.
* 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);
*
* @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.
*
*
* @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 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);
*/
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;
};
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);
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);
}
/**
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;
}
void
GCH_init (const struct GNUNET_CONFIGURATION_Handle *c);
+
/**
* Shut down the hello subsystem.
*/
void
-GCH_shutdown ();
+GCH_shutdown (void);
+
/**
* Get own hello message.
const struct GNUNET_HELLO_Message *
GCH_get_mine (void);
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
* 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
*/
/**
* Channel ID for the next incoming channel.
*/
- CADET_ChannelNumber next_chid;
+ struct GNUNET_CADET_ClientChannelNumber next_chid;
/**
* Handle to communicate with the client
" 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;
}
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);
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);
if (GNUNET_OK !=
GCCH_handle_local_create (c,
- (struct GNUNET_CADET_ChannelCreateMessage *)
+ (struct GNUNET_CADET_ChannelOpenMessageMessage *)
message))
{
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
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");
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",
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;
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;
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)
{
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");
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",
/* 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;
}
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++;
}
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++;
}
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);
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},
* @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);
GML_2s (c), chid);
return NULL;
}
- return GNUNET_CONTAINER_multihashmap32_get (map, chid);
+ return GNUNET_CONTAINER_multihashmap32_get (map,
+ chid.channel_of_client);
}
*/
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);
}
*/
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);
}
*
* @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;
}
{
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
*
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");
}
}
* @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,
*/
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;
* @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,
* @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;
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);
}
*/
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))
GNUNET_memcpy (©[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,
©->header, GNUNET_NO);
}
* @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
*/
void
GML_channel_add (struct CadetClient *client,
- uint32_t chid,
+ struct GNUNET_CADET_ClientChannelNumber chid,
struct CadetChannel *ch);
/**
*/
void
GML_channel_remove (struct CadetClient *client,
- uint32_t chid,
+ struct GNUNET_CADET_ClientChannelNumber chid,
struct CadetChannel *ch);
/**
*
* @return LID of a channel free to use.
*/
-CADET_ChannelNumber
+struct GNUNET_CADET_ClientChannelNumber
GML_get_next_chid (struct CadetClient *c);
/**
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.
* @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.
*/
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.
* @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.
* @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.
*/
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.
*/
void *cont_cls;
+ /**
+ * Task to asynchronously run the drop continuation.
+ */
+ struct GNUNET_SCHEDULER_Task *drop_task;
+
/**
* Time when message was queued for sending.
*/
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.
/**
* Connections that go through this peer; indexed by tid.
*/
- struct GNUNET_CONTAINER_MultiHashMap *connections;
+ struct GNUNET_CONTAINER_MultiShortmap *connections;
/**
* Handle for core transmissions.
*/
static int
notify_broken (void *cls,
- const struct GNUNET_HashCode *key,
+ const struct GNUNET_ShortHashCode *key,
void *value)
{
struct CadetPeer *peer = 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,
direct_path = pop_direct_path (p);
if (NULL != p->connections)
{
- GNUNET_CONTAINER_multihashmap_iterate (p->connections,
- ¬ify_broken,
- p);
- GNUNET_CONTAINER_multihashmap_destroy (p->connections);
- p->connections = NULL;
+ GNUNET_CONTAINER_multishortmap_iterate (p->connections,
+ ¬ify_broken,
+ p);
+ GNUNET_CONTAINER_multishortmap_destroy (p->connections);
+ p->connections = NULL;
}
GNUNET_STATISTICS_update (stats,
"# peers",
* @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;
* @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);
/**
- * 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);
* @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);
* @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);
/**
- * 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);
/**
- * 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);
/**
- * 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);
* @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)
}
/**
- * 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);
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,
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;
}
}
/* 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;
}
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)
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;
}
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);
}
}
+/**
+ * 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).
*
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,
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)
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)
{
{
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;
}
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);
}
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,
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));
}
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));
}
(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));
}
*/
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);
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.
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.
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,
* @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);
/**
/**
- * Connection list and metadata.
+ * Entry in list of connections used by tunnel, with metadata.
*/
struct CadetTConnection
{
struct GNUNET_TIME_Absolute ratchet_expiration;
};
+
/**
* Struct containing all information regarding a tunnel to a peer.
*/
/**
* 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.
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;
* @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;
* @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;
*/
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;
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)
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 */
*/
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;
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;
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);
}
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;
}
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;
}
* @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);
}
*/
static void
handle_data (struct CadetTunnel *t,
- const struct GNUNET_CADET_Data *msg,
+ const struct GNUNET_CADET_ChannelAppDataMessage *msg,
int fwd)
{
struct CadetChannel *ch;
/* 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);
/* 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;
}
*/
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;
/* 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;
}
*/
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 */
*/
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;
}
*/
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;
/* 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;
}
*/
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;
/* 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 */
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:
*/
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];
*/
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];
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 !=
struct CadetTunnel *t;
t = GNUNET_new (struct CadetTunnel);
- t->next_chid = 0;
+ t->next_chid.cn = 0;
t->peer = destination;
if (GNUNET_OK !=
* @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;
* @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;
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;
}
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,
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)
*
* @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.
*/
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;
}
*/
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);
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));
}
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;
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);
for (cht = t->channel_head; NULL != cht; cht = cht->next)
iter (cls, cht->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);
/**
*/
void
GCT_handle_encrypted (struct CadetTunnel *t,
- const struct GNUNET_CADET_Encrypted *msg);
+ const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
/**
*/
void
GCT_handle_kx (struct CadetTunnel *t,
- const struct GNUNET_CADET_KX *msg);
+ const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
/**
*
* @return ID of a channel free to use.
*/
-CADET_ChannelNumber
+struct GNUNET_CADET_ChannelTunnelNumber
GCT_get_next_chid (struct CadetTunnel *t);
[PATHS]
GNUNET_TEST_HOME = /tmp/test-cadet/
-[nat]
-RETURN_LOCAL_ADDRESSES = YES
-DISABLEV6 = YES
-USE_LOCALADDR = YES
-
[peerinfo]
NO_IO = YES
* 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;
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 (
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,
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,
};
struct GNUNET_CRYPTO_EcdsaPublicKey my_zone;
- call->mq = GNUNET_CLIENT_connecT (cfg,
+ call->mq = GNUNET_CLIENT_connect (cfg,
"conversation",
handlers,
&call_error_handler,
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
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 \
/**
- * 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.
*/
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.
*/
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?
*/
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;
}
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,
/**
- * 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
}
+/**
+ * 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
{
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))
{
}
}
/* 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);
}
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));
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);
}
*/
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;
}
return;
}
disconnect_and_free_peer_entry (h,
- &dnm->peer,
+ &pr->peer,
pr);
}
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))
{
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;
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);
}
* 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,
{
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)
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);
}
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,
};
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,
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);
* 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)
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;
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 -
/**
- * 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
*/
/**
- * 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;
}
+++ /dev/null
-/*
- 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 */
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,
+++ /dev/null
-/*
- 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 */
{
if (NULL != p->ch)
{
- GNUNET_CORE_disconnecT (p->ch);
+ GNUNET_CORE_disconnect (p->ch);
p->ch = NULL;
}
if (NULL != p->ghh)
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,
(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,
{
if (NULL != p->ch)
{
- GNUNET_CORE_disconnecT (p->ch);
+ GNUNET_CORE_disconnect (p->ch);
p->ch = NULL;
}
if (NULL != p->ghh)
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,
NULL);
GNUNET_assert (NULL !=
- (p1.ch = GNUNET_CORE_connecT (p1.cfg,
+ (p1.ch = GNUNET_CORE_connect (p1.cfg,
&p1,
&init_notify,
&connect_notify,
}
if (NULL != core)
{
- GNUNET_CORE_disconnecT (core);
+ GNUNET_CORE_disconnect (core);
core = NULL;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
};
core =
- GNUNET_CORE_connecT (cfg,
+ GNUNET_CORE_connect (cfg,
NULL,
&init,
&connect_cb,
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;
}
if (p == &p1)
{
/* connect p2 */
- p2.ch = GNUNET_CORE_connecT (p2.cfg,
+ p2.ch = GNUNET_CORE_connect (p2.cfg,
&p2,
&init_notify,
&connect_notify,
"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;
TIMEOUT),
&timeout_task,
NULL);
- p1.ch = GNUNET_CORE_connecT (p1.cfg,
+ p1.ch = GNUNET_CORE_connect (p1.cfg,
&p1,
&init_notify,
&connect_notify,
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
{
if (NULL != p->ch)
{
- GNUNET_CORE_disconnecT (p->ch);
+ GNUNET_CORE_disconnect (p->ch);
p->ch = NULL;
}
if (NULL != p->ghh)
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,
"WAN_QUOTA_OUT",
¤t_quota_p2_out));
- p1.ch = GNUNET_CORE_connecT (p1.cfg,
+ p1.ch = GNUNET_CORE_connect (p1.cfg,
&p1,
&init_notify,
&connect_notify,
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,
--- /dev/null
+test_datacache_heap
+test_datacache_postgres
+test_datacache_quota_heap
+test_datacache_quota_postgres
+test_datacache_quota_sqlite
+test_datacache_sqlite
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",
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
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,
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,
* The plugin.
*/
struct Plugin *plugin;
-
+
/**
* Requested value hash.
*/
* 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
PluginUpdateCont cont,
void *cont_cls)
{
- struct Plugin *plugin = cls;
struct Value *value;
value = (struct Value*) (long) uid;
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) )
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
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 \
};
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,
* 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)
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);
}
}
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);
}
}
/* 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
0,
NULL,
GDS_my_hello,
- GNUNET_HELLO_size ((const struct
- GNUNET_HELLO_Message *)
- GDS_my_hello));
+ hello_size);
}
else
{
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,
{
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));
* #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;
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))
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,
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);
}
* @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;
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)
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
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,
{
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);
GNUNET_MQ_handler_end ()
};
- core_api = GNUNET_CORE_connecT (GDS_cfg,
+ core_api = GNUNET_CORE_connect (GDS_cfg,
NULL,
&core_init,
&handle_core_connect,
if (NULL == core_api)
return;
- GNUNET_CORE_disconnecT (core_api);
+ GNUNET_CORE_disconnect (core_api);
core_api = NULL;
delete_finger_table_entries();
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))
{
* @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;
gnunet-dns-monitor
gnunet-dns-redirector
gnunet-helper-dns
+test_hexcoder
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,
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,
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;
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,
NULL);
if (NULL == ats)
{
- GNUNET_CORE_disconnecT (core_api);
+ GNUNET_CORE_disconnect (core_api);
core_api = NULL;
return;
}
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;
}
--- /dev/null
+test_fragmentation
+test_fragmentation_parallel
};
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,
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,
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,
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,
};
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,
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,
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)
/**
- * 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
"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,
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)
# 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
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,
#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
};
-/**
- * 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
*/
*/
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
*/
static void
shutdown_task (void *cls)
{
- struct MonitorActivity *ma;
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Shutting down!\n");
GNS_interceptor_done ();
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);
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);
}
}
+
/**
* Called whenever a client is disconnected.
*
}
-/**
- * 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.
*
}
-/**
- * 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.
}
-
/**
* Method called to inform about the ego to be used for the master zone
* for DNS interceptions.
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)
{
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,
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))
{
"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)
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);
}
it_task = GNUNET_SCHEDULER_add_now (&next_it, ith);
}
+
static void
next_it (void *cls)
{
GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
}
+
static void
iterator_cb (void *cls,
const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
GNUNET_free (ith);
}
+
static void
finished_cb (void *cls)
{
}
+
static void
it_error (void *cls)
{
"Error iterating for REVERSE\n");
}
+
static void
check_reverse_records (void *cls)
{
--- /dev/null
+test_gnsrecord_block_expiration
+test_gnsrecord_crypto
+test_gnsrecord_serialization
+zonefiles
gnunet-hello
+test_friend_hello
+test_hello
gnunet-daemon-hostlist
+test_gnunet_daemon_hostlist
+test_gnunet_daemon_hostlist_learning
+test_gnunet_daemon_hostlist_reconnect
/**
* Handle to hostlist server's connect handler
*/
-static GNUNET_CORE_ConnecTEventHandler server_ch;
+static GNUNET_CORE_ConnectEventHandler server_ch;
#endif
/**
* 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
"Hostlist daemon is shutting down\n");
if (NULL != core)
{
- GNUNET_CORE_disconnecT (core);
+ GNUNET_CORE_disconnect (core);
core = NULL;
}
if (bootstrapping)
&client_adv_handler,
learning);
core =
- GNUNET_CORE_connecT (cfg,
+ GNUNET_CORE_connect (cfg,
NULL,
&core_init,
&connect_handler,
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)
{
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);
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;
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);
}
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,
}
GNUNET_free (filename);
}
- p->core = GNUNET_CORE_connecT (p->cfg,
+ p->core = GNUNET_CORE_connect (p->cfg,
NULL,
NULL,
NULL,
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");
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,
gnunet-service-identity
gnunet-identity
+test_identity
+test_identity_defaults
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,
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 \
*/
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
/**
* 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.
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);
/**
*/
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,
+ ...);
/**
(*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
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.
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);
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);
* @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,
/**
* Version of the API (for entire gnunetutil.so library).
*/
-#define GNUNET_UTIL_VERSION 0x000A0101
+#define GNUNET_UTIL_VERSION 0x000A0102
/**
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).
/**
* @ingroup logging
* Use this for fatal errors that cannot be handled
- *
+ *
* @param cond Condition to evaluate
* @param comp Component string to use for logging
*/
/**
* 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().
*/
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 */
/**
* @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
* @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);
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.
*
* @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);
* @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
* 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
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);
* @param handle connection to core to disconnect
*/
void
-GNUNET_CORE_disconnecT (struct GNUNET_CORE_Handle *handle);
+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()
* 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 *
#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).
#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.
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
* @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) \
*/
void
GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *ev,
- GNUNET_MQ_NotifyCallback cb,
+ GNUNET_SCHEDULER_TaskCallback cb,
void *cb_cls);
--- /dev/null
+/*
+ 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 */
+++ /dev/null
-/*
- 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 */
/*
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
*/
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.
*/
};
+/**
+ * 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.
* 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
*/
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,
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
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,
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 */
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);
/**
* 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
/**
* 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.
/**
* 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 **********************************/
*/
#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 *******************************/
/**
/**
* 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.
#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
*/
*/
#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.
*/
--- /dev/null
+test_jsonapi
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);
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;
}
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;
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;
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));
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);
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;
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;
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;
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);
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);
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))
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 */
{ 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 },
if (NULL != last)
{
GNUNET_MQ_notify_sent (last,
- (GNUNET_MQ_NotifyCallback) group_cleanup, grp);
+ (GNUNET_SCHEDULER_TaskCallback) group_cleanup, grp);
}
else
{
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);
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);
gnunet-service-namecache
gnunet-namecache
+test_namecache_api_cache_block
+test_plugin_namecache_postgres
+test_plugin_namecache_sqlite
+zonefiles
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,
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
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,
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,
--- /dev/null
+gnunet-service-nat-auto
+gnunet-nat-auto
+gnunet-nat-server
--- /dev/null
+# 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)
+
--- /dev/null
+/*
+ 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, §ion_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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+[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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 */
endif
bin_PROGRAMS = \
- gnunet-nat-server \
gnunet-nat
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)
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 \
-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
-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 \
+++ /dev/null
-/*
- 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 */
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.
*/
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.
*/
*/
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.
*/
static void
test_finished ()
{
- if (NULL != ah)
- return;
- if (NULL != nt)
- return;
if (NULL != nh)
return;
if (NULL != rtask)
}
-/**
- * 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.
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);
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,
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,
}
}
- 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,
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:
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, §ion_name },
{'s', "stun", NULL,
gettext_noop ("enable STUN processing"),
GNUNET_NO, &GNUNET_GETOPT_set_one, &do_stun },
{'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 },
* @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
{
* 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;
+
};
* Kept in a DLL.
*/
struct ClientHandle *next;
-
+
/**
* Kept in a DLL.
*/
/**
* Underlying handle for this client with the service.
- */
+ */
struct GNUNET_SERVICE_Client *client;
/**
/**
* 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;
+
};
{
/**
* Kept in a DLL.
- */
+ */
struct StunExternalIP *next;
/**
* Kept in a DLL.
- */
+ */
struct StunExternalIP *prev;
/**
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.
*/
/**
- * 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.
* Head of client DLL.
*/
static struct ClientHandle *ch_head;
-
+
/**
* Tail of client DLL.
*/
/**
* 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;
/**
/**
* Free the DLL starting at #lal_head.
- */
+ */
static void
destroy_lal ()
{
#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;
}
struct in6_addr net;
struct in6_addr mask;
unsigned int off;
-
+
if (0 == bits)
return GNUNET_YES;
GNUNET_assert (1 == inet_pton (AF_INET6,
struct IfcProcContext
{
- /**
+ /**
* Head of DLL of local addresses.
*/
struct LocalAddressList *lal_head;
{
struct GNUNET_MQ_Envelope *env;
struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
-
+
env = GNUNET_MQ_msg_extra (msg,
addr_len,
GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
addr_len);
GNUNET_MQ_send (ch->mq,
env);
-}
+}
/**
size_t alen;
struct sockaddr_in v4;
struct sockaddr_in6 v6;
-
+
if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
return;
switch (delta->af)
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) &&
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,
/**
* 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;
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,
}
-/**
- * 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,
for (struct ClientHandle *ch = ch_head;
NULL != ch;
ch = ch->next)
- {
+ {
struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm;
struct GNUNET_MQ_Envelope *env;
int match;
{
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;
* Task we run periodically to scan for network interfaces.
*
* @param cls NULL
- */
+ */
static void
run_scan (void *cls)
{
int found;
int have_nat;
struct LocalAddressList *lnext;
-
+
scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
&run_scan,
NULL);
{
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,
}
}
}
- 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);
}
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");
/**
- * 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) )
{
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;
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;
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) &&
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;
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 (¬ify_client_external_ipv4_change,
+ ch);
GNUNET_SERVICE_client_continue (ch->client);
}
{
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);
struct sockaddr_in v4;
struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
struct GNUNET_MQ_Envelope *env;
-
+
if (! ch->natted_address)
continue;
v4 = *ip;
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
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.
*
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,
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);
stun_stale_timeout = GNUNET_TIME_UNIT_HOURS;
/* Check for UPnP */
- enable_upnp
+ enable_upnp
= GNUNET_CONFIGURATION_get_value_yesno (cfg,
"NAT",
"ENABLE_UPNP");
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",
void *internal_cls)
{
struct ClientHandle *ch = internal_cls;
+ struct LocalAddressList *lal;
GNUNET_CONTAINER_DLL_remove (ch_head,
ch_tail,
}
}
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);
}
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 ());
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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
* Closure for @e cb.
*/
void *cb_cls;
-
+
/**
* How long do we wait for restarting a crashed gnunet-helper-nat-server?
*/
memset (mybuf,
0,
sizeof (mybuf));
- bytes
+ bytes
= GNUNET_DISK_file_read (h->server_stdout_handle,
mybuf,
sizeof (mybuf));
{
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,
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,
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,
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)
/* 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,
/* 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,
*/
void
GN_stop_gnunet_nat_server_ (struct HelperContext *h)
-{
+{
if (NULL != h->server_read_task)
{
GNUNET_SCHEDULER_cancel (h->server_read_task);
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);
*/
struct GNUNET_NAT_ExternalHandle *
GNUNET_NAT_mini_get_external_ipv4_ (GNUNET_NAT_IPCallback cb,
- void *cb_cls);
+ void *cb_cls);
/**
+++ /dev/null
-/*
- 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 */
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
# After how long do we consider STUN data stale?
STUN_STALE = 60 min
-
-[gnunet-nat-server]
-HOSTNAME = gnunet.org
-PORT = 5724
-NOARMBIND = YES
#include "gnunet_util_lib.h"
+
GNUNET_NETWORK_STRUCT_BEGIN
/**
/**
* 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.
/* 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 */
};
};
-/**
- * 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
/*
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
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,
* 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
*/
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,
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) )
{
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++)
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;
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);
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 */
#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"
/**
* Function to call when a error occours
*/
- GNUNET_NAT_STUN_ErrorCallback cb;
+ GNUNET_NAT_TestCallback cb;
/**
* Closure for @e cb.
/**
* 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
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;
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-/*
- 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 */
gnunet-service-nse
gnunet-nse
gnunet-nse-profiler
+test_nse_api
+perf_kdf
}
if (NULL != core_api)
{
- GNUNET_CORE_disconnecT (core_api);
+ GNUNET_CORE_disconnect (core_api);
core_api = NULL;
}
if (NULL != stats)
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 */
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,
gnunet-peerinfo
+test_gnunet_peerinfo.py
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 \
gnunet-service-peerinfo
+test_peerinfo_api
+test_peerinfo_api_friend_only
+test_peerinfo_api_notify_friend_only
+test_peerinfo_shipped_hellos
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,
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;
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,
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
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,
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
{
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);
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);
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);
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);
}
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
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,
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,
}
if (NULL != core_api)
{
- GNUNET_CORE_disconnecT (core_api);
+ GNUNET_CORE_disconnect (core_api);
core_api = NULL;
}
if (NULL != stats)
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 */
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,
return NULL;
}
- h->mq = GNUNET_CLIENT_connecT (cfg,
+ h->mq = GNUNET_CLIENT_connect (cfg,
"revocation",
handlers,
&revocation_mq_error_handler,
struct TestPeer *me = cls;
me->cfg = cfg;
- me->ch = GNUNET_CORE_connecT (cfg,
+ me->ch = GNUNET_CORE_connect (cfg,
me,
NULL,
&connect_cb,
{
struct TestPeer *me = cls;
- GNUNET_CORE_disconnecT (me->ch);
+ GNUNET_CORE_disconnect (me->ch);
me->ch = NULL;
}
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,
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,
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,
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,
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,
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
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,
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,
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 ();
}
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)
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
{
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);
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);
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);
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
{
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
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,
gnunet-template
gnunet-service-template
+test_template_api
gnunet-service-testbed-logger
+test_testbed_logger_api
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,
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
/**
- * 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
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 */
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;
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,
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,
list-keys
gnunet-testing
+test_testing_peerstartup
+test_testing_peerstartup2
+test_testing_portreservation
+test_testing_servicestartup
+test_testing_sharedservices
gnunet-daemon-topology
+test_gnunet_daemon_topology
/**
- * Function called after #GNUNET_CORE_connecT has succeeded
+ * Function called after #GNUNET_CORE_connect has succeeded
* (or failed for good).
*
* @param cls closure
}
if (NULL != handle)
{
- GNUNET_CORE_disconnecT (handle);
+ GNUNET_CORE_disconnect (handle);
handle = NULL;
}
whitelist_peers ();
&blacklist_check,
NULL);
ats = GNUNET_ATS_connectivity_init (cfg);
- handle = GNUNET_CORE_connecT (cfg,
+ handle = GNUNET_CORE_connect (cfg,
NULL,
&core_init,
&connect_notify,
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
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 \
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)
$(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) \
$(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 = \
$(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 = \
$(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)
$(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) \
$(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)
$(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) \
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 \
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)
{
/*
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
* @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
};
-/**
- * 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
*/
*/
static int iterate_all;
-/**
- * Option -t.
- */
-static int test_configuration;
-
/**
* Option -c.
*/
*/
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
*/
_("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,
}
-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.
}
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))
{
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,
{ '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
};
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;
/*
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
#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>
* @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)
{
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",
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--;
#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"
* @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;
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)
{
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;
}
/* 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);
}
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,
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 */
}
-/**
- * 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
if (addrlen == sizeof(struct IPv4TcpAddress))
{
+ struct sockaddr_in s4;
+
v4 = (const struct IPv4TcpAddress *) addr;
if (0 != memcmp (&v4->options,
&plugin->myoptions,
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))
{
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;
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);
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;
/*
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
#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"
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
* @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)
{
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,
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) >
sizeof(addr));
size = GNUNET_NETWORK_socket_recvfrom (rsock,
buf,
- sizeof(buf),
+ sizeof (buf),
(struct sockaddr *) &addr,
&fromlen);
sa = (const struct sockaddr *) &addr;
}
/* 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))
{
struct Plugin *plugin = cls;
const struct GNUNET_SCHEDULER_TaskContext *tc;
-
+
plugin->select_task_v4 = NULL;
if (NULL == plugin->sockv4)
return;
* @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;
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;
}
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;
#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"
#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"
[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
# 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
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;
[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;
# 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
# 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
}
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,
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,
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,
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,
"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,
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,
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,
GNUNET_free (ohh);
return NULL;
}
- ohh->mq = GNUNET_CLIENT_connecT (cfg,
+ ohh->mq = GNUNET_CLIENT_connect (cfg,
"transport",
NULL,
NULL,
--- /dev/null
+test_regex
+test_tun
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
libgnunetutil_la_SOURCES = \
bandwidth.c \
bio.c \
- client_new.c \
+ client.c \
common_allocation.c \
common_endian.c \
common_logging.c \
container_heap.c \
container_meta_data.c \
container_multihashmap.c \
+ container_multishortmap.c \
container_multipeermap.c \
container_multihashmap32.c \
crypto_symmetric.c \
--- /dev/null
+/*
+ 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 */
+++ /dev/null
-/*
- 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 */
}
+/**
+ * @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
/**
* 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);
}
--- /dev/null
+/*
+ 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 */
/**
* Called after the message was sent irrevocably.
*/
- GNUNET_MQ_NotifyCallback sent_cb;
+ GNUNET_SCHEDULER_TaskCallback sent_cb;
/**
* Closure for @e send_cb
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
*/
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 */
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;
{
current_envelope->sent_cb = NULL;
cb (current_envelope->sent_cls);
- }
+ }
GNUNET_free (current_envelope);
}
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 */
*/
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;
GNUNET_assert (NULL != mq);
GNUNET_assert (NULL != mq->cancel_impl);
-
+
mq->evacuate_called = GNUNET_NO;
if (mq->current_envelope == ev)
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,
/* 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,
#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;
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);
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);
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);
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)));
"resolver",
"HOSTNAME",
"localhost");
- mq = GNUNET_CLIENT_connecT (cfg,
+ mq = GNUNET_CLIENT_connect (cfg,
"test-server",
chandlers,
&mq_error_handler,
"localhost");
GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME",
"localhost");
- mq = GNUNET_CLIENT_connecT (cfg,
+ mq = GNUNET_CLIENT_connect (cfg,
"test-server",
NULL,
NULL,
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,
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,
struct GNUNET_MQ_Envelope *env;
struct GNUNET_MessageHeader *msg;
- mq = GNUNET_CLIENT_connecT (cfg,
+ mq = GNUNET_CLIENT_connect (cfg,
service_name,
NULL,
NULL,
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,
}
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)
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;
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;
}
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;
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
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,
--- /dev/null
+gnunet-service-zonemaster
--- /dev/null
+# 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)
+
--- /dev/null
+/*
+ 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 */
--- /dev/null
+[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