aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2017-01-20 07:00:54 +0100
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2017-01-20 07:00:54 +0100
commit3cb90c74c5f591fd2541d154a8e7b05a1c2f4539 (patch)
tree620638f54539749f2a1b27a5991a90880fe7c14d /src
parent7122f35e2c00c29b1af31bdd294e93e6fcc84498 (diff)
parentaedd5919e802370061850486c96da72b25df7f22 (diff)
downloadgnunet-3cb90c74c5f591fd2541d154a8e7b05a1c2f4539.tar.gz
gnunet-3cb90c74c5f591fd2541d154a8e7b05a1c2f4539.zip
- merge; service API change
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am10
-rw-r--r--src/arm/.gitignore4
-rw-r--r--src/arm/arm_api.c2
-rw-r--r--src/arm/arm_monitor_api.c2
-rw-r--r--src/arm/gnunet-arm.c37
-rw-r--r--src/arm/test_exponential_backoff.c2
-rw-r--r--src/ats-tests/.gitignore6
-rw-r--r--src/ats-tests/ats-testing.c25
-rw-r--r--src/ats-tests/ats-testing.h15
-rw-r--r--src/ats/.gitignore2
-rw-r--r--src/ats/ats_api_connectivity.c2
-rw-r--r--src/ats/ats_api_performance.c2
-rw-r--r--src/ats/ats_api_scheduling.c2
-rw-r--r--src/auction/.gitignore5
-rw-r--r--src/auction/Makefile.am74
-rw-r--r--src/auction/auction.conf4
-rw-r--r--src/auction/auction.h77
-rw-r--r--src/auction/gnunet-auction-create.c197
-rw-r--r--src/auction/gnunet-auction-info.c84
-rw-r--r--src/auction/gnunet-auction-join.c84
-rw-r--r--src/auction/gnunet-service-auction.c155
-rw-r--r--src/auction/test_auction_api.c42
-rwxr-xr-xsrc/auction/test_auction_create.sh80
-rw-r--r--src/cadet/Makefile.am37
-rw-r--r--src/cadet/cadet.h92
-rw-r--r--src/cadet/cadet_api.c420
-rw-r--r--src/cadet/cadet_common.c61
-rw-r--r--src/cadet/cadet_protocol.h253
-rw-r--r--src/cadet/gnunet-cadet.c13
-rw-r--r--src/cadet/gnunet-service-cadet-new.c1350
-rw-r--r--src/cadet/gnunet-service-cadet-new.h264
-rw-r--r--src/cadet/gnunet-service-cadet-new_channel.c1077
-rw-r--r--src/cadet/gnunet-service-cadet-new_channel.h191
-rw-r--r--src/cadet/gnunet-service-cadet-new_connection.c665
-rw-r--r--src/cadet/gnunet-service-cadet-new_connection.h196
-rw-r--r--src/cadet/gnunet-service-cadet-new_core.c903
-rw-r--r--src/cadet/gnunet-service-cadet-new_core.h69
-rw-r--r--src/cadet/gnunet-service-cadet-new_dht.c315
-rw-r--r--src/cadet/gnunet-service-cadet-new_dht.h93
-rw-r--r--src/cadet/gnunet-service-cadet-new_hello.c142
-rw-r--r--src/cadet/gnunet-service-cadet-new_hello.h80
-rw-r--r--src/cadet/gnunet-service-cadet-new_paths.c557
-rw-r--r--src/cadet/gnunet-service-cadet-new_paths.h182
-rw-r--r--src/cadet/gnunet-service-cadet-new_peer.c1056
-rw-r--r--src/cadet/gnunet-service-cadet-new_peer.h368
-rw-r--r--src/cadet/gnunet-service-cadet-new_tunnels.c2249
-rw-r--r--src/cadet/gnunet-service-cadet-new_tunnels.h357
-rw-r--r--src/cadet/gnunet-service-cadet_channel.c237
-rw-r--r--src/cadet/gnunet-service-cadet_channel.h16
-rw-r--r--src/cadet/gnunet-service-cadet_connection.c518
-rw-r--r--src/cadet/gnunet-service-cadet_connection.h37
-rw-r--r--src/cadet/gnunet-service-cadet_dht.c90
-rw-r--r--src/cadet/gnunet-service-cadet_hello.h5
-rw-r--r--src/cadet/gnunet-service-cadet_local.c207
-rw-r--r--src/cadet/gnunet-service-cadet_local.h32
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c194
-rw-r--r--src/cadet/gnunet-service-cadet_peer.h15
-rw-r--r--src/cadet/gnunet-service-cadet_tunnel.c255
-rw-r--r--src/cadet/gnunet-service-cadet_tunnel.h8
-rw-r--r--src/cadet/test_cadet.conf5
-rw-r--r--src/cadet/test_cadet_local.c5
-rw-r--r--src/consensus/consensus_api.c2
-rw-r--r--src/conversation/conversation_api.c2
-rw-r--r--src/conversation/conversation_api_call.c2
-rw-r--r--src/core/.gitignore7
-rw-r--r--src/core/Makefile.am1
-rw-r--r--src/core/core_api.c761
-rw-r--r--src/core/core_api_2.c865
-rw-r--r--src/core/core_api_monitor_peers.c2
-rw-r--r--src/core/core_api_mq.c191
-rw-r--r--src/core/test_core_api.c6
-rw-r--r--src/core/test_core_api_reliability.c6
-rw-r--r--src/core/test_core_api_send_to_self.c4
-rw-r--r--src/core/test_core_api_start_only.c12
-rw-r--r--src/core/test_core_defaults.conf6
-rw-r--r--src/core/test_core_quota_compliance.c6
-rw-r--r--src/credential/credential_api.c2
-rw-r--r--src/datacache/.gitignore6
-rw-r--r--src/datacache/plugin_datacache_heap.c3
-rw-r--r--src/datastore/.gitignore14
-rw-r--r--src/datastore/datastore_api.c4
-rw-r--r--src/datastore/plugin_datastore_heap.c8
-rw-r--r--src/dht/.gitignore7
-rw-r--r--src/dht/Makefile.am6
-rw-r--r--src/dht/dht_api.c2
-rw-r--r--src/dht/gnunet-service-dht_hello.c20
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c16
-rw-r--r--src/dht/gnunet-service-dht_routing.c44
-rw-r--r--src/dht/gnunet-service-wdht_neighbours.c4
-rw-r--r--src/dht/gnunet-service-xdht_neighbours.c4
-rw-r--r--src/dht/plugin_block_dht.c15
-rw-r--r--src/dns/.gitignore1
-rw-r--r--src/dns/dns_api.c2
-rw-r--r--src/dv/dv_api.c2
-rw-r--r--src/dv/gnunet-service-dv.c6
-rw-r--r--src/exit/gnunet-daemon-exit.c5
-rw-r--r--src/fragmentation/.gitignore2
-rw-r--r--src/fs/fs_download.c2
-rw-r--r--src/fs/fs_list_indexed.c2
-rw-r--r--src/fs/fs_publish.c4
-rw-r--r--src/fs/fs_search.c2
-rw-r--r--src/fs/fs_unindex.c2
-rw-r--r--src/fs/gnunet-service-fs.c6
-rw-r--r--src/gns/gns.conf.in4
-rw-r--r--src/gns/gns_api.c2
-rw-r--r--src/gns/gnunet-service-gns.c644
-rw-r--r--src/gns/gnunet-service-gns_reverser.c5
-rw-r--r--src/gnsrecord/.gitignore4
-rw-r--r--src/hello/.gitignore2
-rw-r--r--src/hostlist/.gitignore3
-rw-r--r--src/hostlist/gnunet-daemon-hostlist.c10
-rw-r--r--src/hostlist/gnunet-daemon-hostlist_client.c4
-rw-r--r--src/hostlist/gnunet-daemon-hostlist_client.h4
-rw-r--r--src/hostlist/gnunet-daemon-hostlist_server.c2
-rw-r--r--src/hostlist/gnunet-daemon-hostlist_server.h2
-rw-r--r--src/hostlist/test_gnunet_daemon_hostlist_learning.c13
-rw-r--r--src/identity-provider/identity_provider_api.c2
-rw-r--r--src/identity/.gitignore2
-rw-r--r--src/identity/identity_api.c2
-rw-r--r--src/include/Makefile.am2
-rw-r--r--src/include/gnunet_cadet_service.h55
-rw-r--r--src/include/gnunet_client_lib.h2
-rw-r--r--src/include/gnunet_common.h17
-rw-r--r--src/include/gnunet_constants.h6
-rw-r--r--src/include/gnunet_container_lib.h277
-rw-r--r--src/include/gnunet_core_service.h142
-rw-r--r--src/include/gnunet_crypto_lib.h28
-rw-r--r--src/include/gnunet_mq_lib.h13
-rw-r--r--src/include/gnunet_nat_auto_service.h135
-rw-r--r--src/include/gnunet_nat_lib.h591
-rw-r--r--src/include/gnunet_nat_service.h407
-rw-r--r--src/include/gnunet_peerinfo_service.h2
-rw-r--r--src/include/gnunet_protocols.h66
-rw-r--r--src/include/gnunet_signatures.h5
-rw-r--r--src/json/.gitignore1
-rw-r--r--src/jsonapi/.gitignore1
-rw-r--r--src/multicast/gnunet-service-multicast.c54
-rw-r--r--src/multicast/multicast_api.c6
-rw-r--r--src/my/.gitignore1
-rw-r--r--src/namecache/.gitignore4
-rw-r--r--src/namecache/namecache_api.c2
-rw-r--r--src/namestore/.gitignore17
-rw-r--r--src/namestore/namestore_api.c2
-rw-r--r--src/namestore/namestore_api_monitor.c2
-rw-r--r--src/nat-auto/.gitignore3
-rw-r--r--src/nat-auto/Makefile.am58
-rw-r--r--src/nat-auto/gnunet-nat-auto.c381
-rw-r--r--src/nat-auto/gnunet-nat-auto_legacy.c (renamed from src/nat/nat_test.c)2
-rw-r--r--src/nat-auto/gnunet-nat-server.c (renamed from src/nat/gnunet-nat-server.c)47
-rw-r--r--src/nat-auto/gnunet-service-nat-auto.c482
-rw-r--r--src/nat-auto/gnunet-service-nat-auto_legacy.c (renamed from src/nat/nat_auto.c)2
-rw-r--r--src/nat-auto/nat-auto.conf.in15
-rw-r--r--src/nat-auto/nat-auto.h110
-rw-r--r--src/nat-auto/nat_auto_api.c273
-rw-r--r--src/nat-auto/nat_auto_api_test.c (renamed from src/nat/nat_api_test.c)164
-rw-r--r--src/nat/Makefile.am81
-rw-r--r--src/nat/gnunet-nat.c301
-rw-r--r--src/nat/gnunet-service-nat.c1168
-rw-r--r--src/nat/gnunet-service-nat.h35
-rw-r--r--src/nat/gnunet-service-nat_externalip.c314
-rw-r--r--src/nat/gnunet-service-nat_externalip.h92
-rw-r--r--src/nat/gnunet-service-nat_helper.c26
-rw-r--r--src/nat/gnunet-service-nat_mini.h2
-rw-r--r--src/nat/nat.c2054
-rw-r--r--src/nat/nat.conf.in38
-rw-r--r--src/nat/nat.h48
-rw-r--r--src/nat/nat_api.c271
-rw-r--r--src/nat/nat_api_stun.c8
-rw-r--r--src/nat/nat_mini.c712
-rw-r--r--src/nat/nat_stun.c439
-rw-r--r--src/nse/.gitignore2
-rw-r--r--src/nse/gnunet-service-nse.c4
-rw-r--r--src/nse/nse_api.c2
-rw-r--r--src/peerinfo-tool/.gitignore1
-rw-r--r--src/peerinfo-tool/Makefile.am1
-rw-r--r--src/peerinfo/.gitignore4
-rw-r--r--src/peerinfo/peerinfo_api.c4
-rw-r--r--src/peerinfo/peerinfo_api_notify.c2
-rw-r--r--src/peerstore/.gitignore6
-rw-r--r--src/peerstore/peerstore_api.c2
-rw-r--r--src/pq/.gitignore1
-rw-r--r--src/psyc/psyc_api.c6
-rw-r--r--src/psycstore/gnunet-service-psycstore.c4
-rw-r--r--src/psycstore/psycstore_api.c2
-rw-r--r--src/regex/.gitignore7
-rw-r--r--src/regex/regex_api_announce.c2
-rw-r--r--src/regex/regex_api_search.c2
-rw-r--r--src/revocation/gnunet-service-revocation.c4
-rw-r--r--src/revocation/revocation_api.c4
-rw-r--r--src/revocation/test_revocation.c4
-rw-r--r--src/rps/rps_api.c2
-rw-r--r--src/scalarproduct/scalarproduct_api.c4
-rw-r--r--src/secretsharing/secretsharing_api.c4
-rw-r--r--src/set/Makefile.am2
-rw-r--r--src/set/set_api.c4
-rw-r--r--src/social/gnunet-social.c2
-rw-r--r--src/social/social_api.c12
-rw-r--r--src/statistics/.gitignore5
-rw-r--r--src/statistics/statistics_api.c2
-rw-r--r--src/template/.gitignore1
-rw-r--r--src/testbed-logger/.gitignore1
-rw-r--r--src/testbed-logger/testbed_logger_api.c2
-rw-r--r--src/testbed/.gitignore30
-rw-r--r--src/testbed/gnunet-service-testbed_connectionpool.c8
-rw-r--r--src/testbed/testbed_api.c2
-rw-r--r--src/testbed/testbed_api_barriers.c2
-rw-r--r--src/testing/.gitignore5
-rw-r--r--src/topology/.gitignore1
-rw-r--r--src/topology/gnunet-daemon-topology.c6
-rw-r--r--src/transport/.gitignore76
-rw-r--r--src/transport/Makefile.am14
-rw-r--r--src/transport/gnunet-service-transport_neighbours.c8
-rw-r--r--src/transport/gnunet-transport.c246
-rw-r--r--src/transport/plugin_transport_http_server.c25
-rw-r--r--src/transport/plugin_transport_tcp.c138
-rw-r--r--src/transport/plugin_transport_udp.c71
-rw-r--r--src/transport/plugin_transport_udp.h1
-rw-r--r--src/transport/plugin_transport_udp_broadcasting.c1
-rw-r--r--src/transport/transport.conf.in49
-rw-r--r--src/transport/transport_api_address_to_string.c2
-rw-r--r--src/transport/transport_api_blacklist.c2
-rw-r--r--src/transport/transport_api_core.c2
-rw-r--r--src/transport/transport_api_hello_get.c2
-rw-r--r--src/transport/transport_api_manipulation.c2
-rw-r--r--src/transport/transport_api_monitor_peers.c2
-rw-r--r--src/transport/transport_api_monitor_plugins.c2
-rw-r--r--src/transport/transport_api_offer_hello.c2
-rw-r--r--src/tun/.gitignore2
-rw-r--r--src/util/.gitignore55
-rw-r--r--src/util/Makefile.am3
-rw-r--r--src/util/client.c (renamed from src/util/client_new.c)16
-rw-r--r--src/util/common_logging.c23
-rw-r--r--src/util/container_heap.c27
-rw-r--r--src/util/container_multishortmap.c965
-rw-r--r--src/util/mq.c22
-rw-r--r--src/util/resolver_api.c2
-rw-r--r--src/util/test_client.c4
-rw-r--r--src/util/test_container_heap.c13
-rw-r--r--src/util/test_server.c2
-rw-r--r--src/util/test_server_disconnect.c2
-rw-r--r--src/util/test_server_with_client.c2
-rw-r--r--src/util/test_server_with_client_unix.c2
-rw-r--r--src/util/test_service.c2
-rw-r--r--src/util/test_socks.c2
-rw-r--r--src/vpn/gnunet-service-vpn.c12
-rw-r--r--src/vpn/vpn.conf.in2
-rw-r--r--src/vpn/vpn_api.c2
-rw-r--r--src/zonemaster/.gitignore1
-rw-r--r--src/zonemaster/Makefile.am35
-rw-r--r--src/zonemaster/gnunet-service-zonemaster.c776
-rw-r--r--src/zonemaster/zonemaster.conf.in25
251 files changed, 18439 insertions, 9622 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2877cab0b..120d80a3f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,7 @@ if HAVE_TESTING
8 TESTBED = testbed-logger testbed 8 TESTBED = testbed-logger testbed
9 CONSENSUS = consensus 9 CONSENSUS = consensus
10 SECRETSHARING = secretsharing 10 SECRETSHARING = secretsharing
11 ATS_TESTS = ats-tests
11endif 12endif
12 13
13if HAVE_EXPERIMENTAL 14if HAVE_EXPERIMENTAL
@@ -59,6 +60,10 @@ if HAVE_JSON
59endif 60endif
60endif 61endif
61 62
63if HAVE_JSON
64 AUCTION_DIR = auction
65endif
66
62if TALER_ONLY 67if TALER_ONLY
63SUBDIRS = \ 68SUBDIRS = \
64 include \ 69 include \
@@ -85,13 +90,14 @@ SUBDIRS = \
85 template \ 90 template \
86 ats \ 91 ats \
87 nat \ 92 nat \
93 nat-auto \
88 fragmentation \ 94 fragmentation \
89 transport \ 95 transport \
90 ats-tool \ 96 ats-tool \
91 peerinfo-tool \ 97 peerinfo-tool \
92 core \ 98 core \
93 $(TESTBED) \ 99 $(TESTBED) \
94 ats-tests \ 100 $(ATS_TESTS) \
95 nse \ 101 nse \
96 dht \ 102 dht \
97 hostlist \ 103 hostlist \
@@ -110,6 +116,7 @@ SUBDIRS = \
110 vpn \ 116 vpn \
111 gns \ 117 gns \
112 credential \ 118 credential \
119 zonemaster \
113 $(CONVERSATION_DIR) \ 120 $(CONVERSATION_DIR) \
114 fs \ 121 fs \
115 exit \ 122 exit \
@@ -120,6 +127,7 @@ SUBDIRS = \
120 psycstore \ 127 psycstore \
121 psyc \ 128 psyc \
122 social \ 129 social \
130 $(AUCTION_DIR) \
123 $(EXP_DIR) \ 131 $(EXP_DIR) \
124 $(PROVIDER_DIR) 132 $(PROVIDER_DIR)
125 133
diff --git a/src/arm/.gitignore b/src/arm/.gitignore
index 0ea685353..859c6e393 100644
--- a/src/arm/.gitignore
+++ b/src/arm/.gitignore
@@ -1,3 +1,7 @@
1mockup-service 1mockup-service
2gnunet-arm 2gnunet-arm
3gnunet-service-arm 3gnunet-service-arm
4test_arm_api
5test_exponential_backoff
6test_gnunet_arm.py
7test_gnunet_service_arm
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index 2967e62b7..a61343833 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -474,7 +474,7 @@ reconnect_arm (struct GNUNET_ARM_Handle *h)
474 if (NULL != h->mq) 474 if (NULL != h->mq)
475 return GNUNET_OK; 475 return GNUNET_OK;
476 GNUNET_assert (GNUNET_NO == h->currently_up); 476 GNUNET_assert (GNUNET_NO == h->currently_up);
477 h->mq = GNUNET_CLIENT_connecT (h->cfg, 477 h->mq = GNUNET_CLIENT_connect (h->cfg,
478 "arm", 478 "arm",
479 handlers, 479 handlers,
480 &mq_error_handler, 480 &mq_error_handler,
diff --git a/src/arm/arm_monitor_api.c b/src/arm/arm_monitor_api.c
index 471393c7e..b4dc6cb6a 100644
--- a/src/arm/arm_monitor_api.c
+++ b/src/arm/arm_monitor_api.c
@@ -209,7 +209,7 @@ reconnect_arm_monitor (struct GNUNET_ARM_MonitorHandle *h)
209 struct GNUNET_MQ_Envelope *env; 209 struct GNUNET_MQ_Envelope *env;
210 210
211 GNUNET_assert (NULL == h->mq); 211 GNUNET_assert (NULL == h->mq);
212 h->mq = GNUNET_CLIENT_connecT (h->cfg, 212 h->mq = GNUNET_CLIENT_connect (h->cfg,
213 "arm", 213 "arm",
214 handlers, 214 handlers,
215 &mq_error_handler, 215 &mq_error_handler,
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c
index 3b024ea93..b6f4d99a8 100644
--- a/src/arm/gnunet-arm.c
+++ b/src/arm/gnunet-arm.c
@@ -110,11 +110,15 @@ static unsigned int phase;
110 110
111/** 111/**
112 * User defined timestamp for completing operations. 112 * User defined timestamp for completing operations.
113 * FIXME: to be implemented!
114 */ 113 */
115static struct GNUNET_TIME_Relative timeout; 114static struct GNUNET_TIME_Relative timeout;
116 115
117/** 116/**
117 * Task to be run on timeout.
118 */
119static struct GNUNET_SCHEDULER_Task *timeout_task;
120
121/**
118 * Do we want to give our stdout to gnunet-service-arm? 122 * Do we want to give our stdout to gnunet-service-arm?
119 */ 123 */
120static unsigned int no_stdout; 124static unsigned int no_stdout;
@@ -191,6 +195,11 @@ shutdown_task (void *cls)
191 GNUNET_ARM_monitor_stop (m); 195 GNUNET_ARM_monitor_stop (m);
192 m = NULL; 196 m = NULL;
193 } 197 }
198 if (NULL != timeout_task)
199 {
200 GNUNET_SCHEDULER_cancel (timeout_task);
201 timeout_task = NULL;
202 }
194 if ((GNUNET_YES == end) && (GNUNET_YES == delete)) 203 if ((GNUNET_YES == end) && (GNUNET_YES == delete))
195 delete_files (); 204 delete_files ();
196 GNUNET_CONFIGURATION_destroy (cfg); 205 GNUNET_CONFIGURATION_destroy (cfg);
@@ -683,6 +692,18 @@ srv_status (void *cls,
683 692
684 693
685/** 694/**
695 * Task run on timeout (if -T is given).
696 */
697static void
698timeout_task_cb (void *cls)
699{
700 timeout_task = NULL;
701 ret = 2;
702 GNUNET_SCHEDULER_shutdown ();
703}
704
705
706/**
686 * Main function that will be run by the scheduler. 707 * Main function that will be run by the scheduler.
687 * 708 *
688 * @param cls closure 709 * @param cls closure
@@ -739,6 +760,10 @@ run (void *cls,
739 NULL); 760 NULL);
740 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 761 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
741 NULL); 762 NULL);
763 if (0 != timeout.rel_value_us)
764 timeout_task = GNUNET_SCHEDULER_add_delayed (timeout,
765 &timeout_task_cb,
766 NULL);
742} 767}
743 768
744 769
@@ -747,7 +772,7 @@ run (void *cls,
747 * 772 *
748 * @param argc number of arguments from the command line 773 * @param argc number of arguments from the command line
749 * @param argv command line arguments 774 * @param argv command line arguments
750 * @return 0 ok, 1 on error 775 * @return 0 ok, 1 on error, 2 on timeout
751 */ 776 */
752int 777int
753main (int argc, char *const *argv) 778main (int argc, char *const *argv)
@@ -793,10 +818,10 @@ main (int argc, char *const *argv)
793 gettext_noop 818 gettext_noop
794 ("Control services and the Automated Restart Manager (ARM)"), 819 ("Control services and the Automated Restart Manager (ARM)"),
795 options, &run, NULL)) 820 options, &run, NULL))
796 { 821 {
797 GNUNET_free ((void *) argv); 822 GNUNET_free ((void *) argv);
798 return ret; 823 return ret;
799 } 824 }
800 GNUNET_free ((void*) argv); 825 GNUNET_free ((void*) argv);
801 return 1; 826 return 1;
802} 827}
diff --git a/src/arm/test_exponential_backoff.c b/src/arm/test_exponential_backoff.c
index ab47ff635..0905f145d 100644
--- a/src/arm/test_exponential_backoff.c
+++ b/src/arm/test_exponential_backoff.c
@@ -151,7 +151,7 @@ kill_task (void *cbData)
151 GNUNET_free (shutdown_ctx); 151 GNUNET_free (shutdown_ctx);
152 return; 152 return;
153 } 153 }
154 shutdown_ctx->mq = GNUNET_CLIENT_connecT (cfg, 154 shutdown_ctx->mq = GNUNET_CLIENT_connect (cfg,
155 SERVICE, 155 SERVICE,
156 handlers, 156 handlers,
157 &mq_error_handler, 157 &mq_error_handler,
diff --git a/src/ats-tests/.gitignore b/src/ats-tests/.gitignore
index 9e4a44df5..800898bf9 100644
--- a/src/ats-tests/.gitignore
+++ b/src/ats-tests/.gitignore
@@ -1,2 +1,8 @@
1gnunet-solver-eval 1gnunet-solver-eval
2gnunet-ats-sim 2gnunet-ats-sim
3perf_ats_proportional_core_bandwidth
4perf_ats_proportional_core_latency
5perf_ats_proportional_core_none
6perf_ats_proportional_transport_bandwidth
7perf_ats_proportional_transport_latency
8perf_ats_proportional_transport_none
diff --git a/src/ats-tests/ats-testing.c b/src/ats-tests/ats-testing.c
index eb30daa6b..326d3bdd4 100644
--- a/src/ats-tests/ats-testing.c
+++ b/src/ats-tests/ats-testing.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2010-2013, 2016 GNUnet e.V. 3 Copyright (C) 2010-2013, 2016, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -88,11 +88,6 @@ do_shutdown (void *cls)
88 88
89 for (c_op = 0; c_op < p->num_partners; c_op++) 89 for (c_op = 0; c_op < p->num_partners; c_op++)
90 { 90 {
91 if (NULL != p->partners[c_op].cth)
92 {
93 GNUNET_CORE_notify_transmit_ready_cancel (p->partners[c_op].cth);
94 p->partners[c_op].cth = NULL;
95 }
96 if ( (NULL != p->core_connect_ops) && 91 if ( (NULL != p->core_connect_ops) &&
97 (NULL != p->core_connect_ops[c_op].connect_op) ) 92 (NULL != p->core_connect_ops[c_op].connect_op) )
98 { 93 {
@@ -128,15 +123,6 @@ do_shutdown (void *cls)
128 GNUNET_TESTBED_operation_done (p->peer_id_op); 123 GNUNET_TESTBED_operation_done (p->peer_id_op);
129 p->peer_id_op = NULL; 124 p->peer_id_op = NULL;
130 } 125 }
131
132 for (c_op = 0; c_op < p->num_partners; c_op++)
133 {
134 if (NULL != p->partners[c_op].cth)
135 {
136 GNUNET_CORE_notify_transmit_ready_cancel (p->partners[c_op].cth);
137 p->partners[c_op].cth = NULL;
138 }
139 }
140 if (NULL != p->ats_perf_op) 126 if (NULL != p->ats_perf_op)
141 { 127 {
142 GNUNET_TESTBED_operation_done (p->ats_perf_op); 128 GNUNET_TESTBED_operation_done (p->ats_perf_op);
@@ -314,11 +300,6 @@ comm_disconnect_cb (void *cls,
314 "%s disconnected from %s while benchmarking\n", 300 "%s disconnected from %s while benchmarking\n",
315 id, 301 id,
316 GNUNET_i2s (peer)); 302 GNUNET_i2s (peer));
317 if (NULL != p->cth)
318 {
319 GNUNET_CORE_notify_transmit_ready_cancel (p->cth);
320 p->cth = NULL;
321 }
322 } 303 }
323 GNUNET_free(id); 304 GNUNET_free(id);
324} 305}
@@ -403,7 +384,7 @@ core_connect_adapter (void *cls,
403 GNUNET_MQ_handler_end () 384 GNUNET_MQ_handler_end ()
404 }; 385 };
405 386
406 me->ch = GNUNET_CORE_connecT (cfg, 387 me->ch = GNUNET_CORE_connect (cfg,
407 me, 388 me,
408 NULL, 389 NULL,
409 &comm_connect_cb, 390 &comm_connect_cb,
@@ -422,7 +403,7 @@ core_disconnect_adapter (void *cls,
422{ 403{
423 struct BenchmarkPeer *me = cls; 404 struct BenchmarkPeer *me = cls;
424 405
425 GNUNET_CORE_disconnecT (me->ch); 406 GNUNET_CORE_disconnect (me->ch);
426 me->ch = NULL; 407 me->ch = NULL;
427} 408}
428 409
diff --git a/src/ats-tests/ats-testing.h b/src/ats-tests/ats-testing.h
index de189953e..32f0b02d8 100644
--- a/src/ats-tests/ats-testing.h
+++ b/src/ats-tests/ats-testing.h
@@ -285,11 +285,6 @@ struct BenchmarkPartner
285 struct BenchmarkPeer *dest; 285 struct BenchmarkPeer *dest;
286 286
287 /** 287 /**
288 * Core transmit handles
289 */
290 struct GNUNET_CORE_TransmitHandle *cth;
291
292 /**
293 * Message queue handle. 288 * Message queue handle.
294 */ 289 */
295 struct GNUNET_MQ_Handle *mq; 290 struct GNUNET_MQ_Handle *mq;
@@ -335,27 +330,27 @@ struct BenchmarkPartner
335 unsigned int bytes_received; 330 unsigned int bytes_received;
336 331
337 /** 332 /**
338 * Current ATS properties 333 * Current ATS properties
339 */ 334 */
340 struct GNUNET_ATS_Properties props; 335 struct GNUNET_ATS_Properties props;
341 336
342 /** 337 /**
343 * Bandwidth assigned inbound 338 * Bandwidth assigned inbound
344 */ 339 */
345 uint32_t bandwidth_in; 340 uint32_t bandwidth_in;
346 341
347 /** 342 /**
348 * Bandwidth assigned outbound 343 * Bandwidth assigned outbound
349 */ 344 */
350 uint32_t bandwidth_out; 345 uint32_t bandwidth_out;
351 346
352 /** 347 /**
353 * Current preference values for bandwidth 348 * Current preference values for bandwidth
354 */ 349 */
355 double pref_bandwidth; 350 double pref_bandwidth;
356 351
357 /** 352 /**
358 * Current preference values for delay 353 * Current preference values for delay
359 */ 354 */
360 double pref_delay; 355 double pref_delay;
361 356
diff --git a/src/ats/.gitignore b/src/ats/.gitignore
index 7b70f84a5..983dc2843 100644
--- a/src/ats/.gitignore
+++ b/src/ats/.gitignore
@@ -1 +1,3 @@
1gnunet-service-ats 1gnunet-service-ats
2test_ats_api_proportional
3test_ats_reservation_api_proportional
diff --git a/src/ats/ats_api_connectivity.c b/src/ats/ats_api_connectivity.c
index 241e5f93c..d551aacd4 100644
--- a/src/ats/ats_api_connectivity.c
+++ b/src/ats/ats_api_connectivity.c
@@ -195,7 +195,7 @@ reconnect (struct GNUNET_ATS_ConnectivityHandle *ch)
195 struct ClientStartMessage *init; 195 struct ClientStartMessage *init;
196 196
197 GNUNET_assert (NULL == ch->mq); 197 GNUNET_assert (NULL == ch->mq);
198 ch->mq = GNUNET_CLIENT_connecT (ch->cfg, 198 ch->mq = GNUNET_CLIENT_connect (ch->cfg,
199 "ats", 199 "ats",
200 handlers, 200 handlers,
201 &error_handler, 201 &error_handler,
diff --git a/src/ats/ats_api_performance.c b/src/ats/ats_api_performance.c
index dd8666d4c..cd67583d1 100644
--- a/src/ats/ats_api_performance.c
+++ b/src/ats/ats_api_performance.c
@@ -585,7 +585,7 @@ reconnect (struct GNUNET_ATS_PerformanceHandle *ph)
585 struct ClientStartMessage *init; 585 struct ClientStartMessage *init;
586 586
587 GNUNET_assert (NULL == ph->mq); 587 GNUNET_assert (NULL == ph->mq);
588 ph->mq = GNUNET_CLIENT_connecT (ph->cfg, 588 ph->mq = GNUNET_CLIENT_connect (ph->cfg,
589 "ats", 589 "ats",
590 handlers, 590 handlers,
591 &mq_error_handler, 591 &mq_error_handler,
diff --git a/src/ats/ats_api_scheduling.c b/src/ats/ats_api_scheduling.c
index 4a872b90a..faeeb6081 100644
--- a/src/ats/ats_api_scheduling.c
+++ b/src/ats/ats_api_scheduling.c
@@ -532,7 +532,7 @@ reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
532 struct GNUNET_ATS_AddressRecord *ar; 532 struct GNUNET_ATS_AddressRecord *ar;
533 533
534 GNUNET_assert (NULL == sh->mq); 534 GNUNET_assert (NULL == sh->mq);
535 sh->mq = GNUNET_CLIENT_connecT (sh->cfg, 535 sh->mq = GNUNET_CLIENT_connect (sh->cfg,
536 "ats", 536 "ats",
537 handlers, 537 handlers,
538 &error_handler, 538 &error_handler,
diff --git a/src/auction/.gitignore b/src/auction/.gitignore
new file mode 100644
index 000000000..5c3ec20cb
--- /dev/null
+++ b/src/auction/.gitignore
@@ -0,0 +1,5 @@
1gnunet-auction-create
2gnunet-auction-info
3gnunet-auction-join
4gnunet-service-auction
5test_auction_api
diff --git a/src/auction/Makefile.am b/src/auction/Makefile.am
new file mode 100644
index 000000000..87f917283
--- /dev/null
+++ b/src/auction/Makefile.am
@@ -0,0 +1,74 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4pkgcfgdir= $(pkgdatadir)/config.d/
5
6libexecdir= $(pkglibdir)/libexec/
7
8
9pkgcfg_DATA = \
10 auction.conf
11
12if MINGW
13 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
14endif
15
16if USE_COVERAGE
17 AM_CFLAGS = -fprofile-arcs -ftest-coverage
18endif
19
20
21libexec_PROGRAMS = \
22 gnunet-service-auction
23
24gnunet_service_auction_SOURCES = \
25 gnunet-service-auction.c
26gnunet_service_auction_LDADD = \
27 $(top_builddir)/src/util/libgnunetutil.la \
28 -ljansson \
29 $(GN_LIBINTL)
30
31
32bin_PROGRAMS = \
33 gnunet-auction-create \
34 gnunet-auction-info \
35 gnunet-auction-join
36
37gnunet_auction_create_SOURCES = \
38 gnunet-auction-create.c
39gnunet_auction_create_LDADD = \
40 $(top_builddir)/src/util/libgnunetutil.la \
41 -ljansson \
42 $(GN_LIBINTL)
43
44gnunet_auction_info_SOURCES = \
45 gnunet-auction-info.c
46gnunet_auction_info_LDADD = \
47 $(top_builddir)/src/util/libgnunetutil.la \
48 -ljansson \
49 $(GN_LIBINTL)
50
51gnunet_auction_join_SOURCES = \
52 gnunet-auction-join.c
53gnunet_auction_join_LDADD = \
54 $(top_builddir)/src/util/libgnunetutil.la \
55 -ljansson \
56 $(GN_LIBINTL)
57
58
59check_PROGRAMS = \
60 test_auction_api
61
62test_auction_api_SOURCES = \
63 test_auction_api.c
64test_auction_api_LDADD = \
65 $(top_builddir)/src/util/libgnunetutil.la
66
67
68check_SCRIPTS = \
69 test_auction_create.sh
70
71if ENABLE_TEST_RUN
72AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
73TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
74endif
diff --git a/src/auction/auction.conf b/src/auction/auction.conf
new file mode 100644
index 000000000..6ca35896b
--- /dev/null
+++ b/src/auction/auction.conf
@@ -0,0 +1,4 @@
1[auction]
2AUTOSTART = NO
3BINARY = gnunet-service-auction
4UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-auction.sock
diff --git a/src/auction/auction.h b/src/auction/auction.h
new file mode 100644
index 000000000..758307aeb
--- /dev/null
+++ b/src/auction/auction.h
@@ -0,0 +1,77 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2011 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @author Markus Teich
23 * @file auction/auction.h
24 *
25 * @brief Common type definitions for the auction service and API.
26 */
27#ifndef AUCTION_H
28#define AUCTION_H
29
30#include "gnunet_common.h"
31
32GNUNET_NETWORK_STRUCT_BEGIN
33
34/**
35 * Auction creation request sent from the client to the service
36 */
37struct GNUNET_AUCTION_ClientCreateMessage
38{
39 /**
40 * Type: GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_CREATE
41 */
42 struct GNUNET_MessageHeader header;
43
44 /**
45 * When should the auction start
46 */
47 struct GNUNET_TIME_AbsoluteNBO time_start;
48
49 /**
50 * How long is each round allowed to be maximally
51 */
52 struct GNUNET_TIME_RelativeNBO time_round;
53
54 /**
55 * Auction parameter m.
56 * 0 for first price auctions.
57 * >0 for M+1st price auctions.
58 */
59 uint16_t m GNUNET_PACKED;
60
61 /**
62 * Should the auction outcome be public?
63 * 0 for private outcome auctions.
64 * 1 for public outcome auctions.
65 */
66 uint16_t outcome_public GNUNET_PACKED;
67
68 /**
69 * TODO: Price mapping.
70 */
71
72 /* DESCRIPTION text copied to end of this message */
73};
74
75GNUNET_NETWORK_STRUCT_END
76
77#endif
diff --git a/src/auction/gnunet-auction-create.c b/src/auction/gnunet-auction-create.c
new file mode 100644
index 000000000..a4c029572
--- /dev/null
+++ b/src/auction/gnunet-auction-create.c
@@ -0,0 +1,197 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21/**
22 * @file auction/gnunet-auction-create.c
23 * @brief tool to create a new auction
24 * @author Markus Teich
25 */
26#include "platform.h"
27
28#include <float.h>
29
30#include "gnunet_util_lib.h"
31#include "gnunet_json_lib.h"
32/* #include "gnunet_auction_service.h" */
33
34#define FIRST_PRICE 0
35#define OUTCOME_PRIVATE 0
36#define OUTCOME_PUBLIC 1
37
38static int ret; /** Final status code. */
39static char *fndesc; /** filename of the item description */
40static char *fnprices; /** filename of the price map */
41static struct GNUNET_TIME_Relative dround; /** max round duration */
42static struct GNUNET_TIME_Relative dstart; /** time until auction starts */
43static unsigned int m = FIRST_PRICE; /** auction parameter m */
44static int outcome = OUTCOME_PRIVATE; /** outcome */
45static int interactive; /** keep running in foreground */
46
47
48/**
49 * Main function that will be run by the scheduler.
50 *
51 * @param cls closure
52 * @param args remaining command-line arguments
53 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
54 * @param cfg configuration
55 */
56static void
57run (void *cls,
58 char *const *args,
59 const char *cfgfile,
60 const struct GNUNET_CONFIGURATION_Handle *cfg)
61{
62 unsigned int i;
63 double cur, prev = DBL_MAX;
64 json_t *pmap;
65 json_t *parray;
66 json_t *pnode;
67 json_error_t jerr;
68
69 /* cmdline parsing */
70 if (GNUNET_TIME_UNIT_ZERO.rel_value_us == dstart.rel_value_us)
71 {
72 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
73 "required argument --regtime missing or invalid (zero)\n");
74 goto fail;
75 }
76 if (GNUNET_TIME_UNIT_ZERO.rel_value_us == dround.rel_value_us)
77 {
78 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
79 "required argument --roundtime missing or invalid (zero)\n");
80 goto fail;
81 }
82 if (!fndesc)
83 {
84 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
85 "required argument --description missing\n");
86 goto fail;
87 }
88 if (!fnprices)
89 {
90 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
91 "required argument --pricemap missing\n");
92 goto fail;
93 }
94
95 /* parse and check pricemap validity */
96 if (!(pmap = json_load_file (fnprices, JSON_DECODE_INT_AS_REAL, &jerr)))
97 {
98 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
99 "parsing pricemap json at %d:%d: %s\n",
100 jerr.line, jerr.column, jerr.text);
101 goto fail;
102 }
103 if (-1 == json_unpack_ex (pmap, &jerr, JSON_VALIDATE_ONLY,
104 "{s:s, s:[]}", "currency", "prices"))
105 {
106 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
107 "validating pricemap: %s\n", jerr.text);
108 goto fail;
109 }
110 if (!(parray = json_object_get (pmap, "prices")) || !json_is_array (parray))
111 {
112 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
113 "could not get `prices` array node from pricemap\n");
114 goto fail;
115 }
116 if (0 == json_array_size (parray))
117 {
118 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "empty pricemap array\n");
119 goto fail;
120 }
121 json_array_foreach (parray, i, pnode)
122 {
123 if (-1 == json_unpack_ex (pnode, &jerr, 0, "F", &cur))
124 {
125 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
126 "validating pricearray index %d: %s\n", i, jerr.text);
127 goto fail;
128 }
129 if (prev <= cur)
130 {
131 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
132 "validating pricearray index %d: "
133 "prices must be strictly monotonically decreasing\n",
134 i);
135 goto fail;
136 }
137 prev = cur;
138 }
139
140 return;
141
142fail:
143 ret = 1;
144 return;
145}
146
147
148/**
149 * The main function.
150 *
151 * @param argc number of arguments from the command line
152 * @param argv command line arguments
153 * @return 0 ok, 1 on error
154 */
155int
156main (int argc, char *const *argv)
157{
158 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
159 {'d', "description", "FILE",
160 gettext_noop ("description of the item to be sold"),
161 1, &GNUNET_GETOPT_set_filename, &fndesc},
162 {'p', "pricemap", "FILE",
163 gettext_noop ("mapping of possible prices"),
164 1, &GNUNET_GETOPT_set_filename, &fnprices},
165 {'r', "roundtime", "DURATION",
166 gettext_noop ("max duration per round"),
167 1, &GNUNET_GETOPT_set_relative_time, &dround},
168 {'s', "regtime", "DURATION",
169 gettext_noop ("duration until auction starts"),
170 1, &GNUNET_GETOPT_set_relative_time, &dstart},
171 {'m', "m", "NUMBER",
172 gettext_noop ("number of items to sell\n"
173 "0 for first price auction\n"
174 ">0 for vickrey/M+1st price auction"),
175 1, &GNUNET_GETOPT_set_uint, &m},
176 {'u', "public", NULL,
177 gettext_noop ("public auction outcome"),
178 0, &GNUNET_GETOPT_set_one, &outcome},
179 {'i', "interactive", NULL,
180 gettext_noop ("keep running in foreground until auction completes"),
181 0, &GNUNET_GETOPT_set_one, &interactive},
182 GNUNET_GETOPT_OPTION_END
183 };
184 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
185 return 2;
186
187 ret = (GNUNET_OK ==
188 GNUNET_PROGRAM_run (argc, argv,
189 "gnunet-auction-create",
190 gettext_noop ("create a new auction and "
191 "start listening for bidders"),
192 options,
193 &run,
194 NULL)) ? ret : 1;
195 GNUNET_free ((void*) argv);
196 return ret;
197}
diff --git a/src/auction/gnunet-auction-info.c b/src/auction/gnunet-auction-info.c
new file mode 100644
index 000000000..a4af1152a
--- /dev/null
+++ b/src/auction/gnunet-auction-info.c
@@ -0,0 +1,84 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file auction/gnunet-auction.c
23 * @brief auction for writing a tool
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28/* #include "gnunet_auction_service.h" */
29
30/**
31 * Final status code.
32 */
33static int ret;
34
35
36/**
37 * Main function that will be run by the scheduler.
38 *
39 * @param cls closure
40 * @param args remaining command-line arguments
41 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
42 * @param cfg configuration
43 */
44static void
45run (void *cls,
46 char *const *args,
47 const char *cfgfile,
48 const struct GNUNET_CONFIGURATION_Handle *cfg)
49{
50 /* main code here */
51}
52
53
54/**
55 * The main function.
56 *
57 * @param argc number of arguments from the command line
58 * @param argv command line arguments
59 * @return 0 ok, 1 on error
60 */
61int
62main (int argc, char *const *argv)
63{
64 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
65 /* FIMXE: add options here */
66 GNUNET_GETOPT_OPTION_END
67 };
68 if (GNUNET_OK !=
69 GNUNET_STRINGS_get_utf8_args (argc, argv,
70 &argc, &argv))
71 return 2;
72
73 ret = (GNUNET_OK ==
74 GNUNET_PROGRAM_run (argc, argv,
75 "gnunet-auction",
76 gettext_noop ("help text"),
77 options,
78 &run,
79 NULL)) ? ret : 1;
80 GNUNET_free ((void*) argv);
81 return ret;
82}
83
84/* end of gnunet-auction.c */
diff --git a/src/auction/gnunet-auction-join.c b/src/auction/gnunet-auction-join.c
new file mode 100644
index 000000000..a4af1152a
--- /dev/null
+++ b/src/auction/gnunet-auction-join.c
@@ -0,0 +1,84 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file auction/gnunet-auction.c
23 * @brief auction for writing a tool
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28/* #include "gnunet_auction_service.h" */
29
30/**
31 * Final status code.
32 */
33static int ret;
34
35
36/**
37 * Main function that will be run by the scheduler.
38 *
39 * @param cls closure
40 * @param args remaining command-line arguments
41 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
42 * @param cfg configuration
43 */
44static void
45run (void *cls,
46 char *const *args,
47 const char *cfgfile,
48 const struct GNUNET_CONFIGURATION_Handle *cfg)
49{
50 /* main code here */
51}
52
53
54/**
55 * The main function.
56 *
57 * @param argc number of arguments from the command line
58 * @param argv command line arguments
59 * @return 0 ok, 1 on error
60 */
61int
62main (int argc, char *const *argv)
63{
64 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
65 /* FIMXE: add options here */
66 GNUNET_GETOPT_OPTION_END
67 };
68 if (GNUNET_OK !=
69 GNUNET_STRINGS_get_utf8_args (argc, argv,
70 &argc, &argv))
71 return 2;
72
73 ret = (GNUNET_OK ==
74 GNUNET_PROGRAM_run (argc, argv,
75 "gnunet-auction",
76 gettext_noop ("help text"),
77 options,
78 &run,
79 NULL)) ? ret : 1;
80 GNUNET_free ((void*) argv);
81 return ret;
82}
83
84/* end of gnunet-auction.c */
diff --git a/src/auction/gnunet-service-auction.c b/src/auction/gnunet-service-auction.c
new file mode 100644
index 000000000..dac38914d
--- /dev/null
+++ b/src/auction/gnunet-service-auction.c
@@ -0,0 +1,155 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21/**
22 * @file auction/gnunet-service-auction.c
23 * @brief service for executing auctions
24 * @author Markus Teich
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28
29#include "auction.h"
30
31/**
32 * Check AUCTION CREATE messages from the client.
33 *
34 * @param cls the client we received this message from
35 * @param msg the actual message received
36 * @return #GNUNET_OK (always)
37 */
38static int
39check_create (void *cls, const struct GNUNET_AUCTION_ClientCreateMessage *msg)
40{
41 /* always well-formed due to arbitrary length description */
42 return GNUNET_OK;
43}
44
45
46/**
47 * Handler for CREATE messages.
48 *
49 * @param cls the client we received this message from
50 * @param msg the actual message received
51 */
52static void
53handle_create (void *cls, const struct GNUNET_AUCTION_ClientCreateMessage *msg)
54{
55 struct GNUNET_SERVICE_Client *client = cls;
56// struct GNUNET_MQ_Handle *mq;
57// struct GNUNET_MQ_Envelope *env;
58// struct GNUNET_AUCTION_blabla em;
59 uint16_t size;
60
61 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
62 "Received CREATE message from client\n");
63
64 size = ntohs (msg->header.size);
65
66 /**TODO: create auction and return auction object */
67// mq = GNUNET_SERVICE_client_get_mq (client);
68// setup_info_message (&em);
69// env = GNUNET_MQ_msg_copy (&em.header);
70// GNUNET_MQ_send (mq, env);
71
72 GNUNET_SERVICE_client_continue (client);
73}
74
75
76/**
77 * Task run during shutdown.
78 *
79 * @param cls unused
80 */
81static void
82cleanup_task (void *cls)
83{
84 /* FIXME: do clean up here */
85}
86
87
88/**
89 * Callback called when a client connects to the service.
90 *
91 * @param cls closure for the service
92 * @param c the new client that connected to the service
93 * @param mq the message queue used to send messages to the client
94 * @return @a c
95 */
96static void *
97client_connect_cb (void *cls,
98 struct GNUNET_SERVICE_Client *c,
99 struct GNUNET_MQ_Handle *mq)
100{
101 return c;
102}
103
104
105/**
106 * Callback called when a client disconnected from the service
107 *
108 * @param cls closure for the service
109 * @param c the client that disconnected
110 * @param internal_cls should be equal to @a c
111 */
112static void
113client_disconnect_cb (void *cls,
114 struct GNUNET_SERVICE_Client *c,
115 void *internal_cls)
116{
117 GNUNET_assert (c == internal_cls);
118}
119
120
121/**
122 * Process auction requests.
123 *
124 * @param cls closure
125 * @param cfg configuration to use
126 * @param service the initialized service
127 */
128static void
129run (void *cls,
130 const struct GNUNET_CONFIGURATION_Handle *cfg,
131 struct GNUNET_SERVICE_Handle *service)
132{
133 /* FIXME: do setup here */
134 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
135}
136
137
138/**
139 * Define "main" method using service macro.
140 */
141GNUNET_SERVICE_MAIN
142("auction",
143 GNUNET_SERVICE_OPTION_NONE,
144 &run,
145 &client_connect_cb,
146 &client_disconnect_cb,
147 NULL,
148 GNUNET_MQ_hd_var_size (create,
149 GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_CREATE,
150 struct GNUNET_AUCTION_ClientCreateMessage,
151 NULL),
152 GNUNET_MQ_handler_end ())
153
154
155/* end of gnunet-service-auction.c */
diff --git a/src/auction/test_auction_api.c b/src/auction/test_auction_api.c
new file mode 100644
index 000000000..38e93c6fc
--- /dev/null
+++ b/src/auction/test_auction_api.c
@@ -0,0 +1,42 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file auction/test_auction_api.c
22 * @brief testcase for auction.c
23 */
24#include "platform.h"
25
26static int
27check ()
28{
29 return 0;
30}
31
32int
33main (int argc, char *argv[])
34{
35 int ret;
36
37 ret = check ();
38
39 return ret;
40}
41
42/* end of test_auction_api.c */
diff --git a/src/auction/test_auction_create.sh b/src/auction/test_auction_create.sh
new file mode 100755
index 000000000..b0f4de738
--- /dev/null
+++ b/src/auction/test_auction_create.sh
@@ -0,0 +1,80 @@
1#! /bin/sh
2
3trap 'rm -f test.json' EXIT
4
5
6# missing required cmdline args
7gnunet-auction-create -r 1 -d foo -p test.json && exit 1
8gnunet-auction-create -s 1 -d foo -p test.json && exit 1
9gnunet-auction-create -s 1 -r 1 -p test.json && exit 1
10gnunet-auction-create -s 1 -r 1 -d foo && exit 1
11
12
13# no pricemap
14rm -f test.json
15gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
16
17
18# json errors
19cat <<DOG >test.json
20[,]
21DOG
22gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
23
24cat <<DOG >test.json
25bla
26DOG
27gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
28
29
30# unexpected structures
31cat <<DOG >test.json
32{"foo": "bar"}
33DOG
34gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
35
36cat <<DOG >test.json
37{"currency": "foo"}
38DOG
39gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
40
41cat <<DOG >test.json
42{"prices": []}
43DOG
44gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
45
46cat <<DOG >test.json
47{"currency": "foo", "prices": "bar"}
48DOG
49gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
50
51
52# wrong array content
53cat <<DOG >test.json
54{"currency": "foo", "prices": []}
55DOG
56gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
57
58cat <<DOG >test.json
59{"currency": "foo", "prices": ["bar"]}
60DOG
61gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
62
63cat <<DOG >test.json
64{"currency": "foo", "prices": [null]}
65DOG
66gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
67
68cat <<DOG >test.json
69{"currency": "foo", "prices": [1, 2]}
70DOG
71gnunet-auction-create -s 1 -r 1 -d foo -p test.json && exit 1
72
73
74# correct example
75cat <<DOG >test.json
76{"currency": "foo", "prices": [2, 1]}
77DOG
78gnunet-auction-create -s 1 -r 1 -d foo -p test.json || exit 1
79
80rm -f test.json
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am
index d823b4872..53d17dd9c 100644
--- a/src/cadet/Makefile.am
+++ b/src/cadet/Makefile.am
@@ -22,7 +22,9 @@ plugindir = $(libdir)/gnunet
22AM_CLFAGS = -g 22AM_CLFAGS = -g
23 23
24libexec_PROGRAMS = \ 24libexec_PROGRAMS = \
25 gnunet-service-cadet $(EXP_LIBEXEC) 25 gnunet-service-cadet \
26 gnunet-service-cadet-new \
27 $(EXP_LIBEXEC)
26 28
27bin_PROGRAMS = \ 29bin_PROGRAMS = \
28 gnunet-cadet 30 gnunet-cadet
@@ -46,6 +48,27 @@ gnunet_cadet_LDADD = \
46 libgnunetcadet.la \ 48 libgnunetcadet.la \
47 $(top_builddir)/src/util/libgnunetutil.la 49 $(top_builddir)/src/util/libgnunetutil.la
48 50
51gnunet_service_cadet_new_SOURCES = \
52 gnunet-service-cadet-new.c gnunet-service-cadet-new.h \
53 gnunet-service-cadet-new_channel.c gnunet-service-cadet-new_channel.h \
54 gnunet-service-cadet-new_connection.c gnunet-service-cadet-new_connection.h \
55 gnunet-service-cadet-new_core.c gnunet-service-cadet-new_core.h \
56 gnunet-service-cadet-new_dht.c gnunet-service-cadet-new_dht.h \
57 gnunet-service-cadet-new_hello.c gnunet-service-cadet-new_hello.h \
58 gnunet-service-cadet-new_tunnels.c gnunet-service-cadet-new_tunnels.h \
59 gnunet-service-cadet-new_paths.c gnunet-service-cadet-new_paths.h \
60 gnunet-service-cadet-new_peer.c gnunet-service-cadet-new_peer.h
61gnunet_service_cadet_new_LDADD = \
62 $(top_builddir)/src/util/libgnunetutil.la \
63 $(top_builddir)/src/ats/libgnunetats.la \
64 $(top_builddir)/src/core/libgnunetcore.la \
65 $(top_builddir)/src/dht/libgnunetdht.la \
66 $(top_builddir)/src/statistics/libgnunetstatistics.la \
67 $(top_builddir)/src/transport/libgnunettransport.la \
68 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
69 $(top_builddir)/src/hello/libgnunethello.la \
70 $(top_builddir)/src/block/libgnunetblock.la
71
49gnunet_service_cadet_SOURCES = \ 72gnunet_service_cadet_SOURCES = \
50 gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \ 73 gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \
51 gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \ 74 gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
@@ -87,6 +110,11 @@ libgnunetcadettest_a_LIBADD = \
87 110
88if HAVE_TESTING 111if HAVE_TESTING
89check_PROGRAMS = \ 112check_PROGRAMS = \
113 test_cadet_2_speed_reliable_backwards \
114 test_cadet_5_speed \
115 test_cadet_5_speed_ack \
116 test_cadet_5_speed_reliable \
117 test_cadet_5_speed_reliable_backwards \
90 test_cadet_single \ 118 test_cadet_single \
91 test_cadet_local \ 119 test_cadet_local \
92 test_cadet_2_forward \ 120 test_cadet_2_forward \
@@ -96,15 +124,10 @@ check_PROGRAMS = \
96 test_cadet_2_speed_ack \ 124 test_cadet_2_speed_ack \
97 test_cadet_2_speed_backwards \ 125 test_cadet_2_speed_backwards \
98 test_cadet_2_speed_reliable \ 126 test_cadet_2_speed_reliable \
99 test_cadet_2_speed_reliable_backwards \
100 test_cadet_5_forward \ 127 test_cadet_5_forward \
101 test_cadet_5_signal \ 128 test_cadet_5_signal \
102 test_cadet_5_keepalive \ 129 test_cadet_5_keepalive \
103 test_cadet_5_speed \ 130 test_cadet_5_speed_backwards
104 test_cadet_5_speed_ack \
105 test_cadet_5_speed_backwards \
106 test_cadet_5_speed_reliable \
107 test_cadet_5_speed_reliable_backwards
108endif 131endif
109 132
110ld_cadet_test_lib = \ 133ld_cadet_test_lib = \
diff --git a/src/cadet/cadet.h b/src/cadet/cadet.h
index 049f3a85a..c16fb2917 100644
--- a/src/cadet/cadet.h
+++ b/src/cadet/cadet.h
@@ -57,6 +57,7 @@ extern "C"
57#include "gnunet_util_lib.h" 57#include "gnunet_util_lib.h"
58#include "gnunet_peer_lib.h" 58#include "gnunet_peer_lib.h"
59#include "gnunet_core_service.h" 59#include "gnunet_core_service.h"
60#include "gnunet_cadet_service.h"
60#include "gnunet_protocols.h" 61#include "gnunet_protocols.h"
61#include <gnunet_cadet_service.h> 62#include <gnunet_cadet_service.h>
62 63
@@ -64,13 +65,29 @@ extern "C"
64/************************** CONSTANTS ******************************/ 65/************************** CONSTANTS ******************************/
65/******************************************************************************/ 66/******************************************************************************/
66 67
68/**
69 * Minimum value for channel IDs of local clients.
70 */
67#define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI 0x80000000 71#define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI 0x80000000
68#define GNUNET_CADET_LOCAL_CHANNEL_ID_SERV 0xB0000000
69 72
70#define HIGH_PID 0xFFFF0000 73/**
71#define LOW_PID 0x0000FFFF 74 * FIXME.
75 */
76#define HIGH_PID 0xFF000000
77
78/**
79 * FIXME.
80 */
81#define LOW_PID 0x00FFFFFF
72 82
73#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID) 83
84/**
85 * Test if the two PIDs (of type `uint32_t`) are in the range where we
86 * have to worry about overflows. This is the case when @a pid is
87 * large and @a max is small, useful when comparing @a pid smaller
88 * than @a max.
89 */
90#define PID_OVERFLOW(pid, max) (((pid) > HIGH_PID) && ((max) < LOW_PID))
74 91
75/******************************************************************************/ 92/******************************************************************************/
76/************************** MESSAGES ******************************/ 93/************************** MESSAGES ******************************/
@@ -80,6 +97,22 @@ GNUNET_NETWORK_STRUCT_BEGIN
80 97
81 98
82/** 99/**
100 * Number uniquely identifying a channel of a client.
101 */
102struct GNUNET_CADET_ClientChannelNumber
103{
104 /**
105 * Values for channel numbering.
106 * Local channel numbers given by the service (incoming) are
107 * smaller than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI.
108 * Local channel numbers given by the client (created) are
109 * larger than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI.
110 */
111 uint32_t channel_of_client GNUNET_PACKED;
112};
113
114
115/**
83 * Message for a client to create and destroy channels. 116 * Message for a client to create and destroy channels.
84 */ 117 */
85struct GNUNET_CADET_PortMessage 118struct GNUNET_CADET_PortMessage
@@ -98,31 +131,23 @@ struct GNUNET_CADET_PortMessage
98 struct GNUNET_HashCode port GNUNET_PACKED; 131 struct GNUNET_HashCode port GNUNET_PACKED;
99}; 132};
100 133
101/**
102 * Type for channel numbering.
103 * - Local channel numbers given by the service (incoming) are >= 0xB0000000
104 * - Local channel numbers given by the client (created) are >= 0x80000000
105 * - Global channel numbers are < 0x80000000
106 */
107typedef uint32_t CADET_ChannelNumber;
108
109 134
110/** 135/**
111 * Message for a client to create channels. 136 * Message for a client to create channels.
112 */ 137 */
113struct GNUNET_CADET_ChannelCreateMessage 138struct GNUNET_CADET_ChannelOpenMessageMessage
114{ 139{
115 /** 140 /**
116 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_CREATE 141 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_CREATE
117 * 142 *
118 * Size: sizeof(struct GNUNET_CADET_ChannelCreateMessage) 143 * Size: sizeof(struct GNUNET_CADET_ChannelOpenMessageMessage)
119 */ 144 */
120 struct GNUNET_MessageHeader header; 145 struct GNUNET_MessageHeader header;
121 146
122 /** 147 /**
123 * ID of a channel controlled by this client. 148 * ID of a channel controlled by this client.
124 */ 149 */
125 CADET_ChannelNumber channel_id GNUNET_PACKED; 150 struct GNUNET_CADET_ClientChannelNumber channel_id;
126 151
127 /** 152 /**
128 * Channel's peer 153 * Channel's peer
@@ -152,11 +177,11 @@ struct GNUNET_CADET_ChannelDestroyMessage
152 * Size: sizeof(struct GNUNET_CADET_ChannelDestroyMessage) 177 * Size: sizeof(struct GNUNET_CADET_ChannelDestroyMessage)
153 */ 178 */
154 struct GNUNET_MessageHeader header; 179 struct GNUNET_MessageHeader header;
155 180
156 /** 181 /**
157 * ID of a channel controlled by this client. 182 * ID of a channel controlled by this client.
158 */ 183 */
159 CADET_ChannelNumber channel_id GNUNET_PACKED; 184 struct GNUNET_CADET_ClientChannelNumber channel_id;
160}; 185};
161 186
162 187
@@ -173,7 +198,7 @@ struct GNUNET_CADET_LocalData
173 /** 198 /**
174 * ID of the channel 199 * ID of the channel
175 */ 200 */
176 uint32_t id GNUNET_PACKED; 201 struct GNUNET_CADET_ClientChannelNumber id;
177 202
178 /** 203 /**
179 * Payload follows 204 * Payload follows
@@ -195,7 +220,7 @@ struct GNUNET_CADET_LocalAck
195 /** 220 /**
196 * ID of the channel allowed to send more data. 221 * ID of the channel allowed to send more data.
197 */ 222 */
198 CADET_ChannelNumber channel_id GNUNET_PACKED; 223 struct GNUNET_CADET_ClientChannelNumber channel_id;
199 224
200}; 225};
201 226
@@ -214,7 +239,7 @@ struct GNUNET_CADET_LocalInfo
214 /** 239 /**
215 * ID of the channel allowed to send more data. 240 * ID of the channel allowed to send more data.
216 */ 241 */
217 CADET_ChannelNumber channel_id GNUNET_PACKED; 242 struct GNUNET_CADET_ClientChannelNumber channel_id;
218 243
219 /** 244 /**
220 * ID of the owner of the channel (can be local peer). 245 * ID of the owner of the channel (can be local peer).
@@ -258,6 +283,7 @@ struct GNUNET_CADET_LocalInfoPeer
258 * (each path ends in destination) */ 283 * (each path ends in destination) */
259}; 284};
260 285
286
261/** 287/**
262 * Message to inform the client about one of the tunnels in the service. 288 * Message to inform the client about one of the tunnels in the service.
263 */ 289 */
@@ -294,7 +320,7 @@ struct GNUNET_CADET_LocalInfoTunnel
294 */ 320 */
295 uint16_t cstate GNUNET_PACKED; 321 uint16_t cstate GNUNET_PACKED;
296 322
297 /* If TUNNEL (no 'S'): GNUNET_PeerIdentity connection_ids[connections] */ 323 /* If TUNNEL (no 'S'): struct GNUNET_CADET_ConnectionTunnelIdentifier connection_ids[connections] */
298 /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */ 324 /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */
299}; 325};
300 326
@@ -350,25 +376,6 @@ GC_min_pid (uint32_t a, uint32_t b);
350 376
351 377
352/** 378/**
353 * Convert a 256 bit CadetHash into a 512 HashCode to use in GNUNET_h2s,
354 * multihashmap, and other HashCode-based functions.
355 *
356 * @param id A 256 bit hash to expand.
357 *
358 * @return A HashCode containing the original 256 bit hash right-padded with 0.
359 */
360const struct GNUNET_HashCode *
361GC_h2hc (const struct GNUNET_CADET_Hash *id);
362
363/**
364 * Get a string from a Cadet Hash (256 bits).
365 * WARNING: Not reentrant (based on GNUNET_h2s).
366 */
367const char *
368GC_h2s (const struct GNUNET_CADET_Hash *id);
369
370
371/**
372 * Allocate a string with a hexdump of any binary data. 379 * Allocate a string with a hexdump of any binary data.
373 * 380 *
374 * @param bin Arbitrary binary data. 381 * @param bin Arbitrary binary data.
@@ -378,7 +385,10 @@ GC_h2s (const struct GNUNET_CADET_Hash *id);
378 * @return The size of the output. 385 * @return The size of the output.
379 */ 386 */
380size_t 387size_t
381GC_bin2s (void *bin, unsigned int len, char **output); 388GC_bin2s (void *bin,
389 unsigned int len,
390 char **output);
391
382 392
383/** 393/**
384 * Convert a message type into a string to help debug 394 * Convert a message type into a string to help debug
diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c
index d75815588..8f1274d63 100644
--- a/src/cadet/cadet_api.c
+++ b/src/cadet/cadet_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V. 3 Copyright (C) 2011, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -19,7 +19,7 @@
19*/ 19*/
20/** 20/**
21 * @file cadet/cadet_api.c 21 * @file cadet/cadet_api.c
22 * @brief cadet api: client implementation of new cadet service 22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot 23 * @author Bartlomiej Polot
24 */ 24 */
25 25
@@ -41,46 +41,48 @@
41 */ 41 */
42struct GNUNET_CADET_TransmitHandle 42struct GNUNET_CADET_TransmitHandle
43{ 43{
44 /** 44 /**
45 * Double Linked list 45 * Double Linked list
46 */ 46 */
47 struct GNUNET_CADET_TransmitHandle *next; 47 struct GNUNET_CADET_TransmitHandle *next;
48 48
49 /** 49 /**
50 * Double Linked list 50 * Double Linked list
51 */ 51 */
52 struct GNUNET_CADET_TransmitHandle *prev; 52 struct GNUNET_CADET_TransmitHandle *prev;
53 53
54 /** 54 /**
55 * Channel this message is sent on / for (may be NULL for control messages). 55 * Channel this message is sent on / for (may be NULL for control messages).
56 */ 56 */
57 struct GNUNET_CADET_Channel *channel; 57 struct GNUNET_CADET_Channel *channel;
58 58
59 /** 59 /**
60 * Request data task. 60 * Request data task.
61 */ 61 */
62 struct GNUNET_SCHEDULER_Task *request_data_task; 62 struct GNUNET_SCHEDULER_Task *request_data_task;
63 63
64 /** 64 /**
65 * Callback to obtain the message to transmit, or NULL if we 65 * Callback to obtain the message to transmit, or NULL if we
66 * got the message in 'data'. Notice that messages built 66 * got the message in 'data'. Notice that messages built
67 * by 'notify' need to be encapsulated with information about 67 * by 'notify' need to be encapsulated with information about
68 * the 'target'. 68 * the 'target'.
69 */ 69 */
70 GNUNET_CONNECTION_TransmitReadyNotify notify; 70 GNUNET_CONNECTION_TransmitReadyNotify notify;
71 71
72 /** 72 /**
73 * Closure for 'notify' 73 * Closure for 'notify'
74 */ 74 */
75 void *notify_cls; 75 void *notify_cls;
76 76
77 /** 77 /**
78 * Size of the payload. 78 * Size of the payload.
79 */ 79 */
80 size_t size; 80 size_t size;
81}; 81};
82 82
83union CadetInfoCB { 83
84union CadetInfoCB
85{
84 86
85 /** 87 /**
86 * Channel callback. 88 * Channel callback.
@@ -114,14 +116,14 @@ union CadetInfoCB {
114 */ 116 */
115struct GNUNET_CADET_Handle 117struct GNUNET_CADET_Handle
116{ 118{
117 /** 119 /**
118 * Message queue (if available). 120 * Message queue (if available).
119 */ 121 */
120 struct GNUNET_MQ_Handle *mq; 122 struct GNUNET_MQ_Handle *mq;
121 123
122 /** 124 /**
123 * Set of handlers used for processing incoming messages in the channels 125 * Set of handlers used for processing incoming messages in the channels
124 */ 126 */
125 const struct GNUNET_CADET_MessageHandler *message_handlers; 127 const struct GNUNET_CADET_MessageHandler *message_handlers;
126 128
127 /** 129 /**
@@ -134,40 +136,40 @@ struct GNUNET_CADET_Handle
134 */ 136 */
135 struct GNUNET_CONTAINER_MultiHashMap *ports; 137 struct GNUNET_CONTAINER_MultiHashMap *ports;
136 138
137 /** 139 /**
138 * Double linked list of the channels this client is connected to, head. 140 * Double linked list of the channels this client is connected to, head.
139 */ 141 */
140 struct GNUNET_CADET_Channel *channels_head; 142 struct GNUNET_CADET_Channel *channels_head;
141 143
142 /** 144 /**
143 * Double linked list of the channels this client is connected to, tail. 145 * Double linked list of the channels this client is connected to, tail.
144 */ 146 */
145 struct GNUNET_CADET_Channel *channels_tail; 147 struct GNUNET_CADET_Channel *channels_tail;
146 148
147 /** 149 /**
148 * Callback for inbound channel disconnection 150 * Callback for inbound channel disconnection
149 */ 151 */
150 GNUNET_CADET_ChannelEndHandler *cleaner; 152 GNUNET_CADET_ChannelEndHandler *cleaner;
151 153
152 /** 154 /**
153 * Closure for all the handlers given by the client 155 * Closure for all the handlers given by the client
154 */ 156 */
155 void *cls; 157 void *cls;
156 158
157 /** 159 /**
158 * Messages to send to the service, head. 160 * Messages to send to the service, head.
159 */ 161 */
160 struct GNUNET_CADET_TransmitHandle *th_head; 162 struct GNUNET_CADET_TransmitHandle *th_head;
161 163
162 /** 164 /**
163 * Messages to send to the service, tail. 165 * Messages to send to the service, tail.
164 */ 166 */
165 struct GNUNET_CADET_TransmitHandle *th_tail; 167 struct GNUNET_CADET_TransmitHandle *th_tail;
166 168
167 /** 169 /**
168 * chid of the next channel to create (to avoid reusing IDs often) 170 * child of the next channel to create (to avoid reusing IDs often)
169 */ 171 */
170 CADET_ChannelNumber next_chid; 172 struct GNUNET_CADET_ClientChannelNumber next_chid;
171 173
172 /** 174 /**
173 * Configuration given by the client, in case of reconnection 175 * Configuration given by the client, in case of reconnection
@@ -201,9 +203,9 @@ struct GNUNET_CADET_Handle
201 */ 203 */
202struct GNUNET_CADET_Peer 204struct GNUNET_CADET_Peer
203{ 205{
204 /** 206 /**
205 * ID of the peer in short form 207 * ID of the peer in short form
206 */ 208 */
207 GNUNET_PEER_Id id; 209 GNUNET_PEER_Id id;
208 210
209 /** 211 /**
@@ -218,34 +220,34 @@ struct GNUNET_CADET_Peer
218 */ 220 */
219struct GNUNET_CADET_Channel 221struct GNUNET_CADET_Channel
220{ 222{
221 /** 223 /**
222 * DLL next 224 * DLL next
223 */ 225 */
224 struct GNUNET_CADET_Channel *next; 226 struct GNUNET_CADET_Channel *next;
225 227
226 /** 228 /**
227 * DLL prev 229 * DLL prev
228 */ 230 */
229 struct GNUNET_CADET_Channel *prev; 231 struct GNUNET_CADET_Channel *prev;
230 232
231 /** 233 /**
232 * Handle to the cadet this channel belongs to 234 * Handle to the cadet this channel belongs to
233 */ 235 */
234 struct GNUNET_CADET_Handle *cadet; 236 struct GNUNET_CADET_Handle *cadet;
235 237
236 /** 238 /**
237 * Local ID of the channel 239 * Local ID of the channel
238 */ 240 */
239 CADET_ChannelNumber chid; 241 struct GNUNET_CADET_ClientChannelNumber chid;
240 242
241 /** 243 /**
242 * Channel's port, if any. 244 * Channel's port, if any.
243 */ 245 */
244 struct GNUNET_CADET_Port *port; 246 struct GNUNET_CADET_Port *port;
245 247
246 /** 248 /**
247 * Other end of the channel. 249 * Other end of the channel.
248 */ 250 */
249 GNUNET_PEER_Id peer; 251 GNUNET_PEER_Id peer;
250 252
251 /** 253 /**
@@ -253,46 +255,47 @@ struct GNUNET_CADET_Channel
253 */ 255 */
254 void *ctx; 256 void *ctx;
255 257
256 /** 258 /**
257 * Size of packet queued in this channel 259 * Size of packet queued in this channel
258 */ 260 */
259 unsigned int packet_size; 261 unsigned int packet_size;
260 262
261 /** 263 /**
262 * Channel options: reliability, etc. 264 * Channel options: reliability, etc.
263 */ 265 */
264 enum GNUNET_CADET_ChannelOption options; 266 enum GNUNET_CADET_ChannelOption options;
265 267
266 /** 268 /**
267 * Are we allowed to send to the service? 269 * Are we allowed to send to the service?
268 */ 270 */
269 int allow_send; 271 int allow_send;
270 272
271}; 273};
272 274
275
273/** 276/**
274 * Opaque handle to a port. 277 * Opaque handle to a port.
275 */ 278 */
276struct GNUNET_CADET_Port 279struct GNUNET_CADET_Port
277{ 280{
278 /** 281 /**
279 * Handle to the CADET session this port belongs to. 282 * Handle to the CADET session this port belongs to.
280 */ 283 */
281 struct GNUNET_CADET_Handle *cadet; 284 struct GNUNET_CADET_Handle *cadet;
282 285
283 /** 286 /**
284 * Port ID. 287 * Port ID.
285 */ 288 */
286 struct GNUNET_HashCode *hash; 289 struct GNUNET_HashCode *hash;
287 290
288 /** 291 /**
289 * Callback handler for incoming channels on this port. 292 * Callback handler for incoming channels on this port.
290 */ 293 */
291 GNUNET_CADET_InboundChannelNotificationHandler *handler; 294 GNUNET_CADET_InboundChannelNotificationHandler *handler;
292 295
293 /** 296 /**
294 * Closure for @a handler. 297 * Closure for @a handler.
295 */ 298 */
296 void *cls; 299 void *cls;
297}; 300};
298 301
@@ -356,22 +359,20 @@ find_port (const struct GNUNET_CADET_Handle *h,
356 359
357/** 360/**
358 * Get the channel handler for the channel specified by id from the given handle 361 * Get the channel handler for the channel specified by id from the given handle
362 *
359 * @param h Cadet handle 363 * @param h Cadet handle
360 * @param chid ID of the wanted channel 364 * @param chid ID of the wanted channel
361 * @return handle to the required channel or NULL if not found 365 * @return handle to the required channel or NULL if not found
362 */ 366 */
363static struct GNUNET_CADET_Channel * 367static struct GNUNET_CADET_Channel *
364retrieve_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid) 368retrieve_channel (struct GNUNET_CADET_Handle *h,
369 struct GNUNET_CADET_ClientChannelNumber chid)
365{ 370{
366 struct GNUNET_CADET_Channel *ch; 371 struct GNUNET_CADET_Channel *ch;
367 372
368 ch = h->channels_head; 373 for (ch = h->channels_head; NULL != ch; ch = ch->next)
369 while (ch != NULL) 374 if (ch->chid.channel_of_client == chid.channel_of_client)
370 {
371 if (ch->chid == chid)
372 return ch; 375 return ch;
373 ch = ch->next;
374 }
375 return NULL; 376 return NULL;
376} 377}
377 378
@@ -385,21 +386,27 @@ retrieve_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid)
385 * @return Handle to the created channel. 386 * @return Handle to the created channel.
386 */ 387 */
387static struct GNUNET_CADET_Channel * 388static struct GNUNET_CADET_Channel *
388create_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid) 389create_channel (struct GNUNET_CADET_Handle *h,
390 struct GNUNET_CADET_ClientChannelNumber chid)
389{ 391{
390 struct GNUNET_CADET_Channel *ch; 392 struct GNUNET_CADET_Channel *ch;
391 393
392 ch = GNUNET_new (struct GNUNET_CADET_Channel); 394 ch = GNUNET_new (struct GNUNET_CADET_Channel);
393 GNUNET_CONTAINER_DLL_insert (h->channels_head, h->channels_tail, ch); 395 GNUNET_CONTAINER_DLL_insert (h->channels_head,
396 h->channels_tail,
397 ch);
394 ch->cadet = h; 398 ch->cadet = h;
395 if (0 == chid) 399 if (0 == chid.channel_of_client)
396 { 400 {
397 ch->chid = h->next_chid; 401 ch->chid = h->next_chid;
398 while (NULL != retrieve_channel (h, h->next_chid)) 402 while (NULL != retrieve_channel (h,
403 h->next_chid))
399 { 404 {
400 h->next_chid++; 405 h->next_chid.channel_of_client
401 h->next_chid &= ~GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; 406 = htonl (1 + ntohl (h->next_chid.channel_of_client));
402 h->next_chid |= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; 407 if (0 == ntohl (h->next_chid.channel_of_client))
408 h->next_chid.channel_of_client
409 = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
403 } 410 }
404 } 411 }
405 else 412 else
@@ -440,7 +447,9 @@ destroy_channel (struct GNUNET_CADET_Channel *ch, int call_cleaner)
440 } 447 }
441 h = ch->cadet; 448 h = ch->cadet;
442 449
443 GNUNET_CONTAINER_DLL_remove (h->channels_head, h->channels_tail, ch); 450 GNUNET_CONTAINER_DLL_remove (h->channels_head,
451 h->channels_tail,
452 ch);
444 453
445 /* signal channel destruction */ 454 /* signal channel destruction */
446 if ( (NULL != h->cleaner) && (0 != ch->peer) && (GNUNET_YES == call_cleaner) ) 455 if ( (NULL != h->cleaner) && (0 != ch->peer) && (GNUNET_YES == call_cleaner) )
@@ -466,7 +475,7 @@ destroy_channel (struct GNUNET_CADET_Channel *ch, int call_cleaner)
466 if (0 != ch->peer) 475 if (0 != ch->peer)
467 GNUNET_PEER_change_rc (ch->peer, -1); 476 GNUNET_PEER_change_rc (ch->peer, -1);
468 GNUNET_free (ch); 477 GNUNET_free (ch);
469 return; 478
470} 479}
471 480
472 481
@@ -516,13 +525,15 @@ send_ack (struct GNUNET_CADET_Channel *ch)
516 struct GNUNET_CADET_LocalAck *msg; 525 struct GNUNET_CADET_LocalAck *msg;
517 struct GNUNET_MQ_Envelope *env; 526 struct GNUNET_MQ_Envelope *env;
518 527
519 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); 528 env = GNUNET_MQ_msg (msg,
520 529 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
521 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on channel %X\n", ch->chid);
522 msg->channel_id = htonl (ch->chid);
523 GNUNET_MQ_send (ch->cadet->mq, env);
524 530
525 return; 531 LOG (GNUNET_ERROR_TYPE_DEBUG,
532 "Sending ACK on channel %X\n",
533 ch->chid.channel_of_client);
534 msg->channel_id = ch->chid;
535 GNUNET_MQ_send (ch->cadet->mq,
536 env);
526} 537}
527 538
528 539
@@ -555,13 +566,16 @@ request_data (void *cls)
555 th->channel->packet_size = 0; 566 th->channel->packet_size = 0;
556 remove_from_queue (th); 567 remove_from_queue (th);
557 568
558 env = GNUNET_MQ_msg_extra (msg, th->size, 569 env = GNUNET_MQ_msg_extra (msg,
570 th->size,
559 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); 571 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
560 msg->id = htonl (th->channel->chid); 572 msg->id = th->channel->chid;
561 osize = th->notify (th->notify_cls, th->size, &msg[1]); 573 osize = th->notify (th->notify_cls,
574 th->size,
575 &msg[1]);
562 GNUNET_assert (osize == th->size); 576 GNUNET_assert (osize == th->size);
563 GNUNET_MQ_send (th->channel->cadet->mq, env); 577 GNUNET_MQ_send (th->channel->cadet->mq,
564 578 env);
565 GNUNET_free (th); 579 GNUNET_free (th);
566} 580}
567 581
@@ -574,19 +588,21 @@ request_data (void *cls)
574 */ 588 */
575static void 589static void
576handle_channel_created (void *cls, 590handle_channel_created (void *cls,
577 const struct GNUNET_CADET_ChannelCreateMessage *msg) 591 const struct GNUNET_CADET_ChannelOpenMessageMessage *msg)
578{ 592{
579 struct GNUNET_CADET_Handle *h = cls; 593 struct GNUNET_CADET_Handle *h = cls;
580 struct GNUNET_CADET_Channel *ch; 594 struct GNUNET_CADET_Channel *ch;
581 struct GNUNET_CADET_Port *port; 595 struct GNUNET_CADET_Port *port;
582 const struct GNUNET_HashCode *port_number; 596 const struct GNUNET_HashCode *port_number;
583 CADET_ChannelNumber chid; 597 struct GNUNET_CADET_ClientChannelNumber chid;
584 598
585 chid = ntohl (msg->channel_id); 599 chid = msg->channel_id;
586 port_number = &msg->port; 600 port_number = &msg->port;
587 LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X [%s]\n", 601 LOG (GNUNET_ERROR_TYPE_DEBUG,
588 chid, GNUNET_h2s (port_number)); 602 "Creating incoming channel %X [%s]\n",
589 if (chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) 603 ntohl (chid.channel_of_client),
604 GNUNET_h2s (port_number));
605 if (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
590 { 606 {
591 GNUNET_break (0); 607 GNUNET_break (0);
592 return; 608 return;
@@ -636,18 +652,24 @@ handle_channel_destroy (void *cls,
636{ 652{
637 struct GNUNET_CADET_Handle *h = cls; 653 struct GNUNET_CADET_Handle *h = cls;
638 struct GNUNET_CADET_Channel *ch; 654 struct GNUNET_CADET_Channel *ch;
639 CADET_ChannelNumber chid; 655 struct GNUNET_CADET_ClientChannelNumber chid;
640 656
641 chid = ntohl (msg->channel_id); 657 chid = msg->channel_id;
642 LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X Destroy from service\n", chid); 658 LOG (GNUNET_ERROR_TYPE_DEBUG,
643 ch = retrieve_channel (h, chid); 659 "Channel %X Destroy from service\n",
660 ntohl (chid.channel_of_client));
661 ch = retrieve_channel (h,
662 chid);
644 663
645 if (NULL == ch) 664 if (NULL == ch)
646 { 665 {
647 LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X unknown\n", chid); 666 LOG (GNUNET_ERROR_TYPE_DEBUG,
667 "channel %X unknown\n",
668 ntohl (chid.channel_of_client));
648 return; 669 return;
649 } 670 }
650 destroy_channel (ch, GNUNET_YES); 671 destroy_channel (ch,
672 GNUNET_YES);
651} 673}
652 674
653 675
@@ -674,7 +696,8 @@ check_local_data (void *cls,
674 return GNUNET_SYSERR; 696 return GNUNET_SYSERR;
675 } 697 }
676 698
677 ch = retrieve_channel (h, ntohl (message->id)); 699 ch = retrieve_channel (h,
700 message->id);
678 if (NULL == ch) 701 if (NULL == ch)
679 { 702 {
680 GNUNET_break_op (0); 703 GNUNET_break_op (0);
@@ -702,14 +725,17 @@ handle_local_data (void *cls,
702 unsigned int i; 725 unsigned int i;
703 uint16_t type; 726 uint16_t type;
704 727
705 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n"); 728 LOG (GNUNET_ERROR_TYPE_DEBUG,
706 ch = retrieve_channel (h, ntohl (message->id)); 729 "Got a data message!\n");
730 ch = retrieve_channel (h, message->id);
707 GNUNET_assert (NULL != ch); 731 GNUNET_assert (NULL != ch);
708 732
709 payload = (struct GNUNET_MessageHeader *) &message[1]; 733 payload = (struct GNUNET_MessageHeader *) &message[1];
710 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on channel %s [%X]\n", 734 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on channel %s [%X]\n",
711 GC_f2s (ch->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV), 735 GC_f2s (ntohl (ch->chid.channel_of_client) >=
712 GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), ntohl (message->id)); 736 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI),
737 GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)),
738 ntohl (message->id.channel_of_client));
713 739
714 type = ntohs (payload->type); 740 type = ntohs (payload->type);
715 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload type %s\n", GC_m2s (type)); 741 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload type %s\n", GC_m2s (type));
@@ -751,17 +777,21 @@ handle_local_ack (void *cls,
751{ 777{
752 struct GNUNET_CADET_Handle *h = cls; 778 struct GNUNET_CADET_Handle *h = cls;
753 struct GNUNET_CADET_Channel *ch; 779 struct GNUNET_CADET_Channel *ch;
754 CADET_ChannelNumber chid; 780 struct GNUNET_CADET_ClientChannelNumber chid;
755 781
756 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n"); 782 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
757 chid = ntohl (message->channel_id); 783 chid = message->channel_id;
758 ch = retrieve_channel (h, chid); 784 ch = retrieve_channel (h, chid);
759 if (NULL == ch) 785 if (NULL == ch)
760 { 786 {
761 LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK on unknown channel %X\n", chid); 787 LOG (GNUNET_ERROR_TYPE_DEBUG,
788 "ACK on unknown channel %X\n",
789 ntohl (chid.channel_of_client));
762 return; 790 return;
763 } 791 }
764 LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X!\n", ch->chid); 792 LOG (GNUNET_ERROR_TYPE_DEBUG,
793 " on channel %X!\n",
794 ntohl (ch->chid.channel_of_client));
765 ch->allow_send = GNUNET_YES; 795 ch->allow_send = GNUNET_YES;
766 if (0 < ch->packet_size) 796 if (0 < ch->packet_size)
767 { 797 {
@@ -1132,9 +1162,12 @@ handle_get_tunnels (void *cls,
1132{ 1162{
1133 struct GNUNET_CADET_Handle *h = cls; 1163 struct GNUNET_CADET_Handle *h = cls;
1134 1164
1135 h->info_cb.tunnels_cb (h->info_cls, &msg->destination, 1165 h->info_cb.tunnels_cb (h->info_cls,
1136 ntohl (msg->channels), ntohl (msg->connections), 1166 &msg->destination,
1137 ntohs (msg->estate), ntohs (msg->cstate)); 1167 ntohl (msg->channels),
1168 ntohl (msg->connections),
1169 ntohs (msg->estate),
1170 ntohs (msg->cstate));
1138 1171
1139} 1172}
1140 1173
@@ -1170,13 +1203,14 @@ check_get_tunnel (void *cls,
1170 if (esize > msize) 1203 if (esize > msize)
1171 { 1204 {
1172 GNUNET_break_op (0); 1205 GNUNET_break_op (0);
1173 h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); 1206 h->info_cb.tunnel_cb (h->info_cls,
1207 NULL, 0, 0, NULL, NULL, 0, 0);
1174 goto clean_cls; 1208 goto clean_cls;
1175 } 1209 }
1176 ch_n = ntohl (msg->channels); 1210 ch_n = ntohl (msg->channels);
1177 c_n = ntohl (msg->connections); 1211 c_n = ntohl (msg->connections);
1178 esize += ch_n * sizeof (CADET_ChannelNumber); 1212 esize += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
1179 esize += c_n * sizeof (struct GNUNET_CADET_Hash); 1213 esize += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
1180 if (msize != esize) 1214 if (msize != esize)
1181 { 1215 {
1182 GNUNET_break_op (0); 1216 GNUNET_break_op (0);
@@ -1186,7 +1220,8 @@ check_get_tunnel (void *cls,
1186 (unsigned int) esize, 1220 (unsigned int) esize,
1187 ch_n, 1221 ch_n,
1188 c_n); 1222 c_n);
1189 h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); 1223 h->info_cb.tunnel_cb (h->info_cls,
1224 NULL, 0, 0, NULL, NULL, 0, 0);
1190 goto clean_cls; 1225 goto clean_cls;
1191 } 1226 }
1192 1227
@@ -1212,18 +1247,23 @@ handle_get_tunnel (void *cls,
1212 struct GNUNET_CADET_Handle *h = cls; 1247 struct GNUNET_CADET_Handle *h = cls;
1213 unsigned int ch_n; 1248 unsigned int ch_n;
1214 unsigned int c_n; 1249 unsigned int c_n;
1215 struct GNUNET_CADET_Hash *conns; 1250 const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns;
1216 CADET_ChannelNumber *chns; 1251 const struct GNUNET_CADET_ChannelTunnelNumber *chns;
1217 1252
1218 ch_n = ntohl (msg->channels); 1253 ch_n = ntohl (msg->channels);
1219 c_n = ntohl (msg->connections); 1254 c_n = ntohl (msg->connections);
1220 1255
1221 /* Call Callback with tunnel info. */ 1256 /* Call Callback with tunnel info. */
1222 conns = (struct GNUNET_CADET_Hash *) &msg[1]; 1257 conns = (const struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
1223 chns = (CADET_ChannelNumber *) &conns[c_n]; 1258 chns = (const struct GNUNET_CADET_ChannelTunnelNumber *) &conns[c_n];
1224 h->info_cb.tunnel_cb (h->info_cls, &msg->destination, 1259 h->info_cb.tunnel_cb (h->info_cls,
1225 ch_n, c_n, chns, conns, 1260 &msg->destination,
1226 ntohs (msg->estate), ntohs (msg->cstate)); 1261 ch_n,
1262 c_n,
1263 chns,
1264 conns,
1265 ntohs (msg->estate),
1266 ntohs (msg->cstate));
1227} 1267}
1228 1268
1229 1269
@@ -1241,8 +1281,8 @@ do_reconnect (struct GNUNET_CADET_Handle *h)
1241{ 1281{
1242 struct GNUNET_MQ_MessageHandler handlers[] = { 1282 struct GNUNET_MQ_MessageHandler handlers[] = {
1243 GNUNET_MQ_hd_fixed_size (channel_created, 1283 GNUNET_MQ_hd_fixed_size (channel_created,
1244 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE, 1284 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
1245 struct GNUNET_CADET_ChannelCreateMessage, 1285 struct GNUNET_CADET_ChannelOpenMessageMessage,
1246 h), 1286 h),
1247 GNUNET_MQ_hd_fixed_size (channel_destroy, 1287 GNUNET_MQ_hd_fixed_size (channel_destroy,
1248 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY, 1288 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
@@ -1274,7 +1314,7 @@ do_reconnect (struct GNUNET_CADET_Handle *h)
1274 h), 1314 h),
1275 // FIXME 1315 // FIXME
1276// GNUNET_MQ_hd_fixed_Y size (channel_destroyed, 1316// GNUNET_MQ_hd_fixed_Y size (channel_destroyed,
1277// GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK, 1317// GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED,
1278// struct GNUNET_CADET_ChannelDestroyMessage); 1318// struct GNUNET_CADET_ChannelDestroyMessage);
1279 GNUNET_MQ_handler_end () 1319 GNUNET_MQ_handler_end ()
1280 }; 1320 };
@@ -1282,7 +1322,7 @@ do_reconnect (struct GNUNET_CADET_Handle *h)
1282 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET\n"); 1322 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET\n");
1283 1323
1284 GNUNET_assert (NULL == h->mq); 1324 GNUNET_assert (NULL == h->mq);
1285 h->mq = GNUNET_CLIENT_connecT (h->cfg, 1325 h->mq = GNUNET_CLIENT_connect (h->cfg,
1286 "cadet", 1326 "cadet",
1287 handlers, 1327 handlers,
1288 &handle_mq_error, 1328 &handle_mq_error,
@@ -1343,9 +1383,10 @@ reconnect (struct GNUNET_CADET_Handle *h)
1343/******************************************************************************/ 1383/******************************************************************************/
1344 1384
1345struct GNUNET_CADET_Handle * 1385struct GNUNET_CADET_Handle *
1346GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, 1386GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1347 GNUNET_CADET_ChannelEndHandler cleaner, 1387 void *cls,
1348 const struct GNUNET_CADET_MessageHandler *handlers) 1388 GNUNET_CADET_ChannelEndHandler cleaner,
1389 const struct GNUNET_CADET_MessageHandler *handlers)
1349{ 1390{
1350 struct GNUNET_CADET_Handle *h; 1391 struct GNUNET_CADET_Handle *h;
1351 1392
@@ -1364,7 +1405,7 @@ GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1364 } 1405 }
1365 h->cls = cls; 1406 h->cls = cls;
1366 h->message_handlers = handlers; 1407 h->message_handlers = handlers;
1367 h->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; 1408 h->next_chid.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
1368 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; 1409 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1369 h->reconnect_task = NULL; 1410 h->reconnect_task = NULL;
1370 1411
@@ -1384,21 +1425,24 @@ GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
1384 struct GNUNET_CADET_Channel *aux; 1425 struct GNUNET_CADET_Channel *aux;
1385 struct GNUNET_CADET_TransmitHandle *th; 1426 struct GNUNET_CADET_TransmitHandle *th;
1386 1427
1387 LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET DISCONNECT\n"); 1428 LOG (GNUNET_ERROR_TYPE_DEBUG,
1388 1429 "CADET DISCONNECT\n");
1389 ch = handle->channels_head; 1430 ch = handle->channels_head;
1390 while (NULL != ch) 1431 while (NULL != ch)
1391 { 1432 {
1392 aux = ch->next; 1433 aux = ch->next;
1393 if (ch->chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) 1434 if (ntohl (ch->chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1394 { 1435 {
1395 GNUNET_break (0); 1436 GNUNET_break (0);
1396 LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X not destroyed\n", ch->chid); 1437 LOG (GNUNET_ERROR_TYPE_DEBUG,
1438 "channel %X not destroyed\n",
1439 ntohl (ch->chid.channel_of_client));
1397 } 1440 }
1398 destroy_channel (ch, GNUNET_YES); 1441 destroy_channel (ch,
1442 GNUNET_YES);
1399 ch = aux; 1443 ch = aux;
1400 } 1444 }
1401 while ( (th = handle->th_head) != NULL) 1445 while (NULL != (th = handle->th_head))
1402 { 1446 {
1403 struct GNUNET_MessageHeader *msg; 1447 struct GNUNET_MessageHeader *msg;
1404 1448
@@ -1409,7 +1453,7 @@ GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
1409 msg = (struct GNUNET_MessageHeader *) &th[1]; 1453 msg = (struct GNUNET_MessageHeader *) &th[1];
1410 switch (ntohs(msg->type)) 1454 switch (ntohs(msg->type))
1411 { 1455 {
1412 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: 1456 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
1413 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: 1457 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
1414 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN: 1458 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN:
1415 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE: 1459 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE:
@@ -1531,27 +1575,30 @@ GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
1531 const struct GNUNET_HashCode *port, 1575 const struct GNUNET_HashCode *port,
1532 enum GNUNET_CADET_ChannelOption options) 1576 enum GNUNET_CADET_ChannelOption options)
1533{ 1577{
1534 struct GNUNET_CADET_ChannelCreateMessage *msg; 1578 struct GNUNET_CADET_ChannelOpenMessageMessage *msg;
1535 struct GNUNET_MQ_Envelope *env; 1579 struct GNUNET_MQ_Envelope *env;
1536 struct GNUNET_CADET_Channel *ch; 1580 struct GNUNET_CADET_Channel *ch;
1581 struct GNUNET_CADET_ClientChannelNumber chid;
1537 1582
1538 LOG (GNUNET_ERROR_TYPE_DEBUG, 1583 LOG (GNUNET_ERROR_TYPE_DEBUG,
1539 "Creating new channel to %s:%u\n", 1584 "Creating new channel to %s:%u\n",
1540 GNUNET_i2s (peer), port); 1585 GNUNET_i2s (peer), port);
1541 ch = create_channel (h, 0); 1586 chid.channel_of_client = htonl (0);
1587 ch = create_channel (h, chid);
1542 LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", ch); 1588 LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", ch);
1543 LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", ch->chid); 1589 LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n",
1590 ntohl (ch->chid.channel_of_client));
1544 ch->ctx = channel_ctx; 1591 ch->ctx = channel_ctx;
1545 ch->peer = GNUNET_PEER_intern (peer); 1592 ch->peer = GNUNET_PEER_intern (peer);
1546 1593
1547 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE); 1594 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
1548 msg->channel_id = htonl (ch->chid); 1595 msg->channel_id = ch->chid;
1549 msg->port = *port; 1596 msg->port = *port;
1550 msg->peer = *peer; 1597 msg->peer = *peer;
1551 msg->opt = htonl (options); 1598 msg->opt = htonl (options);
1552 ch->allow_send = GNUNET_NO; 1599 ch->allow_send = GNUNET_NO;
1553 GNUNET_MQ_send (h->mq, env); 1600 GNUNET_MQ_send (h->mq,
1554 1601 env);
1555 return ch; 1602 return ch;
1556} 1603}
1557 1604
@@ -1590,7 +1637,7 @@ GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
1590 } 1637 }
1591 1638
1592 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); 1639 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
1593 msg->channel_id = htonl (channel->chid); 1640 msg->channel_id = channel->chid;
1594 GNUNET_MQ_send (h->mq, env); 1641 GNUNET_MQ_send (h->mq, env);
1595 1642
1596 destroy_channel (channel, GNUNET_YES); 1643 destroy_channel (channel, GNUNET_YES);
@@ -1617,7 +1664,7 @@ GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
1617 { 1664 {
1618 case GNUNET_CADET_OPTION_NOBUFFER: 1665 case GNUNET_CADET_OPTION_NOBUFFER:
1619 case GNUNET_CADET_OPTION_RELIABLE: 1666 case GNUNET_CADET_OPTION_RELIABLE:
1620 case GNUNET_CADET_OPTION_OOORDER: 1667 case GNUNET_CADET_OPTION_OUT_OF_ORDER:
1621 if (0 != (option & channel->options)) 1668 if (0 != (option & channel->options))
1622 bool_flag = GNUNET_YES; 1669 bool_flag = GNUNET_YES;
1623 else 1670 else
@@ -1651,7 +1698,8 @@ GNUNET_CADET_notify_transmit_ready (struct GNUNET_CADET_Channel *channel,
1651 LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY\n"); 1698 LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY\n");
1652 LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", channel->chid); 1699 LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", channel->chid);
1653 LOG (GNUNET_ERROR_TYPE_DEBUG, " allow_send %d\n", channel->allow_send); 1700 LOG (GNUNET_ERROR_TYPE_DEBUG, " allow_send %d\n", channel->allow_send);
1654 if (channel->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) 1701 if (ntohl (channel->chid.channel_of_client) >=
1702 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1655 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n"); 1703 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n");
1656 else 1704 else
1657 LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n"); 1705 LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n");
@@ -1946,7 +1994,7 @@ GNUNET_CADET_show_channel (struct GNUNET_CADET_Handle *h,
1946 1994
1947 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL); 1995 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL);
1948 msg->peer = *initiator; 1996 msg->peer = *initiator;
1949 msg->channel_id = htonl (channel_number); 1997 msg->channel_id.channel_of_client = htonl (channel_number);
1950 GNUNET_MQ_send (h->mq, env); 1998 GNUNET_MQ_send (h->mq, env);
1951 1999
1952 h->info_cb.channel_cb = callback; 2000 h->info_cb.channel_cb = callback;
diff --git a/src/cadet/cadet_common.c b/src/cadet/cadet_common.c
index a9d9a35be..95a3144e4 100644
--- a/src/cadet/cadet_common.c
+++ b/src/cadet/cadet_common.c
@@ -51,11 +51,20 @@ GC_f2s (int fwd)
51 } 51 }
52} 52}
53 53
54
55/**
56 * Test if @a bigger is larger than @a smaller.
57 * Considers the case that @a bigger just overflowed
58 * and is thus tiny while @a smaller is still below
59 * `UINT32_MAX`.
60 */
54int 61int
55GC_is_pid_bigger (uint32_t bigger, uint32_t smaller) 62GC_is_pid_bigger (uint32_t bigger,
63 uint32_t smaller)
56{ 64{
57 return (GNUNET_YES == PID_OVERFLOW (smaller, bigger) || 65 return (PID_OVERFLOW (smaller, bigger) ||
58 (bigger > smaller && GNUNET_NO == PID_OVERFLOW (bigger, smaller))); 66 ( (bigger > smaller) &&
67 (! PID_OVERFLOW (bigger, smaller))) );
59} 68}
60 69
61 70
@@ -77,28 +86,6 @@ GC_min_pid (uint32_t a, uint32_t b)
77} 86}
78 87
79 88
80const struct GNUNET_HashCode *
81GC_h2hc (const struct GNUNET_CADET_Hash *id)
82{
83 static struct GNUNET_HashCode hc;
84 GNUNET_memcpy (&hc, id, sizeof (*id));
85
86 return &hc;
87}
88
89
90const char *
91GC_h2s (const struct GNUNET_CADET_Hash *id)
92{
93 static char s[53];
94
95 GNUNET_memcpy (s, GNUNET_h2s_full (GC_h2hc (id)), 52);
96 s[52] = '\0';
97
98 return s;
99}
100
101
102/** 89/**
103 * Allocate a string with a hexdump of any binary data. 90 * Allocate a string with a hexdump of any binary data.
104 * 91 *
@@ -159,7 +146,7 @@ GC_m2s (uint16_t m)
159 /** 146 /**
160 * Request the modification of an existing path 147 * Request the modification of an existing path
161 */ 148 */
162 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: 149 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
163 s = "CONN_ACK"; 150 s = "CONN_ACK";
164 break; 151 break;
165 152
@@ -173,35 +160,35 @@ GC_m2s (uint16_t m)
173 /** 160 /**
174 * At some point, the route will spontaneously change 161 * At some point, the route will spontaneously change
175 */ 162 */
176 case GNUNET_MESSAGE_TYPE_CADET_PATH_CHANGED: 163 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_PATH_CHANGED_UNIMPLEMENTED:
177 s = "PATH_CHNGD"; 164 s = "PATH_CHNGD";
178 break; 165 break;
179 166
180 /** 167 /**
181 * Transport payload data. 168 * Transport payload data.
182 */ 169 */
183 case GNUNET_MESSAGE_TYPE_CADET_DATA: 170 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
184 s = "DATA"; 171 s = "DATA";
185 break; 172 break;
186 173
187 /** 174 /**
188 * Confirm receipt of payload data. 175 * Confirm receipt of payload data.
189 */ 176 */
190 case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: 177 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
191 s = "DATA_ACK"; 178 s = "DATA_ACK";
192 break; 179 break;
193 180
194 /** 181 /**
195 * Key exchange message. 182 * Key exchange message.
196 */ 183 */
197 case GNUNET_MESSAGE_TYPE_CADET_KX: 184 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
198 s = "KX"; 185 s = "KX";
199 break; 186 break;
200 187
201 /** 188 /**
202 * Encrypted. 189 * Encrypted.
203 */ 190 */
204 case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: 191 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
205 s = "ENCRYPTED"; 192 s = "ENCRYPTED";
206 break; 193 break;
207 194
@@ -215,21 +202,21 @@ GC_m2s (uint16_t m)
215 /** 202 /**
216 * ACK for a data packet. 203 * ACK for a data packet.
217 */ 204 */
218 case GNUNET_MESSAGE_TYPE_CADET_ACK: 205 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
219 s = "ACK"; 206 s = "ACK";
220 break; 207 break;
221 208
222 /** 209 /**
223 * POLL for ACK. 210 * POLL for ACK.
224 */ 211 */
225 case GNUNET_MESSAGE_TYPE_CADET_POLL: 212 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
226 s = "POLL"; 213 s = "POLL";
227 break; 214 break;
228 215
229 /** 216 /**
230 * Announce origin is still alive. 217 * Announce origin is still alive.
231 */ 218 */
232 case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: 219 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE:
233 s = "KEEPALIVE"; 220 s = "KEEPALIVE";
234 break; 221 break;
235 222
@@ -250,7 +237,7 @@ GC_m2s (uint16_t m)
250 /** 237 /**
251 * Ask the cadet service to create a new tunnel 238 * Ask the cadet service to create a new tunnel
252 */ 239 */
253 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: 240 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
254 s = "CHAN_CREAT"; 241 s = "CHAN_CREAT";
255 break; 242 break;
256 243
@@ -264,14 +251,14 @@ GC_m2s (uint16_t m)
264 /** 251 /**
265 * Confirm the creation of a channel. 252 * Confirm the creation of a channel.
266 */ 253 */
267 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: 254 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
268 s = "CHAN_ACK"; 255 s = "CHAN_ACK";
269 break; 256 break;
270 257
271 /** 258 /**
272 * Confirm the creation of a channel. 259 * Confirm the creation of a channel.
273 */ 260 */
274 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: 261 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
275 s = "CHAN_NACK"; 262 s = "CHAN_NACK";
276 break; 263 break;
277 264
diff --git a/src/cadet/cadet_protocol.h b/src/cadet/cadet_protocol.h
index d034c63b0..cf32e0d6d 100644
--- a/src/cadet/cadet_protocol.h
+++ b/src/cadet/cadet_protocol.h
@@ -56,12 +56,12 @@ GNUNET_NETWORK_STRUCT_BEGIN
56/** 56/**
57 * Message for cadet connection creation. 57 * Message for cadet connection creation.
58 */ 58 */
59struct GNUNET_CADET_ConnectionCreate 59struct GNUNET_CADET_ConnectionCreateMessage
60{ 60{
61 /** 61 /**
62 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE 62 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
63 * 63 *
64 * Size: sizeof (struct GNUNET_CADET_ConnectionCreate) + 64 * Size: sizeof (struct GNUNET_CADET_ConnectionCreateMessage) +
65 * path_length * sizeof (struct GNUNET_PeerIdentity) 65 * path_length * sizeof (struct GNUNET_PeerIdentity)
66 */ 66 */
67 struct GNUNET_MessageHeader header; 67 struct GNUNET_MessageHeader header;
@@ -70,11 +70,11 @@ struct GNUNET_CADET_ConnectionCreate
70 * For alignment. 70 * For alignment.
71 */ 71 */
72 uint32_t reserved GNUNET_PACKED; 72 uint32_t reserved GNUNET_PACKED;
73 73
74 /** 74 /**
75 * ID of the connection 75 * ID of the connection
76 */ 76 */
77 struct GNUNET_CADET_Hash cid; 77 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
78 78
79 /** 79 /**
80 * path_length structs defining the *whole* path from the origin [0] to the 80 * path_length structs defining the *whole* path from the origin [0] to the
@@ -87,10 +87,10 @@ struct GNUNET_CADET_ConnectionCreate
87/** 87/**
88 * Message for ack'ing a connection 88 * Message for ack'ing a connection
89 */ 89 */
90struct GNUNET_CADET_ConnectionACK 90struct GNUNET_CADET_ConnectionCreateMessageAckMessage
91{ 91{
92 /** 92 /**
93 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK 93 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
94 */ 94 */
95 struct GNUNET_MessageHeader header; 95 struct GNUNET_MessageHeader header;
96 96
@@ -102,7 +102,7 @@ struct GNUNET_CADET_ConnectionACK
102 /** 102 /**
103 * ID of the connection. 103 * ID of the connection.
104 */ 104 */
105 struct GNUNET_CADET_Hash cid; 105 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
106 106
107}; 107};
108 108
@@ -110,10 +110,10 @@ struct GNUNET_CADET_ConnectionACK
110/** 110/**
111 * Message for notifying a disconnection in a path 111 * Message for notifying a disconnection in a path
112 */ 112 */
113struct GNUNET_CADET_ConnectionBroken 113struct GNUNET_CADET_ConnectionBrokenMessage
114{ 114{
115 /** 115 /**
116 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN 116 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN.
117 */ 117 */
118 struct GNUNET_MessageHeader header; 118 struct GNUNET_MessageHeader header;
119 119
@@ -125,7 +125,7 @@ struct GNUNET_CADET_ConnectionBroken
125 /** 125 /**
126 * ID of the connection. 126 * ID of the connection.
127 */ 127 */
128 struct GNUNET_CADET_Hash cid; 128 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
129 129
130 /** 130 /**
131 * ID of the endpoint 131 * ID of the endpoint
@@ -142,7 +142,7 @@ struct GNUNET_CADET_ConnectionBroken
142/** 142/**
143 * Message to destroy a connection. 143 * Message to destroy a connection.
144 */ 144 */
145struct GNUNET_CADET_ConnectionDestroy 145struct GNUNET_CADET_ConnectionDestroyMessage
146{ 146{
147 /** 147 /**
148 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY 148 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
@@ -157,60 +157,31 @@ struct GNUNET_CADET_ConnectionDestroy
157 /** 157 /**
158 * ID of the connection. 158 * ID of the connection.
159 */ 159 */
160 struct GNUNET_CADET_Hash cid; 160 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
161}; 161};
162 162
163 163
164/** 164/******************************************************************************/
165 * Message to acknowledge cadet encrypted traffic. 165/******************************* TUNNEL ***********************************/
166 */ 166/******************************************************************************/
167struct GNUNET_CADET_ACK
168{
169 /**
170 * Type: #GNUNET_MESSAGE_TYPE_CADET_ACK
171 */
172 struct GNUNET_MessageHeader header;
173
174 /**
175 * Maximum packet ID authorized.
176 */
177 uint32_t ack GNUNET_PACKED;
178
179 /**
180 * ID of the connection.
181 */
182 struct GNUNET_CADET_Hash cid;
183};
184
185 167
186/** 168/**
187 * Message to query a peer about its Flow Control status regarding a tunnel. 169 * Unique identifier (counter) for an encrypted message in a channel.
170 * Used to match #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
171 * and #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL messages
172 * against the respective #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED
173 * messages.
188 */ 174 */
189struct GNUNET_CADET_Poll 175struct CadetEncryptedMessageIdentifier
190{ 176{
191 /** 177 /**
192 * Type: #GNUNET_MESSAGE_TYPE_CADET_POLL 178 * This number is incremented by one per message. It may wrap around.
193 */ 179 * In network byte order.
194 struct GNUNET_MessageHeader header;
195
196 /**
197 * Last packet sent.
198 */ 180 */
199 uint32_t pid GNUNET_PACKED; 181 uint32_t pid GNUNET_PACKED;
200
201 /**
202 * ID of the connection.
203 */
204 struct GNUNET_CADET_Hash cid;
205
206}; 182};
207 183
208 184
209
210/******************************************************************************/
211/******************************* TUNNEL ***********************************/
212/******************************************************************************/
213
214/** 185/**
215 * Flags to be used in GNUNET_CADET_KX. 186 * Flags to be used in GNUNET_CADET_KX.
216 */ 187 */
@@ -231,10 +202,10 @@ enum GNUNET_CADET_KX_Flags {
231/** 202/**
232 * Message for a Key eXchange for a tunnel. 203 * Message for a Key eXchange for a tunnel.
233 */ 204 */
234struct GNUNET_CADET_KX 205struct GNUNET_CADET_TunnelKeyExchangeMessage
235{ 206{
236 /** 207 /**
237 * Type: #GNUNET_MESSAGE_TYPE_CADET_KX. 208 * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX.
238 */ 209 */
239 struct GNUNET_MessageHeader header; 210 struct GNUNET_MessageHeader header;
240 211
@@ -247,7 +218,7 @@ struct GNUNET_CADET_KX
247 /** 218 /**
248 * ID of the connection. 219 * ID of the connection.
249 */ 220 */
250 struct GNUNET_CADET_Hash cid; 221 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
251 222
252 /** 223 /**
253 * Sender's ephemeral public ECC key encoded in a 224 * Sender's ephemeral public ECC key encoded in a
@@ -262,35 +233,42 @@ struct GNUNET_CADET_KX
262 * using 'gcry_sexp_sprint'. 233 * using 'gcry_sexp_sprint'.
263 */ 234 */
264 struct GNUNET_CRYPTO_EcdhePublicKey ratchet_key; 235 struct GNUNET_CRYPTO_EcdhePublicKey ratchet_key;
236
237#ifdef NEW_CADET
238 /**
239 * Proof that sender could compute the 3-DH, in lieu of a signature.
240 */
241 struct GNUNET_HashCode triple_dh_proof;
242#endif
265}; 243};
266 244
267 245
268/** 246/**
269 * Axolotl tunnel message. 247 * Axolotl tunnel message.
270 */ 248 */
271struct GNUNET_CADET_Encrypted 249struct GNUNET_CADET_TunnelEncryptedMessage
272{ 250{
273 /** 251 /**
274 * Type: #GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED 252 * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED
275 */ 253 */
276 struct GNUNET_MessageHeader header; 254 struct GNUNET_MessageHeader header;
277 255
278 /** 256 /**
279 * ID of the packet (hop by hop). 257 * ID of the packet (hop by hop).
280 */ 258 */
281 uint32_t pid GNUNET_PACKED; 259 struct CadetEncryptedMessageIdentifier cemi;
282 260
283 /** 261 /**
284 * ID of the connection. 262 * ID of the connection.
285 */ 263 */
286 struct GNUNET_CADET_Hash cid; 264 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
287 265
288 /** 266 /**
289 * MAC of the encrypted message, used to verify message integrity. 267 * MAC of the encrypted message, used to verify message integrity.
290 * Everything after this value will be encrypted with the header key 268 * Everything after this value will be encrypted with the header key
291 * and authenticated. 269 * and authenticated.
292 */ 270 */
293 struct GNUNET_CADET_Hash hmac; 271 struct GNUNET_ShortHashCode hmac;
294 272
295 /**************** AX_HEADER start ****************/ 273 /**************** AX_HEADER start ****************/
296 274
@@ -317,18 +295,69 @@ struct GNUNET_CADET_Encrypted
317}; 295};
318 296
319 297
298/**
299 * Message to query a peer about its Flow Control status regarding a tunnel.
300 *
301 * It is NOT yet clear if we need this.
302 */
303struct GNUNET_CADET_ConnectionHopByHopPollMessage
304{
305 /**
306 * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
307 */
308 struct GNUNET_MessageHeader header;
309
310 /**
311 * Last packet sent.
312 */
313 struct CadetEncryptedMessageIdentifier cemi;
314
315 /**
316 * ID of the connection.
317 */
318 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
319
320};
321
322
323/**
324 * Message to acknowledge cadet encrypted traffic, used for
325 * flow-control on a hop-by-hop basis on the connection-level. Note
326 * that we do use the @e cemi from the tunnel layer as the connection
327 * layer's header is included/shared with the tunnel layer messages,
328 * and we only do flow control for the payload.
329 */
330struct GNUNET_CADET_ConnectionEncryptedAckMessage
331{
332 /**
333 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
334 */
335 struct GNUNET_MessageHeader header;
336
337 /**
338 * Maximum packet ID authorized.
339 */
340 struct CadetEncryptedMessageIdentifier cemi;
341
342 /**
343 * ID of the connection.
344 */
345 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
346};
347
320 348
321/******************************************************************************/ 349/******************************************************************************/
322/******************************* CHANNEL ***********************************/ 350/******************************* CHANNEL ***********************************/
323/******************************************************************************/ 351/******************************************************************************/
324 352
353
325/** 354/**
326 * Message to create a Channel. 355 * Message to create a Channel.
327 */ 356 */
328struct GNUNET_CADET_ChannelCreate 357struct GNUNET_CADET_ChannelOpenMessage
329{ 358{
330 /** 359 /**
331 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE 360 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN
332 */ 361 */
333 struct GNUNET_MessageHeader header; 362 struct GNUNET_MessageHeader header;
334 363
@@ -343,33 +372,42 @@ struct GNUNET_CADET_ChannelCreate
343 struct GNUNET_HashCode port; 372 struct GNUNET_HashCode port;
344 373
345 /** 374 /**
346 * ID of the channel 375 * ID of the channel within the tunnel.
347 */ 376 */
348 CADET_ChannelNumber chid GNUNET_PACKED; 377 struct GNUNET_CADET_ChannelTunnelNumber chid;
349}; 378};
350 379
351 380
352/** 381/**
353 * Message to manage a Channel (ACK, NACK, Destroy). 382 * Message to manage a Channel (ACK, NACK, Destroy).
354 */ 383 */
355struct GNUNET_CADET_ChannelManage 384struct GNUNET_CADET_ChannelManageMessage
356{ 385{
357 /** 386 /**
358 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_{ACK|NACK|DESTROY} 387 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_{ACK|NACK|DESTROY}
359 */ 388 */
360 struct GNUNET_MessageHeader header; 389 struct GNUNET_MessageHeader header;
361 390
391#ifdef NEW_CADET
392 /**
393 * For alignment.
394 */
395 uint32_t reserved GNUNET_PACKED;
396#endif
397
362 /** 398 /**
363 * ID of the channel 399 * ID of the channel
364 */ 400 */
365 CADET_ChannelNumber chid GNUNET_PACKED; 401 struct GNUNET_CADET_ChannelTunnelNumber chid;
366}; 402};
367 403
368 404
405#ifndef NEW_CADET
406
369/** 407/**
370 * Message for cadet data traffic. 408 * Message for cadet data traffic.
371 */ 409 */
372struct GNUNET_CADET_Data 410struct GNUNET_CADET_ChannelAppDataMessage
373{ 411{
374 /** 412 /**
375 * Type: #GNUNET_MESSAGE_TYPE_CADET_UNICAST, 413 * Type: #GNUNET_MESSAGE_TYPE_CADET_UNICAST,
@@ -380,12 +418,13 @@ struct GNUNET_CADET_Data
380 /** 418 /**
381 * Unique ID of the payload message 419 * Unique ID of the payload message
382 */ 420 */
421 /* NEW: struct ChannelMessageIdentifier */
383 uint32_t mid GNUNET_PACKED; 422 uint32_t mid GNUNET_PACKED;
384 423
385 /** 424 /**
386 * ID of the channel 425 * ID of the channel
387 */ 426 */
388 CADET_ChannelNumber chid GNUNET_PACKED; 427 struct GNUNET_CADET_ChannelTunnelNumber chid;
389 428
390 /** 429 /**
391 * Payload follows 430 * Payload follows
@@ -396,17 +435,17 @@ struct GNUNET_CADET_Data
396/** 435/**
397 * Message to acknowledge end-to-end data. 436 * Message to acknowledge end-to-end data.
398 */ 437 */
399struct GNUNET_CADET_DataACK 438struct GNUNET_CADET_ChannelDataAckMessage
400{ 439{
401 /** 440 /**
402 * Type: GNUNET_MESSAGE_TYPE_CADET_DATA_ACK 441 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK
403 */ 442 */
404 struct GNUNET_MessageHeader header; 443 struct GNUNET_MessageHeader header;
405 444
406 /** 445 /**
407 * ID of the channel 446 * ID of the channel
408 */ 447 */
409 CADET_ChannelNumber chid GNUNET_PACKED; 448 struct GNUNET_CADET_ChannelTunnelNumber chid;
410 449
411 /** 450 /**
412 * Bitfield of already-received newer messages 451 * Bitfield of already-received newer messages
@@ -418,10 +457,82 @@ struct GNUNET_CADET_DataACK
418 /** 457 /**
419 * Last message ID received. 458 * Last message ID received.
420 */ 459 */
460 /* NEW: struct ChannelMessageIdentifier */
461 uint32_t mid GNUNET_PACKED;
462};
463
464#else
465
466
467/**
468 * Number used to uniquely identify messages in a CADET Channel.
469 */
470struct ChannelMessageIdentifier
471{
472 /**
473 * Unique ID of the message, cycles around, in NBO.
474 */
421 uint32_t mid GNUNET_PACKED; 475 uint32_t mid GNUNET_PACKED;
422}; 476};
423 477
424 478
479/**
480 * Message for cadet data traffic.
481 */
482struct GNUNET_CADET_ChannelAppDataMessage
483{
484 /**
485 * Type: #GNUNET_MESSAGE_TYPE_CADET_UNICAST,
486 * #GNUNET_MESSAGE_TYPE_CADET_TO_ORIGIN
487 */
488 struct GNUNET_MessageHeader header;
489
490 /**
491 * Unique ID of the payload message.
492 */
493 struct ChannelMessageIdentifier mid;
494
495 /**
496 * ID of the channel
497 */
498 struct GNUNET_CADET_ChannelTunnelNumber gid;
499
500 /**
501 * Payload follows
502 */
503};
504
505
506/**
507 * Message to acknowledge end-to-end data.
508 */
509struct GNUNET_CADET_ChannelDataAckMessage
510{
511 /**
512 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK
513 */
514 struct GNUNET_MessageHeader header;
515
516 /**
517 * ID of the channel
518 */
519 struct GNUNET_CADET_ChannelTunnelNumber gid;
520
521 /**
522 * Bitfield of already-received messages past @e mid.
523 * pid + 1 @ LSB
524 * pid + 64 @ MSB
525 */
526 uint64_t futures GNUNET_PACKED;
527
528 /**
529 * Last message ID received.
530 */
531 struct ChannelMessageIdentifier mid;
532};
533
534
535#endif
425 536
426GNUNET_NETWORK_STRUCT_END 537GNUNET_NETWORK_STRUCT_END
427 538
diff --git a/src/cadet/gnunet-cadet.c b/src/cadet/gnunet-cadet.c
index 5afb64e24..80010ec54 100644
--- a/src/cadet/gnunet-cadet.c
+++ b/src/cadet/gnunet-cadet.c
@@ -727,8 +727,8 @@ tunnel_callback (void *cls,
727 const struct GNUNET_PeerIdentity *peer, 727 const struct GNUNET_PeerIdentity *peer,
728 unsigned int n_channels, 728 unsigned int n_channels,
729 unsigned int n_connections, 729 unsigned int n_connections,
730 uint32_t *channels, 730 const struct GNUNET_CADET_ChannelTunnelNumber *channels,
731 struct GNUNET_CADET_Hash *connections, 731 const struct GNUNET_CADET_ConnectionTunnelIdentifier *connections,
732 unsigned int estate, 732 unsigned int estate,
733 unsigned int cstate) 733 unsigned int cstate)
734{ 734{
@@ -739,10 +739,10 @@ tunnel_callback (void *cls,
739 FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer)); 739 FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer));
740 FPRINTF (stdout, "\t%u channels\n", n_channels); 740 FPRINTF (stdout, "\t%u channels\n", n_channels);
741 for (i = 0; i < n_channels; i++) 741 for (i = 0; i < n_channels; i++)
742 FPRINTF (stdout, "\t\t%X\n", ntohl (channels[i])); 742 FPRINTF (stdout, "\t\t%X\n", ntohl (channels[i].cn));
743 FPRINTF (stdout, "\t%u connections\n", n_connections); 743 FPRINTF (stdout, "\t%u connections\n", n_connections);
744 for (i = 0; i < n_connections; i++) 744 for (i = 0; i < n_connections; i++)
745 FPRINTF (stdout, "\t\t%s\n", GC_h2s (&connections[i])); 745 FPRINTF (stdout, "\t\t%s\n", GNUNET_sh2s (&connections[i].connection_of_tunnel));
746 FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate)); 746 FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate));
747 FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate)); 747 FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate));
748 } 748 }
@@ -827,7 +827,10 @@ show_tunnel (void *cls)
827 GNUNET_SCHEDULER_shutdown (); 827 GNUNET_SCHEDULER_shutdown ();
828 return; 828 return;
829 } 829 }
830 GNUNET_CADET_get_tunnel (mh, &pid, tunnel_callback, NULL); 830 GNUNET_CADET_get_tunnel (mh,
831 &pid,
832 &tunnel_callback,
833 NULL);
831} 834}
832 835
833 836
diff --git a/src/cadet/gnunet-service-cadet-new.c b/src/cadet/gnunet-service-cadet-new.c
new file mode 100644
index 000000000..2f6cc7b11
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new.c
@@ -0,0 +1,1350 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2013, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet-new.c
23 * @brief GNUnet CADET service with encryption
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * Dictionary:
28 * - peer: other cadet instance. If there is direct connection it's a neighbor.
29 * - path: series of directly connected peer from one peer to another.
30 * - connection: path which is being used in a tunnel.
31 * - tunnel: encrypted connection to a peer, neighbor or not.
32 * - channel: logical link between two clients, on the same or different peers.
33 * have properties like reliability.
34 */
35
36#include "platform.h"
37#include "gnunet_util_lib.h"
38#include "cadet.h"
39#include "gnunet_statistics_service.h"
40#include "gnunet-service-cadet-new.h"
41#include "gnunet-service-cadet-new_channel.h"
42#include "gnunet-service-cadet-new_connection.h"
43#include "gnunet-service-cadet-new_core.h"
44#include "gnunet-service-cadet-new_dht.h"
45#include "gnunet-service-cadet-new_hello.h"
46#include "gnunet-service-cadet-new_tunnels.h"
47#include "gnunet-service-cadet-new_peer.h"
48#include "gnunet-service-cadet-new_paths.h"
49
50#define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
51
52
53/**
54 * Struct containing information about a client of the service
55 */
56struct CadetClient
57{
58 /**
59 * Linked list next
60 */
61 struct CadetClient *next;
62
63 /**
64 * Linked list prev
65 */
66 struct CadetClient *prev;
67
68 /**
69 * Tunnels that belong to this client, indexed by local id
70 */
71 struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
72
73 /**
74 * Tunnels this client has accepted, indexed by incoming local id
75 */
76 struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels;
77
78 /**
79 * Channel ID for the next incoming channel.
80 */
81 struct GNUNET_CADET_ClientChannelNumber next_chid;
82
83 /**
84 * Handle to communicate with the client
85 */
86 struct GNUNET_MQ_Handle *mq;
87
88 /**
89 * Client handle.
90 */
91 struct GNUNET_SERVICE_Client *client;
92
93 /**
94 * Ports that this client has declared interest in.
95 * Indexed by port, contains *Client.
96 */
97 struct GNUNET_CONTAINER_MultiHashMap *ports;
98
99 /**
100 * Whether the client is active or shutting down (don't send confirmations
101 * to a client that is shutting down).
102 */
103 int shutting_down;
104
105 /**
106 * ID of the client, mainly for debug messages
107 */
108 unsigned int id;
109};
110
111/******************************************************************************/
112/*********************** GLOBAL VARIABLES ****************************/
113/******************************************************************************/
114
115/****************************** Global variables ******************************/
116
117/**
118 * Handle to the statistics service.
119 */
120struct GNUNET_STATISTICS_Handle *stats;
121
122/**
123 * Handle to communicate with ATS.
124 */
125struct GNUNET_ATS_ConnectivityHandle *ats_ch;
126
127/**
128 * Local peer own ID.
129 */
130struct GNUNET_PeerIdentity my_full_id;
131
132/**
133 * Own private key.
134 */
135struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
136
137/**
138 * Signal that shutdown is happening: prevent recover measures.
139 */
140int shutting_down;
141
142/**
143 * DLL with all the clients, head.
144 */
145static struct CadetClient *clients_head;
146
147/**
148 * DLL with all the clients, tail.
149 */
150static struct CadetClient *clients_tail;
151
152/**
153 * Next ID to assign to a client.
154 */
155static unsigned int next_client_id;
156
157/**
158 * All ports clients of this peer have opened.
159 */
160struct GNUNET_CONTAINER_MultiHashMap *open_ports;
161
162/**
163 * Map from ports to channels where the ports were closed at the
164 * time we got the inbound connection.
165 * Indexed by port, contains `struct CadetChannel`.
166 */
167struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
168
169/**
170 * Map from PIDs to `struct CadetPeer` entries.
171 */
172struct GNUNET_CONTAINER_MultiPeerMap *peers;
173
174/**
175 * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
176 * hash codes to `struct CadetConnection` objects.
177 */
178struct GNUNET_CONTAINER_MultiShortmap *connections;
179
180/**
181 * How many messages are needed to trigger an AXOLOTL ratchet advance.
182 */
183unsigned long long ratchet_messages;
184
185/**
186 * How long until we trigger a ratched advance due to time.
187 */
188struct GNUNET_TIME_Relative ratchet_time;
189
190
191
192/**
193 * Send a message to a client.
194 *
195 * @param c client to get the message
196 * @param env envelope with the message
197 */
198void
199GSC_send_to_client (struct CadetClient *c,
200 struct GNUNET_MQ_Envelope *env)
201{
202 GNUNET_MQ_send (c->mq,
203 env);
204}
205
206
207/**
208 * Return identifier for a client as a string.
209 *
210 * @param c client to identify
211 * @return string for debugging
212 */
213const char *
214GSC_2s (struct CadetClient *c)
215{
216 static char buf[32];
217
218 if (NULL == c)
219 return "Client(NULL)";
220 GNUNET_snprintf (buf,
221 sizeof (buf),
222 "Client(%u)",
223 c->id);
224 return buf;
225}
226
227
228/**
229 * Obtain the next LID to use for incoming connections to
230 * the given client.
231 *
232 * @param c client handle
233 */
234static struct GNUNET_CADET_ClientChannelNumber
235client_get_next_lid (struct CadetClient *c)
236{
237 struct GNUNET_CADET_ClientChannelNumber ccn = c->next_chid;
238
239 /* increment until we have a free one... */
240 while (NULL !=
241 GNUNET_CONTAINER_multihashmap32_get (c->incoming_channels,
242 ntohl (ccn.channel_of_client)))
243 {
244 ccn.channel_of_client
245 = htonl (1 + (ntohl (ccn.channel_of_client)));
246 if (ntohl (ccn.channel_of_client) >=
247 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
248 ccn.channel_of_client = htonl (0);
249 }
250 c->next_chid.channel_of_client
251 = htonl (1 + (ntohl (ccn.channel_of_client)));
252 return ccn;
253}
254
255
256/**
257 * Bind incoming channel to this client, and notify client
258 * about incoming connection.
259 *
260 * @param c client to bind to
261 * @param ch channel to be bound
262 * @param dest peer that establishes the connection
263 * @param port port number
264 * @param options options
265 * @return local channel number assigned to the new client
266 */
267struct GNUNET_CADET_ClientChannelNumber
268GSC_bind (struct CadetClient *c,
269 struct CadetChannel *ch,
270 struct CadetPeer *dest,
271 const struct GNUNET_HashCode *port,
272 uint32_t options)
273{
274 struct GNUNET_MQ_Envelope *env;
275 struct GNUNET_CADET_ChannelOpenMessageMessage *msg;
276 struct GNUNET_CADET_ClientChannelNumber lid;
277
278 lid = client_get_next_lid (c);
279 GNUNET_assert (GNUNET_YES ==
280 GNUNET_CONTAINER_multihashmap32_put (c->incoming_channels,
281 ntohl (lid.channel_of_client),
282 ch,
283 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
284
285 /* notify local client about incoming connection! */
286 env = GNUNET_MQ_msg (msg,
287 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
288 msg->channel_id = lid;
289 msg->port = *port;
290 msg->opt = htonl (options);
291 msg->peer = *GCP_get_id (dest);
292 GSC_send_to_client (c,
293 env);
294 return lid;
295}
296
297
298/******************************************************************************/
299/************************ MAIN FUNCTIONS ****************************/
300/******************************************************************************/
301
302/**
303 * Task run during shutdown.
304 *
305 * @param cls unused
306 */
307static void
308shutdown_task (void *cls)
309{
310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
311 "shutting down\n");
312 shutting_down = GNUNET_YES;
313 GCO_shutdown ();
314 if (NULL != stats)
315 {
316 GNUNET_STATISTICS_destroy (stats,
317 GNUNET_NO);
318 stats = NULL;
319 }
320 if (NULL != open_ports)
321 {
322 GNUNET_CONTAINER_multihashmap_destroy (open_ports);
323 open_ports = NULL;
324 }
325 if (NULL != loose_channels)
326 {
327 GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
328 loose_channels = NULL;
329 }
330 /* All channels, connections and CORE must be down before this point. */
331 GCP_destroy_all_peers ();
332 if (NULL != peers)
333 {
334 GNUNET_CONTAINER_multipeermap_destroy (peers);
335 peers = NULL;
336 }
337 if (NULL != connections)
338 {
339 GNUNET_CONTAINER_multishortmap_destroy (connections);
340 connections = NULL;
341 }
342 if (NULL != ats_ch)
343 {
344 GNUNET_ATS_connectivity_done (ats_ch);
345 ats_ch = NULL;
346 }
347 GCD_shutdown ();
348 GCH_shutdown ();
349 GNUNET_free_non_null (my_private_key);
350 my_private_key = NULL;
351}
352
353
354/**
355 * We had a remote connection @a value to port @a port before
356 * client @a cls opened port @a port. Bind them now.
357 *
358 * @param cls the `struct CadetClient`
359 * @param port the port
360 * @param value the `struct CadetChannel`
361 * @return #GNUNET_YES (iterate over all such channels)
362 */
363static int
364bind_loose_channel (void *cls,
365 const struct GNUNET_HashCode *port,
366 void *value)
367{
368 struct CadetClient *c = cls;
369 struct CadetChannel *ch = value;
370
371 GCCH_bind (ch,
372 c);
373 GNUNET_assert (GNUNET_YES ==
374 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
375 port,
376 value));
377 return GNUNET_YES;
378}
379
380
381/**
382 * Handler for port open requests.
383 *
384 * @param cls Identification of the client.
385 * @param pmsg The actual message.
386 */
387static void
388handle_port_open (void *cls,
389 const struct GNUNET_CADET_PortMessage *pmsg)
390{
391 struct CadetClient *c = cls;
392
393 LOG (GNUNET_ERROR_TYPE_DEBUG,
394 "Open port %s requested by client %u\n",
395 GNUNET_h2s (&pmsg->port),
396 c->id);
397 if (NULL == c->ports)
398 c->ports = GNUNET_CONTAINER_multihashmap_create (4,
399 GNUNET_NO);
400 if (GNUNET_OK !=
401 GNUNET_CONTAINER_multihashmap_put (c->ports,
402 &pmsg->port,
403 c,
404 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
405 {
406 GNUNET_break (0);
407 GNUNET_SERVICE_client_drop (c->client);
408 return;
409 }
410 /* store in global hashmap */
411 /* FIXME only allow one client to have the port open,
412 * have a backup hashmap with waiting clients */
413 GNUNET_CONTAINER_multihashmap_put (open_ports,
414 &pmsg->port,
415 c,
416 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
417 GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
418 &pmsg->port,
419 &bind_loose_channel,
420 c);
421 GNUNET_SERVICE_client_continue (c->client);
422}
423
424
425/**
426 * Handler for port close requests.
427 *
428 * @param cls Identification of the client.
429 * @param pmsg The actual message.
430 */
431static void
432handle_port_close (void *cls,
433 const struct GNUNET_CADET_PortMessage *pmsg)
434{
435 struct CadetClient *c = cls;
436
437 LOG (GNUNET_ERROR_TYPE_DEBUG,
438 "Open port %s requested by client %u\n",
439 GNUNET_h2s (&pmsg->port),
440 c->id);
441 if (GNUNET_YES !=
442 GNUNET_CONTAINER_multihashmap_remove (c->ports,
443 &pmsg->port,
444 c))
445 {
446 GNUNET_break (0);
447 GNUNET_SERVICE_client_drop (c->client);
448 return;
449 }
450 GNUNET_assert (GNUNET_YES ==
451 GNUNET_CONTAINER_multihashmap_remove (open_ports,
452 &pmsg->port,
453 c));
454
455 GNUNET_SERVICE_client_continue (c->client);
456}
457
458
459/**
460 * Handler for requests of new channels.
461 *
462 * @param cls Identification of the client.
463 * @param ccm The actual message.
464 */
465static void
466handle_channel_create (void *cls,
467 const struct GNUNET_CADET_ChannelOpenMessageMessage *ccm)
468{
469 struct CadetClient *c = cls;
470 struct CadetChannel *ch;
471 struct GNUNET_CADET_ClientChannelNumber chid;
472 struct CadetPeer *dst;
473
474 chid = ccm->channel_id;
475 if (ntohl (chid.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
476 {
477 /* Channel ID not in allowed range. */
478 GNUNET_break (0);
479 GNUNET_SERVICE_client_drop (c->client);
480 return;
481 }
482 ch = GNUNET_CONTAINER_multihashmap32_get (c->own_channels,
483 ntohl (chid.channel_of_client));
484 if (NULL != ch)
485 {
486 /* Channel ID already in use. Not allowed. */
487 GNUNET_break (0);
488 GNUNET_SERVICE_client_drop (c->client);
489 return;
490 }
491
492 dst = GCP_get (&ccm->peer,
493 GNUNET_YES);
494
495 /* Create channel */
496 ch = GCCH_channel_local_new (c,
497 chid,
498 dst,
499 &ccm->port,
500 ntohl (ccm->opt));
501 if (NULL == ch)
502 {
503 GNUNET_break (0);
504 GNUNET_SERVICE_client_drop (c->client);
505 return;
506 }
507 GNUNET_assert (GNUNET_YES ==
508 GNUNET_CONTAINER_multihashmap32_put (c->own_channels,
509 ntohl (chid.channel_of_client),
510 ch,
511 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
512
513 LOG (GNUNET_ERROR_TYPE_DEBUG,
514 "New channel %s to %s at port %s requested by client %u\n",
515 GCCH_2s (ch),
516 GNUNET_i2s (&ccm->peer),
517 GNUNET_h2s (&ccm->port),
518 c->id);
519 GNUNET_SERVICE_client_continue (c->client);
520}
521
522
523/**
524 * Return the map which we use for client @a c for a channel ID of @a chid
525 *
526 * @param c client to find map for
527 * @param chid chid to find map for
528 * @return applicable map we use
529 */
530static struct GNUNET_CONTAINER_MultiHashMap32 *
531get_map_by_chid (struct CadetClient *c,
532 struct GNUNET_CADET_ClientChannelNumber chid)
533{
534 return (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
535 ? c->own_channels
536 : c->incoming_channels;
537}
538
539
540/**
541 * Handler for requests of deleting tunnels
542 *
543 * @param cls client identification of the client
544 * @param msg the actual message
545 */
546static void
547handle_channel_destroy (void *cls,
548 const struct GNUNET_CADET_ChannelDestroyMessage *msg)
549{
550 struct CadetClient *c = cls;
551 struct GNUNET_CADET_ClientChannelNumber chid;
552 struct GNUNET_CONTAINER_MultiHashMap32 *map;
553 struct CadetChannel *ch;
554
555 /* Retrieve tunnel */
556 chid = msg->channel_id;
557 map = get_map_by_chid (c,
558 chid);
559 ch = GNUNET_CONTAINER_multihashmap32_get (map,
560 ntohl (chid.channel_of_client));
561 if (NULL == ch)
562 {
563 /* Client attempted to destroy unknown channel */
564 GNUNET_break (0);
565 GNUNET_SERVICE_client_drop (c->client);
566 return;
567 }
568 LOG (GNUNET_ERROR_TYPE_INFO,
569 "Client %u is destroying channel %s\n",
570 c->id,
571 GCCH_2s (ch));
572 GNUNET_assert (GNUNET_YES ==
573 GNUNET_CONTAINER_multihashmap32_remove (map,
574 ntohl (chid.channel_of_client),
575 ch));
576 GCCH_channel_local_destroy (ch);
577 GNUNET_SERVICE_client_continue (c->client);
578}
579
580
581/**
582 * Check for client traffic data message is well-formed
583 *
584 * @param cls identification of the client
585 * @param msg the actual message
586 * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not
587 */
588static int
589check_data (void *cls,
590 const struct GNUNET_CADET_LocalData *msg)
591{
592 const struct GNUNET_MessageHeader *payload;
593 size_t payload_size;
594 size_t payload_claimed_size;
595
596 /* Sanity check for message size */
597 payload_size = ntohs (msg->header.size) - sizeof (*msg);
598 if ( (payload_size < sizeof (struct GNUNET_MessageHeader)) ||
599 (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_size) )
600 {
601 GNUNET_break (0);
602 return GNUNET_SYSERR;
603 }
604 payload = (struct GNUNET_MessageHeader *) &msg[1];
605 payload_claimed_size = ntohs (payload->size);
606 if (payload_size != payload_claimed_size)
607 {
608 GNUNET_break (0);
609 return GNUNET_SYSERR;
610 }
611 return GNUNET_OK;
612}
613
614
615/**
616 * Handler for client traffic
617 *
618 * @param cls identification of the client
619 * @param msg the actual message
620 */
621static void
622handle_data (void *cls,
623 const struct GNUNET_CADET_LocalData *msg)
624{
625 struct CadetClient *c = cls;
626 struct GNUNET_CONTAINER_MultiHashMap32 *map;
627 struct GNUNET_CADET_ClientChannelNumber chid;
628 struct CadetChannel *ch;
629 const struct GNUNET_MessageHeader *payload;
630
631 chid = msg->id;
632 map = get_map_by_chid (c,
633 chid);
634 ch = GNUNET_CONTAINER_multihashmap32_get (map,
635 ntohl (chid.channel_of_client));
636 if (NULL == ch)
637 {
638 /* Channel does not exist! */
639 GNUNET_break (0);
640 GNUNET_SERVICE_client_drop (c->client);
641 return;
642 }
643
644 payload = (const struct GNUNET_MessageHeader *) &msg[1];
645 LOG (GNUNET_ERROR_TYPE_DEBUG,
646 "Received %u bytes payload from client %u for channel %s\n",
647 ntohs (payload->size),
648 c->id,
649 GCCH_2s (ch));
650 if (GNUNET_OK !=
651 GCCH_handle_local_data (ch,
652 payload))
653 {
654 GNUNET_SERVICE_client_drop (c->client);
655 return;
656 }
657 GNUNET_SERVICE_client_continue (c->client);
658}
659
660
661/**
662 * Handler for client's ACKs for payload traffic.
663 *
664 * @param cls identification of the client.
665 * @param msg The actual message.
666 */
667static void
668handle_ack (void *cls,
669 const struct GNUNET_CADET_LocalAck *msg)
670{
671 struct CadetClient *c = cls;
672 struct GNUNET_CONTAINER_MultiHashMap32 *map;
673 struct GNUNET_CADET_ClientChannelNumber chid;
674 struct CadetChannel *ch;
675
676 chid = msg->channel_id;
677 map = get_map_by_chid (c,
678 chid);
679 ch = GNUNET_CONTAINER_multihashmap32_get (map,
680 ntohl (chid.channel_of_client));
681 if (NULL == ch)
682 {
683 /* Channel does not exist! */
684 GNUNET_break (0);
685 GNUNET_SERVICE_client_drop (c->client);
686 return;
687 }
688 LOG (GNUNET_ERROR_TYPE_DEBUG,
689 "Got a local ACK from client %u for channel %s\n",
690 c->id,
691 GCCH_2s (ch));
692 GCCH_handle_local_ack (ch);
693 GNUNET_SERVICE_client_continue (c->client);
694}
695
696
697/**
698 * Iterator over all peers to send a monitoring client info about each peer.
699 *
700 * @param cls Closure ().
701 * @param peer Peer ID (tunnel remote peer).
702 * @param value Peer info.
703 * @return #GNUNET_YES, to keep iterating.
704 */
705static int
706get_all_peers_iterator (void *cls,
707 const struct GNUNET_PeerIdentity *peer,
708 void *value)
709{
710 struct CadetClient *c = cls;
711 struct CadetPeer *p = value;
712 struct GNUNET_MQ_Envelope *env;
713 struct GNUNET_CADET_LocalInfoPeer *msg;
714
715 env = GNUNET_MQ_msg (msg,
716 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
717 msg->destination = *peer;
718 msg->paths = htons (GCP_count_paths (p));
719 msg->tunnel = htons (NULL != GCP_get_tunnel (p,
720 GNUNET_NO));
721 GNUNET_MQ_send (c->mq,
722 env);
723 return GNUNET_YES;
724}
725
726
727/**
728 * Handler for client's INFO PEERS request.
729 *
730 * @param cls Identification of the client.
731 * @param message The actual message.
732 */
733static void
734handle_get_peers (void *cls,
735 const struct GNUNET_MessageHeader *message)
736{
737 struct CadetClient *c = cls;
738 struct GNUNET_MQ_Envelope *env;
739 struct GNUNET_MessageHeader *reply;
740
741 GCP_iterate_all (&get_all_peers_iterator,
742 c);
743 env = GNUNET_MQ_msg (reply,
744 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
745 GNUNET_MQ_send (c->mq,
746 env);
747 GNUNET_SERVICE_client_continue (c->client);
748}
749
750
751/**
752 * Iterator over all paths of a peer to build an InfoPeer message.
753 * Message contains blocks of peers, first not included.
754 *
755 * @param cls message queue for transmission
756 * @param path Path itself
757 * @param off offset of the peer on @a path
758 * @return #GNUNET_YES if should keep iterating.
759 * #GNUNET_NO otherwise.
760 */
761static int
762path_info_iterator (void *cls,
763 struct CadetPeerPath *path,
764 unsigned int off)
765{
766 struct GNUNET_MQ_Handle *mq = cls;
767 struct GNUNET_MQ_Envelope *env;
768 struct GNUNET_MessageHeader *resp;
769 struct GNUNET_PeerIdentity *id;
770 uint16_t path_size;
771 unsigned int i;
772 unsigned int path_length;
773
774 path_length = GCPP_get_length (path);
775 path_size = sizeof (struct GNUNET_PeerIdentity) * (path_length - 1);
776 if (sizeof (*resp) + path_size > UINT16_MAX)
777 {
778 LOG (GNUNET_ERROR_TYPE_WARNING,
779 "Path of %u entries is too long for info message\n",
780 path_length);
781 return GNUNET_YES;
782 }
783 env = GNUNET_MQ_msg_extra (resp,
784 path_size,
785 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
786 id = (struct GNUNET_PeerIdentity *) &resp[1];
787
788 /* Don't copy first peer. First peer is always the local one. Last
789 * peer is always the destination (leave as 0, EOL).
790 */
791 for (i = 0; i < off; i++)
792 id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path,
793 i + 1));
794 GNUNET_MQ_send (mq,
795 env);
796 return GNUNET_YES;
797}
798
799
800/**
801 * Handler for client's SHOW_PEER request.
802 *
803 * @param cls Identification of the client.
804 * @param msg The actual message.
805 */
806static void
807handle_show_peer (void *cls,
808 const struct GNUNET_CADET_LocalInfo *msg)
809{
810 struct CadetClient *c = cls;
811 struct CadetPeer *p;
812 struct GNUNET_MQ_Envelope *env;
813 struct GNUNET_MessageHeader *resp;
814
815 p = GCP_get (&msg->peer,
816 GNUNET_NO);
817 if (NULL != p)
818 GCP_iterate_paths (p,
819 &path_info_iterator,
820 c->mq);
821 /* Send message with 0/0 to indicate the end */
822 env = GNUNET_MQ_msg (resp,
823 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END);
824 GNUNET_MQ_send (c->mq,
825 env);
826 GNUNET_SERVICE_client_continue (c->client);
827}
828
829
830/**
831 * Iterator over all tunnels to send a monitoring client info about each tunnel.
832 *
833 * @param cls Closure ().
834 * @param peer Peer ID (tunnel remote peer).
835 * @param value a `struct CadetPeer`
836 * @return #GNUNET_YES, to keep iterating.
837 */
838static int
839get_all_tunnels_iterator (void *cls,
840 const struct GNUNET_PeerIdentity *peer,
841 void *value)
842{
843 struct CadetClient *c = cls;
844 struct CadetPeer *p = value;
845 struct GNUNET_MQ_Envelope *env;
846 struct GNUNET_CADET_LocalInfoTunnel *msg;
847 struct CadetTunnel *t;
848
849 t = GCP_get_tunnel (p,
850 GNUNET_NO);
851 if (NULL == t)
852 return GNUNET_YES;
853 env = GNUNET_MQ_msg (msg,
854 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
855 msg->destination = *peer;
856 msg->channels = htonl (GCT_count_channels (t));
857 msg->connections = htonl (GCT_count_any_connections (t));
858 msg->cstate = htons ((uint16_t) GCT_get_cstate (t));
859 msg->estate = htons ((uint16_t) GCT_get_estate (t));
860 GNUNET_MQ_send (c->mq,
861 env);
862 return GNUNET_YES;
863}
864
865
866/**
867 * Handler for client's INFO TUNNELS request.
868 *
869 * @param cls client Identification of the client.
870 * @param message The actual message.
871 */
872static void
873handle_get_tunnels (void *cls,
874 const struct GNUNET_MessageHeader *message)
875{
876 struct CadetClient *c = cls;
877 struct GNUNET_MQ_Envelope *env;
878 struct GNUNET_MessageHeader *reply;
879
880 GCP_iterate_all (&get_all_tunnels_iterator,
881 c);
882 env = GNUNET_MQ_msg (reply,
883 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
884 GNUNET_MQ_send (c->mq,
885 env);
886 GNUNET_SERVICE_client_continue (c->client);
887}
888
889
890/**
891 * FIXME.
892 */
893static void
894iter_connection (void *cls,
895 struct CadetConnection *c)
896{
897 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
898 struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
899
900 h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
901 h[msg->connections++] = *(GCC_get_id (c));
902}
903
904
905/**
906 * FIXME.
907 */
908static void
909iter_channel (void *cls,
910 struct CadetChannel *ch)
911{
912 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
913 struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
914 struct GNUNET_CADET_ChannelTunnelNumber *chn
915 = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections];
916
917 chn[msg->channels++] = GCCH_get_id (ch);
918}
919
920
921/**
922 * Handler for client's SHOW_TUNNEL request.
923 *
924 * @param cls Identification of the client.
925 * @param msg The actual message.
926 */
927static void
928handle_show_tunnel (void *cls,
929 const struct GNUNET_CADET_LocalInfo *msg)
930{
931 struct CadetClient *c = cls;
932 struct GNUNET_MQ_Envelope *env;
933 struct GNUNET_CADET_LocalInfoTunnel *resp;
934 struct CadetTunnel *t;
935 struct CadetPeer *p;
936 unsigned int ch_n;
937 unsigned int c_n;
938
939 p = GCP_get (&msg->peer,
940 GNUNET_NO);
941 t = GCP_get_tunnel (p,
942 GNUNET_NO);
943 if (NULL == t)
944 {
945 /* We don't know the tunnel */
946 struct GNUNET_MQ_Envelope *env;
947 struct GNUNET_CADET_LocalInfoTunnel *warn;
948
949 LOG (GNUNET_ERROR_TYPE_INFO,
950 "Tunnel to %s unknown\n",
951 GNUNET_i2s_full (&msg->peer));
952 env = GNUNET_MQ_msg (warn,
953 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
954 warn->destination = msg->peer;
955 GNUNET_MQ_send (c->mq,
956 env);
957 GNUNET_SERVICE_client_continue (c->client);
958 return;
959 }
960
961 /* Initialize context */
962 ch_n = GCT_count_channels (t);
963 c_n = GCT_count_any_connections (t);
964 env = GNUNET_MQ_msg_extra (resp,
965 c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier) +
966 ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber),
967 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
968 resp->destination = msg->peer;
969 /* Do not reorder! #iter_channel needs counters in HBO! */
970 GCT_iterate_connections (t,
971 &iter_connection,
972 resp);
973 GCT_iterate_channels (t,
974 &iter_channel,
975 resp);
976 resp->connections = htonl (resp->connections);
977 resp->channels = htonl (resp->channels);
978 resp->cstate = htons (GCT_get_cstate (t));
979 resp->estate = htons (GCT_get_estate (t));
980 GNUNET_MQ_send (c->mq,
981 env);
982 GNUNET_SERVICE_client_continue (c->client);
983}
984
985
986/**
987 * Iterator over all peers to dump info for each peer.
988 *
989 * @param cls Closure (unused).
990 * @param peer Peer ID (tunnel remote peer).
991 * @param value Peer info.
992 *
993 * @return #GNUNET_YES, to keep iterating.
994 */
995static int
996show_peer_iterator (void *cls,
997 const struct GNUNET_PeerIdentity *peer,
998 void *value)
999{
1000 struct CadetPeer *p = value;
1001 struct CadetTunnel *t;
1002
1003 t = GCP_get_tunnel (p,
1004 GNUNET_NO);
1005 if (NULL != t)
1006 GCT_debug (t,
1007 GNUNET_ERROR_TYPE_ERROR);
1008 LOG (GNUNET_ERROR_TYPE_ERROR, "\n");
1009 return GNUNET_YES;
1010}
1011
1012
1013/**
1014 * Handler for client's INFO_DUMP request.
1015 *
1016 * @param cls Identification of the client.
1017 * @param message The actual message.
1018 */
1019static void
1020handle_info_dump (void *cls,
1021 const struct GNUNET_MessageHeader *message)
1022{
1023 struct CadetClient *c = cls;
1024
1025 LOG (GNUNET_ERROR_TYPE_INFO,
1026 "Received dump info request from client %u\n",
1027 c->id);
1028
1029 LOG (GNUNET_ERROR_TYPE_ERROR,
1030 "*************************** DUMP START ***************************\n");
1031 for (struct CadetClient *ci = clients_head; NULL != ci; ci = ci->next)
1032 {
1033 LOG (GNUNET_ERROR_TYPE_ERROR,
1034 "Client %u (%p), handle: %p, ports: %u, own channels: %u, incoming channels: %u\n",
1035 ci->id,
1036 ci,
1037 ci->client,
1038 (NULL != c->ports)
1039 ? GNUNET_CONTAINER_multihashmap_size (ci->ports)
1040 : 0,
1041 GNUNET_CONTAINER_multihashmap32_size (ci->own_channels),
1042 GNUNET_CONTAINER_multihashmap32_size (ci->incoming_channels));
1043 }
1044 LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n");
1045 GCP_iterate_all (&show_peer_iterator,
1046 NULL);
1047
1048 LOG (GNUNET_ERROR_TYPE_ERROR,
1049 "**************************** DUMP END ****************************\n");
1050
1051 GNUNET_SERVICE_client_continue (c->client);
1052}
1053
1054
1055
1056/**
1057 * Callback called when a client connects to the service.
1058 *
1059 * @param cls closure for the service
1060 * @param client the new client that connected to the service
1061 * @param mq the message queue used to send messages to the client
1062 * @return @a c
1063 */
1064static void *
1065client_connect_cb (void *cls,
1066 struct GNUNET_SERVICE_Client *client,
1067 struct GNUNET_MQ_Handle *mq)
1068{
1069 struct CadetClient *c;
1070
1071 c = GNUNET_new (struct CadetClient);
1072 c->client = client;
1073 c->mq = mq;
1074 c->id = next_client_id++; /* overflow not important: just for debug */
1075 c->own_channels
1076 = GNUNET_CONTAINER_multihashmap32_create (32);
1077 c->incoming_channels
1078 = GNUNET_CONTAINER_multihashmap32_create (32);
1079 GNUNET_CONTAINER_DLL_insert (clients_head,
1080 clients_tail,
1081 c);
1082 GNUNET_STATISTICS_update (stats,
1083 "# clients",
1084 +1,
1085 GNUNET_NO);
1086 return c;
1087}
1088
1089
1090/**
1091 * Iterator for deleting each channel whose client endpoint disconnected.
1092 *
1093 * @param cls Closure (client that has disconnected).
1094 * @param key The local channel id (used to access the hashmap).
1095 * @param value The value stored at the key (channel to destroy).
1096 * @return #GNUNET_OK, keep iterating.
1097 */
1098static int
1099own_channel_destroy_iterator (void *cls,
1100 uint32_t key,
1101 void *value)
1102{
1103 struct CadetClient *c = cls;
1104 struct CadetChannel *ch = value;
1105
1106 GNUNET_assert (GNUNET_YES ==
1107 GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
1108 key,
1109 ch));
1110 LOG (GNUNET_ERROR_TYPE_DEBUG,
1111 "Destroying own channel %s, due to client %u shutdown.\n",
1112 GCCH_2s (ch),
1113 c->id);
1114 GCCH_channel_local_destroy (ch);
1115 return GNUNET_OK;
1116}
1117
1118
1119/**
1120 * Iterator for deleting each channel whose client endpoint disconnected.
1121 *
1122 * @param cls Closure (client that has disconnected).
1123 * @param key The local channel id (used to access the hashmap).
1124 * @param value The value stored at the key (channel to destroy).
1125 * @return #GNUNET_OK, keep iterating.
1126 */
1127static int
1128incoming_channel_destroy_iterator (void *cls,
1129 uint32_t key,
1130 void *value)
1131{
1132 struct CadetChannel *ch = value;
1133 struct CadetClient *c = cls;
1134
1135 GNUNET_assert (GNUNET_YES ==
1136 GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
1137 key,
1138 ch));
1139
1140 LOG (GNUNET_ERROR_TYPE_DEBUG,
1141 "Destroying incoming channel %s due to client %u shutdown.\n",
1142 GCCH_2s (ch),
1143 c->id);
1144 GCCH_channel_incoming_destroy (ch);
1145 return GNUNET_OK;
1146}
1147
1148
1149/**
1150 * Remove client's ports from the global hashmap on disconnect.
1151 *
1152 * @param cls Closure (unused).
1153 * @param key Port.
1154 * @param value the `struct CadetClient` to remove
1155 * @return #GNUNET_OK, keep iterating.
1156 */
1157static int
1158client_release_ports (void *cls,
1159 const struct GNUNET_HashCode *key,
1160 void *value)
1161{
1162 struct CadetClient *c = value;
1163
1164 GNUNET_assert (GNUNET_YES ==
1165 GNUNET_CONTAINER_multihashmap_remove (open_ports,
1166 key,
1167 value));
1168 GNUNET_assert (GNUNET_YES ==
1169 GNUNET_CONTAINER_multihashmap_remove (c->ports,
1170 key,
1171 value));
1172 return GNUNET_OK;
1173}
1174
1175
1176/**
1177 * Callback called when a client disconnected from the service
1178 *
1179 * @param cls closure for the service
1180 * @param client the client that disconnected
1181 * @param internal_cls should be equal to @a c
1182 */
1183static void
1184client_disconnect_cb (void *cls,
1185 struct GNUNET_SERVICE_Client *client,
1186 void *internal_cls)
1187{
1188 struct CadetClient *c = internal_cls;
1189
1190 GNUNET_assert (c->client == client);
1191 c->shutting_down = GNUNET_YES;
1192 if (NULL != c->own_channels)
1193 {
1194 GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
1195 &own_channel_destroy_iterator,
1196 c);
1197 GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
1198 }
1199 if (NULL != c->incoming_channels)
1200 {
1201 GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
1202 &incoming_channel_destroy_iterator,
1203 c);
1204 GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
1205 }
1206 if (NULL != c->ports)
1207 {
1208 GNUNET_CONTAINER_multihashmap_iterate (c->ports,
1209 &client_release_ports,
1210 c);
1211 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
1212 }
1213 GNUNET_CONTAINER_DLL_remove (clients_head,
1214 clients_tail,
1215 c);
1216 GNUNET_STATISTICS_update (stats,
1217 "# clients",
1218 -1,
1219 GNUNET_NO);
1220 GNUNET_free (c);
1221}
1222
1223
1224/**
1225 * Setup CADET internals.
1226 *
1227 * @param cls closure
1228 * @param server the initialized server
1229 * @param c configuration to use
1230 */
1231static void
1232run (void *cls,
1233 const struct GNUNET_CONFIGURATION_Handle *c,
1234 struct GNUNET_SERVICE_Handle *service)
1235{
1236 if (GNUNET_OK !=
1237 GNUNET_CONFIGURATION_get_value_number (c,
1238 "CADET",
1239 "RATCHET_MESSAGES",
1240 &ratchet_messages))
1241 {
1242 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1243 "CADET",
1244 "RATCHET_MESSAGES",
1245 "needs to be a number");
1246 ratchet_messages = 64;
1247 }
1248 if (GNUNET_OK !=
1249 GNUNET_CONFIGURATION_get_value_time (c,
1250 "CADET",
1251 "RATCHET_TIME",
1252 &ratchet_time))
1253 {
1254 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1255 "CADET",
1256 "RATCHET_TIME",
1257 "need delay value");
1258 ratchet_time = GNUNET_TIME_UNIT_HOURS;
1259 }
1260
1261 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1262 if (NULL == my_private_key)
1263 {
1264 GNUNET_break (0);
1265 GNUNET_SCHEDULER_shutdown ();
1266 return;
1267 }
1268 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1269 &my_full_id.public_key);
1270 stats = GNUNET_STATISTICS_create ("cadet",
1271 c);
1272 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1273 NULL);
1274 ats_ch = GNUNET_ATS_connectivity_init (c);
1275 /* FIXME: optimize code to allow GNUNET_YES here! */
1276 open_ports = GNUNET_CONTAINER_multihashmap_create (16,
1277 GNUNET_NO);
1278 loose_channels = GNUNET_CONTAINER_multihashmap_create (16,
1279 GNUNET_NO);
1280 peers = GNUNET_CONTAINER_multipeermap_create (16,
1281 GNUNET_YES);
1282 connections = GNUNET_CONTAINER_multishortmap_create (256,
1283 GNUNET_YES);
1284 GCH_init (c);
1285 GCD_init (c);
1286 GCO_init (c);
1287 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1288 "CADET starting at peer %s\n",
1289 GNUNET_i2s (&my_full_id));
1290
1291}
1292
1293
1294/**
1295 * Define "main" method using service macro.
1296 */
1297GNUNET_SERVICE_MAIN
1298("cadet",
1299 GNUNET_SERVICE_OPTION_NONE,
1300 &run,
1301 &client_connect_cb,
1302 &client_disconnect_cb,
1303 NULL,
1304 GNUNET_MQ_hd_fixed_size (port_open,
1305 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
1306 struct GNUNET_CADET_PortMessage,
1307 NULL),
1308 GNUNET_MQ_hd_fixed_size (port_close,
1309 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
1310 struct GNUNET_CADET_PortMessage,
1311 NULL),
1312 GNUNET_MQ_hd_fixed_size (channel_create,
1313 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
1314 struct GNUNET_CADET_ChannelOpenMessageMessage,
1315 NULL),
1316 GNUNET_MQ_hd_fixed_size (channel_destroy,
1317 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
1318 struct GNUNET_CADET_ChannelDestroyMessage,
1319 NULL),
1320 GNUNET_MQ_hd_var_size (data,
1321 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1322 struct GNUNET_CADET_LocalData,
1323 NULL),
1324 GNUNET_MQ_hd_fixed_size (ack,
1325 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1326 struct GNUNET_CADET_LocalAck,
1327 NULL),
1328 GNUNET_MQ_hd_fixed_size (get_peers,
1329 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
1330 struct GNUNET_MessageHeader,
1331 NULL),
1332 GNUNET_MQ_hd_fixed_size (show_peer,
1333 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
1334 struct GNUNET_CADET_LocalInfo,
1335 NULL),
1336 GNUNET_MQ_hd_fixed_size (get_tunnels,
1337 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
1338 struct GNUNET_MessageHeader,
1339 NULL),
1340 GNUNET_MQ_hd_fixed_size (show_tunnel,
1341 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
1342 struct GNUNET_CADET_LocalInfo,
1343 NULL),
1344 GNUNET_MQ_hd_fixed_size (info_dump,
1345 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP,
1346 struct GNUNET_MessageHeader,
1347 NULL),
1348 GNUNET_MQ_handler_end ());
1349
1350/* end of gnunet-service-cadet-new.c */
diff --git a/src/cadet/gnunet-service-cadet-new.h b/src/cadet/gnunet-service-cadet-new.h
new file mode 100644
index 000000000..9f4667e23
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new.h
@@ -0,0 +1,264 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new.h
24 * @brief Information we track per peer.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#ifndef GNUNET_SERVICE_CADET_H
29#define GNUNET_SERVICE_CADET_H
30
31#include "gnunet_util_lib.h"
32#define NEW_CADET 1
33
34/**
35 * A client to the CADET service. Each client gets a unique handle.
36 */
37struct CadetClient;
38
39/**
40 * A peer in the GNUnet network. Each peer we care about must have one globally
41 * unique such handle within this process.
42 */
43struct CadetPeer;
44
45/**
46 * Tunnel from us to another peer. There can only be at most one
47 * tunnel per peer.
48 */
49struct CadetTunnel;
50
51/**
52 * Entry in the message queue of a `struct CadetTunnel`.
53 */
54struct CadetTunnelQueueEntry;
55
56/**
57 * A path of peer in the GNUnet network. There must only be at most
58 * once such path. Paths may share disjoint prefixes, but must all
59 * end at a unique suffix. Paths must also not be proper subsets of
60 * other existing paths.
61 */
62struct CadetPeerPath;
63
64/**
65 * Entry in a peer path.
66 */
67struct CadetPeerPathEntry
68{
69 /**
70 * DLL of paths where the same @e peer is at the same offset.
71 */
72 struct CadetPeerPathEntry *next;
73
74 /**
75 * DLL of paths where the same @e peer is at the same offset.
76 */
77 struct CadetPeerPathEntry *prev;
78
79 /**
80 * The peer at this offset of the path.
81 */
82 struct CadetPeer *peer;
83
84 /**
85 * Path this entry belongs to.
86 */
87 struct CadetPeerPath *path;
88
89 /**
90 * Connection using this path, or NULL for none.
91 */
92 struct CadetConnection *cc;
93
94 /**
95 * Path's historic score up to this point. Basically, how often did
96 * we succeed or fail to use the path up to this entry in a
97 * connection. Positive values indicate good experiences, negative
98 * values bad experiences. Code updating the score must guard
99 * against overflows.
100 */
101 int score;
102
103};
104
105/**
106 * Entry in list of connections used by tunnel, with metadata.
107 */
108struct CadetTConnection
109{
110 /**
111 * Next in DLL.
112 */
113 struct CadetTConnection *next;
114
115 /**
116 * Prev in DLL.
117 */
118 struct CadetTConnection *prev;
119
120 /**
121 * Connection handle.
122 */
123 struct CadetConnection *cc;
124
125 /**
126 * Tunnel this connection belongs to.
127 */
128 struct CadetTunnel *t;
129
130 /**
131 * Creation time, to keep oldest connection alive.
132 */
133 struct GNUNET_TIME_Absolute created;
134
135 /**
136 * Connection throughput, to keep fastest connection alive.
137 */
138 uint32_t throughput;
139
140 /**
141 * Is the connection currently ready for transmission?
142 */
143 int is_ready;
144};
145
146
147/**
148 * Active path through the network (used by a tunnel). There may
149 * be at most one connection per path.
150 */
151struct CadetConnection;
152
153/**
154 * Description of a segment of a `struct CadetConnection` at the
155 * intermediate peers. Routes are basically entries in a peer's
156 * routing table for forwarding traffic. At both endpoints, the
157 * routes are terminated by a `struct CadetConnection`, which knows
158 * the complete `struct CadetPath` that is formed by the individual
159 * routes.
160 */
161struct CadetRoute;
162
163/**
164 * Logical end-to-end conenction between clients. There can be
165 * any number of channels between clients.
166 */
167struct CadetChannel;
168
169/**
170 * Handle to the statistics service.
171 */
172extern struct GNUNET_STATISTICS_Handle *stats;
173
174/**
175 * Handle to communicate with ATS.
176 */
177extern struct GNUNET_ATS_ConnectivityHandle *ats_ch;
178
179/**
180 * Local peer own ID.
181 */
182extern struct GNUNET_PeerIdentity my_full_id;
183
184/**
185 * Own private key.
186 */
187extern struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
188
189/**
190 * All ports clients of this peer have opened.
191 */
192extern struct GNUNET_CONTAINER_MultiHashMap *open_ports;
193
194/**
195 * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
196 * hash codes to `struct CadetConnection` objects.
197 */
198extern struct GNUNET_CONTAINER_MultiShortmap *connections;
199
200/**
201 * Map from ports to channels where the ports were closed at the
202 * time we got the inbound connection.
203 * Indexed by port, contains `struct CadetChannel`.
204 */
205extern struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
206
207/**
208 * Map from PIDs to `struct CadetPeer` entries.
209 */
210extern struct GNUNET_CONTAINER_MultiPeerMap *peers;
211
212/**
213 * How many messages are needed to trigger an AXOLOTL ratchet advance.
214 */
215extern unsigned long long ratchet_messages;
216
217/**
218 * How long until we trigger a ratched advance due to time.
219 */
220extern struct GNUNET_TIME_Relative ratchet_time;
221
222
223
224/**
225 * Send a message to a client.
226 *
227 * @param c client to get the message
228 * @param env envelope with the message
229 */
230void
231GSC_send_to_client (struct CadetClient *c,
232 struct GNUNET_MQ_Envelope *env);
233
234
235/**
236 * Bind incoming channel to this client, and notify client
237 * about incoming connection.
238 *
239 * @param c client to bind to
240 * @param ch channel to be bound
241 * @param dest peer that establishes the connection
242 * @param port port number
243 * @param options options
244 * @return local channel number assigned to the new client
245 */
246struct GNUNET_CADET_ClientChannelNumber
247GSC_bind (struct CadetClient *c,
248 struct CadetChannel *ch,
249 struct CadetPeer *dest,
250 const struct GNUNET_HashCode *port,
251 uint32_t options);
252
253
254/**
255 * Return identifier for a client as a string.
256 *
257 * @param c client to identify
258 * @return string for debugging
259 */
260const char *
261GSC_2s (struct CadetClient *c);
262
263
264#endif
diff --git a/src/cadet/gnunet-service-cadet-new_channel.c b/src/cadet/gnunet-service-cadet-new_channel.c
new file mode 100644
index 000000000..5acd098b6
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_channel.c
@@ -0,0 +1,1077 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_channel.c
24 * @brief logical links between CADET clients
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 *
28 * TODO:
29 * - estimate max bandwidth using bursts and use to optimize
30 * transmission rate(s)
31 */
32
33#include "platform.h"
34#include "gnunet_util_lib.h"
35#include "cadet.h"
36#include "gnunet_statistics_service.h"
37#include "gnunet-service-cadet-new.h"
38#include "gnunet-service-cadet-new_channel.h"
39#include "gnunet-service-cadet-new_connection.h"
40#include "gnunet-service-cadet-new_tunnels.h"
41#include "gnunet-service-cadet-new_peer.h"
42#include "gnunet-service-cadet-new_paths.h"
43
44#define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
45
46/**
47 * How long do we initially wait before retransmitting?
48 */
49#define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250)
50
51/**
52 * How long do we wait before dropping state about incoming
53 * connection to closed port?
54 */
55#define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
56
57
58/**
59 * All the states a connection can be in.
60 */
61enum CadetChannelState
62{
63 /**
64 * Uninitialized status, should never appear in operation.
65 */
66 CADET_CHANNEL_NEW,
67
68 /**
69 * Connection create message sent, waiting for ACK.
70 */
71 CADET_CHANNEL_CREATE_SENT,
72
73 /**
74 * Connection confirmed, ready to carry traffic.
75 */
76 CADET_CHANNEL_READY
77};
78
79
80/**
81 * Info needed to retry a message in case it gets lost.
82 * Note that we DO use this structure also for unreliable
83 * messages.
84 */
85struct CadetReliableMessage
86{
87 /**
88 * Double linked list, FIFO style
89 */
90 struct CadetReliableMessage *next;
91
92 /**
93 * Double linked list, FIFO style
94 */
95 struct CadetReliableMessage *prev;
96
97 /**
98 * Which channel is this message in?
99 */
100 struct CadetChannel *ch;
101
102 /**
103 * Entry in the tunnels queue for this message, NULL if it has left
104 * the tunnel. Used to cancel transmission in case we receive an
105 * ACK in time.
106 */
107 struct CadetTunnelQueueEntry *qe;
108
109 /**
110 * How soon should we retry if we fail to get an ACK?
111 * Messages in the queue are sorted by this value.
112 */
113 struct GNUNET_TIME_Absolute next_retry;
114
115 /**
116 * How long do we wait for an ACK after transmission?
117 * Use for the back-off calculation.
118 */
119 struct GNUNET_TIME_Relative retry_delay;
120
121 /**
122 * Data message we are trying to send.
123 */
124 struct GNUNET_CADET_ChannelAppDataMessage data_message;
125
126 /* followed by variable-size payload */
127};
128
129
130/**
131 * List of received out-of-order data messages.
132 */
133struct CadetOutOfOrderMessage
134{
135 /**
136 * Double linked list, FIFO style
137 */
138 struct CadetOutOfOrderMessage *next;
139
140 /**
141 * Double linked list, FIFO style
142 */
143 struct CadetOutOfOrderMessage *prev;
144
145 /**
146 * ID of the message (ACK needed to free)
147 */
148 struct ChannelMessageIdentifier mid;
149
150 /**
151 * The envelope with the payload of the out-of-order message
152 */
153 struct GNUNET_MQ_Envelope *env;
154
155};
156
157
158/**
159 * Struct containing all information regarding a channel to a remote client.
160 */
161struct CadetChannel
162{
163 /**
164 * Tunnel this channel is in.
165 */
166 struct CadetTunnel *t;
167
168 /**
169 * Last entry in the tunnel's queue relating to control messages
170 * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
171 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
172 * transmission in case we receive updated information.
173 */
174 struct CadetTunnelQueueEntry *last_control_qe;
175
176 /**
177 * Client owner of the tunnel, if any.
178 * (Used if this channel represends the initiating end of the tunnel.)
179 */
180 struct CadetClient *owner;
181
182 /**
183 * Client destination of the tunnel, if any.
184 * (Used if this channel represents the listening end of the tunnel.)
185 */
186 struct CadetClient *dest;
187
188 /**
189 * Head of DLL of messages sent and not yet ACK'd.
190 */
191 struct CadetReliableMessage *head_sent;
192
193 /**
194 * Tail of DLL of messages sent and not yet ACK'd.
195 */
196 struct CadetReliableMessage *tail_sent;
197
198 /**
199 * Head of DLL of messages received out of order or while client was unready.
200 */
201 struct CadetOutOfOrderMessage *head_recv;
202
203 /**
204 * Tail DLL of messages received out of order or while client was unready.
205 */
206 struct CadetOutOfOrderMessage *tail_recv;
207
208 /**
209 * Task to resend/poll in case no ACK is received.
210 */
211 struct GNUNET_SCHEDULER_Task *retry_task;
212
213 /**
214 * Last time the channel was used
215 */
216 struct GNUNET_TIME_Absolute timestamp;
217
218 /**
219 * Destination port of the channel.
220 */
221 struct GNUNET_HashCode port;
222
223 /**
224 * Counter for exponential backoff.
225 */
226 struct GNUNET_TIME_Relative retry_time;
227
228 /**
229 * How long does it usually take to get an ACK.
230 */
231 struct GNUNET_TIME_Relative expected_delay;
232
233 /**
234 * Bitfield of already-received messages past @e mid_recv.
235 */
236 uint64_t mid_futures;
237
238 /**
239 * Next MID expected for incoming traffic.
240 */
241 struct ChannelMessageIdentifier mid_recv;
242
243 /**
244 * Next MID to use for outgoing traffic.
245 */
246 struct ChannelMessageIdentifier mid_send;
247
248 /**
249 * Total (reliable) messages pending ACK for this channel.
250 */
251 unsigned int pending_messages;
252
253 /**
254 * Maximum (reliable) messages pending ACK for this channel
255 * before we throttle the client.
256 */
257 unsigned int max_pending_messages;
258
259 /**
260 * Number identifying this channel in its tunnel.
261 */
262 struct GNUNET_CADET_ChannelTunnelNumber gid;
263
264 /**
265 * Local tunnel number for local client owning the channel.
266 * ( >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
267 */
268 struct GNUNET_CADET_ClientChannelNumber lid;
269
270 /**
271 * Channel state.
272 */
273 enum CadetChannelState state;
274
275 /**
276 * Can we send data to the client?
277 */
278 int client_ready;
279
280 /**
281 * Can the client send data to us?
282 */
283 int client_allowed;
284
285 /**
286 * Is the tunnel bufferless (minimum latency)?
287 */
288 int nobuffer;
289
290 /**
291 * Is the tunnel reliable?
292 */
293 int reliable;
294
295 /**
296 * Is the tunnel out-of-order?
297 */
298 int out_of_order;
299
300 /**
301 * Flag to signal the destruction of the channel. If this is set to
302 * #GNUNET_YES the channel will be destroyed once the queue is
303 * empty.
304 */
305 int destroy;
306
307};
308
309
310
311/**
312 * Get the static string for identification of the channel.
313 *
314 * @param ch Channel.
315 *
316 * @return Static string with the channel IDs.
317 */
318const char *
319GCCH_2s (const struct CadetChannel *ch)
320{
321 static char buf[128];
322
323 if (NULL == ch)
324 return "(NULL Channel)";
325 GNUNET_snprintf (buf,
326 sizeof (buf),
327 "%s:%s gid:%X (%X)",
328 GCT_2s (ch->t),
329 GNUNET_h2s (&ch->port),
330 ch->gid,
331 ntohl (ch->lid.channel_of_client));
332 return buf;
333}
334
335
336/**
337 * Get the channel's public ID.
338 *
339 * @param ch Channel.
340 *
341 * @return ID used to identify the channel with the remote peer.
342 */
343struct GNUNET_CADET_ChannelTunnelNumber
344GCCH_get_id (const struct CadetChannel *ch)
345{
346 return ch->gid;
347}
348
349
350/**
351 * Destroy the given channel.
352 *
353 * @param ch channel to destroy
354 */
355static void
356channel_destroy (struct CadetChannel *ch)
357{
358 struct CadetReliableMessage *crm;
359 struct CadetOutOfOrderMessage *com;
360
361 while (NULL != (crm = ch->head_sent))
362 {
363 GNUNET_assert (ch == crm->ch);
364 if (NULL != crm->qe)
365 {
366 GCT_send_cancel (crm->qe);
367 crm->qe = NULL;
368 }
369 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
370 ch->tail_sent,
371 crm);
372 GNUNET_free (crm);
373 }
374 while (NULL != (com = ch->head_recv))
375 {
376 GNUNET_CONTAINER_DLL_remove (ch->head_recv,
377 ch->tail_recv,
378 com);
379 GNUNET_MQ_discard (com->env);
380 GNUNET_free (com);
381 }
382 if (NULL != ch->last_control_qe)
383 {
384 GCT_send_cancel (ch->last_control_qe);
385 ch->last_control_qe = NULL;
386 }
387 if (NULL != ch->retry_task)
388 {
389 GNUNET_SCHEDULER_cancel (ch->retry_task);
390 ch->retry_task = NULL;
391 }
392 GCT_remove_channel (ch->t,
393 ch,
394 ch->gid);
395 GNUNET_free (ch);
396}
397
398
399/**
400 * Send a channel create message.
401 *
402 * @param cls Channel for which to send.
403 */
404static void
405send_create (void *cls);
406
407
408/**
409 * Function called once the tunnel confirms that we sent the
410 * create message. Delays for a bit until we retry.
411 *
412 * @param cls our `struct CadetChannel`.
413 */
414static void
415create_sent_cb (void *cls)
416{
417 struct CadetChannel *ch = cls;
418
419 ch->last_control_qe = NULL;
420 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
421 ch->retry_task = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
422 &send_create,
423 ch);
424}
425
426
427/**
428 * Send a channel create message.
429 *
430 * @param cls Channel for which to send.
431 */
432static void
433send_create (void *cls)
434{
435 struct CadetChannel *ch = cls;
436 struct GNUNET_CADET_ChannelOpenMessage msgcc;
437 uint32_t options;
438
439 options = 0;
440 if (ch->nobuffer)
441 options |= GNUNET_CADET_OPTION_NOBUFFER;
442 if (ch->reliable)
443 options |= GNUNET_CADET_OPTION_RELIABLE;
444 if (ch->out_of_order)
445 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
446 msgcc.header.size = htons (sizeof (msgcc));
447 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
448 msgcc.opt = htonl (options);
449 msgcc.port = ch->port;
450 msgcc.chid = ch->gid;
451 ch->state = CADET_CHANNEL_CREATE_SENT;
452 ch->last_control_qe = GCT_send (ch->t,
453 &msgcc.header,
454 &create_sent_cb,
455 ch);
456}
457
458
459/**
460 * Create a new channel.
461 *
462 * @param owner local client owning the channel
463 * @param owner_id local chid of this channel at the @a owner
464 * @param destination peer to which we should build the channel
465 * @param port desired port at @a destination
466 * @param options options for the channel
467 * @return handle to the new channel
468 */
469struct CadetChannel *
470GCCH_channel_local_new (struct CadetClient *owner,
471 struct GNUNET_CADET_ClientChannelNumber owner_id,
472 struct CadetPeer *destination,
473 const struct GNUNET_HashCode *port,
474 uint32_t options)
475{
476 struct CadetChannel *ch;
477
478 ch = GNUNET_new (struct CadetChannel);
479 ch->max_pending_messages = 32; /* FIXME: allow control via options
480 or adjust dynamically... */
481 ch->owner = owner;
482 ch->lid = owner_id;
483 ch->port = *port;
484 ch->t = GCP_get_tunnel (destination,
485 GNUNET_YES);
486 ch->gid = GCT_add_channel (ch->t,
487 ch);
488 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
489 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
490 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
491 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
492 ch->retry_task = GNUNET_SCHEDULER_add_now (&send_create,
493 ch);
494 GNUNET_STATISTICS_update (stats,
495 "# channels",
496 1,
497 GNUNET_NO);
498 return ch;
499}
500
501
502/**
503 * We had an incoming channel to a port that is closed.
504 * It has not been opened for a while, drop it.
505 *
506 * @param cls the channel to drop
507 */
508static void
509timeout_closed_cb (void *cls)
510{
511 struct CadetChannel *ch = cls;
512
513 ch->retry_task = NULL;
514 channel_destroy (ch);
515}
516
517
518/**
519 * Create a new channel.
520 *
521 * @param t tunnel to the remote peer
522 * @param gid identifier of this channel in the tunnel
523 * @param port desired local port
524 * @param options options for the channel
525 * @return handle to the new channel
526 */
527struct CadetChannel *
528GCCH_channel_incoming_new (struct CadetTunnel *t,
529 struct GNUNET_CADET_ChannelTunnelNumber gid,
530 const struct GNUNET_HashCode *port,
531 uint32_t options)
532{
533 struct CadetChannel *ch;
534 struct CadetClient *c;
535
536 ch = GNUNET_new (struct CadetChannel);
537 ch->max_pending_messages = 32; /* FIXME: allow control via options
538 or adjust dynamically... */
539 ch->port = *port;
540 ch->t = t;
541 ch->gid = gid;
542 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
543 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
544 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
545 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
546 GNUNET_STATISTICS_update (stats,
547 "# channels",
548 1,
549 GNUNET_NO);
550
551 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
552 port);
553 if (NULL == c)
554 {
555 /* port closed, wait for it to possibly open */
556 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
557 port,
558 ch,
559 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
560 ch->retry_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
561 &timeout_closed_cb,
562 ch);
563 }
564 else
565 {
566 GCCH_bind (ch,
567 c);
568 }
569 GNUNET_STATISTICS_update (stats,
570 "# channels",
571 1,
572 GNUNET_NO);
573 return ch;
574}
575
576
577/**
578 * Function called once the tunnel confirms that we sent the
579 * ACK message. Just remembers it was sent, we do not expect
580 * ACKs for ACKs ;-).
581 *
582 * @param cls our `struct CadetChannel`.
583 */
584static void
585send_ack_cb (void *cls)
586{
587 struct CadetChannel *ch = cls;
588
589 ch->last_control_qe = NULL;
590}
591
592
593/**
594 * Compute and send the current ACK to the other peer.
595 *
596 * @param ch channel to send the ACK for
597 */
598static void
599send_channel_ack (struct CadetChannel *ch)
600{
601 struct GNUNET_CADET_ChannelDataAckMessage msg;
602
603 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
604 msg.header.size = htons (sizeof (msg));
605 msg.gid = ch->gid;
606 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid) - 1);
607 msg.futures = GNUNET_htonll (ch->mid_futures);
608 if (NULL != ch->last_control_qe)
609 GCT_send_cancel (ch->last_control_qe);
610 ch->last_control_qe = GCT_send (ch->t,
611 &msg.header,
612 &send_ack_cb,
613 ch);
614}
615
616
617/**
618 * Send our initial ACK to the client confirming that the
619 * connection is up.
620 *
621 * @param cls the `struct CadetChannel`
622 */
623static void
624send_connect_ack (void *cls)
625{
626 struct CadetChannel *ch = cls;
627
628 ch->retry_task = NULL;
629 send_channel_ack (ch);
630}
631
632
633/**
634 * A client is bound to the port that we have a channel
635 * open to. Send the acknowledgement for the connection
636 * request and establish the link with the client.
637 *
638 * @param ch open incoming channel
639 * @param c client listening on the respective port
640 */
641void
642GCCH_bind (struct CadetChannel *ch,
643 struct CadetClient *c)
644{
645 uint32_t options;
646
647 if (NULL != ch->retry_task)
648 {
649 /* there might be a timeout task here */
650 GNUNET_SCHEDULER_cancel (ch->retry_task);
651 ch->retry_task = NULL;
652 }
653 options = 0;
654 if (ch->nobuffer)
655 options |= GNUNET_CADET_OPTION_NOBUFFER;
656 if (ch->reliable)
657 options |= GNUNET_CADET_OPTION_RELIABLE;
658 if (ch->out_of_order)
659 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
660 ch->dest = c;
661 ch->lid = GSC_bind (c,
662 ch,
663 GCT_get_destination (ch->t),
664 &ch->port,
665 options);
666 ch->mid_recv.mid = htonl (1); /* The CONNECT counts as message 0! */
667
668 /* notify other peer that we accepted the connection */
669 ch->retry_task = GNUNET_SCHEDULER_add_now (&send_connect_ack,
670 ch);
671}
672
673
674/**
675 * Destroy locally created channel. Called by the
676 * local client, so no need to tell the client.
677 *
678 * @param ch channel to destroy
679 */
680void
681GCCH_channel_local_destroy (struct CadetChannel *ch)
682{
683 if (GNUNET_YES == ch->destroy)
684 {
685 /* other end already destroyed, with the local client gone, no need
686 to finish transmissions, just destroy immediately. */
687 channel_destroy (ch);
688 return;
689 }
690 if (NULL != ch->head_sent)
691 {
692 /* allow send queue to train first */
693 ch->destroy = GNUNET_YES;
694 return;
695 }
696 /* Nothing left to do, just finish destruction */
697 channel_destroy (ch);
698}
699
700
701/**
702 * Destroy channel that was incoming. Called by the
703 * local client, so no need to tell the client.
704 *
705 * @param ch channel to destroy
706 */
707void
708GCCH_channel_incoming_destroy (struct CadetChannel *ch)
709{
710 if (GNUNET_YES == ch->destroy)
711 {
712 /* other end already destroyed, with the remote client gone, no need
713 to finish transmissions, just destroy immediately. */
714 channel_destroy (ch);
715 return;
716 }
717 if (NULL != ch->head_recv)
718 {
719 /* allow local client to see all data first */
720 ch->destroy = GNUNET_YES;
721 return;
722 }
723 /* Nothing left to do, just finish destruction */
724 channel_destroy (ch);
725}
726
727
728/**
729 * Destroy channel, based on the other peer closing the
730 * connection. Also needs to remove this channel from
731 * the tunnel.
732 *
733 * FIXME: need to make it possible to defer destruction until we have
734 * received all messages up to the destroy, and right now the destroy
735 * message (and this API) fails to give is the information we need!
736 *
737 * FIXME: also need to know if the other peer got a destroy from
738 * us before!
739 *
740 * @param ch channel to destroy
741 */
742void
743GCCH_channel_remote_destroy (struct CadetChannel *ch)
744{
745 GNUNET_break (0); // FIXME!
746}
747
748
749/**
750 * Function called once the tunnel has sent one of our messages.
751 * If the message is unreliable, simply frees the `crm`. If the
752 * message was reliable, calculate retransmission time and
753 * wait for ACK (or retransmit).
754 *
755 * @param cls the `struct CadetReliableMessage` that was sent
756 */
757static void
758data_sent_cb (void *cls);
759
760
761/**
762 * We need to retry a transmission, the last one took too long to
763 * be acknowledged.
764 *
765 * @param cls the `struct CadetChannel` where we need to retransmit
766 */
767static void
768retry_transmission (void *cls)
769{
770 struct CadetChannel *ch = cls;
771 struct CadetReliableMessage *crm = ch->head_sent;
772
773 GNUNET_assert (NULL == crm->qe);
774 crm->qe = GCT_send (ch->t,
775 &crm->data_message.header,
776 &data_sent_cb,
777 crm);
778}
779
780
781/**
782 * Check if we can now allow the client to transmit, and if so,
783 * let the client know about it.
784 *
785 * @param ch channel to check
786 */
787static void
788GCCH_check_allow_client (struct CadetChannel *ch)
789{
790 struct GNUNET_MQ_Envelope *env;
791 struct GNUNET_CADET_LocalAck *msg;
792
793 if (GNUNET_YES == ch->client_allowed)
794 return; /* client already allowed! */
795 if (CADET_CHANNEL_READY != ch->state)
796 {
797 /* destination did not yet ACK our CREATE! */
798 LOG (GNUNET_ERROR_TYPE_DEBUG,
799 "Channel %s not yet ready, throttling client until ACK.\n",
800 GCCH_2s (ch));
801 return;
802 }
803 if (ch->pending_messages > ch->max_pending_messages)
804 {
805 /* Too many messages in queue. */
806 LOG (GNUNET_ERROR_TYPE_DEBUG,
807 "Message queue still too long on channel %s, throttling client until ACK.\n",
808 GCCH_2s (ch));
809 return;
810 }
811 if ( (NULL != ch->head_sent) &&
812 (64 <= ntohl (ch->mid_send.mid) - ntohl (ch->head_sent->data_message.mid.mid)) )
813 {
814 LOG (GNUNET_ERROR_TYPE_DEBUG,
815 "Gap in ACKs too big on channel %s, throttling client until ACK.\n",
816 GCCH_2s (ch));
817 return;
818 }
819 ch->client_allowed = GNUNET_YES;
820
821
822 LOG (GNUNET_ERROR_TYPE_DEBUG,
823 "Sending local ack to channel %s client\n",
824 GCCH_2s (ch));
825 env = GNUNET_MQ_msg (msg,
826 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
827 msg->channel_id = ch->lid;
828 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
829 env);
830}
831
832
833/**
834 * Function called once the tunnel has sent one of our messages.
835 * If the message is unreliable, simply frees the `crm`. If the
836 * message was reliable, calculate retransmission time and
837 * wait for ACK (or retransmit).
838 *
839 * @param cls the `struct CadetReliableMessage` that was sent
840 */
841static void
842data_sent_cb (void *cls)
843{
844 struct CadetReliableMessage *crm = cls;
845 struct CadetChannel *ch = crm->ch;
846 struct CadetReliableMessage *off;
847
848 crm->qe = NULL;
849 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
850 ch->tail_sent,
851 crm);
852 if (GNUNET_NO == ch->reliable)
853 {
854 GNUNET_free (crm);
855 ch->pending_messages--;
856 GCCH_check_allow_client (ch);
857 return;
858 }
859 if (0 == crm->retry_delay.rel_value_us)
860 crm->retry_delay = ch->expected_delay;
861 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
862
863 /* find position for re-insertion into the DLL */
864 if ( (NULL == ch->head_sent) ||
865 (crm->next_retry.abs_value_us < ch->head_sent->next_retry.abs_value_us) )
866 {
867 /* insert at HEAD, also (re)schedule retry task! */
868 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
869 ch->tail_sent,
870 crm);
871 if (NULL != ch->retry_task)
872 GNUNET_SCHEDULER_cancel (ch->retry_task);
873 ch->retry_task = GNUNET_SCHEDULER_add_delayed (crm->retry_delay,
874 &retry_transmission,
875 ch);
876 return;
877 }
878 for (off = ch->head_sent; NULL != off; off = off->next)
879 if (crm->next_retry.abs_value_us < off->next_retry.abs_value_us)
880 break;
881 if (NULL == off)
882 {
883 /* insert at tail */
884 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent,
885 ch->tail_sent,
886 crm);
887 }
888 else
889 {
890 /* insert before off */
891 GNUNET_CONTAINER_DLL_insert_after (ch->head_sent,
892 ch->tail_sent,
893 off->prev,
894 crm);
895 }
896}
897
898
899/**
900 * Handle data given by a client.
901 *
902 * Check whether the client is allowed to send in this tunnel, save if
903 * channel is reliable and send an ACK to the client if there is still
904 * buffer space in the tunnel.
905 *
906 * @param ch Channel.
907 * @param message payload to transmit.
908 * @return #GNUNET_OK if everything goes well,
909 * #GNUNET_SYSERR in case of an error.
910 */
911int
912GCCH_handle_local_data (struct CadetChannel *ch,
913 const struct GNUNET_MessageHeader *message)
914{
915 uint16_t payload_size = ntohs (message->size);
916 struct CadetReliableMessage *crm;
917
918 if (GNUNET_NO == ch->client_allowed)
919 {
920 GNUNET_break_op (0);
921 return GNUNET_SYSERR;
922 }
923 ch->client_allowed = GNUNET_NO;
924 ch->pending_messages++;
925
926 /* Everything is correct, send the message. */
927 crm = GNUNET_malloc (sizeof (*crm) + payload_size);
928 crm->ch = ch;
929 crm->data_message.header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + payload_size);
930 crm->data_message.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
931 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
932 crm->data_message.mid = ch->mid_send;
933 crm->data_message.gid = ch->gid;
934 GNUNET_memcpy (&crm[1],
935 message,
936 payload_size);
937 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
938 ch->tail_sent,
939 crm);
940 LOG (GNUNET_ERROR_TYPE_DEBUG,
941 "Sending %u bytes from local client to channel %s\n",
942 payload_size,
943 GCCH_2s (ch));
944 crm->qe = GCT_send (ch->t,
945 &crm->data_message.header,
946 &data_sent_cb,
947 crm);
948 GCCH_check_allow_client (ch);
949 return GNUNET_OK;
950}
951
952
953/**
954 * Try to deliver messages to the local client, if it is ready for more.
955 *
956 * @param ch channel to process
957 */
958static void
959send_client_buffered_data (struct CadetChannel *ch)
960{
961 struct CadetOutOfOrderMessage *com;
962
963 if (GNUNET_NO == ch->client_ready)
964 return; /* client not ready */
965 com = ch->head_recv;
966 if (NULL == com)
967 return; /* none pending */
968 if ( (com->mid.mid != ch->mid_recv.mid) &&
969 (GNUNET_NO == ch->out_of_order) )
970 return; /* missing next one in-order */
971
972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
973 "Passing payload message to client on channel %s\n",
974 GCCH_2s (ch));
975
976 /* all good, pass next message to client */
977 GNUNET_CONTAINER_DLL_remove (ch->head_recv,
978 ch->tail_recv,
979 com);
980 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
981 ch->mid_futures >>= 1; /* equivalent to division by 2 */
982 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
983 com->env);
984 GNUNET_free (com);
985 if ( (0xFFULL == (ch->mid_futures & 0xFFULL)) &&
986 (GNUNET_YES == ch->reliable) )
987 {
988 /* The next 15 messages were also already received (0xFF), this
989 suggests that the sender may be blocked on flow control
990 urgently waiting for an ACK from us. (As we have an inherent
991 maximum of 64 bits, and 15 is getting too close for comfort.)
992 So we should send one now. */
993 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
994 "Sender on channel %s likely blocked on flow-control, sending ACK now.\n",
995 GCCH_2s (ch));
996 if (GNUNET_YES == ch->reliable)
997 send_channel_ack (ch);
998 }
999
1000 if (NULL != ch->head_recv)
1001 return;
1002 if (GNUNET_NO == ch->destroy)
1003 return;
1004 channel_destroy (ch);
1005}
1006
1007
1008/**
1009 * Handle ACK from client on local channel.
1010 *
1011 * @param ch channel to destroy
1012 */
1013void
1014GCCH_handle_local_ack (struct CadetChannel *ch)
1015{
1016 ch->client_ready = GNUNET_YES;
1017 send_client_buffered_data (ch);
1018}
1019
1020
1021#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
1022
1023
1024/**
1025 * Log channel info.
1026 *
1027 * @param ch Channel.
1028 * @param level Debug level to use.
1029 */
1030void
1031GCCH_debug (struct CadetChannel *ch,
1032 enum GNUNET_ErrorType level)
1033{
1034 int do_log;
1035
1036 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1037 "cadet-chn",
1038 __FILE__, __FUNCTION__, __LINE__);
1039 if (0 == do_log)
1040 return;
1041
1042 if (NULL == ch)
1043 {
1044 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1045 return;
1046 }
1047 LOG2 (level,
1048 "CHN Channel %s:%X (%p)\n",
1049 GCT_2s (ch->t),
1050 ch->gid,
1051 ch);
1052 if (NULL != ch->owner)
1053 {
1054 LOG2 (level,
1055 "CHN origin %s ready %s local-id: %u\n",
1056 GSC_2s (ch->owner),
1057 ch->client_ready ? "YES" : "NO",
1058 ntohl (ch->lid.channel_of_client));
1059 }
1060 if (NULL != ch->dest)
1061 {
1062 LOG2 (level,
1063 "CHN destination %s ready %s local-id: %u\n",
1064 GSC_2s (ch->dest),
1065 ch->client_ready ? "YES" : "NO",
1066 ntohl (ch->lid.channel_of_client));
1067 }
1068 LOG2 (level,
1069 "CHN Message IDs recv: %d (%LLX), send: %d\n",
1070 ntohl (ch->mid_recv.mid),
1071 (unsigned long long) ch->mid_futures,
1072 ntohl (ch->mid_send.mid));
1073}
1074
1075
1076
1077/* end of gnunet-service-cadet-new_channel.c */
diff --git a/src/cadet/gnunet-service-cadet-new_channel.h b/src/cadet/gnunet-service-cadet-new_channel.h
new file mode 100644
index 000000000..8caa254d1
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_channel.h
@@ -0,0 +1,191 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_channel.h
24 * @brief GNUnet CADET service with encryption
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#ifndef GNUNET_SERVICE_CADET_CHANNEL_H
29#define GNUNET_SERVICE_CADET_CHANNEL_H
30
31#include "gnunet-service-cadet-new.h"
32#include "gnunet-service-cadet-new_peer.h"
33
34
35/**
36 * A channel is a bidirectional connection between two CADET
37 * clients. Communiation can be reliable, unreliable, in-order
38 * or out-of-order. One client is the "local" client, this
39 * one initiated the connection. The other client is the
40 * "incoming" client, this one listened on a port to accept
41 * the connection from the "local" client.
42 */
43struct CadetChannel;
44
45
46/**
47 * Get the static string for identification of the channel.
48 *
49 * @param ch Channel.
50 *
51 * @return Static string with the channel IDs.
52 */
53const char *
54GCCH_2s (const struct CadetChannel *ch);
55
56
57/**
58 * Log channel info.
59 *
60 * @param ch Channel.
61 * @param level Debug level to use.
62 */
63void
64GCCH_debug (struct CadetChannel *ch,
65 enum GNUNET_ErrorType level);
66
67
68/**
69 * Get the channel's public ID.
70 *
71 * @param ch Channel.
72 *
73 * @return ID used to identify the channel with the remote peer.
74 */
75struct GNUNET_CADET_ChannelTunnelNumber
76GCCH_get_id (const struct CadetChannel *ch);
77
78
79/**
80 * Create a new channel.
81 *
82 * @param owner local client owning the channel
83 * @param owner_id local chid of this channel at the @a owner
84 * @param destination peer to which we should build the channel
85 * @param port desired port at @a destination
86 * @param options options for the channel
87 * @return handle to the new channel
88 */
89struct CadetChannel *
90GCCH_channel_local_new (struct CadetClient *owner,
91 struct GNUNET_CADET_ClientChannelNumber owner_id,
92 struct CadetPeer *destination,
93 const struct GNUNET_HashCode *port,
94 uint32_t options);
95
96
97/**
98 * A client is bound to the port that we have a channel
99 * open to. Send the acknowledgement for the connection
100 * request and establish the link with the client.
101 *
102 * @param ch open incoming channel
103 * @param c client listening on the respective port
104 */
105void
106GCCH_bind (struct CadetChannel *ch,
107 struct CadetClient *c);
108
109
110
111/**
112 * Destroy locally created channel. Called by the
113 * local client, so no need to tell the client.
114 *
115 * @param ch channel to destroy
116 */
117void
118GCCH_channel_local_destroy (struct CadetChannel *ch);
119
120
121/**
122 * Create a new channel.
123 *
124 * @param t tunnel to the remote peer
125 * @param gid identifier of this channel in the tunnel
126 * @param origin peer to who initiated the channel
127 * @param port desired local port
128 * @param options options for the channel
129 * @return handle to the new channel
130 */
131struct CadetChannel *
132GCCH_channel_incoming_new (struct CadetTunnel *t,
133 struct GNUNET_CADET_ChannelTunnelNumber gid,
134 const struct GNUNET_HashCode *port,
135 uint32_t options);
136
137
138/**
139 * Destroy channel that was incoming. Called by the
140 * local client, so no need to tell the client.
141 *
142 * @param ch channel to destroy
143 */
144void
145GCCH_channel_incoming_destroy (struct CadetChannel *ch);
146
147
148/**
149 * Destroy channel, based on the other peer closing the
150 * connection. Also needs to remove this channel from
151 * the tunnel.
152 *
153 * FIXME: need to make it possible to defer destruction until we have
154 * received all messages up to the destroy, and right now the destroy
155 * message (and this API) fails to give is the information we need!
156 *
157 * FIXME: also need to know if the other peer got a destroy from
158 * us before!
159 *
160 * @param ch channel to destroy
161 */
162void
163GCCH_channel_remote_destroy (struct CadetChannel *ch);
164
165
166/**
167 * Handle data given by a client.
168 *
169 * Check whether the client is allowed to send in this tunnel, save if
170 * channel is reliable and send an ACK to the client if there is still
171 * buffer space in the tunnel.
172 *
173 * @param ch Channel.
174 * @param message payload to transmit.
175 * @return #GNUNET_OK if everything goes well,
176 * #GNUNET_SYSERR in case of an error.
177 */
178int
179GCCH_handle_local_data (struct CadetChannel *ch,
180 const struct GNUNET_MessageHeader *message);
181
182
183/**
184 * Handle ACK from client on local channel.
185 *
186 * @param ch channel to destroy
187 */
188void
189GCCH_handle_local_ack (struct CadetChannel *ch);
190
191#endif
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c
new file mode 100644
index 000000000..bf88d78e1
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_connection.c
@@ -0,0 +1,665 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_connection.c
24 * @brief management of CORE-level end-to-end connections; establishes
25 * end-to-end routes and transmits messages along the route
26 * @author Bartlomiej Polot
27 * @author Christian Grothoff
28 *
29 * TODO:
30 * - keepalive messages
31 * - keep performance metrics (?)
32 */
33#include "platform.h"
34#include "gnunet-service-cadet-new_channel.h"
35#include "gnunet-service-cadet-new_connection.h"
36#include "gnunet-service-cadet-new_paths.h"
37#include "gnunet-service-cadet-new_peer.h"
38#include "gnunet-service-cadet-new_tunnels.h"
39#include "gnunet_cadet_service.h"
40#include "cadet_protocol.h"
41
42
43/**
44 * All the states a connection can be in.
45 */
46enum CadetConnectionState
47{
48 /**
49 * Uninitialized status, we have not yet even gotten the message queue.
50 */
51 CADET_CONNECTION_NEW,
52
53 /**
54 * Connection create message in queue, awaiting transmission by CORE.
55 */
56 CADET_CONNECTION_SENDING_CREATE,
57
58 /**
59 * Connection create message sent, waiting for ACK.
60 */
61 CADET_CONNECTION_SENT,
62
63 /**
64 * We are an inbound connection, and received a CREATE. Need to
65 * send an CREATE_ACK back.
66 */
67 CADET_CONNECTION_CREATE_RECEIVED,
68
69 /**
70 * Connection confirmed, ready to carry traffic.
71 */
72 CADET_CONNECTION_READY
73
74};
75
76
77/**
78 * Low-level connection to a destination.
79 */
80struct CadetConnection
81{
82
83 /**
84 * ID of the connection.
85 */
86 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
87
88 /**
89 * To which peer does this connection go?
90 */
91 struct CadetPeer *destination;
92
93 /**
94 * Which tunnel is using this connection?
95 */
96 struct CadetTConnection *ct;
97
98 /**
99 * Path we are using to our destination.
100 */
101 struct CadetPeerPath *path;
102
103 /**
104 * Pending message, NULL if we are ready to transmit.
105 */
106 struct GNUNET_MQ_Envelope *env;
107
108 /**
109 * Handle for calling #GCP_request_mq_cancel() once we are finished.
110 */
111 struct GCP_MessageQueueManager *mq_man;
112
113 /**
114 * Task for connection maintenance.
115 */
116 struct GNUNET_SCHEDULER_Task *task;
117
118 /**
119 * Function to call once we are ready to transmit.
120 */
121 GCC_ReadyCallback ready_cb;
122
123 /**
124 * Closure for @e ready_cb.
125 */
126 void *ready_cb_cls;
127
128 /**
129 * How long do we wait before we try again with a CREATE message?
130 */
131 struct GNUNET_TIME_Relative retry_delay;
132
133 /**
134 * State of the connection.
135 */
136 enum CadetConnectionState state;
137
138 /**
139 * Offset of our @e destination in @e path.
140 */
141 unsigned int off;
142
143 /**
144 * Are we ready to transmit via @e mq_man right now?
145 */
146 int mqm_ready;
147
148};
149
150
151/**
152 * Destroy a connection.
153 *
154 * @param cc connection to destroy
155 */
156void
157GCC_destroy (struct CadetConnection *cc)
158{
159 struct GNUNET_MQ_Envelope *env = NULL;
160
161 if (CADET_CONNECTION_SENDING_CREATE != cc->state)
162 {
163 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
164
165 /* Need to notify next hop that we are down. */
166 env = GNUNET_MQ_msg (destroy_msg,
167 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
168 destroy_msg->cid = cc->cid;
169 }
170 GCP_request_mq_cancel (cc->mq_man,
171 env);
172 cc->mq_man = NULL;
173 GCPP_del_connection (cc->path,
174 cc->off,
175 cc);
176 GNUNET_assert (GNUNET_YES ==
177 GNUNET_CONTAINER_multishortmap_remove (connections,
178 &GCC_get_id (cc)->connection_of_tunnel,
179 cc));
180 GNUNET_free (cc);
181}
182
183
184/**
185 * Return the tunnel associated with this connection.
186 *
187 * @param cc connection to query
188 * @return corresponding entry in the tunnel's connection list
189 */
190struct CadetTConnection *
191GCC_get_ct (struct CadetConnection *cc)
192{
193 return cc->ct;
194}
195
196
197/**
198 * A connection ACK was received for this connection, implying
199 * that the end-to-end connection is up. Process it.
200 *
201 * @param cc the connection that got the ACK.
202 */
203void
204GCC_handle_connection_ack (struct CadetConnection *cc)
205{
206 if (NULL != cc->task)
207 {
208 GNUNET_SCHEDULER_cancel (cc->task);
209 cc->task = NULL;
210 }
211#if FIXME_KEEPALIVE
212 cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period,
213 &send_keepalive,
214 cc);
215#endif
216 cc->state = CADET_CONNECTION_READY;
217 if (GNUNET_YES == cc->mqm_ready)
218 cc->ready_cb (cc->ready_cb_cls,
219 GNUNET_YES);
220}
221
222
223/**
224 * Handle KX message.
225 *
226 * @param cc connection that received encrypted message
227 * @param msg the key exchange message
228 */
229void
230GCC_handle_kx (struct CadetConnection *cc,
231 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
232{
233 if (CADET_CONNECTION_SENT == cc->state)
234 {
235 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
236 clearly something is working, so pretend we got an ACK. */
237 GCC_handle_connection_ack (cc);
238 }
239 GCT_handle_kx (cc->ct,
240 msg);
241}
242
243
244/**
245 * Handle encrypted message.
246 *
247 * @param cc connection that received encrypted message
248 * @param msg the encrypted message to decrypt
249 */
250void
251GCC_handle_encrypted (struct CadetConnection *cc,
252 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
253{
254 if (CADET_CONNECTION_SENT == cc->state)
255 {
256 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
257 clearly something is working, so pretend we got an ACK. */
258 GCC_handle_connection_ack (cc);
259 }
260 GCT_handle_encrypted (cc->ct,
261 msg);
262}
263
264
265/**
266 * Send a CREATE message to the first hop.
267 *
268 * @param cls the `struct CadetConnection` to initiate
269 */
270static void
271send_create (void *cls)
272{
273 struct CadetConnection *cc = cls;
274 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
275 struct GNUNET_PeerIdentity *pids;
276 struct GNUNET_MQ_Envelope *env;
277 unsigned int path_length;
278
279 cc->task = NULL;
280 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
281 path_length = GCPP_get_length (cc->path);
282 env = GNUNET_MQ_msg_extra (create_msg,
283 path_length * sizeof (struct GNUNET_PeerIdentity),
284 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
285 create_msg->cid = cc->cid;
286 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
287 for (unsigned int i=0;i<path_length;i++)
288 pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
289 i));
290 cc->env = env;
291 cc->mqm_ready = GNUNET_NO;
292 cc->state = CADET_CONNECTION_SENT;
293 GCP_send (cc->mq_man,
294 env);
295}
296
297
298/**
299 * Send a CREATE_ACK message towards the origin.
300 *
301 * @param cls the `struct CadetConnection` to initiate
302 */
303static void
304send_create_ack (void *cls)
305{
306 struct CadetConnection *cc = cls;
307 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
308 struct GNUNET_PeerIdentity *pids;
309 struct GNUNET_MQ_Envelope *env;
310 unsigned int path_length;
311
312 cc->task = NULL;
313 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
314 path_length = GCPP_get_length (cc->path);
315 env = GNUNET_MQ_msg_extra (create_msg,
316 path_length * sizeof (struct GNUNET_PeerIdentity),
317 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
318 create_msg->cid = cc->cid;
319 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
320 for (unsigned int i=0;i<path_length;i++)
321 pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
322 i));
323 cc->env = env;
324 cc->mqm_ready = GNUNET_NO;
325 cc->state = CADET_CONNECTION_READY;
326 GCP_send (cc->mq_man,
327 env);
328}
329
330
331/**
332 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
333 * connection that we already have. Either our ACK got lost
334 * or something is fishy. Consider retransmitting the ACK.
335 *
336 * @param cc connection that got the duplicate CREATE
337 */
338void
339GCC_handle_duplicate_create (struct CadetConnection *cc)
340{
341 if (GNUNET_YES == cc->mqm_ready)
342 {
343 /* Tell tunnel that we are not ready for transmission anymore
344 (until CREATE_ACK is done) */
345 cc->ready_cb (cc->ready_cb_cls,
346 GNUNET_NO);
347
348 /* Revert back to the state of having only received the 'CREATE',
349 and immediately proceed to send the CREATE_ACK. */
350 cc->state = CADET_CONNECTION_CREATE_RECEIVED;
351 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
352 cc);
353 }
354 else
355 {
356 /* We are currently sending something else back, which
357 can only be an ACK or payload, either of which would
358 do. So actually no need to do anything. */
359 }
360}
361
362
363/**
364 * There has been a change in the message queue existence for our
365 * peer at the first hop. Adjust accordingly.
366 *
367 * @param cls the `struct CadetConnection`
368 * @param available #GNUNET_YES if sending is now possible,
369 * #GNUNET_NO if sending is no longer possible
370 * #GNUNET_SYSERR if sending is no longer possible
371 * and the last envelope was discarded
372 */
373static void
374manage_first_hop_mq (void *cls,
375 int available)
376{
377 struct CadetConnection *cc = cls;
378
379 if (GNUNET_YES != available)
380 {
381 /* Connection is down, for now... */
382 cc->mqm_ready = GNUNET_NO;
383 cc->state = CADET_CONNECTION_NEW;
384 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
385 if (NULL != cc->task)
386 {
387 GNUNET_SCHEDULER_cancel (cc->task);
388 cc->task = NULL;
389 }
390 cc->ready_cb (cc->ready_cb_cls,
391 GNUNET_NO);
392 return;
393 }
394
395 cc->mqm_ready = GNUNET_YES;
396 switch (cc->state)
397 {
398 case CADET_CONNECTION_NEW:
399 /* Transmit immediately */
400 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
401 cc);
402 break;
403 case CADET_CONNECTION_SENDING_CREATE:
404 /* Should not be possible to be called in this state. */
405 GNUNET_assert (0);
406 break;
407 case CADET_CONNECTION_SENT:
408 /* Retry a bit later... */
409 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
410 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
411 &send_create,
412 cc);
413 break;
414 case CADET_CONNECTION_CREATE_RECEIVED:
415 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
416 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
417 cc);
418 break;
419 case CADET_CONNECTION_READY:
420 cc->ready_cb (cc->ready_cb_cls,
421 GNUNET_YES);
422 break;
423 }
424}
425
426
427/**
428 * Create a connection to @a destination via @a path and notify @a cb
429 * whenever we are ready for more data. Shared logic independent of
430 * who is initiating the connection.
431 *
432 * @param destination where to go
433 * @param path which path to take (may not be the full path)
434 * @param ct which tunnel uses this connection
435 * @param init_state initial state for the connection
436 * @param ready_cb function to call when ready to transmit
437 * @param ready_cb_cls closure for @a cb
438 * @return handle to the connection
439 */
440static struct CadetConnection *
441connection_create (struct CadetPeer *destination,
442 struct CadetPeerPath *path,
443 struct CadetTConnection *ct,
444 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
445 enum CadetConnectionState init_state,
446 GCC_ReadyCallback ready_cb,
447 void *ready_cb_cls)
448{
449 struct CadetConnection *cc;
450 struct CadetPeer *first_hop;
451 unsigned int off;
452
453 off = GCPP_find_peer (path,
454 destination);
455 GNUNET_assert (UINT_MAX > off);
456 cc = GNUNET_new (struct CadetConnection);
457 cc->state = init_state;
458 cc->ct = ct;
459 cc->cid = *cid;
460 GNUNET_assert (GNUNET_OK ==
461 GNUNET_CONTAINER_multishortmap_put (connections,
462 &GCC_get_id (cc)->connection_of_tunnel,
463 cc,
464 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
465 cc->ready_cb = ready_cb;
466 cc->ready_cb_cls = ready_cb_cls;
467 cc->path = path;
468 cc->off = off;
469 GCPP_add_connection (path,
470 off,
471 cc);
472 for (unsigned int i=0;i<off;i++)
473 GCP_add_connection (GCPP_get_peer_at_offset (path,
474 off),
475 cc);
476
477 first_hop = GCPP_get_peer_at_offset (path,
478 0);
479 cc->mq_man = GCP_request_mq (first_hop,
480 &manage_first_hop_mq,
481 cc);
482 return cc;
483}
484
485
486/**
487 * Create a connection to @a destination via @a path and
488 * notify @a cb whenever we are ready for more data. This
489 * is an inbound tunnel, so we must use the existing @a cid
490 *
491 * @param destination where to go
492 * @param path which path to take (may not be the full path)
493 * @param ct which tunnel uses this connection
494 * @param ready_cb function to call when ready to transmit
495 * @param ready_cb_cls closure for @a cb
496 * @return handle to the connection
497 */
498struct CadetConnection *
499GCC_create_inbound (struct CadetPeer *destination,
500 struct CadetPeerPath *path,
501 struct CadetTConnection *ct,
502 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
503 GCC_ReadyCallback ready_cb,
504 void *ready_cb_cls)
505{
506 return connection_create (destination,
507 path,
508 ct,
509 cid,
510 CADET_CONNECTION_CREATE_RECEIVED,
511 ready_cb,
512 ready_cb_cls);
513}
514
515
516/**
517 * Create a connection to @a destination via @a path and
518 * notify @a cb whenever we are ready for more data.
519 *
520 * @param destination where to go
521 * @param path which path to take (may not be the full path)
522 * @param ct tunnel that uses the connection
523 * @param ready_cb function to call when ready to transmit
524 * @param ready_cb_cls closure for @a cb
525 * @return handle to the connection
526 */
527struct CadetConnection *
528GCC_create (struct CadetPeer *destination,
529 struct CadetPeerPath *path,
530 struct CadetTConnection *ct,
531 GCC_ReadyCallback ready_cb,
532 void *ready_cb_cls)
533{
534 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
535
536 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
537 &cid,
538 sizeof (cid));
539 return connection_create (destination,
540 path,
541 ct,
542 &cid,
543 CADET_CONNECTION_NEW,
544 ready_cb,
545 ready_cb_cls);
546}
547
548
549/**
550 * Transmit message @a msg via connection @a cc. Must only be called
551 * (once) after the connection has signalled that it is ready via the
552 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
553 * connection is right now ready for transmission.
554 *
555 * @param cc connection identification
556 * @param env envelope with message to transmit; must NOT
557 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
558 */
559void
560GCC_transmit (struct CadetConnection *cc,
561 struct GNUNET_MQ_Envelope *env)
562{
563 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
564 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
565 cc->mqm_ready = GNUNET_NO;
566 GCP_send (cc->mq_man,
567 env);
568}
569
570
571/**
572 * Obtain the path used by this connection.
573 *
574 * @param cc connection
575 * @return path to @a cc
576 */
577struct CadetPeerPath *
578GCC_get_path (struct CadetConnection *cc)
579{
580 return cc->path;
581}
582
583
584/**
585 * Obtain unique ID for the connection.
586 *
587 * @param cc connection.
588 * @return unique number of the connection
589 */
590const struct GNUNET_CADET_ConnectionTunnelIdentifier *
591GCC_get_id (struct CadetConnection *cc)
592{
593 return &cc->cid;
594}
595
596
597/**
598 * Get a (static) string for a connection.
599 *
600 * @param cc Connection.
601 */
602const char *
603GCC_2s (const struct CadetConnection *cc)
604{
605 static char buf[128];
606
607 if (NULL == cc)
608 return "Connection(NULL)";
609
610 if (NULL != cc->ct)
611 {
612 GNUNET_snprintf (buf,
613 sizeof (buf),
614 "Connection(%s(Tunnel(%s)))",
615 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
616 GCT_2s (cc->ct->t));
617 return buf;
618 }
619 GNUNET_snprintf (buf,
620 sizeof (buf),
621 "Connection(%s(Tunnel(NULL)))",
622 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
623 return buf;
624}
625
626
627#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
628
629
630/**
631 * Log connection info.
632 *
633 * @param cc connection
634 * @param level Debug level to use.
635 */
636void
637GCC_debug (struct CadetConnection *cc,
638 enum GNUNET_ErrorType level)
639{
640 int do_log;
641 char *s;
642
643 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
644 "cadet-con",
645 __FILE__, __FUNCTION__, __LINE__);
646 if (0 == do_log)
647 return;
648 if (NULL == cc)
649 {
650 LOG2 (level,
651 "Connection (NULL)\n");
652 return;
653 }
654 s = GCPP_2s (cc->path);
655 LOG2 (level,
656 "Connection %s to %s via path %s in state %d is %s\n",
657 GCC_2s (cc),
658 GCP_2s (cc->destination),
659 s,
660 cc->state,
661 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
662 GNUNET_free (s);
663}
664
665/* end of gnunet-service-cadet-new_connection.c */
diff --git a/src/cadet/gnunet-service-cadet-new_connection.h b/src/cadet/gnunet-service-cadet-new_connection.h
new file mode 100644
index 000000000..99426776d
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_connection.h
@@ -0,0 +1,196 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_connection.h
24 * @brief
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#ifndef GNUNET_SERVICE_CADET_CONNECTION_H
29#define GNUNET_SERVICE_CADET_CONNECTION_H
30
31#include "gnunet_util_lib.h"
32#include "gnunet-service-cadet-new.h"
33#include "gnunet-service-cadet-new_peer.h"
34#include "cadet_protocol.h"
35
36
37/**
38 * Function called to notify tunnel about change in our readyness.
39 *
40 * @param cls closure
41 * @param is_ready #GNUNET_YES if the connection is now ready for transmission,
42 * #GNUNET_NO if the connection is no longer ready for transmission
43 */
44typedef void
45(*GCC_ReadyCallback)(void *cls,
46 int is_ready);
47
48
49/**
50 * Destroy a connection.
51 *
52 * @param cc connection to destroy
53 */
54void
55GCC_destroy (struct CadetConnection *cc);
56
57
58/**
59 * Create a connection to @a destination via @a path and
60 * notify @a cb whenever we are ready for more data.
61 *
62 * @param destination where to go
63 * @param path which path to take (may not be the full path)
64 * @param ct which tunnel uses this connection
65 * @param ready_cb function to call when ready to transmit
66 * @param ready_cb_cls closure for @a cb
67 * @return handle to the connection
68 */
69struct CadetConnection *
70GCC_create (struct CadetPeer *destination,
71 struct CadetPeerPath *path,
72 struct CadetTConnection *ct,
73 GCC_ReadyCallback ready_cb,
74 void *ready_cb_cls);
75
76
77/**
78 * Create a connection to @a destination via @a path and
79 * notify @a cb whenever we are ready for more data. This
80 * is an inbound tunnel, so we must use the existing @a cid
81 *
82 * @param destination where to go
83 * @param path which path to take (may not be the full path)
84 * @param ct which tunnel uses this connection
85 * @param ready_cb function to call when ready to transmit
86 * @param ready_cb_cls closure for @a cb
87 * @return handle to the connection
88 */
89struct CadetConnection *
90GCC_create_inbound (struct CadetPeer *destination,
91 struct CadetPeerPath *path,
92 struct CadetTConnection *ct,
93 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
94 GCC_ReadyCallback ready_cb,
95 void *ready_cb_cls);
96
97
98/**
99 * Transmit message @a msg via connection @a cc. Must only be called
100 * (once) after the connection has signalled that it is ready via the
101 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
102 * connection is right now ready for transmission.
103 *
104 * @param cc connection identification
105 * @param env envelope with message to transmit;
106 * the #GNUNET_MQ_notify_send() must not have yet been used
107 * for the envelope. Also, the message better match the
108 * connection identifier of this connection...
109 */
110void
111GCC_transmit (struct CadetConnection *cc,
112 struct GNUNET_MQ_Envelope *env);
113
114
115/**
116 * An ACK was received for this connection, process it.
117 *
118 * @param cc the connection that got the ACK.
119 */
120void
121GCC_handle_connection_ack (struct CadetConnection *cc);
122
123
124/**
125 * Handle KX message.
126 *
127 * @param cc connection that received encrypted message
128 * @param msg the key exchange message
129 */
130void
131GCC_handle_kx (struct CadetConnection *cc,
132 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
133
134
135/**
136 * Handle encrypted message.
137 *
138 * @param cc connection that received encrypted message
139 * @param msg the encrypted message to decrypt
140 */
141void
142GCC_handle_encrypted (struct CadetConnection *cc,
143 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
144
145
146/**
147 * Return the tunnel associated with this connection.
148 *
149 * @param cc connection to query
150 * @return corresponding entry in the tunnel's connection list
151 */
152struct CadetTConnection *
153GCC_get_ct (struct CadetConnection *cc);
154
155
156/**
157 * Obtain the path used by this connection.
158 *
159 * @param cc connection
160 * @return path to @a cc
161 */
162struct CadetPeerPath *
163GCC_get_path (struct CadetConnection *cc);
164
165
166/**
167 * Obtain unique ID for the connection.
168 *
169 * @param cc connection.
170 * @return unique number of the connection
171 */
172const struct GNUNET_CADET_ConnectionTunnelIdentifier *
173GCC_get_id (struct CadetConnection *cc);
174
175
176/**
177 * Get a (static) string for a connection.
178 *
179 * @param cc Connection.
180 */
181const char *
182GCC_2s (const struct CadetConnection *cc);
183
184
185/**
186 * Log connection info.
187 *
188 * @param cc connection
189 * @param level Debug level to use.
190 */
191void
192GCC_debug (struct CadetConnection *cc,
193 enum GNUNET_ErrorType level);
194
195
196#endif
diff --git a/src/cadet/gnunet-service-cadet-new_core.c b/src/cadet/gnunet-service-cadet-new_core.c
new file mode 100644
index 000000000..9ce4418de
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_core.c
@@ -0,0 +1,903 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet_core.c
23 * @brief cadet service; interaction with CORE service
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
28 *
29 * TODO:
30 * - pass encrypted ACK to connection (!)
31 * - given BROKEN messages, destroy paths (?)
32 * -
33 * - handle POLL (if needed)
34 */
35#include "platform.h"
36#include "gnunet-service-cadet-new_core.h"
37#include "gnunet-service-cadet-new_paths.h"
38#include "gnunet-service-cadet-new_peer.h"
39#include "gnunet-service-cadet-new_connection.h"
40#include "gnunet-service-cadet-new_tunnels.h"
41#include "gnunet_core_service.h"
42#include "cadet_protocol.h"
43
44/**
45 * Number of messages we are willing to buffer per route.
46 */
47#define ROUTE_BUFFER_SIZE 8
48
49
50/**
51 * Information we keep per direction for a route.
52 */
53struct RouteDirection
54{
55 /**
56 * Target peer.
57 */
58 struct CadetPeer *hop;
59
60 /**
61 * Route this direction is part of.
62 */
63 struct CadetRoute *my_route;
64
65 /**
66 * Message queue manager for @e hop.
67 */
68 struct GCP_MessageQueueManager *mqm;
69
70 /**
71 * Cyclic message buffer to @e hop.
72 */
73 struct GNUNET_MQ_Envelope *out_buffer[ROUTE_BUFFER_SIZE];
74
75 /**
76 * Next write offset to use to append messages to @e out_buffer.
77 */
78 unsigned int out_wpos;
79
80 /**
81 * Next read offset to use to retrieve messages from @e out_buffer.
82 */
83 unsigned int out_rpos;
84
85 /**
86 * Is @e mqm currently ready for transmission?
87 */
88 int is_ready;
89
90};
91
92
93/**
94 * Description of a segment of a `struct CadetConnection` at the
95 * intermediate peers. Routes are basically entries in a peer's
96 * routing table for forwarding traffic. At both endpoints, the
97 * routes are terminated by a `struct CadetConnection`, which knows
98 * the complete `struct CadetPath` that is formed by the individual
99 * routes.
100 */
101struct CadetRoute
102{
103
104 /**
105 * Information about the next hop on this route.
106 */
107 struct RouteDirection next;
108
109 /**
110 * Information about the previous hop on this route.
111 */
112 struct RouteDirection prev;
113
114 /**
115 * Unique identifier for the connection that uses this route.
116 */
117 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
118
119 /**
120 * When was this route last in use?
121 */
122 struct GNUNET_TIME_Absolute last_use;
123
124};
125
126
127/**
128 * Handle to the CORE service.
129 */
130static struct GNUNET_CORE_Handle *core;
131
132/**
133 * Routes on which this peer is an intermediate.
134 */
135static struct GNUNET_CONTAINER_MultiShortmap *routes;
136
137
138/**
139 * Get the route corresponding to a hash.
140 *
141 * @param cid hash generated from the connection identifier
142 */
143static struct CadetRoute *
144get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
145{
146 return GNUNET_CONTAINER_multishortmap_get (routes,
147 &cid->connection_of_tunnel);
148}
149
150
151/**
152 * We message @a msg from @a prev. Find its route by @a cid and
153 * forward to the next hop. Drop and signal broken route if we do not
154 * have a route.
155 *
156 * @param prev previous hop (sender)
157 * @param cid connection identifier, tells us which route to use
158 * @param msg the message to forward
159 */
160static void
161route_message (struct CadetPeer *prev,
162 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
163 const struct GNUNET_MessageHeader *msg)
164{
165 struct CadetRoute *route;
166 struct RouteDirection *dir;
167 struct GNUNET_MQ_Envelope *env;
168
169 route = get_route (cid);
170 if (NULL == route)
171 {
172 struct GNUNET_MQ_Envelope *env;
173 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
174
175 env = GNUNET_MQ_msg (bm,
176 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
177 bm->cid = *cid;
178 bm->peer1 = my_full_id;
179 GCP_send_ooo (prev,
180 env);
181 return;
182 }
183 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
184 if (GNUNET_YES == dir->is_ready)
185 {
186 dir->is_ready = GNUNET_NO;
187 GCP_send (dir->mqm,
188 GNUNET_MQ_msg_copy (msg));
189 return;
190 }
191 env = dir->out_buffer[dir->out_wpos];
192 if (NULL != env)
193 {
194 /* Queue full, drop earliest message in queue */
195 GNUNET_assert (dir->out_rpos == dir->out_wpos);
196 GNUNET_MQ_discard (env);
197 dir->out_rpos++;
198 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
199 dir->out_rpos = 0;
200 }
201 env = GNUNET_MQ_msg_copy (msg);
202 dir->out_buffer[dir->out_wpos] = env;
203 dir->out_wpos++;
204 if (ROUTE_BUFFER_SIZE == dir->out_wpos)
205 dir->out_wpos = 0;
206}
207
208
209/**
210 * Check if the create_connection message has the appropriate size.
211 *
212 * @param cls Closure (unused).
213 * @param msg Message to check.
214 *
215 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
216 */
217static int
218check_connection_create (void *cls,
219 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
220{
221 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
222
223 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
224 {
225 GNUNET_break_op (0);
226 return GNUNET_NO;
227 }
228 return GNUNET_YES;
229}
230
231
232/**
233 * Free internal data of a route direction.
234 *
235 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
236 */
237static void
238destroy_direction (struct RouteDirection *dir)
239{
240 for (unsigned int i=0;i<ROUTE_BUFFER_SIZE;i++)
241 if (NULL != dir->out_buffer[i])
242 {
243 GNUNET_MQ_discard (dir->out_buffer[i]);
244 dir->out_buffer[i] = NULL;
245 }
246 if (NULL != dir->mqm)
247 {
248 GCP_request_mq_cancel (dir->mqm,
249 NULL);
250 dir->mqm = NULL;
251 }
252}
253
254
255/**
256 * Destroy our state for @a route.
257 *
258 * @param route route to destroy
259 */
260static void
261destroy_route (struct CadetRoute *route)
262{
263 destroy_direction (&route->prev);
264 destroy_direction (&route->next);
265 GNUNET_free (route);
266}
267
268
269/**
270 * Send message that a route is broken between @a peer1 and @a peer2.
271 *
272 * @param target where to send the message
273 * @param cid connection identifier to use
274 * @param peer1 one of the peers where a link is broken
275 * @param peer2 another one of the peers where a link is broken
276 */
277static void
278send_broken (struct RouteDirection *target,
279 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
280 const struct GNUNET_PeerIdentity *peer1,
281 const struct GNUNET_PeerIdentity *peer2)
282{
283 struct GNUNET_MQ_Envelope *env;
284 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
285
286 env = GNUNET_MQ_msg (bm,
287 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
288 bm->cid = *cid;
289 if (NULL != peer1)
290 bm->peer1 = *peer1;
291 if (NULL != peer2)
292 bm->peer2 = *peer2;
293 GCP_request_mq_cancel (target->mqm,
294 env);
295 target->mqm = NULL;
296}
297
298
299/**
300 * Function called when the message queue to the previous hop
301 * becomes available/unavailable. We expect this function to
302 * be called immediately when we register, and then again
303 * later if the connection ever goes down.
304 *
305 * @param cls the `struct RouteDirection`
306 * @param available #GNUNET_YES if sending is now possible,
307 * #GNUNET_NO if sending is no longer possible
308 * #GNUNET_SYSERR if sending is no longer possible
309 * and the last envelope was discarded
310 */
311static void
312dir_ready_cb (void *cls,
313 int ready)
314{
315 struct RouteDirection *dir = cls;
316 struct CadetRoute *route = dir->my_route;
317 struct RouteDirection *odir;
318
319 if (GNUNET_YES == ready)
320 {
321 struct GNUNET_MQ_Envelope *env;
322
323 dir->is_ready = GNUNET_YES;
324 if (NULL != (env = dir->out_buffer[dir->out_rpos]))
325 {
326 dir->out_buffer[dir->out_rpos] = NULL;
327 dir->out_rpos++;
328 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
329 dir->out_rpos = 0;
330 dir->is_ready = GNUNET_NO;
331 GCP_send (dir->mqm,
332 env);
333 }
334 return;
335 }
336 odir = (dir == &route->next) ? &route->prev : &route->next;
337 send_broken (&route->next,
338 &route->cid,
339 GCP_get_id (odir->hop),
340 &my_full_id);
341 destroy_route (route);
342}
343
344
345/**
346 * Initialize one of the directions of a route.
347 *
348 * @param route route the direction belongs to
349 * @param dir direction to initialize
350 * @param hop next hop on in the @a dir
351 */
352static void
353dir_init (struct RouteDirection *dir,
354 struct CadetRoute *route,
355 struct CadetPeer *hop)
356{
357 dir->hop = hop;
358 dir->my_route = route;
359 dir->mqm = GCP_request_mq (hop,
360 &dir_ready_cb,
361 dir);
362 GNUNET_assert (GNUNET_YES == dir->is_ready);
363}
364
365
366/**
367 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
368 *
369 * @param cls Closure (CadetPeer for neighbor that sent the message).
370 * @param msg Message itself.
371 */
372static void
373handle_connection_create (void *cls,
374 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
375{
376 struct CadetPeer *sender = cls;
377 struct CadetPeer *next;
378 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
379 struct CadetRoute *route;
380 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
381 unsigned int path_length;
382 unsigned int off;
383
384 path_length = size / sizeof (struct GNUNET_PeerIdentity);
385 /* Initiator is at offset 0. */
386 for (off=1;off<path_length;off++)
387 if (0 == memcmp (&my_full_id,
388 &pids[off],
389 sizeof (struct GNUNET_PeerIdentity)))
390 break;
391 if (off == path_length)
392 {
393 /* We are not on the path, bogus request */
394 GNUNET_break_op (0);
395 return;
396 }
397 /* Check previous hop */
398 if (sender != GCP_get (&pids[off - 1],
399 GNUNET_NO))
400 {
401 /* sender is not on the path, not allowed */
402 GNUNET_break_op (0);
403 return;
404 }
405 if (NULL !=
406 get_route (&msg->cid))
407 {
408 /* Duplicate CREATE, pass it on, previous one might have been lost! */
409 route_message (sender,
410 &msg->cid,
411 &msg->header);
412 return;
413 }
414 if (off == path_length - 1)
415 {
416 /* We are the destination, create connection */
417 struct CadetConnection *cc;
418 struct CadetPeerPath *path;
419 struct CadetPeer *origin;
420
421 cc = GNUNET_CONTAINER_multishortmap_get (connections,
422 &msg->cid.connection_of_tunnel);
423 if (NULL != cc)
424 {
425 /* Duplicate CREATE, likely our ACK got lost, retransmit the ACK! */
426 GNUNET_break (0); // FIXME: not implemented!
427 return;
428 }
429
430 path = GCPP_get_path_from_route (path_length,
431 pids);
432 origin = GCP_get (&pids[0],
433 GNUNET_YES);
434 GCT_add_inbound_connection (GCT_create_tunnel (origin),
435 &msg->cid,
436 path);
437 return;
438 }
439 /* We are merely a hop on the way, check if we can support the route */
440 next = GCP_get (&pids[off + 1],
441 GNUNET_NO);
442 if ( (NULL == next) ||
443 (GNUNET_NO == GCP_has_core_connection (next)) )
444 {
445 /* unworkable, send back BROKEN notification */
446 struct GNUNET_MQ_Envelope *env;
447 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
448
449 env = GNUNET_MQ_msg (bm,
450 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
451 bm->cid = msg->cid;
452 bm->peer1 = pids[off + 1];
453 bm->peer2 = my_full_id;
454 GCP_send_ooo (sender,
455 env);
456 return;
457 }
458
459 /* Workable route, create routing entry */
460 route = GNUNET_new (struct CadetRoute);
461 route->cid = msg->cid;
462 dir_init (&route->prev,
463 route,
464 sender);
465 dir_init (&route->next,
466 route,
467 next);
468 GNUNET_assert (GNUNET_OK ==
469 GNUNET_CONTAINER_multishortmap_put (routes,
470 &route->cid.connection_of_tunnel,
471 route,
472 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
473}
474
475
476/**
477 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
478 *
479 * @param cls Closure (CadetPeer for neighbor that sent the message).
480 * @param msg Message itself.
481 */
482static void
483handle_connection_create_ack (void *cls,
484 const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
485{
486 struct CadetPeer *peer = cls;
487 struct CadetConnection *cc;
488
489 /* First, check if ACK belongs to a connection that ends here. */
490 cc = GNUNET_CONTAINER_multishortmap_get (connections,
491 &msg->cid.connection_of_tunnel);
492 if (NULL != cc)
493 {
494 /* verify ACK came from the right direction */
495 struct CadetPeerPath *path = GCC_get_path (cc);
496
497 if (peer !=
498 GCPP_get_peer_at_offset (path,
499 0))
500 {
501 /* received ACK from unexpected direction, ignore! */
502 GNUNET_break_op (0);
503 return;
504 }
505 GCC_handle_connection_ack (cc);
506 return;
507 }
508
509 /* We're just an intermediary peer, route the message along its path */
510 route_message (peer,
511 &msg->cid,
512 &msg->header);
513}
514
515
516/**
517 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
518 *
519 * @param cls Closure (CadetPeer for neighbor that sent the message).
520 * @param msg Message itself.
521 * @deprecated duplicate logic with #handle_destroy(); dedup!
522 */
523static void
524handle_connection_broken (void *cls,
525 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
526{
527 struct CadetPeer *peer = cls;
528 struct CadetConnection *cc;
529 struct CadetRoute *route;
530
531 /* First, check if message belongs to a connection that ends here. */
532 cc = GNUNET_CONTAINER_multishortmap_get (connections,
533 &msg->cid.connection_of_tunnel);
534 if (NULL != cc)
535 {
536 /* verify message came from the right direction */
537 struct CadetPeerPath *path = GCC_get_path (cc);
538
539 if (peer !=
540 GCPP_get_peer_at_offset (path,
541 0))
542 {
543 /* received message from unexpected direction, ignore! */
544 GNUNET_break_op (0);
545 return;
546 }
547 GCC_destroy (cc);
548
549 /* FIXME: also destroy the path up to the specified link! */
550 return;
551 }
552
553 /* We're just an intermediary peer, route the message along its path */
554 route = get_route (&msg->cid);
555 route_message (peer,
556 &msg->cid,
557 &msg->header);
558 destroy_route (route);
559 /* FIXME: also destroy paths we MAY have up to the specified link! */
560}
561
562
563/**
564 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
565 *
566 * @param cls Closure (CadetPeer for neighbor that sent the message).
567 * @param msg Message itself.
568 */
569static void
570handle_connection_destroy (void *cls,
571 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
572{
573 struct CadetPeer *peer = cls;
574 struct CadetConnection *cc;
575 struct CadetRoute *route;
576
577 /* First, check if message belongs to a connection that ends here. */
578 cc = GNUNET_CONTAINER_multishortmap_get (connections,
579 &msg->cid.connection_of_tunnel);
580 if (NULL != cc)
581 {
582 /* verify message came from the right direction */
583 struct CadetPeerPath *path = GCC_get_path (cc);
584
585 if (peer !=
586 GCPP_get_peer_at_offset (path,
587 0))
588 {
589 /* received message from unexpected direction, ignore! */
590 GNUNET_break_op (0);
591 return;
592 }
593 GCC_destroy (cc);
594 return;
595 }
596
597 /* We're just an intermediary peer, route the message along its path */
598 route = get_route (&msg->cid);
599 route_message (peer,
600 &msg->cid,
601 &msg->header);
602 destroy_route (route);
603}
604
605
606/**
607 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_HOP_BY_HOP_ENCRYPTED_ACK.
608 *
609 * @param cls Closure (CadetPeer for neighbor that sent the message).
610 * @param msg Message itself.
611 */
612static void
613handle_hop_by_hop_encrypted_ack (void *cls,
614 const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
615{
616 struct CadetPeer *peer = cls;
617 struct CadetConnection *cc;
618
619 /* First, check if message belongs to a connection that ends here. */
620 cc = GNUNET_CONTAINER_multishortmap_get (connections,
621 &msg->cid.connection_of_tunnel);
622 if (NULL != cc)
623 {
624 /* verify message came from the right direction */
625 struct CadetPeerPath *path = GCC_get_path (cc);
626
627 if (peer !=
628 GCPP_get_peer_at_offset (path,
629 0))
630 {
631 /* received message from unexpected direction, ignore! */
632 GNUNET_break_op (0);
633 return;
634 }
635#if FIXME
636 GCC_handle_ack (peer,
637 msg);
638#endif
639 return;
640 }
641
642 /* We're just an intermediary peer, route the message along its path */
643 route_message (peer,
644 &msg->cid,
645 &msg->header);
646}
647
648
649/**
650 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
651 *
652 * @param cls Closure (CadetPeer for neighbor that sent the message).
653 * @param msg Message itself.
654 */
655static void
656handle_poll (void *cls,
657 const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
658{
659 struct CadetPeer *peer = cls;
660
661#if FIXME
662 GCC_handle_poll (peer,
663 msg);
664#endif
665}
666
667
668/**
669 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
670 *
671 * @param cls Closure (CadetPeer for neighbor that sent the message).
672 * @param msg Message itself.
673 */
674static void
675handle_tunnel_kx (void *cls,
676 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
677{
678 struct CadetPeer *peer = cls;
679 struct CadetConnection *cc;
680
681 /* First, check if message belongs to a connection that ends here. */
682 cc = GNUNET_CONTAINER_multishortmap_get (connections,
683 &msg->cid.connection_of_tunnel);
684 if (NULL != cc)
685 {
686 /* verify message came from the right direction */
687 struct CadetPeerPath *path = GCC_get_path (cc);
688
689 if (peer !=
690 GCPP_get_peer_at_offset (path,
691 0))
692 {
693 /* received message from unexpected direction, ignore! */
694 GNUNET_break_op (0);
695 return;
696 }
697 GCC_handle_kx (cc,
698 msg);
699 return;
700 }
701
702 /* We're just an intermediary peer, route the message along its path */
703 route_message (peer,
704 &msg->cid,
705 &msg->header);
706}
707
708
709/**
710 * Check if the encrypted message has the appropriate size.
711 *
712 * @param cls Closure (unused).
713 * @param msg Message to check.
714 *
715 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
716 */
717static int
718check_tunnel_encrypted (void *cls,
719 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
720{
721 return GNUNET_YES;
722}
723
724
725/**
726 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
727 *
728 * @param cls Closure (CadetPeer for neighbor that sent the message).
729 * @param msg Message itself.
730 */
731static void
732handle_tunnel_encrypted (void *cls,
733 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
734{
735 struct CadetPeer *peer = cls;
736 struct CadetConnection *cc;
737
738 /* First, check if message belongs to a connection that ends here. */
739 cc = GNUNET_CONTAINER_multishortmap_get (connections,
740 &msg->cid.connection_of_tunnel);
741 if (NULL != cc)
742 {
743 /* verify message came from the right direction */
744 struct CadetPeerPath *path = GCC_get_path (cc);
745
746 if (peer !=
747 GCPP_get_peer_at_offset (path,
748 0))
749 {
750 /* received message from unexpected direction, ignore! */
751 GNUNET_break_op (0);
752 return;
753 }
754 GCC_handle_encrypted (cc,
755 msg);
756 return;
757 }
758
759 /* We're just an intermediary peer, route the message along its path */
760 route_message (peer,
761 &msg->cid,
762 &msg->header);
763}
764
765
766/**
767 * Function called after #GNUNET_CORE_connect has succeeded (or failed
768 * for good). Note that the private key of the peer is intentionally
769 * not exposed here; if you need it, your process should try to read
770 * the private key file directly (which should work if you are
771 * authorized...). Implementations of this function must not call
772 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
773 * do this later).
774 *
775 * @param cls closure
776 * @param my_identity ID of this peer, NULL if we failed
777 */
778static void
779core_init_cb (void *cls,
780 const struct GNUNET_PeerIdentity *my_identity)
781{
782 if (NULL == my_identity)
783 {
784 GNUNET_break (0);
785 return;
786 }
787 GNUNET_break (0 ==
788 memcmp (my_identity,
789 &my_full_id,
790 sizeof (struct GNUNET_PeerIdentity)));
791}
792
793
794/**
795 * Method called whenever a given peer connects.
796 *
797 * @param cls closure
798 * @param peer peer identity this notification is about
799 */
800static void *
801core_connect_cb (void *cls,
802 const struct GNUNET_PeerIdentity *peer,
803 struct GNUNET_MQ_Handle *mq)
804{
805 struct CadetPeer *cp;
806
807 cp = GCP_get (peer,
808 GNUNET_YES);
809 GCP_set_mq (cp,
810 mq);
811 return cp;
812}
813
814
815/**
816 * Method called whenever a peer disconnects.
817 *
818 * @param cls closure
819 * @param peer peer identity this notification is about
820 */
821static void
822core_disconnect_cb (void *cls,
823 const struct GNUNET_PeerIdentity *peer,
824 void *peer_cls)
825{
826 struct CadetPeer *cp = peer_cls;
827
828 GCP_set_mq (cp,
829 NULL);
830}
831
832
833/**
834 * Initialize the CORE subsystem.
835 *
836 * @param c Configuration.
837 */
838void
839GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
840{
841 struct GNUNET_MQ_MessageHandler handlers[] = {
842 GNUNET_MQ_hd_var_size (connection_create,
843 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
844 struct GNUNET_CADET_ConnectionCreateMessage,
845 NULL),
846 GNUNET_MQ_hd_fixed_size (connection_create_ack,
847 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
848 struct GNUNET_CADET_ConnectionCreateMessageAckMessage,
849 NULL),
850 GNUNET_MQ_hd_fixed_size (connection_broken,
851 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
852 struct GNUNET_CADET_ConnectionBrokenMessage,
853 NULL),
854 GNUNET_MQ_hd_fixed_size (connection_destroy,
855 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
856 struct GNUNET_CADET_ConnectionDestroyMessage,
857 NULL),
858 GNUNET_MQ_hd_fixed_size (hop_by_hop_encrypted_ack,
859 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
860 struct GNUNET_CADET_ConnectionEncryptedAckMessage,
861 NULL),
862 GNUNET_MQ_hd_fixed_size (poll,
863 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
864 struct GNUNET_CADET_ConnectionHopByHopPollMessage,
865 NULL),
866 GNUNET_MQ_hd_fixed_size (tunnel_kx,
867 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
868 struct GNUNET_CADET_TunnelKeyExchangeMessage,
869 NULL),
870 GNUNET_MQ_hd_var_size (tunnel_encrypted,
871 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
872 struct GNUNET_CADET_TunnelEncryptedMessage,
873 NULL),
874 GNUNET_MQ_handler_end ()
875 };
876
877 routes = GNUNET_CONTAINER_multishortmap_create (1024,
878 GNUNET_NO);
879 core = GNUNET_CORE_connect (c,
880 NULL,
881 &core_init_cb,
882 &core_connect_cb,
883 &core_disconnect_cb,
884 handlers);
885}
886
887
888/**
889 * Shut down the CORE subsystem.
890 */
891void
892GCO_shutdown ()
893{
894 if (NULL != core)
895 {
896 GNUNET_CORE_disconnect (core);
897 core = NULL;
898 }
899 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
900 GNUNET_CONTAINER_multishortmap_destroy (routes);
901}
902
903/* end of gnunet-cadet-service_core.c */
diff --git a/src/cadet/gnunet-service-cadet-new_core.h b/src/cadet/gnunet-service-cadet-new_core.h
new file mode 100644
index 000000000..65b0a6ba5
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_core.h
@@ -0,0 +1,69 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet_core.h
23 * @brief cadet service; interaction with CORE service
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
28 */
29
30#ifndef GNUNET_SERVICE_CADET_CORE_H
31#define GNUNET_SERVICE_CADET_CORE_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "gnunet_util_lib.h"
42
43
44/**
45 * Initialize the CORE subsystem.
46 *
47 * @param c Configuration.
48 */
49void
50GCO_init (const struct GNUNET_CONFIGURATION_Handle *c);
51
52
53/**
54 * Shut down the CORE subsystem.
55 */
56void
57GCO_shutdown (void);
58
59
60#if 0 /* keep Emacsens' auto-indent happy */
61{
62#endif
63#ifdef __cplusplus
64}
65#endif
66
67/* ifndef GNUNET_CADET_SERVICE_CORE_H */
68#endif
69/* end of gnunet-cadet-service_core.h */
diff --git a/src/cadet/gnunet-service-cadet-new_dht.c b/src/cadet/gnunet-service-cadet-new_dht.c
new file mode 100644
index 000000000..3cf3f0301
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_dht.c
@@ -0,0 +1,315 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/gnunet-service-cadet-new_dht.c
22 * @brief Information we track per peer.
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-service-cadet-new.h"
32#include "gnunet-service-cadet-new_dht.h"
33#include "gnunet-service-cadet-new_hello.h"
34#include "gnunet-service-cadet-new_peer.h"
35#include "gnunet-service-cadet-new_paths.h"
36
37#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
38
39
40/**
41 * Handle for DHT searches.
42 */
43struct GCD_search_handle
44{
45 /**
46 * DHT_GET handle.
47 */
48 struct GNUNET_DHT_GetHandle *dhtget;
49
50};
51
52
53/**
54 * Handle to use DHT.
55 */
56static struct GNUNET_DHT_Handle *dht_handle;
57
58/**
59 * How often to PUT own ID in the DHT.
60 */
61static struct GNUNET_TIME_Relative id_announce_time;
62
63/**
64 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
65 */
66static unsigned long long dht_replication_level;
67
68/**
69 * Task to periodically announce itself in the network.
70 */
71static struct GNUNET_SCHEDULER_Task *announce_id_task;
72
73/**
74 * Delay for the next ID announce.
75 */
76static struct GNUNET_TIME_Relative announce_delay;
77
78
79/**
80 * Function to process paths received for a new peer addition. The recorded
81 * paths form the initial tunnel, which can be optimized later.
82 * Called on each result obtained for the DHT search.
83 *
84 * @param cls closure
85 * @param exp when will this value expire
86 * @param key key of the result
87 * @param get_path path of the get request
88 * @param get_path_length lenght of @a get_path
89 * @param put_path path of the put request
90 * @param put_path_length length of the @a put_path
91 * @param type type of the result
92 * @param size number of bytes in data
93 * @param data pointer to the result data
94 */
95static void
96dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
97 const struct GNUNET_HashCode *key,
98 const struct GNUNET_PeerIdentity *get_path,
99 unsigned int get_path_length,
100 const struct GNUNET_PeerIdentity *put_path,
101 unsigned int put_path_length,
102 enum GNUNET_BLOCK_Type type,
103 size_t size,
104 const void *data)
105{
106 const struct GNUNET_HELLO_Message *hello = data;
107 struct CadetPeer *peer;
108
109 GCPP_try_path_from_dht (get_path,
110 get_path_length,
111 put_path,
112 put_path_length);
113 if ( (size >= sizeof (struct GNUNET_HELLO_Message)) &&
114 (ntohs (hello->header.size) == size) &&
115 (size == GNUNET_HELLO_size (hello)) )
116 {
117 peer = GCP_get (&put_path[0],
118 GNUNET_YES);
119 LOG (GNUNET_ERROR_TYPE_DEBUG,
120 "Got HELLO for %s\n",
121 GCP_2s (peer));
122 GCP_set_hello (peer,
123 hello);
124 }
125}
126
127
128/**
129 * Periodically announce self id in the DHT
130 *
131 * @param cls closure
132 */
133static void
134announce_id (void *cls)
135{
136 struct GNUNET_HashCode phash;
137 const struct GNUNET_HELLO_Message *hello;
138 size_t size;
139 struct GNUNET_TIME_Absolute expiration;
140 struct GNUNET_TIME_Relative next_put;
141
142 hello = GCH_get_mine ();
143 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
144 if (0 == size)
145 {
146 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
147 announce_delay);
148 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
149 }
150 else
151 {
152 expiration = GNUNET_HELLO_get_last_expiration (hello);
153 announce_delay = GNUNET_TIME_UNIT_SECONDS;
154 }
155
156 /* Call again in id_announce_time, unless HELLO expires first,
157 * but wait at least 1s. */
158 next_put
159 = GNUNET_TIME_absolute_get_remaining (expiration);
160 next_put
161 = GNUNET_TIME_relative_min (next_put,
162 id_announce_time);
163 next_put
164 = GNUNET_TIME_relative_max (next_put,
165 GNUNET_TIME_UNIT_SECONDS);
166 announce_id_task
167 = GNUNET_SCHEDULER_add_delayed (next_put,
168 &announce_id,
169 cls);
170 GNUNET_STATISTICS_update (stats,
171 "# DHT announce",
172 1,
173 GNUNET_NO);
174 memset (&phash,
175 0,
176 sizeof (phash));
177 GNUNET_memcpy (&phash,
178 &my_full_id,
179 sizeof (my_full_id));
180 LOG (GNUNET_ERROR_TYPE_DEBUG,
181 "Announcing my HELLO (%u bytes) in the DHT\n",
182 size);
183 GNUNET_DHT_put (dht_handle, /* DHT handle */
184 &phash, /* Key to use */
185 dht_replication_level, /* Replication level */
186 GNUNET_DHT_RO_RECORD_ROUTE
187 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
188 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
189 size, /* Size of the data */
190 (const char *) hello, /* Data itself */
191 expiration, /* Data expiration */
192 NULL, /* Continuation */
193 NULL); /* Continuation closure */
194}
195
196
197/**
198 * Initialize the DHT subsystem.
199 *
200 * @param c Configuration.
201 */
202void
203GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
204{
205 LOG (GNUNET_ERROR_TYPE_DEBUG,
206 "init\n");
207 if (GNUNET_OK !=
208 GNUNET_CONFIGURATION_get_value_number (c,
209 "CADET",
210 "DHT_REPLICATION_LEVEL",
211 &dht_replication_level))
212 {
213 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
214 "CADET",
215 "DHT_REPLICATION_LEVEL",
216 "USING DEFAULT");
217 dht_replication_level = 3;
218 }
219
220 if (GNUNET_OK !=
221 GNUNET_CONFIGURATION_get_value_time (c,
222 "CADET",
223 "ID_ANNOUNCE_TIME",
224 &id_announce_time))
225 {
226 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
227 "CADET",
228 "ID_ANNOUNCE_TIME",
229 "MISSING");
230 GNUNET_SCHEDULER_shutdown ();
231 return;
232 }
233
234 dht_handle = GNUNET_DHT_connect (c,
235 64);
236 GNUNET_break (NULL != dht_handle);
237 announce_delay = GNUNET_TIME_UNIT_SECONDS;
238 announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id,
239 NULL);
240}
241
242
243/**
244 * Shut down the DHT subsystem.
245 */
246void
247GCD_shutdown (void)
248{
249 if (NULL != dht_handle)
250 {
251 GNUNET_DHT_disconnect (dht_handle);
252 dht_handle = NULL;
253 }
254 if (NULL != announce_id_task)
255 {
256 GNUNET_SCHEDULER_cancel (announce_id_task);
257 announce_id_task = NULL;
258 }
259}
260
261
262/**
263 * Search DHT for paths to @a peeR_id
264 *
265 * @param peer_id peer to search for
266 * @return handle to abort search
267 */
268struct GCD_search_handle *
269GCD_search (const struct GNUNET_PeerIdentity *peer_id)
270{
271 struct GNUNET_HashCode phash;
272 struct GCD_search_handle *h;
273
274 LOG (GNUNET_ERROR_TYPE_DEBUG,
275 "Starting DHT GET for peer %s\n",
276 GNUNET_i2s (peer_id));
277 GNUNET_STATISTICS_update (stats,
278 "# DHT search",
279 1,
280 GNUNET_NO);
281 memset (&phash,
282 0,
283 sizeof (phash));
284 GNUNET_memcpy (&phash,
285 peer_id,
286 sizeof (*peer_id));
287
288 h = GNUNET_new (struct GCD_search_handle);
289 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
290 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
291 &phash, /* key to search */
292 dht_replication_level, /* replication level */
293 GNUNET_DHT_RO_RECORD_ROUTE |
294 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
295 NULL, /* xquery */
296 0, /* xquery bits */
297 &dht_get_id_handler,
298 h);
299 return h;
300}
301
302
303/**
304 * Stop DHT search started with #GCD_search().
305 *
306 * @param h handle to search to stop
307 */
308void
309GCD_search_stop (struct GCD_search_handle *h)
310{
311 GNUNET_DHT_get_stop (h->dhtget);
312 GNUNET_free (h);
313}
314
315/* end of gnunet-service-cadet_dht.c */
diff --git a/src/cadet/gnunet-service-cadet-new_dht.h b/src/cadet/gnunet-service-cadet-new_dht.h
new file mode 100644
index 000000000..81f16ae99
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_dht.h
@@ -0,0 +1,93 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet_dht.h
23 * @brief cadet service; dealing with DHT requests and results
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCD (Gnunet Cadet Dht)
28 */
29#ifndef GNUNET_SERVICE_CADET_DHT_H
30#define GNUNET_SERVICE_CADET_DHT_H
31
32#ifdef __cplusplus
33extern "C"
34{
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "platform.h"
41#include "gnunet_util_lib.h"
42
43/**
44 * Handle for DHT search operation.
45 */
46struct GCD_search_handle;
47
48
49/**
50 * Initialize the DHT subsystem.
51 *
52 * @param c Configuration.
53 */
54void
55GCD_init (const struct GNUNET_CONFIGURATION_Handle *c);
56
57
58/**
59 * Shut down the DHT subsystem.
60 */
61void
62GCD_shutdown (void);
63
64
65/**
66 * Search DHT for paths to @a peeR_id
67 *
68 * @param peer_id peer to search for
69 * @return handle to abort search
70 */
71struct GCD_search_handle *
72GCD_search (const struct GNUNET_PeerIdentity *peer_id);
73
74
75/**
76 * Stop DHT search started with #GCD_search().
77 *
78 * @param h handle to search to stop
79 */
80void
81GCD_search_stop (struct GCD_search_handle *h);
82
83
84#if 0 /* keep Emacsens' auto-indent happy */
85{
86#endif
87#ifdef __cplusplus
88}
89#endif
90
91/* ifndef GNUNET_CADET_SERVICE_DHT_H */
92#endif
93/* end of gnunet-service-cadet_dht.h */
diff --git a/src/cadet/gnunet-service-cadet-new_hello.c b/src/cadet/gnunet-service-cadet-new_hello.c
new file mode 100644
index 000000000..9d4635021
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_hello.c
@@ -0,0 +1,142 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "platform.h"
22#include "gnunet_util_lib.h"
23
24#include "gnunet_statistics_service.h"
25#include "gnunet_peerinfo_service.h"
26#include "cadet_protocol.h"
27#include "gnunet-service-cadet-new.h"
28#include "gnunet-service-cadet-new_hello.h"
29#include "gnunet-service-cadet-new_peer.h"
30
31#define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__)
32
33/**
34 * Hello message of local peer.
35 */
36static struct GNUNET_HELLO_Message *mine;
37
38/**
39 * Handle to peerinfo service.
40 */
41static struct GNUNET_PEERINFO_Handle *peerinfo;
42
43/**
44 * Iterator context.
45 */
46static struct GNUNET_PEERINFO_NotifyContext* nc;
47
48
49/**
50 * Process each hello message received from peerinfo.
51 *
52 * @param cls Closure (unused).
53 * @param peer Identity of the peer.
54 * @param hello Hello of the peer.
55 * @param err_msg Error message.
56 */
57static void
58got_hello (void *cls,
59 const struct GNUNET_PeerIdentity *id,
60 const struct GNUNET_HELLO_Message *hello,
61 const char *err_msg)
62{
63 struct CadetPeer *peer;
64
65 if ( (NULL == id) ||
66 (NULL == hello) )
67 return;
68 if (0 == memcmp (id,
69 &my_full_id,
70 sizeof (struct GNUNET_PeerIdentity)))
71 {
72 GNUNET_free_non_null (mine);
73 mine = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (&hello->header);
74 return;
75 }
76
77 LOG (GNUNET_ERROR_TYPE_DEBUG,
78 "Hello for %s (%d bytes), expires on %s\n",
79 GNUNET_i2s (id),
80 GNUNET_HELLO_size (hello),
81 GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration (hello)));
82 peer = GCP_get (id,
83 GNUNET_YES);
84 GCP_set_hello (peer,
85 hello);
86
87}
88
89
90/**
91 * Initialize the hello subsystem.
92 *
93 * @param c Configuration.
94 */
95void
96GCH_init (const struct GNUNET_CONFIGURATION_Handle *c)
97{
98 GNUNET_assert (NULL == nc);
99 peerinfo = GNUNET_PEERINFO_connect (c);
100 nc = GNUNET_PEERINFO_notify (c,
101 GNUNET_NO,
102 &got_hello,
103 NULL);
104}
105
106
107/**
108 * Shut down the hello subsystem.
109 */
110void
111GCH_shutdown ()
112{
113 if (NULL != nc)
114 {
115 GNUNET_PEERINFO_notify_cancel (nc);
116 nc = NULL;
117 }
118 if (NULL != peerinfo)
119 {
120 GNUNET_PEERINFO_disconnect (peerinfo);
121 peerinfo = NULL;
122 }
123 if (NULL != mine)
124 {
125 GNUNET_free (mine);
126 mine = NULL;
127 }
128}
129
130
131/**
132 * Get own hello message.
133 *
134 * @return Own hello message.
135 */
136const struct GNUNET_HELLO_Message *
137GCH_get_mine (void)
138{
139 return mine;
140}
141
142/* end of gnunet-service-cadet-new_hello.c */
diff --git a/src/cadet/gnunet-service-cadet-new_hello.h b/src/cadet/gnunet-service-cadet-new_hello.h
new file mode 100644
index 000000000..4291ae985
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_hello.h
@@ -0,0 +1,80 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file cadet/gnunet-service-cadet_hello.h
23 * @brief cadet service; dealing with hello messages
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCH (Gnunet Cadet Hello)
28 */
29
30#ifndef GNUNET_SERVICE_CADET_HELLO_H
31#define GNUNET_SERVICE_CADET_HELLO_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "platform.h"
42#include "gnunet_util_lib.h"
43#include "gnunet_hello_lib.h"
44
45
46/**
47 * Initialize the hello subsystem.
48 *
49 * @param c Configuration.
50 */
51void
52GCH_init (const struct GNUNET_CONFIGURATION_Handle *c);
53
54
55/**
56 * Shut down the hello subsystem.
57 */
58void
59GCH_shutdown (void);
60
61
62/**
63 * Get own hello message.
64 *
65 * @return Own hello message.
66 */
67const struct GNUNET_HELLO_Message *
68GCH_get_mine (void);
69
70
71#if 0 /* keep Emacsens' auto-indent happy */
72{
73#endif
74#ifdef __cplusplus
75}
76#endif
77
78/* ifndef GNUNET_CADET_SERVICE_HELLO_H */
79#endif
80/* end of gnunet-cadet-service_hello.h */
diff --git a/src/cadet/gnunet-service-cadet-new_paths.c b/src/cadet/gnunet-service-cadet-new_paths.c
new file mode 100644
index 000000000..3cfce337c
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_paths.c
@@ -0,0 +1,557 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_paths.c
24 * @brief Information we track per path.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 *
28 * TODO:
29 * - path desirability score calculations are not done
30 * (and will be tricky to have during path changes)
31 */
32#include "platform.h"
33#include "gnunet-service-cadet-new_peer.h"
34#include "gnunet-service-cadet-new_paths.h"
35
36
37/**
38 * Information regarding a possible path to reach a peer.
39 */
40struct CadetPeerPath
41{
42
43 /**
44 * Array of all the peers on the path. If @e hn is non-NULL, the
45 * last one is our owner.
46 */
47 struct CadetPeerPathEntry *entries;
48
49 /**
50 * Node of this path in the owner's heap. Used to update our position
51 * in the heap whenever our @e desirability changes.
52 */
53 struct GNUNET_CONTAINER_HeapNode *hn;
54
55 /**
56 * Connections using this path, by destination peer
57 * (each hop of the path could correspond to an
58 * active connection).
59 */
60 struct GNUNET_CONTAINER_MultiPeerMap *connections;
61
62 /**
63 * Desirability of the path. How unique is it for the various peers
64 * on it?
65 */
66 GNUNET_CONTAINER_HeapCostType desirability;
67
68 /**
69 * Length of the @e entries array.
70 */
71 unsigned int entries_length;
72
73};
74
75
76/**
77 * Return how much we like keeping the path. This is an aggregate
78 * score based on various factors, including the age of the path
79 * (older == better), and the value of this path to all of its ajacent
80 * peers. For example, long paths that end at a peer that we have no
81 * shorter way to reach are very desirable, while long paths that end
82 * at a peer for which we have a shorter way as well are much less
83 * desirable. Higher values indicate more valuable paths. The
84 * returned value should be used to decide which paths to remember.
85 *
86 * @param path path to return the length for
87 * @return desirability of the path, larger is more desirable
88 */
89GNUNET_CONTAINER_HeapCostType
90GCPP_get_desirability (const struct CadetPeerPath *path)
91{
92 return path->desirability;
93}
94
95
96/**
97 * Return connection to @a destination using @a path, or return
98 * NULL if no such connection exists.
99 *
100 * @param path path to traverse
101 * @param destination destination node to get to, must be on path
102 * @param off offset of @a destination on @a path
103 * @return NULL if we have no existing connection
104 * otherwise connection from us to @a destination via @a path
105 */
106struct CadetConnection *
107GCPP_get_connection (struct CadetPeerPath *path,
108 struct CadetPeer *destination,
109 unsigned int off)
110{
111 struct CadetPeerPathEntry *entry;
112
113 GNUNET_assert (off < path->entries_length);
114 entry = &path->entries[off];
115 GNUNET_assert (entry->peer == destination);
116 return entry->cc;
117}
118
119
120/**
121 * Notify @a path that it is used for connection @a cc
122 * which ends at the path's offset @a off.
123 *
124 * @param path the path to remember the @a cc
125 * @param off the offset where the @a cc ends
126 * @param cc the connection to remember
127 */
128void
129GCPP_add_connection (struct CadetPeerPath *path,
130 unsigned int off,
131 struct CadetConnection *cc)
132{
133 struct CadetPeerPathEntry *entry;
134
135 GNUNET_assert (off < path->entries_length);
136 entry = &path->entries[off];
137 GNUNET_assert (NULL == entry->cc);
138 entry->cc = cc;
139}
140
141
142
143/**
144 * Notify @a path that it is no longer used for connection @a cc which
145 * ended at the path's offset @a off.
146 *
147 * @param path the path to forget the @a cc
148 * @param off the offset where the @a cc ended
149 * @param cc the connection to forget
150 */
151void
152GCPP_del_connection (struct CadetPeerPath *path,
153 unsigned int off,
154 struct CadetConnection *cc)
155{
156 struct CadetPeerPathEntry *entry;
157
158 GNUNET_assert (off < path->entries_length);
159 entry = &path->entries[off];
160 GNUNET_assert (cc == entry->cc);
161 entry->cc = NULL;
162}
163
164
165/**
166 * This path is no longer needed, free resources.
167 *
168 * @param path path resources to free
169 */
170static void
171path_destroy (struct CadetPeerPath *path)
172{
173 GNUNET_assert (0 ==
174 GNUNET_CONTAINER_multipeermap_size (path->connections));
175 GNUNET_CONTAINER_multipeermap_destroy (path->connections);
176 GNUNET_free (path->entries);
177 GNUNET_free (path);
178}
179
180
181/**
182 * The owning peer of this path is no longer interested in maintaining
183 * it, so the path should be discarded or shortened (in case a
184 * previous peer on the path finds the path desirable).
185 *
186 * @param path the path that is being released
187 */
188void
189GCPP_release (struct CadetPeerPath *path)
190{
191 struct CadetPeerPathEntry *entry;
192
193 path->hn = NULL;
194 entry = &path->entries[path->entries_length - 1];
195 while (1)
196 {
197 /* cut 'off' end of path, verifying it is not in use */
198 GNUNET_assert (NULL ==
199 GNUNET_CONTAINER_multipeermap_get (path->connections,
200 GCP_get_id (entry->peer)));
201 GCP_path_entry_remove (entry->peer,
202 entry,
203 path->entries_length - 1);
204 path->entries_length--; /* We don't bother shrinking the 'entries' array,
205 as it's probably not worth it. */
206 if (0 == path->entries_length)
207 break; /* the end */
208
209 /* see if new peer at the end likes this path any better */
210 entry = &path->entries[path->entries_length - 1];
211 path->hn = GCP_attach_path (entry->peer,
212 path,
213 path->entries_length);
214 if (NULL != path->hn)
215 return; /* yep, got attached, we are done. */
216 }
217
218 /* nobody wants us, discard the path */
219 path_destroy (path);
220}
221
222
223/**
224 * Updates the score for an entry on the path based
225 * on our experiences with using @a path.
226 *
227 * @param path the path to update
228 * @param off offset of the entry to update
229 * @param delta change in the score to apply
230 */
231void
232GCPP_update_score (struct CadetPeerPath *path,
233 unsigned int off,
234 int delta)
235{
236 struct CadetPeerPathEntry *entry;
237
238 GNUNET_assert (off < path->entries_length);
239 entry = &path->entries[off];
240
241 /* Add delta, with checks for overflows */
242 if (delta >= 0)
243 {
244 if (delta + entry->score < entry->score)
245 entry->score = INT_MAX;
246 else
247 entry->score += delta;
248 }
249 else
250 {
251 if (delta + entry->score > entry->score)
252 entry->score = INT_MIN;
253 else
254 entry->score += delta;
255 }
256
257 /* FIXME: update path desirability! */
258}
259
260
261/**
262 * Closure for #find_peer_at() and #check_match().
263 */
264struct CheckMatchContext
265{
266
267 /**
268 * Set to a matching path, if any.
269 */
270 struct CadetPeerPath *match;
271
272 /**
273 * Array the combined paths.
274 */
275 struct CadetPeer **cpath;
276
277};
278
279
280/**
281 * Check if the given path is identical on all of the
282 * hops until @a off, and not longer than @a off. If the
283 * @a path matches, store it in `match`.
284 *
285 * @param cls the `struct CheckMatchContext` to check against
286 * @param path the path to check
287 * @param off offset to check at
288 * @return #GNUNET_YES (continue to iterate), or if found #GNUNET_NO
289 */
290static int
291check_match (void *cls,
292 struct CadetPeerPath *path,
293 unsigned int off)
294{
295 struct CheckMatchContext *cm_ctx = cls;
296
297 if (path->entries_length > off)
298 return GNUNET_YES; /* too long, cannot be useful */
299 for (unsigned int i=0;i<off;i++)
300 if (cm_ctx->cpath[i] !=
301 GCPP_get_peer_at_offset (path,
302 i))
303 return GNUNET_YES; /* missmatch, ignore */
304 cm_ctx->match = path;
305 return GNUNET_NO; /* match, we are done! */
306}
307
308
309/**
310 * Extend path @a path by the @a num_peers from the @a peers
311 * array, assuming the owners past the current owner want it.
312 *
313 * @param path path to extend
314 * @param peers list of peers beyond the end of @a path
315 * @param num_peers length of the @a peers array
316 */
317static void
318extend_path (struct CadetPeerPath *path,
319 struct CadetPeer **peers,
320 unsigned int num_peers)
321{
322 unsigned int old_len = path->entries_length;
323 struct GNUNET_CONTAINER_HeapNode *hn;
324 int i;
325
326 /* If we extend an existing path, detach it from the
327 old owner and re-attach to the new one */
328 hn = NULL;
329 for (i=num_peers-1;i>=0;i--)
330 {
331 /* FIXME: note that path->desirability is used, but not yet updated here! */
332 hn = GCP_attach_path (peers[i],
333 path,
334 old_len + (unsigned int) i);
335 if (NULL != hn)
336 break;
337 }
338 if (NULL == hn)
339 return; /* none of the peers is interested in this path */
340 GCP_detach_path (path->entries[old_len-1].peer,
341 path,
342 path->hn);
343 path->hn = hn;
344 GNUNET_array_grow (path->entries,
345 path->entries_length,
346 old_len + i);
347 for (;i >= 0;i--)
348 {
349 struct CadetPeerPathEntry *entry = &path->entries[old_len + i];
350
351 entry->peer = peers[i];
352 entry->path = path;
353 GCP_path_entry_add (entry->peer,
354 entry,
355 old_len + i);
356 }
357}
358
359
360/**
361 * Create a peer path based on the result of a DHT lookup. If we
362 * already know this path, or one that is longer, simply return NULL.
363 * Otherwise, we try to extend an existing path, or create a new one
364 * if applicable.
365 *
366 * @param get_path path of the get request
367 * @param get_path_length lenght of @a get_path
368 * @param put_path path of the put request
369 * @param put_path_length length of the @a put_path
370 * @return a path through the network
371 */
372void
373GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
374 unsigned int get_path_length,
375 const struct GNUNET_PeerIdentity *put_path,
376 unsigned int put_path_length)
377{
378 struct CheckMatchContext cm_ctx;
379 struct CadetPeer *cpath[get_path_length + put_path_length];
380 struct CadetPeerPath *path;
381 struct GNUNET_CONTAINER_HeapNode *hn;
382 int i;
383
384 /* precompute 'cpath' so we can avoid doing the lookups lots of times */
385 for (unsigned int off=0;off<get_path_length + put_path_length;off++)
386 {
387 const struct GNUNET_PeerIdentity *pid;
388
389 pid = (off < get_path_length)
390 ? &get_path[get_path_length - off]
391 : &put_path[get_path_length + put_path_length - off];
392 cpath[off] = GCP_get (pid,
393 GNUNET_YES);
394 }
395
396 /* First figure out if this path is a subset of an existing path, an
397 extension of an existing path, or a new path. */
398 cm_ctx.cpath = cpath;
399 cm_ctx.match = NULL;
400 for (i=get_path_length + put_path_length-1;i>=0;i--)
401 {
402 GCP_iterate_paths_at (cpath[i],
403 (unsigned int) i,
404 &check_match,
405 &cm_ctx);
406 if (NULL != cm_ctx.match)
407 {
408 if (i == get_path_length + put_path_length - 1)
409 {
410 /* Existing path includes this one, nothing to do! */
411 return;
412 }
413 if (cm_ctx.match->entries_length == i + 1)
414 {
415 /* Existing path ends in the middle of new path, extend it! */
416 extend_path (cm_ctx.match,
417 &cpath[i],
418 get_path_length + put_path_length - i);
419 return;
420 }
421 }
422 }
423
424 /* No match at all, create completely new path */
425 path = GNUNET_new (struct CadetPeerPath);
426
427 /* First, try to attach it */
428 hn = NULL;
429 for (i=get_path_length + put_path_length-1;i>=0;i--)
430 {
431 path->entries_length = i;
432 /* FIXME: note that path->desirability is used, but not yet initialized here! */
433 hn = GCP_attach_path (cpath[i],
434 path,
435 (unsigned int) i);
436 if (NULL != hn)
437 break;
438 }
439 if (NULL == hn)
440 {
441 /* None of the peers on the path care about it. */
442 GNUNET_free (path);
443 return;
444 }
445 path->hn = hn;
446 path->entries_length = i;
447 path->entries = GNUNET_new_array (path->entries_length,
448 struct CadetPeerPathEntry);
449 for (;i>=0;i--)
450 {
451 struct CadetPeerPathEntry *entry = &path->entries[i];
452
453 entry->peer = cpath[i];
454 entry->path = path;
455 GCP_path_entry_add (entry->peer,
456 entry,
457 i);
458 }
459}
460
461
462/**
463 * We got an incoming connection, obtain the corresponding path.
464 *
465 * @param path_length number of segments on the @a path
466 * @param path through the network, in reverse order (we are at the end!)
467 * @return corresponding path object
468 */
469struct CadetPeerPath *
470GCPP_get_path_from_route (unsigned int path_length,
471 const struct GNUNET_PeerIdentity *pids)
472{
473 GNUNET_assert (0); // FIXME!
474 return NULL;
475}
476
477
478/**
479 * Return the length of the path. Excludes one end of the
480 * path, so the loopback path has length 0.
481 *
482 * @param path path to return the length for
483 * @return number of peers on the path
484 */
485unsigned int
486GCPP_get_length (struct CadetPeerPath *path)
487{
488 return path->entries_length;
489}
490
491
492/**
493 * Find peer's offset on path.
494 *
495 * @param path path to search
496 * @param cp peer to look for
497 * @return offset of @a cp on @a path, or UINT_MAX if not found
498 */
499unsigned int
500GCPP_find_peer (struct CadetPeerPath *path,
501 struct CadetPeer *cp)
502{
503 for (unsigned int off = 0;
504 off < path->entries_length;
505 off++)
506 if (cp == GCPP_get_peer_at_offset (path,
507 off))
508 return off;
509 return UINT_MAX;
510}
511
512
513/**
514 * Obtain the peer at offset @a off in @a path.
515 *
516 * @param path peer path to inspect
517 * @param off offset to return, must be smaller than path length
518 * @return the peer at offset @a off
519 */
520struct CadetPeer *
521GCPP_get_peer_at_offset (struct CadetPeerPath *path,
522 unsigned int off)
523{
524 return path->entries[off].peer;
525}
526
527
528/**
529 * Convert a path to a human-readable string.
530 *
531 * @param path path to convert
532 * @return string, to be freed by caller (unlike other *_2s APIs!)
533 */
534char *
535GCPP_2s (struct CadetPeerPath *path)
536{
537 char *s;
538 char *old;
539
540 old = GNUNET_strdup ("");
541 for (unsigned int i = 0;
542 i < path->entries_length;
543 i++)
544 {
545 GNUNET_asprintf (&s,
546 "%s %s",
547 old,
548 GCP_2s (GCPP_get_peer_at_offset (path,
549 i)));
550 GNUNET_free_non_null (old);
551 old = s;
552 }
553 return old;
554}
555
556
557/* end of gnunet-service-cadet-new_paths.c */
diff --git a/src/cadet/gnunet-service-cadet-new_paths.h b/src/cadet/gnunet-service-cadet-new_paths.h
new file mode 100644
index 000000000..5714368c7
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_paths.h
@@ -0,0 +1,182 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_paths.h
24 * @brief Information we track per path.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#ifndef GNUNET_SERVICE_CADET_PATHS_H
29#define GNUNET_SERVICE_CADET_PATHS_H
30
31#include "gnunet_util_lib.h"
32#include "gnunet-service-cadet-new.h"
33
34/**
35 * Create a peer path based on the result of a DHT lookup. If we
36 * already know this path, or one that is longer, simply return NULL.
37 * Otherwise, we try to extend an existing path, or create a new one
38 * if applicable.
39 *
40 * @param get_path path of the get request
41 * @param get_path_length lenght of @a get_path
42 * @param put_path path of the put request
43 * @param put_path_length length of the @a put_path
44 */
45void
46GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
47 unsigned int get_path_length,
48 const struct GNUNET_PeerIdentity *put_path,
49 unsigned int put_path_length);
50
51
52/**
53 * We got an incoming connection, obtain the corresponding path.
54 *
55 * @param path_length number of segments on the @a path
56 * @param path through the network, in reverse order (we are at the end!)
57 * @return corresponding path object
58 */
59struct CadetPeerPath *
60GCPP_get_path_from_route (unsigned int path_length,
61 const struct GNUNET_PeerIdentity *pids);
62
63
64/**
65 * Return the length of the path. Excludes one end of the
66 * path, so the loopback path has length 0.
67 *
68 * @param path path to return the length for
69 * @return number of peers on the path
70 */
71unsigned int
72GCPP_get_length (struct CadetPeerPath *path);
73
74
75/**
76 * Return connection to @a destination using @a path, or return
77 * NULL if no such connection exists.
78 *
79 * @param path path to traverse
80 * @param destination destination node to get to, must be on path
81 * @param off offset of @a destination on @a path
82 * @return NULL if we have no existing connection
83 * otherwise connection from us to @a destination via @a path
84 */
85struct CadetConnection *
86GCPP_get_connection (struct CadetPeerPath *path,
87 struct CadetPeer *destination,
88 unsigned int off);
89
90
91/**
92 * Notify @a path that it is used for connection @a cc
93 * which ends at the path's offset @a off.
94 *
95 * @param path the path to remember the @a cc
96 * @param off the offset where the @a cc ends
97 * @param cc the connection to remember
98 */
99void
100GCPP_add_connection (struct CadetPeerPath *path,
101 unsigned int off,
102 struct CadetConnection *cc);
103
104
105/**
106 * Notify @a path that it is no longer used for connection @a cc which
107 * ended at the path's offset @a off.
108 *
109 * @param path the path to forget the @a cc
110 * @param off the offset where the @a cc ended
111 * @param cc the connection to forget
112 */
113void
114GCPP_del_connection (struct CadetPeerPath *path,
115 unsigned int off,
116 struct CadetConnection *cc);
117
118
119/**
120 * Find peer's offset on path.
121 *
122 * @param path path to search
123 * @param cp peer to look for
124 * @return offset of @a cp on @a path, or UINT_MAX if not found
125 */
126unsigned int
127GCPP_find_peer (struct CadetPeerPath *path,
128 struct CadetPeer *cp);
129
130
131/**
132 * Return how much we like keeping the path. This is an aggregate
133 * score based on various factors, including the age of the path
134 * (older == better), and the value of this path to all of its ajacent
135 * peers. For example, long paths that end at a peer that we have no
136 * shorter way to reach are very desirable, while long paths that end
137 * at a peer for which we have a shorter way as well are much less
138 * desirable. Higher values indicate more valuable paths. The
139 * returned value should be used to decide which paths to remember.
140 *
141 * @param path path to return the length for
142 * @return desirability of the path, larger is more desirable
143 */
144GNUNET_CONTAINER_HeapCostType
145GCPP_get_desirability (const struct CadetPeerPath *path);
146
147
148/**
149 * The given peer @a cp used to own this @a path. However, it is no
150 * longer interested in maintaining it, so the path should be
151 * discarded or shortened (in case a previous peer on the path finds
152 * the path desirable).
153 *
154 * @param path the path that is being released
155 */
156void
157GCPP_release (struct CadetPeerPath *path);
158
159
160/**
161 * Obtain the peer at offset @a off in @a path.
162 *
163 * @param path peer path to inspect
164 * @param off offset to return, must be smaller than path length
165 * @return peer at offset @a off
166 */
167struct CadetPeer *
168GCPP_get_peer_at_offset (struct CadetPeerPath *path,
169 unsigned int off);
170
171
172/**
173 * Convert a path to a human-readable string.
174 *
175 * @param path path to convert
176 * @return string, to be freed by caller (unlike other *_2s APIs!)
177 */
178char *
179GCPP_2s (struct CadetPeerPath *p);
180
181
182#endif
diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c
new file mode 100644
index 000000000..47f725e09
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_peer.c
@@ -0,0 +1,1056 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_peer.c
24 * @brief Information we track per peer.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 *
28 * TODO:
29 * - implement GCP_set_hello() / do HELLO advertising properly
30 * - optimize stopping/restarting DHT search to situations
31 * where we actually need it (i.e. not if we have a direct connection,
32 * or if we already have plenty of good short ones, or maybe even
33 * to take a break if we have some connections and have searched a lot (?))
34 * - optimize MQM ready scans (O(n) -> O(1))
35 */
36#include "platform.h"
37#include "gnunet_util_lib.h"
38#include "gnunet_signatures.h"
39#include "gnunet_transport_service.h"
40#include "gnunet_ats_service.h"
41#include "gnunet_core_service.h"
42#include "gnunet_statistics_service.h"
43#include "cadet_protocol.h"
44#include "cadet_path.h"
45#include "gnunet-service-cadet-new.h"
46#include "gnunet-service-cadet-new_connection.h"
47#include "gnunet-service-cadet-new_dht.h"
48#include "gnunet-service-cadet-new_peer.h"
49#include "gnunet-service-cadet-new_paths.h"
50#include "gnunet-service-cadet-new_tunnels.h"
51
52/**
53 * How long do we wait until tearing down an idle peer?
54 */
55#define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
56
57/**
58 * How long do we keep paths around if we no longer care about the peer?
59 */
60#define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
61
62
63
64
65/**
66 * Data structure used to track whom we have to notify about changes
67 * to our message queue.
68 */
69struct GCP_MessageQueueManager
70{
71
72 /**
73 * Kept in a DLL.
74 */
75 struct GCP_MessageQueueManager *next;
76
77 /**
78 * Kept in a DLL.
79 */
80 struct GCP_MessageQueueManager *prev;
81
82 /**
83 * Function to call with updated message queue object.
84 */
85 GCP_MessageQueueNotificationCallback cb;
86
87 /**
88 * Closure for @e cb.
89 */
90 void *cb_cls;
91
92 /**
93 * The peer this is for.
94 */
95 struct CadetPeer *cp;
96
97 /**
98 * Envelope this manager would like to transmit once it is its turn.
99 */
100 struct GNUNET_MQ_Envelope *env;
101
102};
103
104
105/**
106 * Struct containing all information regarding a given peer
107 */
108struct CadetPeer
109{
110 /**
111 * ID of the peer
112 */
113 struct GNUNET_PeerIdentity pid;
114
115 /**
116 * Last time we heard from this peer
117 */
118 struct GNUNET_TIME_Absolute last_contact;
119
120 /**
121 * Array of DLLs of paths traversing the peer, organized by the
122 * offset of the peer on the larger path.
123 */
124 struct CadetPeerPathEntry **path_heads;
125
126 /**
127 * Array of DLL of paths traversing the peer, organized by the
128 * offset of the peer on the larger path.
129 */
130 struct CadetPeerPathEntry **path_tails;
131
132 /**
133 * Notifications to call when @e core_mq changes.
134 */
135 struct GCP_MessageQueueManager *mqm_head;
136
137 /**
138 * Notifications to call when @e core_mq changes.
139 */
140 struct GCP_MessageQueueManager *mqm_tail;
141
142 /**
143 * MIN-heap of paths owned by this peer (they also end at this
144 * peer). Ordered by desirability.
145 */
146 struct GNUNET_CONTAINER_Heap *path_heap;
147
148 /**
149 * Handle to stop the DHT search for paths to this peer
150 */
151 struct GCD_search_handle *search_h;
152
153 /**
154 * Task to stop the DHT search for paths to this peer
155 */
156 struct GNUNET_SCHEDULER_Task *search_delayedXXX;
157
158 /**
159 * Task to destroy this entry.
160 */
161 struct GNUNET_SCHEDULER_Task *destroy_task;
162
163 /**
164 * Tunnel to this peer, if any.
165 */
166 struct CadetTunnel *t;
167
168 /**
169 * Connections that go through this peer; indexed by tid.
170 */
171 struct GNUNET_CONTAINER_MultiShortmap *connections;
172
173 /**
174 * Handle for core transmissions.
175 */
176 struct GNUNET_MQ_Handle *core_mq;
177
178 /**
179 * Hello message of the peer.
180 */
181 struct GNUNET_HELLO_Message *hello;
182
183 /**
184 * Handle to us offering the HELLO to the transport.
185 */
186 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
187
188 /**
189 * Handle to our ATS request asking ATS to suggest an address
190 * to TRANSPORT for this peer (to establish a direct link).
191 */
192 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
193
194 /**
195 * How many messages are in the queue to this peer.
196 */
197 unsigned int queue_n;
198
199 /**
200 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
201 */
202 unsigned int num_paths;
203
204 /**
205 * Number of message queue managers of this peer that have a message in waiting.
206 *
207 * Used to quickly see if we need to bother scanning the @e msm_head DLL.
208 * TODO: could be replaced by another DLL that would then allow us to avoid
209 * the O(n)-scan of the DLL for ready entries!
210 */
211 unsigned int mqm_ready_counter;
212
213 /**
214 * Current length of the @e path_heads and @path_tails arrays.
215 * The arrays should be grown as needed.
216 */
217 unsigned int path_dll_length;
218
219};
220
221
222/**
223 * Get the static string for a peer ID.
224 *
225 * @param peer Peer.
226 *
227 * @return Static string for it's ID.
228 */
229const char *
230GCP_2s (const struct CadetPeer *peer)
231{
232 if (NULL == peer)
233 return "PEER(NULL)";
234 return GNUNET_i2s (&peer->pid);
235}
236
237
238/**
239 * This peer is no longer be needed, clean it up now.
240 *
241 * @param cls peer to clean up
242 */
243static void
244destroy_peer (void *cls)
245{
246 struct CadetPeer *cp = cls;
247
248 cp->destroy_task = NULL;
249 GNUNET_assert (NULL == cp->t);
250 GNUNET_assert (NULL == cp->core_mq);
251 GNUNET_assert (0 == cp->path_dll_length);
252 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
253 GNUNET_assert (GNUNET_YES ==
254 GNUNET_CONTAINER_multipeermap_remove (peers,
255 &cp->pid,
256 cp));
257 GNUNET_free_non_null (cp->path_heads);
258 GNUNET_free_non_null (cp->path_tails);
259 cp->path_dll_length = 0;
260 if (NULL != cp->search_h)
261 {
262 GCD_search_stop (cp->search_h);
263 cp->search_h = NULL;
264 }
265 /* FIXME: clean up search_delayedXXX! */
266
267 if (NULL != cp->hello_offer)
268 {
269 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
270 cp->hello_offer = NULL;
271 }
272 if (NULL != cp->connectivity_suggestion)
273 {
274 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
275 cp->connectivity_suggestion = NULL;
276 }
277 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
278 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
279 GNUNET_free_non_null (cp->hello);
280 /* Peer should not be freed if paths exist; if there are no paths,
281 there ought to be no connections, and without connections, no
282 notifications. Thus we can assert that mqm_head is empty at this
283 point. */
284 GNUNET_assert (NULL == cp->mqm_head);
285 GNUNET_free (cp);
286}
287
288
289/**
290 * Set the message queue to @a mq for peer @a cp and notify watchers.
291 *
292 * @param cp peer to modify
293 * @param mq message queue to set (can be NULL)
294 */
295void
296GCP_set_mq (struct CadetPeer *cp,
297 struct GNUNET_MQ_Handle *mq)
298{
299 cp->core_mq = mq;
300
301 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
302 NULL != mqm;
303 mqm = mqm->next)
304 {
305 if (NULL == mq)
306 {
307 if (NULL != mqm->env)
308 {
309 GNUNET_MQ_discard (mqm->env);
310 mqm->env = NULL;
311 mqm->cb (mqm->cb_cls,
312 GNUNET_SYSERR);
313 }
314 else
315 {
316 mqm->cb (mqm->cb_cls,
317 GNUNET_NO);
318 }
319 }
320 else
321 {
322 GNUNET_assert (NULL == mqm->env);
323 mqm->cb (mqm->cb_cls,
324 GNUNET_YES);
325 }
326 }
327}
328
329
330/**
331 * Transmit current envelope from this @a mqm.
332 *
333 * @param mqm mqm to transmit message for now
334 */
335static void
336mqm_execute (struct GCP_MessageQueueManager *mqm)
337{
338 struct CadetPeer *cp = mqm->cp;
339
340 /* Move entry to the end of the DLL, to be fair. */
341 if (mqm != cp->mqm_tail)
342 {
343 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
344 cp->mqm_tail,
345 mqm);
346 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
347 cp->mqm_tail,
348 mqm);
349 }
350 GNUNET_MQ_send (cp->core_mq,
351 mqm->env);
352 mqm->env = NULL;
353 cp->mqm_ready_counter--;
354}
355
356
357/**
358 * Function called when CORE took one of the messages from
359 * a message queue manager and transmitted it.
360 *
361 * @param cls the `struct CadetPeeer` where we made progress
362 */
363static void
364mqm_send_done (void *cls)
365{
366 struct CadetPeer *cp = cls;
367
368 if (0 == cp->mqm_ready_counter)
369 return; /* nothing to do */
370 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
371 NULL != mqm;
372 mqm = mqm->next)
373 {
374 if (NULL == mqm->env)
375 continue;
376 mqm_execute (mqm);
377 return;
378 }
379}
380
381
382/**
383 * Send the message in @a env to @a cp.
384 *
385 * @param mqm the message queue manager to use for transmission
386 * @param env envelope with the message to send; must NOT
387 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
388 */
389void
390GCP_send (struct GCP_MessageQueueManager *mqm,
391 struct GNUNET_MQ_Envelope *env)
392{
393 struct CadetPeer *cp = mqm->cp;
394
395 GNUNET_assert (NULL != cp->core_mq);
396 GNUNET_assert (NULL == mqm->env);
397 GNUNET_MQ_notify_sent (env,
398 &mqm_send_done,
399 cp);
400 mqm->env = env;
401 cp->mqm_ready_counter++;
402 if (0 != GNUNET_MQ_get_length (cp->core_mq))
403 return;
404 mqm_execute (mqm);
405}
406
407
408/**
409 * Function called to destroy a peer now.
410 *
411 * @param cls NULL
412 * @param pid identity of the peer (unused)
413 * @param value the `struct CadetPeer` to clean up
414 * @return #GNUNET_OK (continue to iterate)
415 */
416static int
417destroy_iterator_cb (void *cls,
418 const struct GNUNET_PeerIdentity *pid,
419 void *value)
420{
421 struct CadetPeer *cp = value;
422
423 if (NULL != cp->destroy_task)
424 {
425 GNUNET_SCHEDULER_cancel (cp->destroy_task);
426 cp->destroy_task = NULL;
427 }
428 destroy_peer (cp);
429 return GNUNET_OK;
430}
431
432
433/**
434 * Clean up all entries about all peers.
435 * Must only be called after all tunnels, CORE-connections and
436 * connections are down.
437 */
438void
439GCP_destroy_all_peers ()
440{
441 GNUNET_CONTAINER_multipeermap_iterate (peers,
442 &destroy_iterator_cb,
443 NULL);
444}
445
446
447/**
448 * This peer may no longer be needed, consider cleaning it up.
449 *
450 * @param cp peer to clean up
451 */
452static void
453consider_peer_destroy (struct CadetPeer *cp);
454
455
456/**
457 * We really no longere care about a peer, stop hogging memory with paths to it.
458 * Afterwards, see if there is more to be cleaned up about this peer.
459 *
460 * @param cls a `struct CadetPeer`.
461 */
462static void
463drop_paths (void *cls)
464{
465 struct CadetPeer *cp = cls;
466 struct CadetPeerPath *path;
467
468 cp->destroy_task = NULL;
469 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
470 GCPP_release (path);
471 consider_peer_destroy (cp);
472}
473
474
475/**
476 * This peer may no longer be needed, consider cleaning it up.
477 *
478 * @param cp peer to clean up
479 */
480static void
481consider_peer_destroy (struct CadetPeer *cp)
482{
483 struct GNUNET_TIME_Relative exp;
484
485 if (NULL != cp->destroy_task)
486 {
487 GNUNET_SCHEDULER_cancel (cp->destroy_task);
488 cp->destroy_task = NULL;
489 }
490 if (NULL != cp->t)
491 return; /* still relevant! */
492 if (NULL != cp->core_mq)
493 return; /* still relevant! */
494 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
495 return; /* still relevant! */
496 if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
497 {
498 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
499 &drop_paths,
500 cp);
501 return;
502 }
503 if (0 < cp->path_dll_length)
504 return; /* still relevant! */
505 if (NULL != cp->hello)
506 {
507 /* relevant only until HELLO expires */
508 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
509 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
510 &destroy_peer,
511 cp);
512 return;
513 }
514 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
515 &destroy_peer,
516 cp);
517}
518
519
520/**
521 * Add an entry to the DLL of all of the paths that this peer is on.
522 *
523 * @param cp peer to modify
524 * @param entry an entry on a path
525 * @param off offset of this peer on the path
526 */
527void
528GCP_path_entry_add (struct CadetPeer *cp,
529 struct CadetPeerPathEntry *entry,
530 unsigned int off)
531{
532 if (off >= cp->path_dll_length)
533 {
534 unsigned int len = cp->path_dll_length;
535
536 GNUNET_array_grow (cp->path_heads,
537 len,
538 off + 4);
539 GNUNET_array_grow (cp->path_tails,
540 cp->path_dll_length,
541 off + 4);
542 }
543 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
544 cp->path_tails[off],
545 entry);
546 cp->num_paths++;
547
548 /* If we have a tunnel to this peer, tell the tunnel that there is a
549 new path available. */
550 if (NULL != cp->t)
551 GCT_consider_path (cp->t,
552 entry->path,
553 off);
554}
555
556
557/**
558 * Remove an entry from the DLL of all of the paths that this peer is on.
559 *
560 * @param cp peer to modify
561 * @param entry an entry on a path
562 * @param off offset of this peer on the path
563 */
564void
565GCP_path_entry_remove (struct CadetPeer *cp,
566 struct CadetPeerPathEntry *entry,
567 unsigned int off)
568{
569 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
570 cp->path_tails[off],
571 entry);
572 GNUNET_assert (0 < cp->num_paths);
573 cp->num_paths--;
574}
575
576
577/**
578 * Try adding a @a path to this @a peer. If the peer already
579 * has plenty of paths, return NULL.
580 *
581 * @param cp peer to which the @a path leads to
582 * @param path a path looking for an owner; may not be fully initialized yet!
583 * @param off offset of @a cp in @a path
584 * @return NULL if this peer does not care to become a new owner,
585 * otherwise the node in the peer's path heap for the @a path.
586 */
587struct GNUNET_CONTAINER_HeapNode *
588GCP_attach_path (struct CadetPeer *cp,
589 struct CadetPeerPath *path,
590 unsigned int off)
591{
592 GNUNET_CONTAINER_HeapCostType desirability;
593 struct CadetPeerPath *root;
594 GNUNET_CONTAINER_HeapCostType root_desirability;
595 struct GNUNET_CONTAINER_HeapNode *hn;
596
597 /* FIXME: desirability is not yet initialized; tricky! */
598 desirability = GCPP_get_desirability (path);
599 if (GNUNET_NO ==
600 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
601 (void **) &root,
602 &root_desirability))
603 {
604 root = NULL;
605 root_desirability = 0;
606 }
607
608 if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
609 (desirability < root_desirability) )
610 return NULL;
611
612 /* Yes, we'd like to add this path, add to our heap */
613 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
614 (void *) cp,
615 desirability);
616
617 /* Consider maybe dropping other paths because of the new one */
618 if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
619 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
620 {
621 /* Now we have way too many, drop least desirable UNLESS it is in use!
622 (Note that this intentionally keeps highly desireable, but currently
623 unused paths around in the hope that we might be able to switch, even
624 if the number of paths exceeds the threshold.) */
625 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
626 if (NULL ==
627 GCPP_get_connection (root,
628 cp,
629 GCPP_get_length (root) - 1))
630 {
631 /* Got plenty of paths to this destination, and this is a low-quality
632 one that we don't care, allow it to die. */
633 GNUNET_assert (root ==
634 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
635 GCPP_release (root);
636 }
637 }
638 return hn;
639}
640
641
642/**
643 * This peer can no longer own @a path as the path
644 * has been extended and a peer further down the line
645 * is now the new owner.
646 *
647 * @param cp old owner of the @a path
648 * @param path path where the ownership is lost
649 * @param hn note in @a cp's path heap that must be deleted
650 */
651void
652GCP_detach_path (struct CadetPeer *cp,
653 struct CadetPeerPath *path,
654 struct GNUNET_CONTAINER_HeapNode *hn)
655{
656 GNUNET_assert (path ==
657 GNUNET_CONTAINER_heap_remove_node (hn));
658}
659
660
661/**
662 * Add a @a connection to this @a cp.
663 *
664 * @param cp peer via which the @a connection goes
665 * @param cc the connection to add
666 */
667void
668GCP_add_connection (struct CadetPeer *cp,
669 struct CadetConnection *cc)
670{
671 GNUNET_assert (GNUNET_OK ==
672 GNUNET_CONTAINER_multishortmap_put (cp->connections,
673 &GCC_get_id (cc)->connection_of_tunnel,
674 cc,
675 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
676}
677
678
679/**
680 * Remove a @a connection that went via this @a cp.
681 *
682 * @param cp peer via which the @a connection went
683 * @param cc the connection to remove
684 */
685void
686GCP_remove_connection (struct CadetPeer *cp,
687 struct CadetConnection *cc)
688{
689 GNUNET_assert (GNUNET_YES ==
690 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
691 &GCC_get_id (cc)->connection_of_tunnel,
692 cc));
693}
694
695
696/**
697 * This peer is now on more "active" duty, activate processes related to it.
698 *
699 * @param cp the more-active peer
700 */
701static void
702consider_peer_activate (struct CadetPeer *cp)
703{
704 uint32_t strength;
705
706 if (NULL != cp->destroy_task)
707 {
708 /* It's active, do not destory! */
709 GNUNET_SCHEDULER_cancel (cp->destroy_task);
710 cp->destroy_task = NULL;
711 }
712 if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
713 (NULL == cp->t) )
714 {
715 /* We're just on a path or directly connected; don't bother too much */
716 if (NULL != cp->connectivity_suggestion)
717 {
718 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
719 cp->connectivity_suggestion = NULL;
720 }
721 if (NULL != cp->search_h)
722 {
723 GCD_search_stop (cp->search_h);
724 cp->search_h = NULL;
725 }
726 return;
727 }
728 if (NULL == cp->core_mq)
729 {
730 /* Lacks direct connection, try to create one by querying the DHT */
731 if ( (NULL == cp->search_h) &&
732 (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
733 cp->search_h
734 = GCD_search (&cp->pid);
735 }
736 else
737 {
738 /* Have direct connection, stop DHT search if active */
739 if (NULL != cp->search_h)
740 {
741 GCD_search_stop (cp->search_h);
742 cp->search_h = NULL;
743 }
744 }
745
746 /* If we have a tunnel, our urge for connections is much bigger */
747 strength = (NULL != cp->t) ? 32 : 1;
748 if (NULL != cp->connectivity_suggestion)
749 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
750 cp->connectivity_suggestion
751 = GNUNET_ATS_connectivity_suggest (ats_ch,
752 &cp->pid,
753 strength);
754}
755
756
757/**
758 * Retrieve the CadetPeer stucture associated with the
759 * peer. Optionally create one and insert it in the appropriate
760 * structures if the peer is not known yet.
761 *
762 * @param peer_id Full identity of the peer.
763 * @param create #GNUNET_YES if a new peer should be created if unknown.
764 * #GNUNET_NO to return NULL if peer is unknown.
765 * @return Existing or newly created peer structure.
766 * NULL if unknown and not requested @a create
767 */
768struct CadetPeer *
769GCP_get (const struct GNUNET_PeerIdentity *peer_id,
770 int create)
771{
772 struct CadetPeer *cp;
773
774 cp = GNUNET_CONTAINER_multipeermap_get (peers,
775 peer_id);
776 if (NULL != cp)
777 return cp;
778 if (GNUNET_NO == create)
779 return NULL;
780 cp = GNUNET_new (struct CadetPeer);
781 cp->pid = *peer_id;
782 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
783 GNUNET_YES);
784 cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
785 GNUNET_assert (GNUNET_YES ==
786 GNUNET_CONTAINER_multipeermap_put (peers,
787 &cp->pid,
788 cp,
789 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
790 return cp;
791}
792
793
794/**
795 * Obtain the peer identity for a `struct CadetPeer`.
796 *
797 * @param cp our peer handle
798 * @return the peer identity
799 */
800const struct GNUNET_PeerIdentity *
801GCP_get_id (struct CadetPeer *cp)
802{
803 return &cp->pid;
804}
805
806
807/**
808 * Iterate over all known peers.
809 *
810 * @param iter Iterator.
811 * @param cls Closure for @c iter.
812 */
813void
814GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
815 void *cls)
816{
817 GNUNET_CONTAINER_multipeermap_iterate (peers,
818 iter,
819 cls);
820}
821
822
823/**
824 * Count the number of known paths toward the peer.
825 *
826 * @param peer Peer to get path info.
827 * @return Number of known paths.
828 */
829unsigned int
830GCP_count_paths (const struct CadetPeer *peer)
831{
832 return peer->num_paths;
833}
834
835
836/**
837 * Iterate over the paths to a peer.
838 *
839 * @param peer Peer to get path info.
840 * @param callback Function to call for every path.
841 * @param callback_cls Closure for @a callback.
842 * @return Number of iterated paths.
843 */
844unsigned int
845GCP_iterate_paths (struct CadetPeer *peer,
846 GCP_PathIterator callback,
847 void *callback_cls)
848{
849 unsigned int ret = 0;
850
851 for (unsigned int i=0;i<peer->path_dll_length;i++)
852 {
853 for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
854 NULL != pe;
855 pe = pe->next)
856 {
857 if (GNUNET_NO ==
858 callback (callback_cls,
859 pe->path,
860 i))
861 return ret;
862 ret++;
863 }
864 }
865 return ret;
866}
867
868
869/**
870 * Iterate over the paths to @a peer where
871 * @a peer is at distance @a dist from us.
872 *
873 * @param peer Peer to get path info.
874 * @param dist desired distance of @a peer to us on the path
875 * @param callback Function to call for every path.
876 * @param callback_cls Closure for @a callback.
877 * @return Number of iterated paths.
878 */
879unsigned int
880GCP_iterate_paths_at (struct CadetPeer *peer,
881 unsigned int dist,
882 GCP_PathIterator callback,
883 void *callback_cls)
884{
885 unsigned int ret = 0;
886
887 if (dist<peer->path_dll_length)
888 return 0;
889 for (struct CadetPeerPathEntry *pe = peer->path_heads[dist];
890 NULL != pe;
891 pe = pe->next)
892 {
893 if (GNUNET_NO ==
894 callback (callback_cls,
895 pe->path,
896 dist))
897 return ret;
898 ret++;
899 }
900 return ret;
901}
902
903
904/**
905 * Get the tunnel towards a peer.
906 *
907 * @param peer Peer to get from.
908 * @param create #GNUNET_YES to create a tunnel if we do not have one
909 * @return Tunnel towards peer.
910 */
911struct CadetTunnel *
912GCP_get_tunnel (struct CadetPeer *peer,
913 int create)
914{
915 if (NULL == peer)
916 return NULL;
917 if ( (NULL != peer->t) ||
918 (GNUNET_NO == create) )
919 return peer->t;
920 peer->t = GCT_create_tunnel (peer);
921 consider_peer_activate (peer);
922 return peer->t;
923}
924
925
926/**
927 * We got a HELLO for a @a peer, remember it, and possibly
928 * trigger adequate actions (like trying to connect).
929 *
930 * @param peer the peer we got a HELLO for
931 * @param hello the HELLO to remember
932 */
933void
934GCP_set_hello (struct CadetPeer *peer,
935 const struct GNUNET_HELLO_Message *hello)
936{
937 /* FIXME: keep HELLO, possibly offer to TRANSPORT... */
938
939 consider_peer_destroy (peer);
940}
941
942
943/**
944 * The tunnel to the given peer no longer exists, remove it from our
945 * data structures, and possibly clean up the peer itself.
946 *
947 * @param peer the peer affected
948 * @param t the dead tunnel
949 */
950void
951GCP_drop_tunnel (struct CadetPeer *peer,
952 struct CadetTunnel *t)
953{
954 GNUNET_assert (peer->t == t);
955 peer->t = NULL;
956 consider_peer_destroy (peer);
957}
958
959
960/**
961 * Test if @a cp has a core-level connection
962 *
963 * @param cp peer to test
964 * @return #GNUNET_YES if @a cp has a core-level connection
965 */
966int
967GCP_has_core_connection (struct CadetPeer *cp)
968{
969 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
970}
971
972
973/**
974 * Start message queue change notifications.
975 *
976 * @param cp peer to notify for
977 * @param cb function to call if mq becomes available or unavailable
978 * @param cb_cls closure for @a cb
979 * @return handle to cancel request
980 */
981struct GCP_MessageQueueManager *
982GCP_request_mq (struct CadetPeer *cp,
983 GCP_MessageQueueNotificationCallback cb,
984 void *cb_cls)
985{
986 struct GCP_MessageQueueManager *mqm;
987
988 mqm = GNUNET_new (struct GCP_MessageQueueManager);
989 mqm->cb = cb;
990 mqm->cb_cls = cb_cls;
991 mqm->cp = cp;
992 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
993 cp->mqm_tail,
994 mqm);
995 if (NULL != cp->core_mq)
996 cb (cb_cls,
997 GNUNET_YES);
998 return mqm;
999}
1000
1001
1002/**
1003 * Stops message queue change notifications.
1004 *
1005 * @param mqm handle matching request to cancel
1006 * @param last_env final message to transmit, or NULL
1007 */
1008void
1009GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1010 struct GNUNET_MQ_Envelope *last_env)
1011{
1012 struct CadetPeer *cp = mqm->cp;
1013
1014 if (NULL != mqm->env)
1015 GNUNET_MQ_discard (mqm->env);
1016 if (NULL != last_env)
1017 {
1018 if (NULL != cp->core_mq)
1019 GNUNET_MQ_send (cp->core_mq,
1020 last_env);
1021 else
1022 GNUNET_MQ_discard (last_env);
1023 }
1024 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1025 cp->mqm_tail,
1026 mqm);
1027 GNUNET_free (mqm);
1028}
1029
1030
1031/**
1032 * Send the message in @a env to @a cp, overriding queueing logic.
1033 * This function should only be used to send error messages outside
1034 * of flow and congestion control, similar to ICMP. Note that
1035 * the envelope may be silently discarded as well.
1036 *
1037 * @param cp peer to send the message to
1038 * @param env envelope with the message to send
1039 */
1040void
1041GCP_send_ooo (struct CadetPeer *cp,
1042 struct GNUNET_MQ_Envelope *env)
1043{
1044 if (NULL == cp->core_mq)
1045 {
1046 GNUNET_MQ_discard (env);
1047 return;
1048 }
1049 GNUNET_MQ_send (cp->core_mq,
1050 env);
1051}
1052
1053
1054
1055
1056/* end of gnunet-service-cadet-new_peer.c */
diff --git a/src/cadet/gnunet-service-cadet-new_peer.h b/src/cadet/gnunet-service-cadet-new_peer.h
new file mode 100644
index 000000000..c633f47e5
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_peer.h
@@ -0,0 +1,368 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_peer.h
24 * @brief Information we track per peer.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#ifndef GNUNET_SERVICE_CADET_PEER_H
29#define GNUNET_SERVICE_CADET_PEER_H
30
31#include "gnunet-service-cadet-new.h"
32#include "gnunet_hello_lib.h"
33
34
35/**
36 * Get the static string for a peer ID.
37 *
38 * @param peer Peer.
39 *
40 * @return Static string for it's ID.
41 */
42const char *
43GCP_2s (const struct CadetPeer *peer);
44
45
46/**
47 * Retrieve the CadetPeer stucture associated with the
48 * peer. Optionally create one and insert it in the appropriate
49 * structures if the peer is not known yet.
50 *
51 * @param peer_id Full identity of the peer.
52 * @param create #GNUNET_YES if a new peer should be created if unknown.
53 * #GNUNET_NO to return NULL if peer is unknown.
54 * @return Existing or newly created peer structure.
55 * NULL if unknown and not requested @a create
56 */
57struct CadetPeer *
58GCP_get (const struct GNUNET_PeerIdentity *peer_id,
59 int create);
60
61
62/**
63 * Obtain the peer identity for a `struct CadetPeer`.
64 *
65 * @param cp our peer handle
66 * @return the peer identity
67 */
68const struct GNUNET_PeerIdentity *
69GCP_get_id (struct CadetPeer *cp);
70
71
72/**
73 * Iterate over all known peers.
74 *
75 * @param iter Iterator.
76 * @param cls Closure for @c iter.
77 */
78void
79GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
80 void *cls);
81
82
83/**
84 * Count the number of known paths toward the peer.
85 *
86 * @param cp Peer to get path info.
87 * @return Number of known paths.
88 */
89unsigned int
90GCP_count_paths (const struct CadetPeer *cp);
91
92
93/**
94 * Peer path iterator.
95 *
96 * @param cls Closure.
97 * @param path Path itself
98 * @param off offset of the target peer in @a path
99 * @return #GNUNET_YES if should keep iterating.
100 * #GNUNET_NO otherwise.
101 */
102typedef int
103(*GCP_PathIterator) (void *cls,
104 struct CadetPeerPath *path,
105 unsigned int off);
106
107
108/**
109 * Iterate over the paths to a peer.
110 *
111 * @param cp Peer to get path info.
112 * @param callback Function to call for every path.
113 * @param callback_cls Closure for @a callback.
114 * @return Number of iterated paths.
115 */
116unsigned int
117GCP_iterate_paths (struct CadetPeer *cp,
118 GCP_PathIterator callback,
119 void *callback_cls);
120
121
122/**
123 * Iterate over the paths to @a peer where
124 * @a peer is at distance @a dist from us.
125 *
126 * @param peer Peer to get path info.
127 * @param dist desired distance of @a peer to us on the path
128 * @param callback Function to call for every path.
129 * @param callback_cls Closure for @a callback.
130 * @return Number of iterated paths.
131 */
132unsigned int
133GCP_iterate_paths_at (struct CadetPeer *peer,
134 unsigned int dist,
135 GCP_PathIterator callback,
136 void *callback_cls);
137
138
139/**
140 * Remove an entry from the DLL of all of the paths that this peer is on.
141 *
142 * @param cp peer to modify
143 * @param entry an entry on a path
144 * @param off offset of this peer on the path
145 */
146void
147GCP_path_entry_remove (struct CadetPeer *cp,
148 struct CadetPeerPathEntry *entry,
149 unsigned int off);
150
151
152/**
153 * Add an entry to the DLL of all of the paths that this peer is on.
154 *
155 * @param cp peer to modify
156 * @param entry an entry on a path
157 * @param off offset of this peer on the path
158 */
159void
160GCP_path_entry_add (struct CadetPeer *cp,
161 struct CadetPeerPathEntry *entry,
162 unsigned int off);
163
164
165/**
166 * Get the tunnel towards a peer.
167 *
168 * @param cp Peer to get from.
169 * @param create #GNUNET_YES to create a tunnel if we do not have one
170 * @return Tunnel towards peer.
171 */
172struct CadetTunnel *
173GCP_get_tunnel (struct CadetPeer *cp,
174 int create);
175
176
177/**
178 * The tunnel to the given peer no longer exists, remove it from our
179 * data structures, and possibly clean up the peer itself.
180 *
181 * @param cp the peer affected
182 * @param t the dead tunnel
183 */
184void
185GCP_drop_tunnel (struct CadetPeer *cp,
186 struct CadetTunnel *t);
187
188
189/**
190 * Try adding a @a path to this @a cp. If the peer already
191 * has plenty of paths, return NULL.
192 *
193 * @param cp peer to which the @a path leads to
194 * @param path a path looking for an owner; may not be fully initialized yet!
195 * @param off offset of @a cp in @a path
196 * @return NULL if this peer does not care to become a new owner,
197 * otherwise the node in the peer's path heap for the @a path.
198 */
199struct GNUNET_CONTAINER_HeapNode *
200GCP_attach_path (struct CadetPeer *cp,
201 struct CadetPeerPath *path,
202 unsigned int off);
203
204
205/**
206 * This peer can no longer own @a path as the path
207 * has been extended and a peer further down the line
208 * is now the new owner.
209 *
210 * @param cp old owner of the @a path
211 * @param path path where the ownership is lost
212 * @param hn note in @a cp's path heap that must be deleted
213 */
214void
215GCP_detach_path (struct CadetPeer *cp,
216 struct CadetPeerPath *path,
217 struct GNUNET_CONTAINER_HeapNode *hn);
218
219
220/**
221 * Add a @a connection to this @a cp.
222 *
223 * @param cp peer via which the @a connection goes
224 * @param cc the connection to add
225 */
226void
227GCP_add_connection (struct CadetPeer *cp,
228 struct CadetConnection *cc);
229
230
231/**
232 * Remove a @a connection that went via this @a cp.
233 *
234 * @param cp peer via which the @a connection went
235 * @param cc the connection to remove
236 */
237void
238GCP_remove_connection (struct CadetPeer *cp,
239 struct CadetConnection *cc);
240
241
242/**
243 * We got a HELLO for a @a cp, remember it, and possibly
244 * trigger adequate actions (like trying to connect).
245 *
246 * @param cp the peer we got a HELLO for
247 * @param hello the HELLO to remember
248 */
249void
250GCP_set_hello (struct CadetPeer *cp,
251 const struct GNUNET_HELLO_Message *hello);
252
253
254/**
255 * Clean up all entries about all peers.
256 * Must only be called after all tunnels, CORE-connections and
257 * connections are down.
258 */
259void
260GCP_destroy_all_peers (void);
261
262
263/**
264 * Data structure used to track whom we have to notify about changes
265 * in our ability to transmit to a given peer.
266 *
267 * All queue managers will be given equal chance for sending messages
268 * to @a cp. This construct this guarantees fairness for access to @a
269 * cp among the different message queues. Each connection or route
270 * will have its respective message queue managers for each direction.
271 */
272struct GCP_MessageQueueManager;
273
274
275/**
276 * Function to call with updated message queue object.
277 *
278 * @param cls closure
279 * @param available #GNUNET_YES if sending is now possible,
280 * #GNUNET_NO if sending is no longer possible
281 * #GNUNET_SYSERR if sending is no longer possible
282 * and the last envelope was discarded
283 */
284typedef void
285(*GCP_MessageQueueNotificationCallback)(void *cls,
286 int available);
287
288
289/**
290 * Start message queue change notifications. Will create a new slot
291 * to manage the message queue to the given @a cp.
292 *
293 * @param cp peer to notify for
294 * @param cb function to call if mq becomes available or unavailable
295 * @param cb_cls closure for @a cb
296 * @return handle to cancel request
297 */
298struct GCP_MessageQueueManager *
299GCP_request_mq (struct CadetPeer *cp,
300 GCP_MessageQueueNotificationCallback cb,
301 void *cb_cls);
302
303
304/**
305 * Test if @a cp has a core-level connection
306 *
307 * @param cp peer to test
308 * @return #GNUNET_YES if @a cp has a core-level connection
309 */
310int
311GCP_has_core_connection (struct CadetPeer *cp);
312
313
314/**
315 * Send the message in @a env via a @a mqm. Must only be called at
316 * most once after the respective
317 * #GCP_MessageQueueNotificationCallback was called with `available`
318 * set to #GNUNET_YES, and not after the callback was called with
319 * `available` set to #GNUNET_NO or #GNUNET_SYSERR.
320 *
321 * @param mqm message queue manager for the transmission
322 * @param env envelope with the message to send; must NOT
323 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
324 */
325void
326GCP_send (struct GCP_MessageQueueManager *mqm,
327 struct GNUNET_MQ_Envelope *env);
328
329
330/**
331 * Send the message in @a env to @a cp, overriding queueing logic.
332 * This function should only be used to send error messages outside
333 * of flow and congestion control, similar to ICMP. Note that
334 * the envelope may be silently discarded as well.
335 *
336 * @param cp peer to send the message to
337 * @param env envelope with the message to send
338 */
339void
340GCP_send_ooo (struct CadetPeer *cp,
341 struct GNUNET_MQ_Envelope *env);
342
343
344/**
345 * Stops message queue change notifications and sends a last message.
346 * In practice, this is implemented by sending that @a last_env
347 * message immediately (if any), ignoring queue order.
348 *
349 * @param mqm handle matching request to cancel
350 * @param last_env final message to transmit, or NULL
351 */
352void
353GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
354 struct GNUNET_MQ_Envelope *last_env);
355
356
357/**
358 * Set the message queue to @a mq for peer @a cp and notify watchers.
359 *
360 * @param cp peer to modify
361 * @param mq message queue to set (can be NULL)
362 */
363void
364GCP_set_mq (struct CadetPeer *cp,
365 struct GNUNET_MQ_Handle *mq);
366
367
368#endif
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c b/src/cadet/gnunet-service-cadet-new_tunnels.c
new file mode 100644
index 000000000..23b270b82
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_tunnels.c
@@ -0,0 +1,2249 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2013, 2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_tunnels.c
24 * @brief Information we track per tunnel.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 *
28 * FIXME:
29 * - when managing connections, distinguish those that
30 * have (recently) had traffic from those that were
31 * never ready (or not recently)
32 * - implement sending and receiving KX messages
33 * - implement processing of incoming decrypted plaintext messages
34 * - clean up KX logic!
35 */
36#include "platform.h"
37#include "gnunet_util_lib.h"
38#include "gnunet_statistics_service.h"
39#include "gnunet_signatures.h"
40#include "cadet_protocol.h"
41#include "cadet_path.h"
42#include "gnunet-service-cadet-new.h"
43#include "gnunet-service-cadet-new_channel.h"
44#include "gnunet-service-cadet-new_connection.h"
45#include "gnunet-service-cadet-new_tunnels.h"
46#include "gnunet-service-cadet-new_peer.h"
47#include "gnunet-service-cadet-new_paths.h"
48
49
50#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__)
51
52
53/**
54 * How long do we wait until tearing down an idle tunnel?
55 */
56#define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90)
57
58/**
59 * Yuck, replace by 'offsetof' expression?
60 * FIXME.
61 */
62#define AX_HEADER_SIZE (sizeof (uint32_t) * 2\
63 + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey))
64
65
66/**
67 * Maximum number of skipped keys we keep in memory per tunnel.
68 */
69#define MAX_SKIPPED_KEYS 64
70
71/**
72 * Maximum number of keys (and thus ratchet steps) we are willing to
73 * skip before we decide this is either a bogus packet or a DoS-attempt.
74 */
75#define MAX_KEY_GAP 256
76
77
78/**
79 * Struct to old keys for skipped messages while advancing the Axolotl ratchet.
80 */
81struct CadetTunnelSkippedKey
82{
83 /**
84 * DLL next.
85 */
86 struct CadetTunnelSkippedKey *next;
87
88 /**
89 * DLL prev.
90 */
91 struct CadetTunnelSkippedKey *prev;
92
93 /**
94 * When was this key stored (for timeout).
95 */
96 struct GNUNET_TIME_Absolute timestamp;
97
98 /**
99 * Header key.
100 */
101 struct GNUNET_CRYPTO_SymmetricSessionKey HK;
102
103 /**
104 * Message key.
105 */
106 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
107
108 /**
109 * Key number for a given HK.
110 */
111 unsigned int Kn;
112};
113
114
115/**
116 * Axolotl data, according to https://github.com/trevp/axolotl/wiki .
117 */
118struct CadetTunnelAxolotl
119{
120 /**
121 * A (double linked) list of stored message keys and associated header keys
122 * for "skipped" messages, i.e. messages that have not been
123 * received despite the reception of more recent messages, (head).
124 */
125 struct CadetTunnelSkippedKey *skipped_head;
126
127 /**
128 * Skipped messages' keys DLL, tail.
129 */
130 struct CadetTunnelSkippedKey *skipped_tail;
131
132 /**
133 * 32-byte root key which gets updated by DH ratchet.
134 */
135 struct GNUNET_CRYPTO_SymmetricSessionKey RK;
136
137 /**
138 * 32-byte header key (send).
139 */
140 struct GNUNET_CRYPTO_SymmetricSessionKey HKs;
141
142 /**
143 * 32-byte header key (recv)
144 */
145 struct GNUNET_CRYPTO_SymmetricSessionKey HKr;
146
147 /**
148 * 32-byte next header key (send).
149 */
150 struct GNUNET_CRYPTO_SymmetricSessionKey NHKs;
151
152 /**
153 * 32-byte next header key (recv).
154 */
155 struct GNUNET_CRYPTO_SymmetricSessionKey NHKr;
156
157 /**
158 * 32-byte chain keys (used for forward-secrecy updating, send).
159 */
160 struct GNUNET_CRYPTO_SymmetricSessionKey CKs;
161
162 /**
163 * 32-byte chain keys (used for forward-secrecy updating, recv).
164 */
165 struct GNUNET_CRYPTO_SymmetricSessionKey CKr;
166
167 /**
168 * ECDH for key exchange (A0 / B0).
169 */
170 struct GNUNET_CRYPTO_EcdhePrivateKey *kx_0;
171
172 /**
173 * ECDH Ratchet key (send).
174 */
175 struct GNUNET_CRYPTO_EcdhePrivateKey *DHRs;
176
177 /**
178 * ECDH Ratchet key (recv).
179 */
180 struct GNUNET_CRYPTO_EcdhePublicKey DHRr;
181
182 /**
183 * When does this ratchet expire and a new one is triggered.
184 */
185 struct GNUNET_TIME_Absolute ratchet_expiration;
186
187 /**
188 * Number of elements in @a skipped_head <-> @a skipped_tail.
189 */
190 unsigned int skipped;
191
192 /**
193 * Message number (reset to 0 with each new ratchet, next message to send).
194 */
195 uint32_t Ns;
196
197 /**
198 * Message number (reset to 0 with each new ratchet, next message to recv).
199 */
200 uint32_t Nr;
201
202 /**
203 * Previous message numbers (# of msgs sent under prev ratchet)
204 */
205 uint32_t PNs;
206
207 /**
208 * True (#GNUNET_YES) if we have to send a new ratchet key in next msg.
209 */
210 int ratchet_flag;
211
212 /**
213 * Number of messages recieved since our last ratchet advance.
214 * - If this counter = 0, we cannot send a new ratchet key in next msg.
215 * - If this counter > 0, we can (but don't yet have to) send a new key.
216 */
217 unsigned int ratchet_allowed;
218
219 /**
220 * Number of messages recieved since our last ratchet advance.
221 * - If this counter = 0, we cannot send a new ratchet key in next msg.
222 * - If this counter > 0, we can (but don't yet have to) send a new key.
223 */
224 unsigned int ratchet_counter;
225
226};
227
228
229/**
230 * Struct used to save messages in a non-ready tunnel to send once connected.
231 */
232struct CadetTunnelQueueEntry
233{
234 /**
235 * We are entries in a DLL
236 */
237 struct CadetTunnelQueueEntry *next;
238
239 /**
240 * We are entries in a DLL
241 */
242 struct CadetTunnelQueueEntry *prev;
243
244 /**
245 * Tunnel these messages belong in.
246 */
247 struct CadetTunnel *t;
248
249 /**
250 * Continuation to call once sent (on the channel layer).
251 */
252 GNUNET_SCHEDULER_TaskCallback cont;
253
254 /**
255 * Closure for @c cont.
256 */
257 void *cont_cls;
258
259 /**
260 * Envelope of message to send follows.
261 */
262 struct GNUNET_MQ_Envelope *env;
263
264 /**
265 * Where to put the connection identifier into the payload
266 * of the message in @e env once we have it?
267 */
268 struct GNUNET_CADET_ConnectionTunnelIdentifier *cid;
269};
270
271
272/**
273 * Struct containing all information regarding a tunnel to a peer.
274 */
275struct CadetTunnel
276{
277 /**
278 * Destination of the tunnel.
279 */
280 struct CadetPeer *destination;
281
282 /**
283 * Peer's ephemeral key, to recreate @c e_key and @c d_key when own
284 * ephemeral key changes.
285 */
286 struct GNUNET_CRYPTO_EcdhePublicKey peers_ephemeral_key;
287
288 /**
289 * Encryption ("our") key. It is only "confirmed" if kx_ctx is NULL.
290 */
291 struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
292
293 /**
294 * Decryption ("their") key. It is only "confirmed" if kx_ctx is NULL.
295 */
296 struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
297
298 /**
299 * Axolotl info.
300 */
301 struct CadetTunnelAxolotl ax;
302
303 /**
304 * State of the tunnel connectivity.
305 */
306 enum CadetTunnelCState cstate;
307
308 /**
309 * State of the tunnel encryption.
310 */
311 enum CadetTunnelEState estate;
312
313 /**
314 * Task to start the rekey process.
315 */
316 struct GNUNET_SCHEDULER_Task *rekey_task;
317
318 /**
319 * Tokenizer for decrypted messages.
320 */
321 struct GNUNET_MessageStreamTokenizer *mst;
322
323 /**
324 * Dispatcher for decrypted messages only (do NOT use for sending!).
325 */
326 struct GNUNET_MQ_Handle *mq;
327
328 /**
329 * DLL of connections that are actively used to reach the destination peer.
330 */
331 struct CadetTConnection *connection_head;
332
333 /**
334 * DLL of connections that are actively used to reach the destination peer.
335 */
336 struct CadetTConnection *connection_tail;
337
338 /**
339 * Channels inside this tunnel. Maps
340 * `struct GNUNET_CADET_ChannelTunnelNumber` to a `struct CadetChannel`.
341 */
342 struct GNUNET_CONTAINER_MultiHashMap32 *channels;
343
344 /**
345 * Channel ID for the next created channel in this tunnel.
346 */
347 struct GNUNET_CADET_ChannelTunnelNumber next_chid;
348
349 /**
350 * Queued messages, to transmit once tunnel gets connected.
351 */
352 struct CadetTunnelQueueEntry *tq_head;
353
354 /**
355 * Queued messages, to transmit once tunnel gets connected.
356 */
357 struct CadetTunnelQueueEntry *tq_tail;
358
359 /**
360 * Task scheduled if there are no more channels using the tunnel.
361 */
362 struct GNUNET_SCHEDULER_Task *destroy_task;
363
364 /**
365 * Task to trim connections if too many are present.
366 */
367 struct GNUNET_SCHEDULER_Task *maintain_connections_task;
368
369 /**
370 * Ephemeral message in the queue (to avoid queueing more than one).
371 */
372 struct CadetConnectionQueue *ephm_hKILL;
373
374 /**
375 * Pong message in the queue.
376 */
377 struct CadetConnectionQueue *pong_hKILL;
378
379 /**
380 * Number of connections in the @e connection_head DLL.
381 */
382 unsigned int num_connections;
383
384 /**
385 * Number of entries in the @e tq_head DLL.
386 */
387 unsigned int tq_len;
388};
389
390
391/**
392 * Get the static string for the peer this tunnel is directed.
393 *
394 * @param t Tunnel.
395 *
396 * @return Static string the destination peer's ID.
397 */
398const char *
399GCT_2s (const struct CadetTunnel *t)
400{
401 static char buf[64];
402
403 if (NULL == t)
404 return "T(NULL)";
405
406 GNUNET_snprintf (buf,
407 sizeof (buf),
408 "T(%s)",
409 GCP_2s (t->destination));
410 return buf;
411}
412
413
414/**
415 * Return the peer to which this tunnel goes.
416 *
417 * @param t a tunnel
418 * @return the destination of the tunnel
419 */
420struct CadetPeer *
421GCT_get_destination (struct CadetTunnel *t)
422{
423 return t->destination;
424}
425
426
427/**
428 * Count channels of a tunnel.
429 *
430 * @param t Tunnel on which to count.
431 *
432 * @return Number of channels.
433 */
434unsigned int
435GCT_count_channels (struct CadetTunnel *t)
436{
437 return GNUNET_CONTAINER_multihashmap32_size (t->channels);
438}
439
440
441/**
442 * Lookup a channel by its @a chid.
443 *
444 * @param t tunnel to look in
445 * @param chid number of channel to find
446 * @return NULL if channel does not exist
447 */
448struct CadetChannel *
449lookup_channel (struct CadetTunnel *t,
450 struct GNUNET_CADET_ChannelTunnelNumber chid)
451{
452 return GNUNET_CONTAINER_multihashmap32_get (t->channels,
453 ntohl (chid.cn));
454}
455
456
457/**
458 * Count all created connections of a tunnel. Not necessarily ready connections!
459 *
460 * @param t Tunnel on which to count.
461 *
462 * @return Number of connections created, either being established or ready.
463 */
464unsigned int
465GCT_count_any_connections (struct CadetTunnel *t)
466{
467 return t->num_connections;
468}
469
470
471/**
472 * Get the connectivity state of a tunnel.
473 *
474 * @param t Tunnel.
475 *
476 * @return Tunnel's connectivity state.
477 */
478enum CadetTunnelCState
479GCT_get_cstate (struct CadetTunnel *t)
480{
481 return t->cstate;
482}
483
484
485/**
486 * Get the encryption state of a tunnel.
487 *
488 * @param t Tunnel.
489 *
490 * @return Tunnel's encryption state.
491 */
492enum CadetTunnelEState
493GCT_get_estate (struct CadetTunnel *t)
494{
495 return t->estate;
496}
497
498
499/**
500 * Create a new Axolotl ephemeral (ratchet) key.
501 *
502 * @param t Tunnel.
503 */
504static void
505new_ephemeral (struct CadetTunnel *t)
506{
507 GNUNET_free_non_null (t->ax.DHRs);
508 t->ax.DHRs = GNUNET_CRYPTO_ecdhe_key_create ();
509}
510
511
512/* ************************************** start core crypto ***************************** */
513
514
515/**
516 * Calculate HMAC.
517 *
518 * @param plaintext Content to HMAC.
519 * @param size Size of @c plaintext.
520 * @param iv Initialization vector for the message.
521 * @param key Key to use.
522 * @param hmac[out] Destination to store the HMAC.
523 */
524static void
525t_hmac (const void *plaintext,
526 size_t size,
527 uint32_t iv,
528 const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
529 struct GNUNET_ShortHashCode *hmac)
530{
531 static const char ctx[] = "cadet authentication key";
532 struct GNUNET_CRYPTO_AuthKey auth_key;
533 struct GNUNET_HashCode hash;
534
535 GNUNET_CRYPTO_hmac_derive_key (&auth_key,
536 key,
537 &iv, sizeof (iv),
538 key, sizeof (*key),
539 ctx, sizeof (ctx),
540 NULL);
541 /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */
542 GNUNET_CRYPTO_hmac (&auth_key,
543 plaintext,
544 size,
545 &hash);
546 GNUNET_memcpy (hmac,
547 &hash,
548 sizeof (*hmac));
549}
550
551
552/**
553 * Perform a HMAC.
554 *
555 * @param key Key to use.
556 * @param hash[out] Resulting HMAC.
557 * @param source Source key material (data to HMAC).
558 * @param len Length of @a source.
559 */
560static void
561t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
562 struct GNUNET_HashCode *hash,
563 const void *source,
564 unsigned int len)
565{
566 static const char ctx[] = "axolotl HMAC-HASH";
567 struct GNUNET_CRYPTO_AuthKey auth_key;
568
569 GNUNET_CRYPTO_hmac_derive_key (&auth_key,
570 key,
571 ctx, sizeof (ctx),
572 NULL);
573 GNUNET_CRYPTO_hmac (&auth_key,
574 source,
575 len,
576 hash);
577}
578
579
580/**
581 * Derive a symmetric encryption key from an HMAC-HASH.
582 *
583 * @param key Key to use for the HMAC.
584 * @param[out] out Key to generate.
585 * @param source Source key material (data to HMAC).
586 * @param len Length of @a source.
587 */
588static void
589t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
590 struct GNUNET_CRYPTO_SymmetricSessionKey *out,
591 const void *source,
592 unsigned int len)
593{
594 static const char ctx[] = "axolotl derive key";
595 struct GNUNET_HashCode h;
596
597 t_ax_hmac_hash (key,
598 &h,
599 source,
600 len);
601 GNUNET_CRYPTO_kdf (out, sizeof (*out),
602 ctx, sizeof (ctx),
603 &h, sizeof (h),
604 NULL);
605}
606
607
608/**
609 * Encrypt data with the axolotl tunnel key.
610 *
611 * @param t Tunnel whose key to use.
612 * @param dst Destination with @a size bytes for the encrypted data.
613 * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes
614 * @param size Size of the buffers at @a src and @a dst
615 */
616static void
617t_ax_encrypt (struct CadetTunnel *t,
618 void *dst,
619 const void *src,
620 size_t size)
621{
622 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
623 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
624 struct CadetTunnelAxolotl *ax;
625 size_t out_size;
626
627 ax = &t->ax;
628 ax->ratchet_counter++;
629 if ( (GNUNET_YES == ax->ratchet_allowed) &&
630 ( (ratchet_messages <= ax->ratchet_counter) ||
631 (0 == GNUNET_TIME_absolute_get_remaining (ax->ratchet_expiration).rel_value_us)) )
632 {
633 ax->ratchet_flag = GNUNET_YES;
634 }
635 if (GNUNET_YES == ax->ratchet_flag)
636 {
637 /* Advance ratchet */
638 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
639 struct GNUNET_HashCode dh;
640 struct GNUNET_HashCode hmac;
641 static const char ctx[] = "axolotl ratchet";
642
643 new_ephemeral (t);
644 ax->HKs = ax->NHKs;
645
646 /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
647 GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
648 &ax->DHRr,
649 &dh);
650 t_ax_hmac_hash (&ax->RK,
651 &hmac,
652 &dh,
653 sizeof (dh));
654 GNUNET_CRYPTO_kdf (keys, sizeof (keys),
655 ctx, sizeof (ctx),
656 &hmac, sizeof (hmac),
657 NULL);
658 ax->RK = keys[0];
659 ax->NHKs = keys[1];
660 ax->CKs = keys[2];
661
662 ax->PNs = ax->Ns;
663 ax->Ns = 0;
664 ax->ratchet_flag = GNUNET_NO;
665 ax->ratchet_allowed = GNUNET_NO;
666 ax->ratchet_counter = 0;
667 ax->ratchet_expiration
668 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
669 ratchet_time);
670 }
671
672 t_hmac_derive_key (&ax->CKs,
673 &MK,
674 "0",
675 1);
676 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
677 &MK,
678 NULL, 0,
679 NULL);
680
681 out_size = GNUNET_CRYPTO_symmetric_encrypt (src,
682 size,
683 &MK,
684 &iv,
685 dst);
686 GNUNET_assert (size == out_size);
687 t_hmac_derive_key (&ax->CKs,
688 &ax->CKs,
689 "1",
690 1);
691}
692
693
694/**
695 * Decrypt data with the axolotl tunnel key.
696 *
697 * @param t Tunnel whose key to use.
698 * @param dst Destination for the decrypted data, must contain @a size bytes.
699 * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes.
700 * @param size Size of the @a src and @a dst buffers
701 */
702static void
703t_ax_decrypt (struct CadetTunnel *t,
704 void *dst,
705 const void *src,
706 size_t size)
707{
708 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
709 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
710 struct CadetTunnelAxolotl *ax;
711 size_t out_size;
712
713 ax = &t->ax;
714 t_hmac_derive_key (&ax->CKr,
715 &MK,
716 "0",
717 1);
718 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
719 &MK,
720 NULL, 0,
721 NULL);
722 GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
723 out_size = GNUNET_CRYPTO_symmetric_decrypt (src,
724 size,
725 &MK,
726 &iv,
727 dst);
728 GNUNET_assert (out_size == size);
729 t_hmac_derive_key (&ax->CKr,
730 &ax->CKr,
731 "1",
732 1);
733}
734
735
736/**
737 * Encrypt header with the axolotl header key.
738 *
739 * @param t Tunnel whose key to use.
740 * @param msg Message whose header to encrypt.
741 */
742static void
743t_h_encrypt (struct CadetTunnel *t,
744 struct GNUNET_CADET_TunnelEncryptedMessage *msg)
745{
746 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
747 struct CadetTunnelAxolotl *ax;
748 size_t out_size;
749
750 ax = &t->ax;
751 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
752 &ax->HKs,
753 NULL, 0,
754 NULL);
755 out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns,
756 AX_HEADER_SIZE,
757 &ax->HKs,
758 &iv,
759 &msg->Ns);
760 GNUNET_assert (AX_HEADER_SIZE == out_size);
761}
762
763
764/**
765 * Decrypt header with the current axolotl header key.
766 *
767 * @param t Tunnel whose current ax HK to use.
768 * @param src Message whose header to decrypt.
769 * @param dst Where to decrypt header to.
770 */
771static void
772t_h_decrypt (struct CadetTunnel *t,
773 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
774 struct GNUNET_CADET_TunnelEncryptedMessage *dst)
775{
776 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
777 struct CadetTunnelAxolotl *ax;
778 size_t out_size;
779
780 ax = &t->ax;
781 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
782 &ax->HKr,
783 NULL, 0,
784 NULL);
785 out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns,
786 AX_HEADER_SIZE,
787 &ax->HKr,
788 &iv,
789 &dst->Ns);
790 GNUNET_assert (AX_HEADER_SIZE == out_size);
791}
792
793
794/**
795 * Delete a key from the list of skipped keys.
796 *
797 * @param t Tunnel to delete from.
798 * @param key Key to delete.
799 */
800static void
801delete_skipped_key (struct CadetTunnel *t,
802 struct CadetTunnelSkippedKey *key)
803{
804 GNUNET_CONTAINER_DLL_remove (t->ax.skipped_head,
805 t->ax.skipped_tail,
806 key);
807 GNUNET_free (key);
808 t->ax.skipped--;
809}
810
811
812/**
813 * Decrypt and verify data with the appropriate tunnel key and verify that the
814 * data has not been altered since it was sent by the remote peer.
815 *
816 * @param t Tunnel whose key to use.
817 * @param dst Destination for the plaintext.
818 * @param src Source of the message. Can overlap with @c dst.
819 * @param size Size of the message.
820 * @return Size of the decrypted data, -1 if an error was encountered.
821 */
822static ssize_t
823try_old_ax_keys (struct CadetTunnel *t,
824 void *dst,
825 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
826 size_t size)
827{
828 struct CadetTunnelSkippedKey *key;
829 struct GNUNET_ShortHashCode *hmac;
830 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
831 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
832 struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
833 size_t esize;
834 size_t res;
835 size_t len;
836 unsigned int N;
837
838 LOG (GNUNET_ERROR_TYPE_DEBUG,
839 "Trying skipped keys\n");
840 hmac = &plaintext_header.hmac;
841 esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
842
843 /* Find a correct Header Key */
844 valid_HK = NULL;
845 for (key = t->ax.skipped_head; NULL != key; key = key->next)
846 {
847 t_hmac (&src->Ns,
848 AX_HEADER_SIZE + esize,
849 0,
850 &key->HK,
851 hmac);
852 if (0 == memcmp (hmac,
853 &src->hmac,
854 sizeof (*hmac)))
855 {
856 valid_HK = &key->HK;
857 break;
858 }
859 }
860 if (NULL == key)
861 return -1;
862
863 /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
864 GNUNET_assert (size > sizeof (struct GNUNET_CADET_TunnelEncryptedMessage));
865 len = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
866 GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader));
867
868 /* Decrypt header */
869 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
870 &key->HK,
871 NULL, 0,
872 NULL);
873 res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns,
874 AX_HEADER_SIZE,
875 &key->HK,
876 &iv,
877 &plaintext_header.Ns);
878 GNUNET_assert (AX_HEADER_SIZE == res);
879
880 /* Find the correct message key */
881 N = ntohl (plaintext_header.Ns);
882 while ( (NULL != key) &&
883 (N != key->Kn) )
884 key = key->next;
885 if ( (NULL == key) ||
886 (0 != memcmp (&key->HK,
887 valid_HK,
888 sizeof (*valid_HK))) )
889 return -1;
890
891 /* Decrypt payload */
892 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
893 &key->MK,
894 NULL,
895 0,
896 NULL);
897 res = GNUNET_CRYPTO_symmetric_decrypt (&src[1],
898 len,
899 &key->MK,
900 &iv,
901 dst);
902 delete_skipped_key (t,
903 key);
904 return res;
905}
906
907
908/**
909 * Delete a key from the list of skipped keys.
910 *
911 * @param t Tunnel to delete from.
912 * @param HKr Header Key to use.
913 */
914static void
915store_skipped_key (struct CadetTunnel *t,
916 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr)
917{
918 struct CadetTunnelSkippedKey *key;
919
920 key = GNUNET_new (struct CadetTunnelSkippedKey);
921 key->timestamp = GNUNET_TIME_absolute_get ();
922 key->Kn = t->ax.Nr;
923 key->HK = t->ax.HKr;
924 t_hmac_derive_key (&t->ax.CKr,
925 &key->MK,
926 "0",
927 1);
928 t_hmac_derive_key (&t->ax.CKr,
929 &t->ax.CKr,
930 "1",
931 1);
932 GNUNET_CONTAINER_DLL_insert (t->ax.skipped_head,
933 t->ax.skipped_tail,
934 key);
935 t->ax.skipped++;
936 t->ax.Nr++;
937}
938
939
940/**
941 * Stage skipped AX keys and calculate the message key.
942 * Stores each HK and MK for skipped messages.
943 *
944 * @param t Tunnel where to stage the keys.
945 * @param HKr Header key.
946 * @param Np Received meesage number.
947 * @return #GNUNET_OK if keys were stored.
948 * #GNUNET_SYSERR if an error ocurred (Np not expected).
949 */
950static int
951store_ax_keys (struct CadetTunnel *t,
952 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr,
953 uint32_t Np)
954{
955 int gap;
956
957 gap = Np - t->ax.Nr;
958 LOG (GNUNET_ERROR_TYPE_DEBUG,
959 "Storing skipped keys [%u, %u)\n",
960 t->ax.Nr,
961 Np);
962 if (MAX_KEY_GAP < gap)
963 {
964 /* Avoid DoS (forcing peer to do 2^33 chain HMAC operations) */
965 /* TODO: start new key exchange on return */
966 GNUNET_break_op (0);
967 LOG (GNUNET_ERROR_TYPE_WARNING,
968 "Got message %u, expected %u+\n",
969 Np,
970 t->ax.Nr);
971 return GNUNET_SYSERR;
972 }
973 if (0 > gap)
974 {
975 /* Delayed message: don't store keys, flag to try old keys. */
976 return GNUNET_SYSERR;
977 }
978
979 while (t->ax.Nr < Np)
980 store_skipped_key (t,
981 HKr);
982
983 while (t->ax.skipped > MAX_SKIPPED_KEYS)
984 delete_skipped_key (t,
985 t->ax.skipped_tail);
986 return GNUNET_OK;
987}
988
989
990/**
991 * Decrypt and verify data with the appropriate tunnel key and verify that the
992 * data has not been altered since it was sent by the remote peer.
993 *
994 * @param t Tunnel whose key to use.
995 * @param dst Destination for the plaintext.
996 * @param src Source of the message. Can overlap with @c dst.
997 * @param size Size of the message.
998 * @return Size of the decrypted data, -1 if an error was encountered.
999 */
1000static ssize_t
1001t_ax_decrypt_and_validate (struct CadetTunnel *t,
1002 void *dst,
1003 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
1004 size_t size)
1005{
1006 struct CadetTunnelAxolotl *ax;
1007 struct GNUNET_ShortHashCode msg_hmac;
1008 struct GNUNET_HashCode hmac;
1009 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
1010 uint32_t Np;
1011 uint32_t PNp;
1012 size_t esize; /* Size of encryped payload */
1013
1014 esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
1015 ax = &t->ax;
1016
1017 /* Try current HK */
1018 t_hmac (&src->Ns,
1019 AX_HEADER_SIZE + esize,
1020 0, &ax->HKr,
1021 &msg_hmac);
1022 if (0 != memcmp (&msg_hmac,
1023 &src->hmac,
1024 sizeof (msg_hmac)))
1025 {
1026 static const char ctx[] = "axolotl ratchet";
1027 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
1028 struct GNUNET_CRYPTO_SymmetricSessionKey HK;
1029 struct GNUNET_HashCode dh;
1030 struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
1031
1032 /* Try Next HK */
1033 t_hmac (&src->Ns,
1034 AX_HEADER_SIZE + esize,
1035 0,
1036 &ax->NHKr,
1037 &msg_hmac);
1038 if (0 != memcmp (&msg_hmac,
1039 &src->hmac,
1040 sizeof (msg_hmac)))
1041 {
1042 /* Try the skipped keys, if that fails, we're out of luck. */
1043 return try_old_ax_keys (t,
1044 dst,
1045 src,
1046 size);
1047 }
1048 HK = ax->HKr;
1049 ax->HKr = ax->NHKr;
1050 t_h_decrypt (t,
1051 src,
1052 &plaintext_header);
1053 Np = ntohl (plaintext_header.Ns);
1054 PNp = ntohl (plaintext_header.PNs);
1055 DHRp = &plaintext_header.DHRs;
1056 store_ax_keys (t,
1057 &HK,
1058 PNp);
1059
1060 /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
1061 GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
1062 DHRp,
1063 &dh);
1064 t_ax_hmac_hash (&ax->RK,
1065 &hmac,
1066 &dh, sizeof (dh));
1067 GNUNET_CRYPTO_kdf (keys, sizeof (keys),
1068 ctx, sizeof (ctx),
1069 &hmac, sizeof (hmac),
1070 NULL);
1071
1072 /* Commit "purported" keys */
1073 ax->RK = keys[0];
1074 ax->NHKr = keys[1];
1075 ax->CKr = keys[2];
1076 ax->DHRr = *DHRp;
1077 ax->Nr = 0;
1078 ax->ratchet_allowed = GNUNET_YES;
1079 }
1080 else
1081 {
1082 t_h_decrypt (t,
1083 src,
1084 &plaintext_header);
1085 Np = ntohl (plaintext_header.Ns);
1086 PNp = ntohl (plaintext_header.PNs);
1087 }
1088 if ( (Np != ax->Nr) &&
1089 (GNUNET_OK != store_ax_keys (t,
1090 &ax->HKr,
1091 Np)) )
1092 {
1093 /* Try the skipped keys, if that fails, we're out of luck. */
1094 return try_old_ax_keys (t,
1095 dst,
1096 src,
1097 size);
1098 }
1099
1100 t_ax_decrypt (t,
1101 dst,
1102 &src[1],
1103 esize);
1104 ax->Nr = Np + 1;
1105 return esize;
1106}
1107
1108
1109/**
1110 * Send a KX message.
1111 *
1112 * FIXME: does not take care of sender-authentication yet!
1113 *
1114 * @param t Tunnel on which to send it.
1115 * @param force_reply Force the other peer to reply with a KX message.
1116 */
1117static void
1118send_kx (struct CadetTunnel *t,
1119 int force_reply)
1120{
1121 struct CadetTunnelAxolotl *ax = &t->ax;
1122 struct CadetConnection *c;
1123 struct GNUNET_MQ_Envelope *env;
1124 struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
1125 enum GNUNET_CADET_KX_Flags flags;
1126
1127#if FIXME
1128 if (NULL != t->ephm_h)
1129 {
1130 LOG (GNUNET_ERROR_TYPE_INFO,
1131 " already queued, nop\n");
1132 return;
1133 }
1134#endif
1135 c = NULL; // FIXME: figure out where to transmit...
1136
1137 // GNUNET_assert (GNUNET_NO == GCT_is_loopback (t));
1138 env = GNUNET_MQ_msg (msg,
1139 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
1140 flags = GNUNET_CADET_KX_FLAG_NONE;
1141 if (GNUNET_YES == force_reply)
1142 flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
1143 msg->flags = htonl (flags);
1144 msg->cid = *GCC_get_id (c);
1145 GNUNET_CRYPTO_ecdhe_key_get_public (ax->kx_0,
1146 &msg->ephemeral_key);
1147 GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs,
1148 &msg->ratchet_key);
1149
1150 // FIXME: send 'env'.
1151#if FIXME
1152 t->ephm_h = GCC_send_prebuilt_message (&msg.header,
1153 UINT16_MAX,
1154 zero,
1155 c,
1156 GCC_is_origin (c, GNUNET_YES),
1157 GNUNET_YES, &ephm_sent, t);
1158 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
1159 GCT_change_estate (t, CADET_TUNNEL_KEY_SENT);
1160#endif
1161}
1162
1163
1164/**
1165 * Handle KX message.
1166 *
1167 * FIXME: sender-authentication in KX is missing!
1168 *
1169 * @param ct connection/tunnel combo that received encrypted message
1170 * @param msg the key exchange message
1171 */
1172void
1173GCT_handle_kx (struct CadetTConnection *ct,
1174 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1175{
1176 struct CadetTunnel *t = ct->t;
1177 struct CadetTunnelAxolotl *ax = &t->ax;
1178 struct GNUNET_HashCode key_material[3];
1179 struct GNUNET_CRYPTO_SymmetricSessionKey keys[5];
1180 const char salt[] = "CADET Axolotl salt";
1181 const struct GNUNET_PeerIdentity *pid;
1182 int am_I_alice;
1183
1184 pid = GCP_get_id (t->destination);
1185 if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id,
1186 pid))
1187 am_I_alice = GNUNET_YES;
1188 else if (0 < GNUNET_CRYPTO_cmp_peer_identity (&my_full_id,
1189 pid))
1190 am_I_alice = GNUNET_NO;
1191 else
1192 {
1193 GNUNET_break_op (0);
1194 return;
1195 }
1196
1197 if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->flags)))
1198 {
1199 if (NULL != t->rekey_task)
1200 {
1201 GNUNET_SCHEDULER_cancel (t->rekey_task);
1202 t->rekey_task = NULL;
1203 }
1204 send_kx (t,
1205 GNUNET_NO);
1206 }
1207
1208 if (0 == memcmp (&ax->DHRr,
1209 &msg->ratchet_key,
1210 sizeof (msg->ratchet_key)))
1211 {
1212 LOG (GNUNET_ERROR_TYPE_INFO,
1213 " known ratchet key, exit\n");
1214 return;
1215 }
1216
1217 ax->DHRr = msg->ratchet_key;
1218
1219 /* ECDH A B0 */
1220 if (GNUNET_YES == am_I_alice)
1221 {
1222 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* A */
1223 &msg->ephemeral_key, /* B0 */
1224 &key_material[0]);
1225 }
1226 else
1227 {
1228 GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* B0 */
1229 &pid->public_key, /* A */
1230 &key_material[0]);
1231 }
1232
1233 /* ECDH A0 B */
1234 if (GNUNET_YES == am_I_alice)
1235 {
1236 GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* A0 */
1237 &pid->public_key, /* B */
1238 &key_material[1]);
1239 }
1240 else
1241 {
1242 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* A */
1243 &msg->ephemeral_key, /* B0 */
1244 &key_material[1]);
1245
1246
1247 }
1248
1249 /* ECDH A0 B0 */
1250 /* (This is the triple-DH, we could probably safely skip this,
1251 as A0/B0 are already in the key material.) */
1252 GNUNET_CRYPTO_ecc_ecdh (ax->kx_0, /* A0 or B0 */
1253 &msg->ephemeral_key, /* B0 or A0 */
1254 &key_material[2]);
1255
1256 /* KDF */
1257 GNUNET_CRYPTO_kdf (keys, sizeof (keys),
1258 salt, sizeof (salt),
1259 &key_material, sizeof (key_material),
1260 NULL);
1261
1262 if (0 == memcmp (&ax->RK,
1263 &keys[0],
1264 sizeof (ax->RK)))
1265 {
1266 LOG (GNUNET_ERROR_TYPE_INFO,
1267 " known handshake key, exit\n");
1268 return;
1269 }
1270 ax->RK = keys[0];
1271 if (GNUNET_YES == am_I_alice)
1272 {
1273 ax->HKr = keys[1];
1274 ax->NHKs = keys[2];
1275 ax->NHKr = keys[3];
1276 ax->CKr = keys[4];
1277 ax->ratchet_flag = GNUNET_YES;
1278 }
1279 else
1280 {
1281 ax->HKs = keys[1];
1282 ax->NHKr = keys[2];
1283 ax->NHKs = keys[3];
1284 ax->CKs = keys[4];
1285 ax->ratchet_flag = GNUNET_NO;
1286 ax->ratchet_allowed = GNUNET_NO;
1287 ax->ratchet_counter = 0;
1288 ax->ratchet_expiration
1289 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
1290 ratchet_time);
1291 }
1292 ax->PNs = 0;
1293 ax->Nr = 0;
1294 ax->Ns = 0;
1295
1296#if FIXME
1297 /* After KX is done, update state machine and begin transmissions... */
1298 GCT_change_estate (t,
1299 CADET_TUNNEL_KEY_PING);
1300 send_queued_data (t);
1301#endif
1302}
1303
1304
1305/* ************************************** end core crypto ***************************** */
1306
1307
1308/**
1309 * Add a channel to a tunnel.
1310 *
1311 * @param t Tunnel.
1312 * @param ch Channel
1313 * @return unique number identifying @a ch within @a t
1314 */
1315struct GNUNET_CADET_ChannelTunnelNumber
1316GCT_add_channel (struct CadetTunnel *t,
1317 struct CadetChannel *ch)
1318{
1319 struct GNUNET_CADET_ChannelTunnelNumber ret;
1320 uint32_t chid;
1321
1322 chid = ntohl (t->next_chid.cn);
1323 while (NULL !=
1324 GNUNET_CONTAINER_multihashmap32_get (t->channels,
1325 chid))
1326 chid++;
1327 GNUNET_assert (GNUNET_YES ==
1328 GNUNET_CONTAINER_multihashmap32_put (t->channels,
1329 chid,
1330 ch,
1331 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1332 t->next_chid.cn = htonl (chid + 1);
1333 ret.cn = htonl (chid);
1334 return ret;
1335}
1336
1337
1338/**
1339 * This tunnel is no longer used, destroy it.
1340 *
1341 * @param cls the idle tunnel
1342 */
1343static void
1344destroy_tunnel (void *cls)
1345{
1346 struct CadetTunnel *t = cls;
1347 struct CadetTConnection *ct;
1348 struct CadetTunnelQueueEntry *tqe;
1349
1350 t->destroy_task = NULL;
1351 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (t->channels));
1352 while (NULL != (ct = t->connection_head))
1353 {
1354 GNUNET_assert (ct->t == t);
1355 GNUNET_CONTAINER_DLL_remove (t->connection_head,
1356 t->connection_tail,
1357 ct);
1358 GCC_destroy (ct->cc);
1359 GNUNET_free (ct);
1360 }
1361 while (NULL != (tqe = t->tq_head))
1362 {
1363 GNUNET_CONTAINER_DLL_remove (t->tq_head,
1364 t->tq_tail,
1365 tqe);
1366 GNUNET_MQ_discard (tqe->env);
1367 GNUNET_free (tqe);
1368 }
1369 GCP_drop_tunnel (t->destination,
1370 t);
1371 GNUNET_CONTAINER_multihashmap32_destroy (t->channels);
1372 if (NULL != t->maintain_connections_task)
1373 {
1374 GNUNET_SCHEDULER_cancel (t->maintain_connections_task);
1375 t->maintain_connections_task = NULL;
1376 }
1377 GNUNET_MST_destroy (t->mst);
1378 GNUNET_MQ_destroy (t->mq);
1379 GNUNET_free (t);
1380}
1381
1382
1383/**
1384 * A connection is @a is_ready for transmission. Looks at our message
1385 * queue and if there is a message, sends it out via the connection.
1386 *
1387 * @param cls the `struct CadetTConnection` that is @a is_ready
1388 * @param is_ready #GNUNET_YES if connection are now ready,
1389 * #GNUNET_NO if connection are no longer ready
1390 */
1391static void
1392connection_ready_cb (void *cls,
1393 int is_ready)
1394{
1395 struct CadetTConnection *ct = cls;
1396 struct CadetTunnel *t = ct->t;
1397 struct CadetTunnelQueueEntry *tq = t->tq_head;
1398
1399 if (GNUNET_NO == ct->is_ready)
1400 {
1401 ct->is_ready = GNUNET_NO;
1402 return;
1403 }
1404 ct->is_ready = GNUNET_YES;
1405 if (NULL == tq)
1406 return; /* no messages pending right now */
1407
1408 /* ready to send message 'tq' on tunnel 'ct' */
1409 GNUNET_assert (t == tq->t);
1410 GNUNET_CONTAINER_DLL_remove (t->tq_head,
1411 t->tq_tail,
1412 tq);
1413 if (NULL != tq->cid)
1414 *tq->cid = *GCC_get_id (ct->cc);
1415 ct->is_ready = GNUNET_NO;
1416 GCC_transmit (ct->cc,
1417 tq->env);
1418 tq->cont (tq->cont_cls);
1419 GNUNET_free (tq);
1420}
1421
1422
1423/**
1424 * Called when either we have a new connection, or a new message in the
1425 * queue, or some existing connection has transmission capacity. Looks
1426 * at our message queue and if there is a message, picks a connection
1427 * to send it on.
1428 *
1429 * FIXME: yuck... Need better selection logic!
1430 *
1431 * @param t tunnel to process messages on
1432 */
1433static void
1434trigger_transmissions (struct CadetTunnel *t)
1435{
1436 struct CadetTConnection *ct;
1437
1438 if (NULL == t->tq_head)
1439 return; /* no messages pending right now */
1440 for (ct = t->connection_head;
1441 NULL != ct;
1442 ct = ct->next)
1443 if (GNUNET_YES == ct->is_ready)
1444 break;
1445 if (NULL == ct)
1446 return; /* no connections ready */
1447
1448 /* FIXME: a bit hackish to do it like this... */
1449 connection_ready_cb (ct,
1450 GNUNET_YES);
1451}
1452
1453
1454/**
1455 * Function called to maintain the connections underlying our tunnel.
1456 * Tries to maintain (incl. tear down) connections for the tunnel, and
1457 * if there is a significant change, may trigger transmissions.
1458 *
1459 * Basically, needs to check if there are connections that perform
1460 * badly, and if so eventually kill them and trigger a replacement.
1461 * The strategy is to open one more connection than
1462 * #DESIRED_CONNECTIONS_PER_TUNNEL, and then periodically kick out the
1463 * least-performing one, and then inquire for new ones.
1464 *
1465 * @param cls the `struct CadetTunnel`
1466 */
1467static void
1468maintain_connections_cb (void *cls)
1469{
1470 struct CadetTunnel *t = cls;
1471
1472 GNUNET_break (0); // FIXME: implement!
1473}
1474
1475
1476/**
1477 * Consider using the path @a p for the tunnel @a t.
1478 * The tunnel destination is at offset @a off in path @a p.
1479 *
1480 * @param cls our tunnel
1481 * @param path a path to our destination
1482 * @param off offset of the destination on path @a path
1483 * @return #GNUNET_YES (should keep iterating)
1484 */
1485static int
1486consider_path_cb (void *cls,
1487 struct CadetPeerPath *path,
1488 unsigned int off)
1489{
1490 struct CadetTunnel *t = cls;
1491 unsigned int min_length = UINT_MAX;
1492 GNUNET_CONTAINER_HeapCostType max_desire = 0;
1493 struct CadetTConnection *ct;
1494
1495 /* Check if we care about the new path. */
1496 for (ct = t->connection_head;
1497 NULL != ct;
1498 ct = ct->next)
1499 {
1500 struct CadetPeerPath *ps;
1501
1502 ps = GCC_get_path (ct->cc);
1503 if (ps == path)
1504 return GNUNET_YES; /* duplicate */
1505 min_length = GNUNET_MIN (min_length,
1506 GCPP_get_length (ps));
1507 max_desire = GNUNET_MAX (max_desire,
1508 GCPP_get_desirability (ps));
1509 }
1510
1511 /* FIXME: not sure we should really just count
1512 'num_connections' here, as they may all have
1513 consistently failed to connect. */
1514
1515 /* We iterate by increasing path length; if we have enough paths and
1516 this one is more than twice as long than what we are currently
1517 using, then ignore all of these super-long ones! */
1518 if ( (t->num_connections > DESIRED_CONNECTIONS_PER_TUNNEL) &&
1519 (min_length * 2 < off) )
1520 {
1521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1522 "Ignoring paths of length %u, they are way too long.\n",
1523 min_length * 2);
1524 return GNUNET_NO;
1525 }
1526 /* If we have enough paths and this one looks no better, ignore it. */
1527 if ( (t->num_connections >= DESIRED_CONNECTIONS_PER_TUNNEL) &&
1528 (min_length < GCPP_get_length (path)) &&
1529 (max_desire > GCPP_get_desirability (path)) )
1530 {
1531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1532 "Ignoring path (%u/%llu) to %s, got something better already.\n",
1533 GCPP_get_length (path),
1534 (unsigned long long) GCPP_get_desirability (path),
1535 GCP_2s (t->destination));
1536 return GNUNET_YES;
1537 }
1538
1539 /* Path is interesting (better by some metric, or we don't have
1540 enough paths yet). */
1541 ct = GNUNET_new (struct CadetTConnection);
1542 ct->created = GNUNET_TIME_absolute_get ();
1543 ct->t = t;
1544 ct->cc = GCC_create (t->destination,
1545 path,
1546 ct,
1547 &connection_ready_cb,
1548 ct);
1549 /* FIXME: schedule job to kill connection (and path?) if it takes
1550 too long to get ready! (And track performance data on how long
1551 other connections took with the tunnel!)
1552 => Note: to be done within 'connection'-logic! */
1553 GNUNET_CONTAINER_DLL_insert (t->connection_head,
1554 t->connection_tail,
1555 ct);
1556 t->num_connections++;
1557 return GNUNET_YES;
1558}
1559
1560
1561/**
1562 * Consider using the path @a p for the tunnel @a t.
1563 * The tunnel destination is at offset @a off in path @a p.
1564 *
1565 * @param cls our tunnel
1566 * @param path a path to our destination
1567 * @param off offset of the destination on path @a path
1568 */
1569void
1570GCT_consider_path (struct CadetTunnel *t,
1571 struct CadetPeerPath *p,
1572 unsigned int off)
1573{
1574 (void) consider_path_cb (t,
1575 p,
1576 off);
1577}
1578
1579
1580/**
1581 *
1582 *
1583 * @param cls the `struct CadetTunnel` for which we decrypted the message
1584 * @param msg the message we received on the tunnel
1585 */
1586static void
1587handle_plaintext_keepalive (void *cls,
1588 const struct GNUNET_MessageHeader *msg)
1589{
1590 struct CadetTunnel *t = cls;
1591 GNUNET_break (0); // FIXME
1592}
1593
1594
1595/**
1596 * Check that @a msg is well-formed.
1597 *
1598 * @param cls the `struct CadetTunnel` for which we decrypted the message
1599 * @param msg the message we received on the tunnel
1600 * @return #GNUNET_OK (any variable-size payload goes)
1601 */
1602static int
1603check_plaintext_data (void *cls,
1604 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1605{
1606 return GNUNET_OK;
1607}
1608
1609
1610/**
1611 *
1612 *
1613 * @param cls the `struct CadetTunnel` for which we decrypted the message
1614 * @param msg the message we received on the tunnel
1615 */
1616static void
1617handle_plaintext_data (void *cls,
1618 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1619{
1620 struct CadetTunnel *t = cls;
1621 GNUNET_break (0); // FIXME!
1622}
1623
1624
1625/**
1626 *
1627 *
1628 * @param cls the `struct CadetTunnel` for which we decrypted the message
1629 * @param ack the message we received on the tunnel
1630 */
1631static void
1632handle_plaintext_data_ack (void *cls,
1633 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1634{
1635 struct CadetTunnel *t = cls;
1636 GNUNET_break (0); // FIXME!
1637}
1638
1639
1640/**
1641 *
1642 *
1643 * @param cls the `struct CadetTunnel` for which we decrypted the message
1644 * @param cc the message we received on the tunnel
1645 */
1646static void
1647handle_plaintext_channel_create (void *cls,
1648 const struct GNUNET_CADET_ChannelOpenMessage *cc)
1649{
1650 struct CadetTunnel *t = cls;
1651 GNUNET_break (0); // FIXME!
1652}
1653
1654
1655/**
1656 *
1657 *
1658 * @param cls the `struct CadetTunnel` for which we decrypted the message
1659 * @param cm the message we received on the tunnel
1660 */
1661static void
1662handle_plaintext_channel_nack (void *cls,
1663 const struct GNUNET_CADET_ChannelManageMessage *cm)
1664{
1665 struct CadetTunnel *t = cls;
1666 GNUNET_break (0); // FIXME!
1667}
1668
1669
1670/**
1671 *
1672 *
1673 * @param cls the `struct CadetTunnel` for which we decrypted the message
1674 * @param cm the message we received on the tunnel
1675 */
1676static void
1677handle_plaintext_channel_ack (void *cls,
1678 const struct GNUNET_CADET_ChannelManageMessage *cm)
1679{
1680 struct CadetTunnel *t = cls;
1681 GNUNET_break (0); // FIXME!
1682}
1683
1684
1685/**
1686 * We received a message saying that a channel should be destroyed.
1687 * Pass it on to the correct channel.
1688 *
1689 * @param cls the `struct CadetTunnel` for which we decrypted the message
1690 * @param cm the message we received on the tunnel
1691 */
1692static void
1693handle_plaintext_channel_destroy (void *cls,
1694 const struct GNUNET_CADET_ChannelManageMessage *cm)
1695{
1696 struct CadetTunnel *t = cls;
1697 struct CadetChannel *cc = lookup_channel (t,
1698 cm->chid);
1699
1700 GCCH_channel_remote_destroy (cc);
1701}
1702
1703
1704/**
1705 * Handles a message we decrypted, by injecting it into
1706 * our message queue (which will do the dispatching).
1707 *
1708 * @param cls the `struct CadetTunnel` that got the message
1709 * @param msg the message
1710 * @return #GNUNET_OK (continue to process)
1711 */
1712static int
1713handle_decrypted (void *cls,
1714 const struct GNUNET_MessageHeader *msg)
1715{
1716 struct CadetTunnel *t = cls;
1717
1718 GNUNET_MQ_inject_message (t->mq,
1719 msg);
1720 return GNUNET_OK;
1721}
1722
1723
1724/**
1725 * Function called if we had an error processing
1726 * an incoming decrypted message.
1727 *
1728 * @param cls the `struct CadetTunnel`
1729 * @param error error code
1730 */
1731static void
1732decrypted_error_cb (void *cls,
1733 enum GNUNET_MQ_Error error)
1734{
1735 GNUNET_break_op (0);
1736}
1737
1738
1739/**
1740 * Create a tunnel to @a destionation. Must only be called
1741 * from within #GCP_get_tunnel().
1742 *
1743 * @param destination where to create the tunnel to
1744 * @return new tunnel to @a destination
1745 */
1746struct CadetTunnel *
1747GCT_create_tunnel (struct CadetPeer *destination)
1748{
1749 struct GNUNET_MQ_MessageHandler handlers[] = {
1750 GNUNET_MQ_hd_fixed_size (plaintext_keepalive,
1751 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE,
1752 struct GNUNET_MessageHeader,
1753 NULL),
1754 GNUNET_MQ_hd_var_size (plaintext_data,
1755 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA,
1756 struct GNUNET_CADET_ChannelAppDataMessage,
1757 NULL),
1758 GNUNET_MQ_hd_fixed_size (plaintext_data_ack,
1759 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK,
1760 struct GNUNET_CADET_ChannelDataAckMessage,
1761 NULL),
1762 GNUNET_MQ_hd_fixed_size (plaintext_channel_create,
1763 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
1764 struct GNUNET_CADET_ChannelOpenMessage,
1765 NULL),
1766 GNUNET_MQ_hd_fixed_size (plaintext_channel_nack,
1767 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED,
1768 struct GNUNET_CADET_ChannelManageMessage,
1769 NULL),
1770 GNUNET_MQ_hd_fixed_size (plaintext_channel_ack,
1771 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK,
1772 struct GNUNET_CADET_ChannelManageMessage,
1773 NULL),
1774 GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy,
1775 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
1776 struct GNUNET_CADET_ChannelManageMessage,
1777 NULL),
1778 GNUNET_MQ_handler_end ()
1779 };
1780 struct CadetTunnel *t;
1781
1782 t = GNUNET_new (struct CadetTunnel);
1783 t->destination = destination;
1784 t->channels = GNUNET_CONTAINER_multihashmap32_create (8);
1785 (void) GCP_iterate_paths (destination,
1786 &consider_path_cb,
1787 t);
1788 t->maintain_connections_task
1789 = GNUNET_SCHEDULER_add_now (&maintain_connections_cb,
1790 t);
1791 t->mq = GNUNET_MQ_queue_for_callbacks (NULL,
1792 NULL,
1793 NULL,
1794 NULL,
1795 handlers,
1796 &decrypted_error_cb,
1797 t);
1798 t->mst = GNUNET_MST_create (&handle_decrypted,
1799 t);
1800 return t;
1801}
1802
1803
1804/**
1805 * Remove a channel from a tunnel.
1806 *
1807 * @param t Tunnel.
1808 * @param ch Channel
1809 * @param gid unique number identifying @a ch within @a t
1810 */
1811void
1812GCT_remove_channel (struct CadetTunnel *t,
1813 struct CadetChannel *ch,
1814 struct GNUNET_CADET_ChannelTunnelNumber gid)
1815{
1816 GNUNET_assert (GNUNET_YES ==
1817 GNUNET_CONTAINER_multihashmap32_remove (t->channels,
1818 ntohl (gid.cn),
1819 ch));
1820 if (0 ==
1821 GNUNET_CONTAINER_multihashmap32_size (t->channels))
1822 {
1823 t->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY,
1824 &destroy_tunnel,
1825 t);
1826 }
1827}
1828
1829
1830/**
1831 * Change the tunnel encryption state.
1832 * If the encryption state changes to OK, stop the rekey task.
1833 *
1834 * @param t Tunnel whose encryption state to change, or NULL.
1835 * @param state New encryption state.
1836 */
1837void
1838GCT_change_estate (struct CadetTunnel *t,
1839 enum CadetTunnelEState state)
1840{
1841 enum CadetTunnelEState old = t->estate;
1842
1843 t->estate = state;
1844 LOG (GNUNET_ERROR_TYPE_DEBUG,
1845 "Tunnel %s estate changed from %d to %d\n",
1846 GCT_2s (t),
1847 old,
1848 state);
1849
1850 if ( (CADET_TUNNEL_KEY_OK != old) &&
1851 (CADET_TUNNEL_KEY_OK == t->estate) )
1852 {
1853 if (NULL != t->rekey_task)
1854 {
1855 GNUNET_SCHEDULER_cancel (t->rekey_task);
1856 t->rekey_task = NULL;
1857 }
1858#if FIXME
1859 /* Send queued data if tunnel is not loopback */
1860 if (myid != GCP_get_short_id (t->peer))
1861 send_queued_data (t);
1862#endif
1863 }
1864}
1865
1866
1867/**
1868 * Add a @a connection to the @a tunnel.
1869 *
1870 * @param t a tunnel
1871 * @param cid connection identifer to use for the connection
1872 * @param path path to use for the connection
1873 */
1874void
1875GCT_add_inbound_connection (struct CadetTunnel *t,
1876 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
1877 struct CadetPeerPath *path)
1878{
1879 struct CadetConnection *cc;
1880 struct CadetTConnection *ct;
1881
1882 ct = GNUNET_new (struct CadetTConnection);
1883 ct->created = GNUNET_TIME_absolute_get ();
1884 ct->t = t;
1885 ct->cc = GCC_create_inbound (t->destination,
1886 path,
1887 ct,
1888 cid,
1889 &connection_ready_cb,
1890 t);
1891 /* FIXME: schedule job to kill connection (and path?) if it takes
1892 too long to get ready! (And track performance data on how long
1893 other connections took with the tunnel!)
1894 => Note: to be done within 'connection'-logic! */
1895 GNUNET_CONTAINER_DLL_insert (t->connection_head,
1896 t->connection_tail,
1897 ct);
1898 t->num_connections++;
1899}
1900
1901
1902/**
1903 * Handle encrypted message.
1904 *
1905 * @param ct connection/tunnel combo that received encrypted message
1906 * @param msg the encrypted message to decrypt
1907 */
1908void
1909GCT_handle_encrypted (struct CadetTConnection *ct,
1910 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1911{
1912 struct CadetTunnel *t = ct->t;
1913 uint16_t size = ntohs (msg->header.size);
1914 char cbuf [size] GNUNET_ALIGN;
1915 ssize_t decrypted_size;
1916
1917 GNUNET_STATISTICS_update (stats,
1918 "# received encrypted",
1919 1,
1920 GNUNET_NO);
1921
1922 decrypted_size = t_ax_decrypt_and_validate (t,
1923 cbuf,
1924 msg,
1925 size);
1926
1927 if (-1 == decrypted_size)
1928 {
1929 GNUNET_STATISTICS_update (stats,
1930 "# unable to decrypt",
1931 1,
1932 GNUNET_NO);
1933 if (CADET_TUNNEL_KEY_PING <= t->estate)
1934 {
1935 GNUNET_break_op (0);
1936 LOG (GNUNET_ERROR_TYPE_WARNING,
1937 "Wrong crypto, tunnel %s\n",
1938 GCT_2s (t));
1939 GCT_debug (t,
1940 GNUNET_ERROR_TYPE_WARNING);
1941 }
1942 return;
1943 }
1944
1945 GCT_change_estate (t,
1946 CADET_TUNNEL_KEY_OK);
1947 /* The MST will ultimately call #handle_decrypted() on each message. */
1948 GNUNET_break_op (GNUNET_OK ==
1949 GNUNET_MST_from_buffer (t->mst,
1950 cbuf,
1951 decrypted_size,
1952 GNUNET_YES,
1953 GNUNET_NO));
1954}
1955
1956
1957/**
1958 * Sends an already built message on a tunnel, encrypting it and
1959 * choosing the best connection if not provided.
1960 *
1961 * @param message Message to send. Function modifies it.
1962 * @param t Tunnel on which this message is transmitted.
1963 * @param cont Continuation to call once message is really sent.
1964 * @param cont_cls Closure for @c cont.
1965 * @return Handle to cancel message. NULL if @c cont is NULL.
1966 */
1967struct CadetTunnelQueueEntry *
1968GCT_send (struct CadetTunnel *t,
1969 const struct GNUNET_MessageHeader *message,
1970 GNUNET_SCHEDULER_TaskCallback cont,
1971 void *cont_cls)
1972{
1973 struct CadetTunnelQueueEntry *tq;
1974 uint16_t payload_size;
1975 struct GNUNET_MQ_Envelope *env;
1976 struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
1977
1978 /* FIXME: what about KX not yet being ready? (see "is_ready()" check in old code!) */
1979
1980 payload_size = ntohs (message->size);
1981 env = GNUNET_MQ_msg_extra (ax_msg,
1982 payload_size,
1983 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
1984 t_ax_encrypt (t,
1985 &ax_msg[1],
1986 message,
1987 payload_size);
1988 ax_msg->Ns = htonl (t->ax.Ns++);
1989 ax_msg->PNs = htonl (t->ax.PNs);
1990 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs,
1991 &ax_msg->DHRs);
1992 t_h_encrypt (t,
1993 ax_msg);
1994 t_hmac (&ax_msg->Ns,
1995 AX_HEADER_SIZE + payload_size,
1996 0,
1997 &t->ax.HKs,
1998 &ax_msg->hmac);
1999 // ax_msg->pid = htonl (GCC_get_pid (c, fwd)); // FIXME: connection flow-control not (re)implemented yet!
2000
2001 tq = GNUNET_malloc (sizeof (*tq));
2002 tq->t = t;
2003 tq->env = env;
2004 tq->cid = &ax_msg->cid;
2005 tq->cont = cont;
2006 tq->cont_cls = cont_cls;
2007 GNUNET_CONTAINER_DLL_insert_tail (t->tq_head,
2008 t->tq_tail,
2009 tq);
2010 trigger_transmissions (t);
2011 return tq;
2012}
2013
2014
2015/**
2016 * Cancel a previously sent message while it's in the queue.
2017 *
2018 * ONLY can be called before the continuation given to the send
2019 * function is called. Once the continuation is called, the message is
2020 * no longer in the queue!
2021 *
2022 * @param q Handle to the queue entry to cancel.
2023 */
2024void
2025GCT_send_cancel (struct CadetTunnelQueueEntry *q)
2026{
2027 struct CadetTunnel *t = q->t;
2028
2029 GNUNET_CONTAINER_DLL_remove (t->tq_head,
2030 t->tq_tail,
2031 q);
2032 GNUNET_free (q);
2033}
2034
2035
2036/**
2037 * Iterate over all connections of a tunnel.
2038 *
2039 * @param t Tunnel whose connections to iterate.
2040 * @param iter Iterator.
2041 * @param iter_cls Closure for @c iter.
2042 */
2043void
2044GCT_iterate_connections (struct CadetTunnel *t,
2045 GCT_ConnectionIterator iter,
2046 void *iter_cls)
2047{
2048 for (struct CadetTConnection *ct = t->connection_head;
2049 NULL != ct;
2050 ct = ct->next)
2051 iter (iter_cls,
2052 ct->cc);
2053}
2054
2055
2056/**
2057 * Closure for #iterate_channels_cb.
2058 */
2059struct ChanIterCls
2060{
2061 /**
2062 * Function to call.
2063 */
2064 GCT_ChannelIterator iter;
2065
2066 /**
2067 * Closure for @e iter.
2068 */
2069 void *iter_cls;
2070};
2071
2072
2073/**
2074 * Helper function for #GCT_iterate_channels.
2075 *
2076 * @param cls the `struct ChanIterCls`
2077 * @param key unused
2078 * @param value a `struct CadetChannel`
2079 * @return #GNUNET_OK
2080 */
2081static int
2082iterate_channels_cb (void *cls,
2083 uint32_t key,
2084 void *value)
2085{
2086 struct ChanIterCls *ctx = cls;
2087 struct CadetChannel *ch = value;
2088
2089 ctx->iter (ctx->iter_cls,
2090 ch);
2091 return GNUNET_OK;
2092}
2093
2094
2095/**
2096 * Iterate over all channels of a tunnel.
2097 *
2098 * @param t Tunnel whose channels to iterate.
2099 * @param iter Iterator.
2100 * @param iter_cls Closure for @c iter.
2101 */
2102void
2103GCT_iterate_channels (struct CadetTunnel *t,
2104 GCT_ChannelIterator iter,
2105 void *iter_cls)
2106{
2107 struct ChanIterCls ctx;
2108
2109 ctx.iter = iter;
2110 ctx.iter_cls = iter_cls;
2111 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
2112 &iterate_channels_cb,
2113 &ctx);
2114
2115}
2116
2117
2118/**
2119 * Call #GCCH_debug() on a channel.
2120 *
2121 * @param cls points to the log level to use
2122 * @param key unused
2123 * @param value the `struct CadetChannel` to dump
2124 * @return #GNUNET_OK (continue iteration)
2125 */
2126static int
2127debug_channel (void *cls,
2128 uint32_t key,
2129 void *value)
2130{
2131 const enum GNUNET_ErrorType *level = cls;
2132 struct CadetChannel *ch = value;
2133
2134 GCCH_debug (ch, *level);
2135 return GNUNET_OK;
2136}
2137
2138
2139/**
2140 * Get string description for tunnel connectivity state.
2141 *
2142 * @param cs Tunnel state.
2143 *
2144 * @return String representation.
2145 */
2146static const char *
2147cstate2s (enum CadetTunnelCState cs)
2148{
2149 static char buf[32];
2150
2151 switch (cs)
2152 {
2153 case CADET_TUNNEL_NEW:
2154 return "CADET_TUNNEL_NEW";
2155 case CADET_TUNNEL_SEARCHING:
2156 return "CADET_TUNNEL_SEARCHING";
2157 case CADET_TUNNEL_WAITING:
2158 return "CADET_TUNNEL_WAITING";
2159 case CADET_TUNNEL_READY:
2160 return "CADET_TUNNEL_READY";
2161 case CADET_TUNNEL_SHUTDOWN:
2162 return "CADET_TUNNEL_SHUTDOWN";
2163 default:
2164 SPRINTF (buf, "%u (UNKNOWN STATE)", cs);
2165 return buf;
2166 }
2167}
2168
2169
2170/**
2171 * Get string description for tunnel encryption state.
2172 *
2173 * @param es Tunnel state.
2174 *
2175 * @return String representation.
2176 */
2177static const char *
2178estate2s (enum CadetTunnelEState es)
2179{
2180 static char buf[32];
2181
2182 switch (es)
2183 {
2184 case CADET_TUNNEL_KEY_UNINITIALIZED:
2185 return "CADET_TUNNEL_KEY_UNINITIALIZED";
2186 case CADET_TUNNEL_KEY_SENT:
2187 return "CADET_TUNNEL_KEY_SENT";
2188 case CADET_TUNNEL_KEY_PING:
2189 return "CADET_TUNNEL_KEY_PING";
2190 case CADET_TUNNEL_KEY_OK:
2191 return "CADET_TUNNEL_KEY_OK";
2192 case CADET_TUNNEL_KEY_REKEY:
2193 return "CADET_TUNNEL_KEY_REKEY";
2194 default:
2195 SPRINTF (buf, "%u (UNKNOWN STATE)", es);
2196 return buf;
2197 }
2198}
2199
2200
2201#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-tun",__VA_ARGS__)
2202
2203
2204/**
2205 * Log all possible info about the tunnel state.
2206 *
2207 * @param t Tunnel to debug.
2208 * @param level Debug level to use.
2209 */
2210void
2211GCT_debug (const struct CadetTunnel *t,
2212 enum GNUNET_ErrorType level)
2213{
2214 struct CadetTConnection *iter_c;
2215 int do_log;
2216
2217 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
2218 "cadet-tun",
2219 __FILE__, __FUNCTION__, __LINE__);
2220 if (0 == do_log)
2221 return;
2222
2223 LOG2 (level,
2224 "TTT TUNNEL TOWARDS %s in cstate %s, estate %s tq_len: %u #cons: %u\n",
2225 GCT_2s (t),
2226 cstate2s (t->cstate),
2227 estate2s (t->estate),
2228 t->tq_len,
2229 t->num_connections);
2230#if DUMP_KEYS_TO_STDERR
2231 ax_debug (t->ax, level);
2232#endif
2233 LOG2 (level,
2234 "TTT channels:\n");
2235 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
2236 &debug_channel,
2237 &level);
2238 LOG2 (level,
2239 "TTT connections:\n");
2240 for (iter_c = t->connection_head; NULL != iter_c; iter_c = iter_c->next)
2241 GCC_debug (iter_c->cc,
2242 level);
2243
2244 LOG2 (level,
2245 "TTT TUNNEL END\n");
2246}
2247
2248
2249/* end of gnunet-service-cadet-new_tunnels.c */
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.h b/src/cadet/gnunet-service-cadet-new_tunnels.h
new file mode 100644
index 000000000..82e4b0da6
--- /dev/null
+++ b/src/cadet/gnunet-service-cadet-new_tunnels.h
@@ -0,0 +1,357 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file cadet/gnunet-service-cadet-new_tunnels.h
24 * @brief Information we track per tunnel.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#ifndef GNUNET_SERVICE_CADET_TUNNELS_H
29#define GNUNET_SERVICE_CADET_TUNNELS_H
30
31#include "gnunet-service-cadet-new.h"
32#include "cadet_protocol.h"
33
34
35/**
36 * How many connections would we like to have per tunnel?
37 */
38#define DESIRED_CONNECTIONS_PER_TUNNEL 3
39
40
41/**
42 * All the connectivity states a tunnel can be in.
43 */
44enum CadetTunnelCState
45{
46 /**
47 * Uninitialized status, should never appear in operation.
48 */
49 CADET_TUNNEL_NEW,
50
51 /**
52 * No path to the peer known yet.
53 */
54 CADET_TUNNEL_SEARCHING,
55
56 /**
57 * Request sent, not yet answered.
58 */
59 CADET_TUNNEL_WAITING,
60
61 /**
62 * Peer connected and ready to accept data.
63 */
64 CADET_TUNNEL_READY,
65
66 /**
67 * Tunnel being shut down, don't try to keep it alive.
68 */
69 CADET_TUNNEL_SHUTDOWN
70};
71
72
73
74/**
75 * All the encryption states a tunnel can be in.
76 */
77enum CadetTunnelEState
78{
79 /**
80 * Uninitialized status, should never appear in operation.
81 */
82 CADET_TUNNEL_KEY_UNINITIALIZED,
83
84 /**
85 * Ephemeral key sent, waiting for peer's key.
86 */
87 CADET_TUNNEL_KEY_SENT,
88
89 /**
90 * In OTR: New ephemeral key and ping sent, waiting for pong.
91 *
92 * This means that we DO have the peer's ephemeral key, otherwise the
93 * state would be KEY_SENT. We DO NOT have a valid session key (either no
94 * previous key or previous key expired).
95 *
96 *
97 * In Axolotl: Key sent and received but no deciphered traffic yet.
98 *
99 * This means that we can send traffic (otherwise we would never complete
100 * the handshake), but we don't have complete confirmation. Since the first
101 * traffic MUST be a complete channel creation 3-way handshake, no payload
102 * will be sent before confirmation.
103 */
104 CADET_TUNNEL_KEY_PING,
105
106 /**
107 * Handshake completed: session key available.
108 */
109 CADET_TUNNEL_KEY_OK,
110
111 /**
112 * New ephemeral key and ping sent, waiting for pong. Unlike KEY_PING,
113 * we still have a valid session key and therefore we *can* still send
114 * traffic on the tunnel.
115 */
116 CADET_TUNNEL_KEY_REKEY
117};
118
119
120/**
121 * Get the static string for the peer this tunnel is directed.
122 *
123 * @param t Tunnel.
124 *
125 * @return Static string the destination peer's ID.
126 */
127const char *
128GCT_2s (const struct CadetTunnel *t);
129
130
131/**
132 * Create a tunnel to @a destionation. Must only be called
133 * from within #GCP_get_tunnel().
134 *
135 * @param destination where to create the tunnel to
136 * @return new tunnel to @a destination
137 */
138struct CadetTunnel *
139GCT_create_tunnel (struct CadetPeer *destination);
140
141
142/**
143 * Add a @a connection to the @a tunnel.
144 *
145 * @param t a tunnel
146 * @param cid connection identifer to use for the connection
147 * @param path path to use for the connection
148 */
149void
150GCT_add_inbound_connection (struct CadetTunnel *t,
151 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
152 struct CadetPeerPath *path);
153
154
155/**
156 * Return the peer to which this tunnel goes.
157 *
158 * @param t a tunnel
159 * @return the destination of the tunnel
160 */
161struct CadetPeer *
162GCT_get_destination (struct CadetTunnel *t);
163
164
165/**
166 * Consider using the path @a p for the tunnel @a t.
167 * The tunnel destination is at offset @a off in path @a p.
168 *
169 * @param cls our tunnel
170 * @param path a path to our destination
171 * @param off offset of the destination on path @a path
172 */
173void
174GCT_consider_path (struct CadetTunnel *t,
175 struct CadetPeerPath *p,
176 unsigned int off);
177
178
179/**
180 * Add a channel to a tunnel.
181 *
182 * @param t Tunnel.
183 * @param ch Channel
184 * @return unique number identifying @a ch within @a t
185 */
186struct GNUNET_CADET_ChannelTunnelNumber
187GCT_add_channel (struct CadetTunnel *t,
188 struct CadetChannel *ch);
189
190
191/**
192 * Remove a channel from a tunnel.
193 *
194 * @param t Tunnel.
195 * @param ch Channel
196 * @param gid unique number identifying @a ch within @a t
197 */
198void
199GCT_remove_channel (struct CadetTunnel *t,
200 struct CadetChannel *ch,
201 struct GNUNET_CADET_ChannelTunnelNumber gid);
202
203
204/**
205 * Sends an already built message on a tunnel, encrypting it and
206 * choosing the best connection if not provided.
207 *
208 * @param message Message to send. Function modifies it.
209 * @param t Tunnel on which this message is transmitted.
210 * @param cont Continuation to call once message is really sent.
211 * @param cont_cls Closure for @c cont.
212 * @return Handle to cancel message. NULL if @c cont is NULL.
213 */
214struct CadetTunnelQueueEntry *
215GCT_send (struct CadetTunnel *t,
216 const struct GNUNET_MessageHeader *message,
217 GNUNET_SCHEDULER_TaskCallback cont,
218 void *cont_cls);
219
220
221/**
222 * Cancel a previously sent message while it's in the queue.
223 *
224 * ONLY can be called before the continuation given to the send
225 * function is called. Once the continuation is called, the message is
226 * no longer in the queue!
227 *
228 * @param q Handle to the queue entry to cancel.
229 */
230void
231GCT_send_cancel (struct CadetTunnelQueueEntry *q);
232
233
234/**
235 * Return the number of channels using a tunnel.
236 *
237 * @param t tunnel to count obtain the number of channels for
238 * @return number of channels using the tunnel
239 */
240unsigned int
241GCT_count_channels (struct CadetTunnel *t);
242
243
244/**
245 * Return the number of connections available for a tunnel.
246 *
247 * @param t tunnel to count obtain the number of connections for
248 * @return number of connections available for the tunnel
249 */
250unsigned int
251GCT_count_any_connections (struct CadetTunnel *t);
252
253
254/**
255 * Iterator over connections.
256 *
257 * @param cls closure
258 * @param c one of the connections
259 */
260typedef void
261(*GCT_ConnectionIterator) (void *cls,
262 struct CadetConnection *c);
263
264
265/**
266 * Iterate over all connections of a tunnel.
267 *
268 * @param t Tunnel whose connections to iterate.
269 * @param iter Iterator.
270 * @param iter_cls Closure for @c iter.
271 */
272void
273GCT_iterate_connections (struct CadetTunnel *t,
274 GCT_ConnectionIterator iter,
275 void *iter_cls);
276
277
278/**
279 * Iterator over channels.
280 *
281 * @param cls closure
282 * @param ch one of the channels
283 */
284typedef void
285(*GCT_ChannelIterator) (void *cls,
286 struct CadetChannel *ch);
287
288
289/**
290 * Iterate over all channels of a tunnel.
291 *
292 * @param t Tunnel whose channels to iterate.
293 * @param iter Iterator.
294 * @param iter_cls Closure for @c iter.
295 */
296void
297GCT_iterate_channels (struct CadetTunnel *t,
298 GCT_ChannelIterator iter,
299 void *iter_cls);
300
301
302/**
303 * Get the connectivity state of a tunnel.
304 *
305 * @param t Tunnel.
306 *
307 * @return Tunnel's connectivity state.
308 */
309enum CadetTunnelCState
310GCT_get_cstate (struct CadetTunnel *t);
311
312
313/**
314 * Get the encryption state of a tunnel.
315 *
316 * @param t Tunnel.
317 *
318 * @return Tunnel's encryption state.
319 */
320enum CadetTunnelEState
321GCT_get_estate (struct CadetTunnel *t);
322
323
324/**
325 * Handle KX message.
326 *
327 * @param ct connection/tunnel combo that received encrypted message
328 * @param msg the key exchange message
329 */
330void
331GCT_handle_kx (struct CadetTConnection *ct,
332 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
333
334
335/**
336 * Handle encrypted message.
337 *
338 * @param ct connection/tunnel combo that received encrypted message
339 * @param msg the encrypted message to decrypt
340 */
341void
342GCT_handle_encrypted (struct CadetTConnection *ct,
343 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
344
345
346/**
347 * Log all possible info about the tunnel state.
348 *
349 * @param t Tunnel to debug.
350 * @param level Debug level to use.
351 */
352void
353GCT_debug (const struct CadetTunnel *t,
354 enum GNUNET_ErrorType level);
355
356
357#endif
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c
index 22349aa80..dee0c37d7 100644
--- a/src/cadet/gnunet-service-cadet_channel.c
+++ b/src/cadet/gnunet-service-cadet_channel.c
@@ -58,7 +58,7 @@ enum CadetChannelState
58 /** 58 /**
59 * Connection confirmed, ready to carry traffic. 59 * Connection confirmed, ready to carry traffic.
60 */ 60 */
61 CADET_CHANNEL_READY, 61 CADET_CHANNEL_READY
62}; 62};
63 63
64 64
@@ -125,7 +125,7 @@ struct CadetReliableMessage
125 */ 125 */
126 struct GNUNET_TIME_Absolute timestamp; 126 struct GNUNET_TIME_Absolute timestamp;
127 127
128 /* struct GNUNET_CADET_Data with payload */ 128 /* struct GNUNET_CADET_ChannelAppDataMessage with payload */
129}; 129};
130 130
131 131
@@ -216,19 +216,19 @@ struct CadetChannel
216 /** 216 /**
217 * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) 217 * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
218 */ 218 */
219 CADET_ChannelNumber gid; 219 struct GNUNET_CADET_ChannelTunnelNumber gid;
220 220
221 /** 221 /**
222 * Local tunnel number for root (owner) client. 222 * Local tunnel number for root (owner) client.
223 * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 ) 223 * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
224 */ 224 */
225 CADET_ChannelNumber lid_root; 225 struct GNUNET_CADET_ClientChannelNumber lid_root;
226 226
227 /** 227 /**
228 * Local tunnel number for local destination clients (incoming number) 228 * Local tunnel number for local destination clients (incoming number)
229 * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0). 229 * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0).
230 */ 230 */
231 CADET_ChannelNumber lid_dest; 231 struct GNUNET_CADET_ClientChannelNumber lid_dest;
232 232
233 /** 233 /**
234 * Channel state. 234 * Channel state.
@@ -368,7 +368,7 @@ is_loopback (const struct CadetChannel *ch)
368 * @param rel Reliability data for retransmission. 368 * @param rel Reliability data for retransmission.
369 */ 369 */
370static struct CadetReliableMessage * 370static struct CadetReliableMessage *
371copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid, 371copy_message (const struct GNUNET_CADET_ChannelAppDataMessage *msg, uint32_t mid,
372 struct CadetChannelReliability *rel) 372 struct CadetChannelReliability *rel)
373{ 373{
374 struct CadetReliableMessage *copy; 374 struct CadetReliableMessage *copy;
@@ -378,7 +378,7 @@ copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid,
378 copy = GNUNET_malloc (sizeof (*copy) + size); 378 copy = GNUNET_malloc (sizeof (*copy) + size);
379 copy->mid = mid; 379 copy->mid = mid;
380 copy->rel = rel; 380 copy->rel = rel;
381 copy->type = GNUNET_MESSAGE_TYPE_CADET_DATA; 381 copy->type = GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA;
382 GNUNET_memcpy (&copy[1], msg, size); 382 GNUNET_memcpy (&copy[1], msg, size);
383 383
384 return copy; 384 return copy;
@@ -393,7 +393,7 @@ copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid,
393 * @param rel Reliability data to the corresponding direction. 393 * @param rel Reliability data to the corresponding direction.
394 */ 394 */
395static void 395static void
396add_buffered_data (const struct GNUNET_CADET_Data *msg, 396add_buffered_data (const struct GNUNET_CADET_ChannelAppDataMessage *msg,
397 struct CadetChannelReliability *rel) 397 struct CadetChannelReliability *rel)
398{ 398{
399 struct CadetReliableMessage *copy; 399 struct CadetReliableMessage *copy;
@@ -513,11 +513,11 @@ channel_get_options (struct CadetChannel *ch)
513static void 513static void
514send_destroy (struct CadetChannel *ch, int local_only) 514send_destroy (struct CadetChannel *ch, int local_only)
515{ 515{
516 struct GNUNET_CADET_ChannelManage msg; 516 struct GNUNET_CADET_ChannelManageMessage msg;
517 517
518 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); 518 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
519 msg.header.size = htons (sizeof (msg)); 519 msg.header.size = htons (sizeof (msg));
520 msg.chid = htonl (ch->gid); 520 msg.chid = ch->gid;
521 521
522 /* If root is not NULL, notify. 522 /* If root is not NULL, notify.
523 * If it's NULL, check lid_root. When a local destroy comes in, root 523 * If it's NULL, check lid_root. When a local destroy comes in, root
@@ -526,12 +526,12 @@ send_destroy (struct CadetChannel *ch, int local_only)
526 */ 526 */
527 if (NULL != ch->root) 527 if (NULL != ch->root)
528 GML_send_channel_destroy (ch->root, ch->lid_root); 528 GML_send_channel_destroy (ch->root, ch->lid_root);
529 else if (0 == ch->lid_root && GNUNET_NO == local_only) 529 else if (0 == ch->lid_root.channel_of_client && GNUNET_NO == local_only)
530 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); 530 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
531 531
532 if (NULL != ch->dest) 532 if (NULL != ch->dest)
533 GML_send_channel_destroy (ch->dest, ch->lid_dest); 533 GML_send_channel_destroy (ch->dest, ch->lid_dest);
534 else if (0 == ch->lid_dest && GNUNET_NO == local_only) 534 else if (0 == ch->lid_dest.channel_of_client && GNUNET_NO == local_only)
535 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL); 535 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL);
536} 536}
537 537
@@ -552,7 +552,10 @@ send_client_create (struct CadetChannel *ch)
552 opt = 0; 552 opt = 0;
553 opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0; 553 opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0;
554 opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0; 554 opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0;
555 GML_send_channel_create (ch->dest, ch->lid_dest, &ch->port, opt, 555 GML_send_channel_create (ch->dest,
556 ch->lid_dest,
557 &ch->port,
558 opt,
556 GCT_get_destination (ch->t)); 559 GCT_get_destination (ch->t));
557 560
558} 561}
@@ -570,7 +573,7 @@ send_client_create (struct CadetChannel *ch)
570 */ 573 */
571static void 574static void
572send_client_data (struct CadetChannel *ch, 575send_client_data (struct CadetChannel *ch,
573 const struct GNUNET_CADET_Data *msg, 576 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
574 int fwd) 577 int fwd)
575{ 578{
576 if (fwd) 579 if (fwd)
@@ -628,7 +631,7 @@ send_client_buffered_data (struct CadetChannel *ch,
628 { 631 {
629 if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable) 632 if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable)
630 { 633 {
631 struct GNUNET_CADET_Data *msg = (struct GNUNET_CADET_Data *) &copy[1]; 634 struct GNUNET_CADET_ChannelAppDataMessage *msg = (struct GNUNET_CADET_ChannelAppDataMessage *) &copy[1];
632 635
633 LOG (GNUNET_ERROR_TYPE_DEBUG, " have %u! now expecting %u\n", 636 LOG (GNUNET_ERROR_TYPE_DEBUG, " have %u! now expecting %u\n",
634 copy->mid, rel->mid_recv + 1); 637 copy->mid, rel->mid_recv + 1);
@@ -728,7 +731,7 @@ channel_retransmit_message (void *cls)
728 struct CadetChannelReliability *rel = cls; 731 struct CadetChannelReliability *rel = cls;
729 struct CadetReliableMessage *copy; 732 struct CadetReliableMessage *copy;
730 struct CadetChannel *ch; 733 struct CadetChannel *ch;
731 struct GNUNET_CADET_Data *payload; 734 struct GNUNET_CADET_ChannelAppDataMessage *payload;
732 int fwd; 735 int fwd;
733 736
734 rel->retry_task = NULL; 737 rel->retry_task = NULL;
@@ -740,7 +743,7 @@ channel_retransmit_message (void *cls)
740 return; 743 return;
741 } 744 }
742 745
743 payload = (struct GNUNET_CADET_Data *) &copy[1]; 746 payload = (struct GNUNET_CADET_ChannelAppDataMessage *) &copy[1];
744 fwd = (rel == ch->root_rel); 747 fwd = (rel == ch->root_rel);
745 748
746 /* Message not found in the queue that we are going to use. */ 749 /* Message not found in the queue that we are going to use. */
@@ -805,7 +808,7 @@ ch_message_sent (void *cls,
805 808
806 switch (chq->type) 809 switch (chq->type)
807 { 810 {
808 case GNUNET_MESSAGE_TYPE_CADET_DATA: 811 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
809 LOG (GNUNET_ERROR_TYPE_DEBUG, "data MID %u sent\n", copy->mid); 812 LOG (GNUNET_ERROR_TYPE_DEBUG, "data MID %u sent\n", copy->mid);
810 GNUNET_assert (chq == copy->chq); 813 GNUNET_assert (chq == copy->chq);
811 copy->timestamp = GNUNET_TIME_absolute_get (); 814 copy->timestamp = GNUNET_TIME_absolute_get ();
@@ -841,16 +844,16 @@ ch_message_sent (void *cls,
841 break; 844 break;
842 845
843 846
844 case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: 847 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
845 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: 848 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
846 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: 849 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
847 LOG (GNUNET_ERROR_TYPE_DEBUG, "sent %s\n", GC_m2s (chq->type)); 850 LOG (GNUNET_ERROR_TYPE_DEBUG, "sent %s\n", GC_m2s (chq->type));
848 rel = chq->rel; 851 rel = chq->rel;
849 GNUNET_assert (rel->uniq == chq); 852 GNUNET_assert (rel->uniq == chq);
850 rel->uniq = NULL; 853 rel->uniq = NULL;
851 854
852 if (CADET_CHANNEL_READY != rel->ch->state 855 if (CADET_CHANNEL_READY != rel->ch->state
853 && GNUNET_MESSAGE_TYPE_CADET_DATA_ACK != type 856 && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK != type
854 && GNUNET_NO == rel->ch->destroy) 857 && GNUNET_NO == rel->ch->destroy)
855 { 858 {
856 GNUNET_assert (NULL == rel->retry_task); 859 GNUNET_assert (NULL == rel->retry_task);
@@ -879,11 +882,11 @@ ch_message_sent (void *cls,
879static void 882static void
880send_create (struct CadetChannel *ch) 883send_create (struct CadetChannel *ch)
881{ 884{
882 struct GNUNET_CADET_ChannelCreate msgcc; 885 struct GNUNET_CADET_ChannelOpenMessage msgcc;
883 886
884 msgcc.header.size = htons (sizeof (msgcc)); 887 msgcc.header.size = htons (sizeof (msgcc));
885 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE); 888 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
886 msgcc.chid = htonl (ch->gid); 889 msgcc.chid = ch->gid;
887 msgcc.port = ch->port; 890 msgcc.port = ch->port;
888 msgcc.opt = htonl (channel_get_options (ch)); 891 msgcc.opt = htonl (channel_get_options (ch));
889 892
@@ -900,14 +903,15 @@ send_create (struct CadetChannel *ch)
900static void 903static void
901send_ack (struct CadetChannel *ch, int fwd) 904send_ack (struct CadetChannel *ch, int fwd)
902{ 905{
903 struct GNUNET_CADET_ChannelManage msg; 906 struct GNUNET_CADET_ChannelManageMessage msg;
904 907
905 msg.header.size = htons (sizeof (msg)); 908 msg.header.size = htons (sizeof (msg));
906 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK); 909 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
907 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending channel %s ack for channel %s\n", 910 LOG (GNUNET_ERROR_TYPE_DEBUG,
911 " sending channel %s ack for channel %s\n",
908 GC_f2s (fwd), GCCH_2s (ch)); 912 GC_f2s (fwd), GCCH_2s (ch));
909 913
910 msg.chid = htonl (ch->gid); 914 msg.chid =ch->gid;
911 GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL); 915 GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL);
912} 916}
913 917
@@ -925,8 +929,9 @@ fire_and_forget (const struct GNUNET_MessageHeader *msg,
925 struct CadetChannel *ch, 929 struct CadetChannel *ch,
926 int force) 930 int force)
927{ 931{
928 GNUNET_break (NULL == GCT_send_prebuilt_message (msg, ch->t, NULL, 932 GNUNET_break (NULL ==
929 force, NULL, NULL)); 933 GCT_send_prebuilt_message (msg, ch->t, NULL,
934 force, NULL, NULL));
930} 935}
931 936
932 937
@@ -938,15 +943,15 @@ fire_and_forget (const struct GNUNET_MessageHeader *msg,
938static void 943static void
939send_nack (struct CadetChannel *ch) 944send_nack (struct CadetChannel *ch)
940{ 945{
941 struct GNUNET_CADET_ChannelManage msg; 946 struct GNUNET_CADET_ChannelManageMessage msg;
942 947
943 msg.header.size = htons (sizeof (msg)); 948 msg.header.size = htons (sizeof (msg));
944 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK); 949 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED);
945 LOG (GNUNET_ERROR_TYPE_DEBUG, 950 LOG (GNUNET_ERROR_TYPE_DEBUG,
946 " sending channel NACK for channel %s\n", 951 " sending channel NACK for channel %s\n",
947 GCCH_2s (ch)); 952 GCCH_2s (ch));
948 953
949 msg.chid = htonl (ch->gid); 954 msg.chid = ch->gid;
950 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); 955 GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
951} 956}
952 957
@@ -1019,7 +1024,7 @@ channel_rel_free_all (struct CadetChannelReliability *rel)
1019 */ 1024 */
1020static unsigned int 1025static unsigned int
1021channel_rel_free_sent (struct CadetChannelReliability *rel, 1026channel_rel_free_sent (struct CadetChannelReliability *rel,
1022 const struct GNUNET_CADET_DataACK *msg) 1027 const struct GNUNET_CADET_ChannelDataAckMessage *msg)
1023{ 1028{
1024 struct CadetReliableMessage *copy; 1029 struct CadetReliableMessage *copy;
1025 struct CadetReliableMessage *next; 1030 struct CadetReliableMessage *next;
@@ -1252,7 +1257,7 @@ channel_save_copy (struct CadetChannel *ch,
1252static struct CadetChannel * 1257static struct CadetChannel *
1253channel_new (struct CadetTunnel *t, 1258channel_new (struct CadetTunnel *t,
1254 struct CadetClient *owner, 1259 struct CadetClient *owner,
1255 CADET_ChannelNumber lid_root) 1260 struct GNUNET_CADET_ClientChannelNumber lid_root)
1256{ 1261{
1257 struct CadetChannel *ch; 1262 struct CadetChannel *ch;
1258 1263
@@ -1295,35 +1300,35 @@ handle_loopback (struct CadetChannel *ch,
1295 1300
1296 switch (type) 1301 switch (type)
1297 { 1302 {
1298 case GNUNET_MESSAGE_TYPE_CADET_DATA: 1303 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
1299 /* Don't send hop ACK, wait for client to ACK */ 1304 /* Don't send hop ACK, wait for client to ACK */
1300 LOG (GNUNET_ERROR_TYPE_DEBUG, "SEND loopback %u (%u)\n", 1305 LOG (GNUNET_ERROR_TYPE_DEBUG, "SEND loopback %u (%u)\n",
1301 ntohl (((struct GNUNET_CADET_Data *) msgh)->mid), ntohs (msgh->size)); 1306 ntohl (((struct GNUNET_CADET_ChannelAppDataMessage *) msgh)->mid), ntohs (msgh->size));
1302 GCCH_handle_data (ch, (struct GNUNET_CADET_Data *) msgh, fwd); 1307 GCCH_handle_data (ch, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd);
1303 break; 1308 break;
1304 1309
1305 case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: 1310 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
1306 GCCH_handle_data_ack (ch, (struct GNUNET_CADET_DataACK *) msgh, fwd); 1311 GCCH_handle_data_ack (ch, (struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd);
1307 break; 1312 break;
1308 1313
1309 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: 1314 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
1310 GCCH_handle_create (ch->t, 1315 GCCH_handle_create (ch->t,
1311 (struct GNUNET_CADET_ChannelCreate *) msgh); 1316 (struct GNUNET_CADET_ChannelOpenMessage *) msgh);
1312 break; 1317 break;
1313 1318
1314 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: 1319 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
1315 GCCH_handle_ack (ch, 1320 GCCH_handle_ack (ch,
1316 (struct GNUNET_CADET_ChannelManage *) msgh, 1321 (struct GNUNET_CADET_ChannelManageMessage *) msgh,
1317 fwd); 1322 fwd);
1318 break; 1323 break;
1319 1324
1320 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: 1325 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
1321 GCCH_handle_nack (ch); 1326 GCCH_handle_nack (ch);
1322 break; 1327 break;
1323 1328
1324 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: 1329 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
1325 GCCH_handle_destroy (ch, 1330 GCCH_handle_destroy (ch,
1326 (struct GNUNET_CADET_ChannelManage *) msgh, 1331 (struct GNUNET_CADET_ChannelManageMessage *) msgh,
1327 fwd); 1332 fwd);
1328 break; 1333 break;
1329 1334
@@ -1393,7 +1398,7 @@ GCCH_destroy (struct CadetChannel *ch)
1393 * 1398 *
1394 * @return ID used to identify the channel with the remote peer. 1399 * @return ID used to identify the channel with the remote peer.
1395 */ 1400 */
1396CADET_ChannelNumber 1401struct GNUNET_CADET_ChannelTunnelNumber
1397GCCH_get_id (const struct CadetChannel *ch) 1402GCCH_get_id (const struct CadetChannel *ch)
1398{ 1403{
1399 return ch->gid; 1404 return ch->gid;
@@ -1518,7 +1523,7 @@ GCCH_is_terminal (struct CadetChannel *ch, int fwd)
1518void 1523void
1519GCCH_send_data_ack (struct CadetChannel *ch, int fwd) 1524GCCH_send_data_ack (struct CadetChannel *ch, int fwd)
1520{ 1525{
1521 struct GNUNET_CADET_DataACK msg; 1526 struct GNUNET_CADET_ChannelDataAckMessage msg;
1522 struct CadetChannelReliability *rel; 1527 struct CadetChannelReliability *rel;
1523 struct CadetReliableMessage *copy; 1528 struct CadetReliableMessage *copy;
1524 unsigned int delta; 1529 unsigned int delta;
@@ -1531,15 +1536,15 @@ GCCH_send_data_ack (struct CadetChannel *ch, int fwd)
1531 rel = fwd ? ch->dest_rel : ch->root_rel; 1536 rel = fwd ? ch->dest_rel : ch->root_rel;
1532 ack = rel->mid_recv - 1; 1537 ack = rel->mid_recv - 1;
1533 1538
1534 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA_ACK); 1539 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
1535 msg.header.size = htons (sizeof (msg)); 1540 msg.header.size = htons (sizeof (msg));
1536 msg.chid = htonl (ch->gid); 1541 msg.chid = ch->gid;
1537 msg.mid = htonl (ack); 1542 msg.mid = htonl (ack);
1538 1543
1539 msg.futures = 0LL; 1544 msg.futures = 0LL;
1540 for (copy = rel->head_recv; NULL != copy; copy = copy->next) 1545 for (copy = rel->head_recv; NULL != copy; copy = copy->next)
1541 { 1546 {
1542 if (copy->type != GNUNET_MESSAGE_TYPE_CADET_DATA) 1547 if (copy->type != GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA)
1543 { 1548 {
1544 LOG (GNUNET_ERROR_TYPE_DEBUG, " Type %s, expected DATA\n", 1549 LOG (GNUNET_ERROR_TYPE_DEBUG, " Type %s, expected DATA\n",
1545 GC_m2s (copy->type)); 1550 GC_m2s (copy->type));
@@ -1657,7 +1662,7 @@ GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
1657 { 1662 {
1658 LOG2 (level, "CHN cli %s\n", GML_2s (ch->root)); 1663 LOG2 (level, "CHN cli %s\n", GML_2s (ch->root));
1659 LOG2 (level, "CHN ready %s\n", ch->root_rel->client_ready ? "YES" : "NO"); 1664 LOG2 (level, "CHN ready %s\n", ch->root_rel->client_ready ? "YES" : "NO");
1660 LOG2 (level, "CHN id %X\n", ch->lid_root); 1665 LOG2 (level, "CHN id %X\n", ch->lid_root.channel_of_client);
1661 LOG2 (level, "CHN recv %d\n", ch->root_rel->n_recv); 1666 LOG2 (level, "CHN recv %d\n", ch->root_rel->n_recv);
1662 LOG2 (level, "CHN MID r: %d, s: %d\n", 1667 LOG2 (level, "CHN MID r: %d, s: %d\n",
1663 ch->root_rel->mid_recv, ch->root_rel->mid_send); 1668 ch->root_rel->mid_recv, ch->root_rel->mid_send);
@@ -1733,17 +1738,18 @@ GCCH_handle_local_ack (struct CadetChannel *ch, int fwd)
1733 * @param message Data message. 1738 * @param message Data message.
1734 * @param size Size of data. 1739 * @param size Size of data.
1735 * 1740 *
1736 * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error. 1741 * @return #GNUNET_OK if everything goes well, #GNUNET_SYSERR in case of en error.
1737 */ 1742 */
1738int 1743int
1739GCCH_handle_local_data (struct CadetChannel *ch, 1744GCCH_handle_local_data (struct CadetChannel *ch,
1740 struct CadetClient *c, int fwd, 1745 struct CadetClient *c,
1746 int fwd,
1741 const struct GNUNET_MessageHeader *message, 1747 const struct GNUNET_MessageHeader *message,
1742 size_t size) 1748 size_t size)
1743{ 1749{
1744 struct CadetChannelReliability *rel; 1750 struct CadetChannelReliability *rel;
1745 struct GNUNET_CADET_Data *payload; 1751 struct GNUNET_CADET_ChannelAppDataMessage *payload;
1746 uint16_t p2p_size = sizeof(struct GNUNET_CADET_Data) + size; 1752 uint16_t p2p_size = sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + size;
1747 unsigned char cbuf[p2p_size]; 1753 unsigned char cbuf[p2p_size];
1748 unsigned char buffer; 1754 unsigned char buffer;
1749 1755
@@ -1769,13 +1775,13 @@ GCCH_handle_local_data (struct CadetChannel *ch,
1769 rel->client_allowed = GNUNET_NO; 1775 rel->client_allowed = GNUNET_NO;
1770 1776
1771 /* Ok, everything is correct, send the message. */ 1777 /* Ok, everything is correct, send the message. */
1772 payload = (struct GNUNET_CADET_Data *) cbuf; 1778 payload = (struct GNUNET_CADET_ChannelAppDataMessage *) cbuf;
1773 payload->mid = htonl (rel->mid_send); 1779 payload->mid = htonl (rel->mid_send);
1774 rel->mid_send++; 1780 rel->mid_send++;
1775 GNUNET_memcpy (&payload[1], message, size); 1781 GNUNET_memcpy (&payload[1], message, size);
1776 payload->header.size = htons (p2p_size); 1782 payload->header.size = htons (p2p_size);
1777 payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA); 1783 payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1778 payload->chid = htonl (ch->gid); 1784 payload->chid = ch->gid;
1779 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n"); 1785 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
1780 GCCH_send_prebuilt_message (&payload->header, ch, fwd, NULL); 1786 GCCH_send_prebuilt_message (&payload->header, ch, fwd, NULL);
1781 1787
@@ -1840,16 +1846,16 @@ GCCH_handle_local_destroy (struct CadetChannel *ch,
1840 */ 1846 */
1841int 1847int
1842GCCH_handle_local_create (struct CadetClient *c, 1848GCCH_handle_local_create (struct CadetClient *c,
1843 struct GNUNET_CADET_ChannelCreateMessage *msg) 1849 struct GNUNET_CADET_ChannelOpenMessageMessage *msg)
1844{ 1850{
1845 struct CadetChannel *ch; 1851 struct CadetChannel *ch;
1846 struct CadetTunnel *t; 1852 struct CadetTunnel *t;
1847 struct CadetPeer *peer; 1853 struct CadetPeer *peer;
1848 CADET_ChannelNumber chid; 1854 struct GNUNET_CADET_ClientChannelNumber chid;
1849 1855
1850 LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n", 1856 LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n",
1851 GNUNET_i2s (&msg->peer), GNUNET_h2s (&msg->port)); 1857 GNUNET_i2s (&msg->peer), GNUNET_h2s (&msg->port));
1852 chid = ntohl (msg->channel_id); 1858 chid = msg->channel_id;
1853 1859
1854 /* Sanity check for duplicate channel IDs */ 1860 /* Sanity check for duplicate channel IDs */
1855 if (NULL != GML_channel_get (c, chid)) 1861 if (NULL != GML_channel_get (c, chid))
@@ -1908,7 +1914,7 @@ GCCH_handle_local_create (struct CadetClient *c,
1908 */ 1914 */
1909void 1915void
1910GCCH_handle_data (struct CadetChannel *ch, 1916GCCH_handle_data (struct CadetChannel *ch,
1911 const struct GNUNET_CADET_Data *msg, 1917 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
1912 int fwd) 1918 int fwd)
1913{ 1919{
1914 struct CadetChannelReliability *rel; 1920 struct CadetChannelReliability *rel;
@@ -1966,24 +1972,26 @@ GCCH_handle_data (struct CadetChannel *ch,
1966 1972
1967 mid = ntohl (msg->mid); 1973 mid = ntohl (msg->mid);
1968 LOG (GNUNET_ERROR_TYPE_INFO, "<== %s (%s %4u) on chan %s (%p) %s [%5u]\n", 1974 LOG (GNUNET_ERROR_TYPE_INFO, "<== %s (%s %4u) on chan %s (%p) %s [%5u]\n",
1969 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_DATA), GC_m2s (payload_type), mid, 1975 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA), GC_m2s (payload_type), mid,
1970 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size)); 1976 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
1971 1977
1972 if (GNUNET_NO == ch->reliable || 1978 if ( (GNUNET_NO == ch->reliable) ||
1973 ( !GC_is_pid_bigger (rel->mid_recv, mid) && 1979 ( (! GC_is_pid_bigger (rel->mid_recv, mid)) &&
1974 GC_is_pid_bigger (rel->mid_recv + 64, mid) ) ) 1980 GC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
1975 { 1981 {
1976 if (GNUNET_YES == ch->reliable) 1982 if (GNUNET_YES == ch->reliable)
1977 { 1983 {
1978 /* Is this the exact next expected messasge? */ 1984 /* Is this the exact next expected messasge? */
1979 if (mid == rel->mid_recv) 1985 if (mid == rel->mid_recv)
1980 { 1986 {
1981 LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected, sending to client\n"); 1987 LOG (GNUNET_ERROR_TYPE_DEBUG,
1988 "as expected, sending to client\n");
1982 send_client_data (ch, msg, fwd); 1989 send_client_data (ch, msg, fwd);
1983 } 1990 }
1984 else 1991 else
1985 { 1992 {
1986 LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n"); 1993 LOG (GNUNET_ERROR_TYPE_DEBUG,
1994 "save for later\n");
1987 add_buffered_data (msg, rel); 1995 add_buffered_data (msg, rel);
1988 } 1996 }
1989 } 1997 }
@@ -2001,7 +2009,7 @@ GCCH_handle_data (struct CadetChannel *ch,
2001 if (GC_is_pid_bigger (rel->mid_recv, mid)) 2009 if (GC_is_pid_bigger (rel->mid_recv, mid))
2002 { 2010 {
2003 GNUNET_break_op (0); 2011 GNUNET_break_op (0);
2004 LOG (GNUNET_ERROR_TYPE_INFO, 2012 LOG (GNUNET_ERROR_TYPE_WARNING,
2005 "MID %u on channel %s not expected (window: %u - %u). Dropping!\n", 2013 "MID %u on channel %s not expected (window: %u - %u). Dropping!\n",
2006 mid, GCCH_2s (ch), rel->mid_recv, rel->mid_recv + 63); 2014 mid, GCCH_2s (ch), rel->mid_recv, rel->mid_recv + 63);
2007 } 2015 }
@@ -2036,7 +2044,7 @@ GCCH_handle_data (struct CadetChannel *ch,
2036 */ 2044 */
2037void 2045void
2038GCCH_handle_data_ack (struct CadetChannel *ch, 2046GCCH_handle_data_ack (struct CadetChannel *ch,
2039 const struct GNUNET_CADET_DataACK *msg, 2047 const struct GNUNET_CADET_ChannelDataAckMessage *msg,
2040 int fwd) 2048 int fwd)
2041{ 2049{
2042 struct CadetChannelReliability *rel; 2050 struct CadetChannelReliability *rel;
@@ -2061,7 +2069,7 @@ GCCH_handle_data_ack (struct CadetChannel *ch,
2061 ack = ntohl (msg->mid); 2069 ack = ntohl (msg->mid);
2062 LOG (GNUNET_ERROR_TYPE_INFO, 2070 LOG (GNUNET_ERROR_TYPE_INFO,
2063 "<== %s (0x%010lX %4u) on chan %s (%p) %s [%5u]\n", 2071 "<== %s (0x%010lX %4u) on chan %s (%p) %s [%5u]\n",
2064 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_DATA_ACK), msg->futures, ack, 2072 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK), msg->futures, ack,
2065 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size)); 2073 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
2066 2074
2067 if (GNUNET_YES == fwd) 2075 if (GNUNET_YES == fwd)
@@ -2143,22 +2151,23 @@ GCCH_handle_data_ack (struct CadetChannel *ch,
2143 */ 2151 */
2144struct CadetChannel * 2152struct CadetChannel *
2145GCCH_handle_create (struct CadetTunnel *t, 2153GCCH_handle_create (struct CadetTunnel *t,
2146 const struct GNUNET_CADET_ChannelCreate *msg) 2154 const struct GNUNET_CADET_ChannelOpenMessage *msg)
2147{ 2155{
2148 CADET_ChannelNumber chid; 2156 struct GNUNET_CADET_ClientChannelNumber chid;
2157 struct GNUNET_CADET_ChannelTunnelNumber gid;
2149 struct CadetChannel *ch; 2158 struct CadetChannel *ch;
2150 struct CadetClient *c; 2159 struct CadetClient *c;
2151 int new_channel; 2160 int new_channel;
2152 const struct GNUNET_HashCode *port; 2161 const struct GNUNET_HashCode *port;
2153 2162
2154 chid = ntohl (msg->chid); 2163 gid = msg->chid;
2155 2164 ch = GCT_get_channel (t, gid);
2156 ch = GCT_get_channel (t, chid);
2157 if (NULL == ch) 2165 if (NULL == ch)
2158 { 2166 {
2159 /* Create channel */ 2167 /* Create channel */
2160 ch = channel_new (t, NULL, 0); 2168 chid.channel_of_client = htonl (0);
2161 ch->gid = chid; 2169 ch = channel_new (t, NULL, chid);
2170 ch->gid = gid;
2162 channel_set_options (ch, ntohl (msg->opt)); 2171 channel_set_options (ch, ntohl (msg->opt));
2163 new_channel = GNUNET_YES; 2172 new_channel = GNUNET_YES;
2164 } 2173 }
@@ -2170,7 +2179,7 @@ GCCH_handle_create (struct CadetTunnel *t,
2170 2179
2171 LOG (GNUNET_ERROR_TYPE_INFO, 2180 LOG (GNUNET_ERROR_TYPE_INFO,
2172 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n", 2181 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
2173 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE), chid, port, 2182 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN), chid, port,
2174 GCCH_2s (ch), ch, GC_f2s (GNUNET_YES), ntohs (msg->header.size)); 2183 GCCH_2s (ch), ch, GC_f2s (GNUNET_YES), ntohs (msg->header.size));
2175 2184
2176 if (GNUNET_YES == new_channel || GCT_is_loopback (t)) 2185 if (GNUNET_YES == new_channel || GCT_is_loopback (t))
@@ -2243,7 +2252,7 @@ GCCH_handle_nack (struct CadetChannel *ch)
2243{ 2252{
2244 LOG (GNUNET_ERROR_TYPE_INFO, 2253 LOG (GNUNET_ERROR_TYPE_INFO,
2245 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n", 2254 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
2246 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK), ch->gid, 0, 2255 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED), ch->gid, 0,
2247 GCCH_2s (ch), ch, "---", 0); 2256 GCCH_2s (ch), ch, "---", 0);
2248 2257
2249 send_client_nack (ch); 2258 send_client_nack (ch);
@@ -2263,12 +2272,12 @@ GCCH_handle_nack (struct CadetChannel *ch)
2263 */ 2272 */
2264void 2273void
2265GCCH_handle_ack (struct CadetChannel *ch, 2274GCCH_handle_ack (struct CadetChannel *ch,
2266 const struct GNUNET_CADET_ChannelManage *msg, 2275 const struct GNUNET_CADET_ChannelManageMessage *msg,
2267 int fwd) 2276 int fwd)
2268{ 2277{
2269 LOG (GNUNET_ERROR_TYPE_INFO, 2278 LOG (GNUNET_ERROR_TYPE_INFO,
2270 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n", 2279 "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
2271 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK), ch->gid, 0, 2280 GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK), ch->gid, 0,
2272 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size)); 2281 GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
2273 2282
2274 /* If this is a remote (non-loopback) channel, find 'fwd'. */ 2283 /* If this is a remote (non-loopback) channel, find 'fwd'. */
@@ -2299,7 +2308,7 @@ GCCH_handle_ack (struct CadetChannel *ch,
2299 */ 2308 */
2300void 2309void
2301GCCH_handle_destroy (struct CadetChannel *ch, 2310GCCH_handle_destroy (struct CadetChannel *ch,
2302 const struct GNUNET_CADET_ChannelManage *msg, 2311 const struct GNUNET_CADET_ChannelManageMessage *msg,
2303 int fwd) 2312 int fwd)
2304{ 2313{
2305 struct CadetChannelReliability *rel; 2314 struct CadetChannelReliability *rel;
@@ -2374,13 +2383,13 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2374 data_id = 0; 2383 data_id = 0;
2375 switch (type) 2384 switch (type)
2376 { 2385 {
2377 case GNUNET_MESSAGE_TYPE_CADET_DATA: 2386 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
2378 { 2387 {
2379 struct GNUNET_CADET_Data *data_msg; 2388 struct GNUNET_CADET_ChannelAppDataMessage *data_msg;
2380 struct GNUNET_MessageHeader *payload_msg; 2389 struct GNUNET_MessageHeader *payload_msg;
2381 uint16_t payload_type; 2390 uint16_t payload_type;
2382 2391
2383 data_msg = (struct GNUNET_CADET_Data *) message; 2392 data_msg = (struct GNUNET_CADET_ChannelAppDataMessage *) message;
2384 data_id = ntohl (data_msg->mid); 2393 data_id = ntohl (data_msg->mid);
2385 payload_msg = (struct GNUNET_MessageHeader *) &data_msg[1]; 2394 payload_msg = (struct GNUNET_MessageHeader *) &data_msg[1];
2386 payload_type = ntohs (payload_msg->type); 2395 payload_type = ntohs (payload_msg->type);
@@ -2388,28 +2397,29 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2388 info[31] = '\0'; 2397 info[31] = '\0';
2389 break; 2398 break;
2390 } 2399 }
2391 case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: 2400 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
2392 { 2401 {
2393 struct GNUNET_CADET_DataACK *ack_msg; 2402 struct GNUNET_CADET_ChannelDataAckMessage *ack_msg;
2394 ack_msg = (struct GNUNET_CADET_DataACK *) message; 2403 ack_msg = (struct GNUNET_CADET_ChannelDataAckMessage *) message;
2395 data_id = ntohl (ack_msg->mid); 2404 data_id = ntohl (ack_msg->mid);
2396 SPRINTF (info, "0x%010lX", ack_msg->futures); 2405 SPRINTF (info, "0x%010lX",
2406 (unsigned long int) ack_msg->futures);
2397 break; 2407 break;
2398 } 2408 }
2399 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: 2409 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
2400 { 2410 {
2401 struct GNUNET_CADET_ChannelCreate *cc_msg; 2411 struct GNUNET_CADET_ChannelOpenMessage *cc_msg;
2402 cc_msg = (struct GNUNET_CADET_ChannelCreate *) message; 2412 cc_msg = (struct GNUNET_CADET_ChannelOpenMessage *) message;
2403 SPRINTF (info, " 0x%08X", ntohl (cc_msg->chid)); 2413 SPRINTF (info, " 0x%08X", ntohl (cc_msg->chid.cn));
2404 break; 2414 break;
2405 } 2415 }
2406 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: 2416 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
2407 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: 2417 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
2408 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: 2418 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
2409 { 2419 {
2410 struct GNUNET_CADET_ChannelManage *m_msg; 2420 struct GNUNET_CADET_ChannelManageMessage *m_msg;
2411 m_msg = (struct GNUNET_CADET_ChannelManage *) message; 2421 m_msg = (struct GNUNET_CADET_ChannelManageMessage *) message;
2412 SPRINTF (info, " 0x%08X", ntohl (m_msg->chid)); 2422 SPRINTF (info, " 0x%08X", ntohl (m_msg->chid.cn));
2413 break; 2423 break;
2414 } 2424 }
2415 default: 2425 default:
@@ -2428,7 +2438,7 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2428 2438
2429 switch (type) 2439 switch (type)
2430 { 2440 {
2431 case GNUNET_MESSAGE_TYPE_CADET_DATA: 2441 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
2432 if (GNUNET_YES == ch->reliable) 2442 if (GNUNET_YES == ch->reliable)
2433 { 2443 {
2434 chq = GNUNET_new (struct CadetChannelQueue); 2444 chq = GNUNET_new (struct CadetChannelQueue);
@@ -2474,9 +2484,9 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2474 break; 2484 break;
2475 2485
2476 2486
2477 case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: 2487 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
2478 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: 2488 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
2479 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: 2489 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
2480 chq = GNUNET_new (struct CadetChannelQueue); 2490 chq = GNUNET_new (struct CadetChannelQueue);
2481 chq->type = type; 2491 chq->type = type;
2482 chq->rel = fwd ? ch->root_rel : ch->dest_rel; 2492 chq->rel = fwd ? ch->root_rel : ch->dest_rel;
@@ -2495,22 +2505,23 @@ GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2495 } 2505 }
2496 } 2506 }
2497 2507
2508 chq->rel->uniq = chq;
2498 chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES, 2509 chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES,
2499 &ch_message_sent, chq); 2510 &ch_message_sent, chq);
2500 if (NULL == chq->tq) 2511 if (NULL == chq->tq)
2501 { 2512 {
2502 GNUNET_break (0); 2513 GNUNET_break (0);
2514 chq->rel->uniq = NULL;
2503 GCT_debug (ch->t, GNUNET_ERROR_TYPE_ERROR); 2515 GCT_debug (ch->t, GNUNET_ERROR_TYPE_ERROR);
2504 GNUNET_free (chq); 2516 GNUNET_free (chq);
2505 chq = NULL; 2517 chq = NULL;
2506 return; 2518 return;
2507 } 2519 }
2508 chq->rel->uniq = chq;
2509 break; 2520 break;
2510 2521
2511 2522
2512 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: 2523 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
2513 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: 2524 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
2514 fire_and_forget (message, ch, GNUNET_YES); 2525 fire_and_forget (message, ch, GNUNET_YES);
2515 break; 2526 break;
2516 2527
@@ -2538,9 +2549,13 @@ GCCH_2s (const struct CadetChannel *ch)
2538 if (NULL == ch) 2549 if (NULL == ch)
2539 return "(NULL Channel)"; 2550 return "(NULL Channel)";
2540 2551
2541 SPRINTF (buf, "%s:%s gid:%X (%X / %X)", 2552 SPRINTF (buf,
2542 GCT_2s (ch->t), GNUNET_h2s (&ch->port), 2553 "%s:%s gid:%X (%X / %X)",
2543 ch->gid, ch->lid_root, ch->lid_dest); 2554 GCT_2s (ch->t),
2555 GNUNET_h2s (&ch->port),
2556 ntohl (ch->gid.cn),
2557 ntohl (ch->lid_root.channel_of_client),
2558 ntohl (ch->lid_dest.channel_of_client));
2544 2559
2545 return buf; 2560 return buf;
2546} 2561}
diff --git a/src/cadet/gnunet-service-cadet_channel.h b/src/cadet/gnunet-service-cadet_channel.h
index eeea02712..1eeebf34b 100644
--- a/src/cadet/gnunet-service-cadet_channel.h
+++ b/src/cadet/gnunet-service-cadet_channel.h
@@ -69,7 +69,7 @@ GCCH_destroy (struct CadetChannel *ch);
69 * 69 *
70 * @return ID used to identify the channel with the remote peer. 70 * @return ID used to identify the channel with the remote peer.
71 */ 71 */
72CADET_ChannelNumber 72struct GNUNET_CADET_ChannelTunnelNumber
73GCCH_get_id (const struct CadetChannel *ch); 73GCCH_get_id (const struct CadetChannel *ch);
74 74
75/** 75/**
@@ -224,7 +224,7 @@ GCCH_handle_local_destroy (struct CadetChannel *ch,
224 */ 224 */
225int 225int
226GCCH_handle_local_create (struct CadetClient *c, 226GCCH_handle_local_create (struct CadetClient *c,
227 struct GNUNET_CADET_ChannelCreateMessage *msg); 227 struct GNUNET_CADET_ChannelOpenMessageMessage *msg);
228 228
229/** 229/**
230 * Handler for cadet network payload traffic. 230 * Handler for cadet network payload traffic.
@@ -238,7 +238,7 @@ GCCH_handle_local_create (struct CadetClient *c,
238 */ 238 */
239void 239void
240GCCH_handle_data (struct CadetChannel *ch, 240GCCH_handle_data (struct CadetChannel *ch,
241 const struct GNUNET_CADET_Data *msg, 241 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
242 int fwd); 242 int fwd);
243 243
244 244
@@ -254,7 +254,7 @@ GCCH_handle_data (struct CadetChannel *ch,
254 */ 254 */
255void 255void
256GCCH_handle_data_ack (struct CadetChannel *ch, 256GCCH_handle_data_ack (struct CadetChannel *ch,
257 const struct GNUNET_CADET_DataACK *msg, 257 const struct GNUNET_CADET_ChannelDataAckMessage *msg,
258 int fwd); 258 int fwd);
259 259
260 260
@@ -268,7 +268,7 @@ GCCH_handle_data_ack (struct CadetChannel *ch,
268 */ 268 */
269struct CadetChannel * 269struct CadetChannel *
270GCCH_handle_create (struct CadetTunnel *t, 270GCCH_handle_create (struct CadetTunnel *t,
271 const struct GNUNET_CADET_ChannelCreate *msg); 271 const struct GNUNET_CADET_ChannelOpenMessage *msg);
272 272
273 273
274/** 274/**
@@ -294,7 +294,7 @@ GCCH_handle_nack (struct CadetChannel *ch);
294 */ 294 */
295void 295void
296GCCH_handle_ack (struct CadetChannel *ch, 296GCCH_handle_ack (struct CadetChannel *ch,
297 const struct GNUNET_CADET_ChannelManage *msg, 297 const struct GNUNET_CADET_ChannelManageMessage *msg,
298 int fwd); 298 int fwd);
299 299
300 300
@@ -310,7 +310,7 @@ GCCH_handle_ack (struct CadetChannel *ch,
310 */ 310 */
311void 311void
312GCCH_handle_destroy (struct CadetChannel *ch, 312GCCH_handle_destroy (struct CadetChannel *ch,
313 const struct GNUNET_CADET_ChannelManage *msg, 313 const struct GNUNET_CADET_ChannelManageMessage *msg,
314 int fwd); 314 int fwd);
315 315
316 316
@@ -347,6 +347,8 @@ const char *
347GCCH_2s (const struct CadetChannel *ch); 347GCCH_2s (const struct CadetChannel *ch);
348 348
349 349
350
351
350#if 0 /* keep Emacsens' auto-indent happy */ 352#if 0 /* keep Emacsens' auto-indent happy */
351{ 353{
352#endif 354#endif
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c
index 1c500f716..931b32b95 100644
--- a/src/cadet/gnunet-service-cadet_connection.c
+++ b/src/cadet/gnunet-service-cadet_connection.c
@@ -112,17 +112,17 @@ struct CadetFlowControl
112 /** 112 /**
113 * ID of the next packet to send. 113 * ID of the next packet to send.
114 */ 114 */
115 uint32_t next_pid; 115 struct CadetEncryptedMessageIdentifier next_pid;
116 116
117 /** 117 /**
118 * ID of the last packet sent towards the peer. 118 * ID of the last packet sent towards the peer.
119 */ 119 */
120 uint32_t last_pid_sent; 120 struct CadetEncryptedMessageIdentifier last_pid_sent;
121 121
122 /** 122 /**
123 * ID of the last packet received from the peer. 123 * ID of the last packet received from the peer.
124 */ 124 */
125 uint32_t last_pid_recv; 125 struct CadetEncryptedMessageIdentifier last_pid_recv;
126 126
127 /** 127 /**
128 * Bitmap of past 32 messages received: 128 * Bitmap of past 32 messages received:
@@ -132,14 +132,15 @@ struct CadetFlowControl
132 uint32_t recv_bitmap; 132 uint32_t recv_bitmap;
133 133
134 /** 134 /**
135 * Last ACK sent to the peer (peer can't send more than this PID). 135 * Last ACK sent to the peer (peer is not allowed to send
136 * messages with PIDs higher than this value).
136 */ 137 */
137 uint32_t last_ack_sent; 138 struct CadetEncryptedMessageIdentifier last_ack_sent;
138 139
139 /** 140 /**
140 * Last ACK sent towards the origin (for traffic towards leaf node). 141 * Last ACK sent towards the origin (for traffic towards leaf node).
141 */ 142 */
142 uint32_t last_ack_recv; 143 struct CadetEncryptedMessageIdentifier last_ack_recv;
143 144
144 /** 145 /**
145 * Task to poll the peer in case of a lost ACK causes stall. 146 * Task to poll the peer in case of a lost ACK causes stall.
@@ -217,7 +218,7 @@ struct CadetConnection
217 /** 218 /**
218 * ID of the connection. 219 * ID of the connection.
219 */ 220 */
220 struct GNUNET_CADET_Hash id; 221 struct GNUNET_CADET_ConnectionTunnelIdentifier id;
221 222
222 /** 223 /**
223 * Path being used for the tunnel. At the origin of the connection 224 * Path being used for the tunnel. At the origin of the connection
@@ -321,7 +322,7 @@ extern struct GNUNET_PeerIdentity my_full_id;
321/** 322/**
322 * Connections known, indexed by cid (CadetConnection). 323 * Connections known, indexed by cid (CadetConnection).
323 */ 324 */
324static struct GNUNET_CONTAINER_MultiHashMap *connections; 325static struct GNUNET_CONTAINER_MultiShortmap *connections;
325 326
326/** 327/**
327 * How many connections are we willing to maintain. 328 * How many connections are we willing to maintain.
@@ -358,7 +359,8 @@ static void
358fc_debug (struct CadetFlowControl *fc) 359fc_debug (struct CadetFlowControl *fc)
359{ 360{
360 LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n", 361 LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
361 fc->last_pid_recv, fc->last_ack_sent); 362 ntohl (fc->last_pid_recv.pid),
363 ntohl (fc->last_ack_sent.pid));
362 LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n", 364 LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
363 fc->last_pid_sent, fc->last_ack_recv); 365 fc->last_pid_sent, fc->last_ack_recv);
364 LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n", 366 LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
@@ -452,11 +454,11 @@ GCC_state2s (enum CadetConnectionState s)
452static void 454static void
453fc_init (struct CadetFlowControl *fc) 455fc_init (struct CadetFlowControl *fc)
454{ 456{
455 fc->next_pid = (uint32_t) 0; 457 fc->next_pid.pid = 0;
456 fc->last_pid_sent = (uint32_t) -1; 458 fc->last_pid_sent.pid = htonl (UINT32_MAX);
457 fc->last_pid_recv = (uint32_t) -1; 459 fc->last_pid_recv.pid = htonl (UINT32_MAX);
458 fc->last_ack_sent = (uint32_t) 0; 460 fc->last_ack_sent.pid = (uint32_t) 0;
459 fc->last_ack_recv = (uint32_t) 0; 461 fc->last_ack_recv.pid = (uint32_t) 0;
460 fc->poll_task = NULL; 462 fc->poll_task = NULL;
461 fc->poll_time = GNUNET_TIME_UNIT_SECONDS; 463 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
462 fc->queue_n = 0; 464 fc->queue_n = 0;
@@ -472,9 +474,10 @@ fc_init (struct CadetFlowControl *fc)
472 * @return conntection with the given ID @cid or NULL if not found. 474 * @return conntection with the given ID @cid or NULL if not found.
473 */ 475 */
474static struct CadetConnection * 476static struct CadetConnection *
475connection_get (const struct GNUNET_CADET_Hash *cid) 477connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
476{ 478{
477 return GNUNET_CONTAINER_multihashmap_get (connections, GC_h2hc (cid)); 479 return GNUNET_CONTAINER_multishortmap_get (connections,
480 &cid->connection_of_tunnel);
478} 481}
479 482
480 483
@@ -540,12 +543,16 @@ send_poll (void *cls);
540 * @param force Don't optimize out. 543 * @param force Don't optimize out.
541 */ 544 */
542static void 545static void
543send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force) 546send_ack (struct CadetConnection *c,
547 unsigned int buffer,
548 int fwd,
549 int force)
544{ 550{
551 static struct CadetEncryptedMessageIdentifier zero;
545 struct CadetFlowControl *next_fc; 552 struct CadetFlowControl *next_fc;
546 struct CadetFlowControl *prev_fc; 553 struct CadetFlowControl *prev_fc;
547 struct GNUNET_CADET_ACK msg; 554 struct GNUNET_CADET_ConnectionEncryptedAckMessage msg;
548 uint32_t ack; 555 struct CadetEncryptedMessageIdentifier ack_cemi;
549 int delta; 556 int delta;
550 557
551 GCC_check_connections (); 558 GCC_check_connections ();
@@ -558,24 +565,28 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
558 GC_f2s (fwd), GCC_2s (c)); 565 GC_f2s (fwd), GCC_2s (c));
559 566
560 /* Check if we need to transmit the ACK. */ 567 /* Check if we need to transmit the ACK. */
561 delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv; 568 delta = ntohl (prev_fc->last_ack_sent.pid) - ntohl (prev_fc->last_pid_recv.pid);
562 if (3 < delta && buffer < delta && GNUNET_NO == force) 569 if (3 < delta && buffer < delta && GNUNET_NO == force)
563 { 570 {
564 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, delta > 3\n"); 571 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, delta > 3\n");
565 LOG (GNUNET_ERROR_TYPE_DEBUG, 572 LOG (GNUNET_ERROR_TYPE_DEBUG,
566 " last pid recv: %u, last ack sent: %u\n", 573 " last pid recv: %u, last ack sent: %u\n",
567 prev_fc->last_pid_recv, prev_fc->last_ack_sent); 574 ntohl (prev_fc->last_pid_recv.pid),
575 ntohl (prev_fc->last_ack_sent.pid));
568 GCC_check_connections (); 576 GCC_check_connections ();
569 return; 577 return;
570 } 578 }
571 579
572 /* Ok, ACK might be necessary, what PID to ACK? */ 580 /* Ok, ACK might be necessary, what PID to ACK? */
573 ack = prev_fc->last_pid_recv + buffer; 581 ack_cemi.pid = htonl (ntohl (prev_fc->last_pid_recv.pid) + buffer);
574 LOG (GNUNET_ERROR_TYPE_DEBUG, 582 LOG (GNUNET_ERROR_TYPE_DEBUG,
575 " ACK %u, last PID %u, last ACK %u, qmax %u, q %u\n", 583 " ACK %u, last PID %u, last ACK %u, qmax %u, q %u\n",
576 ack, prev_fc->last_pid_recv, prev_fc->last_ack_sent, 584 ntohl (ack_cemi.pid),
585 ntohl (prev_fc->last_pid_recv.pid),
586 ntohl (prev_fc->last_ack_sent.pid),
577 next_fc->queue_max, next_fc->queue_n); 587 next_fc->queue_max, next_fc->queue_n);
578 if (ack == prev_fc->last_ack_sent && GNUNET_NO == force) 588 if ( (ack_cemi.pid == prev_fc->last_ack_sent.pid) &&
589 (GNUNET_NO == force) )
579 { 590 {
580 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); 591 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
581 GCC_check_connections (); 592 GCC_check_connections ();
@@ -585,7 +596,8 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
585 /* Check if message is already in queue */ 596 /* Check if message is already in queue */
586 if (NULL != prev_fc->ack_msg) 597 if (NULL != prev_fc->ack_msg)
587 { 598 {
588 if (GC_is_pid_bigger (ack, prev_fc->last_ack_sent)) 599 if (GC_is_pid_bigger (ntohl (ack_cemi.pid),
600 ntohl (prev_fc->last_ack_sent.pid)))
589 { 601 {
590 LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n"); 602 LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n");
591 GCC_cancel (prev_fc->ack_msg); 603 GCC_cancel (prev_fc->ack_msg);
@@ -598,17 +610,22 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
598 return; 610 return;
599 } 611 }
600 } 612 }
601 613 GNUNET_break (GC_is_pid_bigger (ntohl (ack_cemi.pid),
602 prev_fc->last_ack_sent = ack; 614 ntohl (prev_fc->last_ack_sent.pid)));
615 prev_fc->last_ack_sent = ack_cemi;
603 616
604 /* Build ACK message and send on conn */ 617 /* Build ACK message and send on conn */
605 msg.header.size = htons (sizeof (msg)); 618 msg.header.size = htons (sizeof (msg));
606 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ACK); 619 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK);
607 msg.ack = htonl (ack); 620 msg.cemi = ack_cemi;
608 msg.cid = c->id; 621 msg.cid = c->id;
609 622
610 prev_fc->ack_msg = GCC_send_prebuilt_message (&msg.header, UINT16_MAX, ack, 623 prev_fc->ack_msg = GCC_send_prebuilt_message (&msg.header,
611 c, !fwd, GNUNET_YES, 624 UINT16_MAX,
625 zero,
626 c,
627 !fwd,
628 GNUNET_YES,
612 NULL, NULL); 629 NULL, NULL);
613 GNUNET_assert (NULL != prev_fc->ack_msg); 630 GNUNET_assert (NULL != prev_fc->ack_msg);
614 GCC_check_connections (); 631 GCC_check_connections ();
@@ -672,8 +689,12 @@ update_perf (struct CadetConnection *c,
672 */ 689 */
673static void 690static void
674conn_message_sent (void *cls, 691conn_message_sent (void *cls,
675 struct CadetConnection *c, int fwd, int sent, 692 struct CadetConnection *c,
676 uint16_t type, uint16_t payload_type, uint32_t pid, 693 int fwd,
694 int sent,
695 uint16_t type,
696 uint16_t payload_type,
697 struct CadetEncryptedMessageIdentifier pid,
677 size_t size, 698 size_t size,
678 struct GNUNET_TIME_Relative wait) 699 struct GNUNET_TIME_Relative wait)
679{ 700{
@@ -684,8 +705,11 @@ conn_message_sent (void *cls,
684 GCC_check_connections (); 705 GCC_check_connections ();
685 LOG (GNUNET_ERROR_TYPE_INFO, 706 LOG (GNUNET_ERROR_TYPE_INFO,
686 ">>> %s (%s %4u) on conn %s (%p) %s [%5u] in queue %s\n", 707 ">>> %s (%s %4u) on conn %s (%p) %s [%5u] in queue %s\n",
687 GC_m2s (type), GC_m2s (payload_type), pid, GCC_2s (c), c, 708 GC_m2s (type), GC_m2s (payload_type),
688 GC_f2s(fwd), size, 709 ntohl (pid.pid),
710 GCC_2s (c),
711 c,
712 GC_f2s (fwd), size,
689 GNUNET_STRINGS_relative_time_to_string (wait, GNUNET_YES)); 713 GNUNET_STRINGS_relative_time_to_string (wait, GNUNET_YES));
690 714
691 /* If c is NULL, nothing to update. */ 715 /* If c is NULL, nothing to update. */
@@ -703,7 +727,8 @@ conn_message_sent (void *cls,
703 727
704 LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s pid %u\n", 728 LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s pid %u\n",
705 sent ? "" : "not ", GC_f2s (fwd), 729 sent ? "" : "not ", GC_f2s (fwd),
706 GC_m2s (type), GC_m2s (payload_type), pid); 730 GC_m2s (type), GC_m2s (payload_type),
731 ntohl (pid.pid));
707 GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); 732 GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG);
708 733
709 /* Update flow control info. */ 734 /* Update flow control info. */
@@ -722,7 +747,7 @@ conn_message_sent (void *cls,
722 } 747 }
723 else /* CONN_CREATE or CONN_ACK */ 748 else /* CONN_CREATE or CONN_ACK */
724 { 749 {
725 GNUNET_assert (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED != type); 750 GNUNET_assert (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED != type);
726 forced = GNUNET_YES; 751 forced = GNUNET_YES;
727 } 752 }
728 753
@@ -742,18 +767,19 @@ conn_message_sent (void *cls,
742 switch (type) 767 switch (type)
743 { 768 {
744 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: 769 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
745 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: 770 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
746 c->maintenance_q = NULL; 771 c->maintenance_q = NULL;
747 /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */ 772 /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */
748 if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd) 773 if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd)
749 schedule_next_keepalive (c, fwd); 774 schedule_next_keepalive (c, fwd);
750 break; 775 break;
751 776
752 case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: 777 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
753 if (GNUNET_YES == sent) 778 if (GNUNET_YES == sent)
754 { 779 {
755 fc->last_pid_sent = pid; 780 fc->last_pid_sent = pid;
756 if (GC_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv)) 781 if (GC_is_pid_bigger (ntohl (fc->last_pid_sent.pid) + 1,
782 ntohl (fc->last_ack_recv.pid)) )
757 GCC_start_poll (c, fwd); 783 GCC_start_poll (c, fwd);
758 GCC_send_ack (c, fwd, GNUNET_NO); 784 GCC_send_ack (c, fwd, GNUNET_NO);
759 connection_reset_timeout (c, fwd); 785 connection_reset_timeout (c, fwd);
@@ -764,23 +790,23 @@ conn_message_sent (void *cls,
764 { 790 {
765 fc->queue_n--; 791 fc->queue_n--;
766 LOG (GNUNET_ERROR_TYPE_DEBUG, 792 LOG (GNUNET_ERROR_TYPE_DEBUG,
767 "! accounting pid %u\n", 793 "! accounting pid %u\n",
768 fc->last_pid_sent); 794 ntohl (fc->last_pid_sent.pid));
769 } 795 }
770 else 796 else
771 { 797 {
772 LOG (GNUNET_ERROR_TYPE_DEBUG, 798 LOG (GNUNET_ERROR_TYPE_DEBUG,
773 "! forced, Q_N not accounting pid %u\n", 799 "! forced, Q_N not accounting pid %u\n",
774 fc->last_pid_sent); 800 ntohl (fc->last_pid_sent.pid));
775 } 801 }
776 break; 802 break;
777 803
778 case GNUNET_MESSAGE_TYPE_CADET_KX: 804 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
779 if (GNUNET_YES == sent) 805 if (GNUNET_YES == sent)
780 connection_reset_timeout (c, fwd); 806 connection_reset_timeout (c, fwd);
781 break; 807 break;
782 808
783 case GNUNET_MESSAGE_TYPE_CADET_POLL: 809 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
784 fc->poll_msg = NULL; 810 fc->poll_msg = NULL;
785 if (2 == c->destroy) 811 if (2 == c->destroy)
786 { 812 {
@@ -801,7 +827,7 @@ conn_message_sent (void *cls,
801 LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task); 827 LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task);
802 break; 828 break;
803 829
804 case GNUNET_MESSAGE_TYPE_CADET_ACK: 830 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
805 fc->ack_msg = NULL; 831 fc->ack_msg = NULL;
806 break; 832 break;
807 833
@@ -905,7 +931,7 @@ check_neighbours (const struct CadetConnection *c)
905 */ 931 */
906static int 932static int
907check_connection (void *cls, 933check_connection (void *cls,
908 const struct GNUNET_HashCode *key, 934 const struct GNUNET_ShortHashCode *key,
909 void *value) 935 void *value)
910{ 936{
911 struct CadetConnection *c = value; 937 struct CadetConnection *c = value;
@@ -925,9 +951,9 @@ GCC_check_connections ()
925 return; 951 return;
926 if (NULL == connections) 952 if (NULL == connections)
927 return; 953 return;
928 GNUNET_CONTAINER_multihashmap_iterate (connections, 954 GNUNET_CONTAINER_multishortmap_iterate (connections,
929 &check_connection, 955 &check_connection,
930 NULL); 956 NULL);
931} 957}
932 958
933 959
@@ -953,9 +979,11 @@ get_hop (struct CadetConnection *c, int fwd)
953 * @param ooo_pid PID of the out-of-order message. 979 * @param ooo_pid PID of the out-of-order message.
954 */ 980 */
955static uint32_t 981static uint32_t
956get_recv_bitmask (uint32_t last_pid_recv, uint32_t ooo_pid) 982get_recv_bitmask (struct CadetEncryptedMessageIdentifier last_pid_recv,
983 struct CadetEncryptedMessageIdentifier ooo_pid)
957{ 984{
958 return 1 << (last_pid_recv - ooo_pid); 985 // FIXME: should assert that the delta is in range...
986 return 1 << (ntohl (last_pid_recv.pid) - ntohl (ooo_pid.pid));
959} 987}
960 988
961 989
@@ -967,14 +995,18 @@ get_recv_bitmask (uint32_t last_pid_recv, uint32_t ooo_pid)
967 * @param last_pid_recv Last in-order PID received. 995 * @param last_pid_recv Last in-order PID received.
968 */ 996 */
969static int 997static int
970is_ooo_ok (uint32_t last_pid_recv, uint32_t ooo_pid, uint32_t ooo_bitmap) 998is_ooo_ok (struct CadetEncryptedMessageIdentifier last_pid_recv,
999 struct CadetEncryptedMessageIdentifier ooo_pid,
1000 uint32_t ooo_bitmap)
971{ 1001{
972 uint32_t mask; 1002 uint32_t mask;
973 1003
974 if (GC_is_pid_bigger (last_pid_recv - 31, ooo_pid)) 1004 if (GC_is_pid_bigger (ntohl (last_pid_recv.pid) - 31,
1005 ntohl (ooo_pid.pid)))
975 return GNUNET_NO; 1006 return GNUNET_NO;
976 1007
977 mask = get_recv_bitmask (last_pid_recv, ooo_pid); 1008 mask = get_recv_bitmask (last_pid_recv,
1009 ooo_pid);
978 if (0 != (ooo_bitmap & mask)) 1010 if (0 != (ooo_bitmap & mask))
979 return GNUNET_NO; 1011 return GNUNET_NO;
980 1012
@@ -1021,10 +1053,11 @@ is_fwd (const struct CadetConnection *c,
1021static void 1053static void
1022send_connection_ack (struct CadetConnection *c, int fwd) 1054send_connection_ack (struct CadetConnection *c, int fwd)
1023{ 1055{
1024 struct GNUNET_CADET_ConnectionACK msg; 1056 static struct CadetEncryptedMessageIdentifier zero;
1057 struct GNUNET_CADET_ConnectionCreateMessageAckMessage msg;
1025 struct CadetTunnel *t; 1058 struct CadetTunnel *t;
1026 const uint16_t size = sizeof (struct GNUNET_CADET_ConnectionACK); 1059 const uint16_t size = sizeof (struct GNUNET_CADET_ConnectionCreateMessageAckMessage);
1027 const uint16_t type = GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK; 1060 const uint16_t type = GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK;
1028 1061
1029 GCC_check_connections (); 1062 GCC_check_connections ();
1030 t = c->t; 1063 t = c->t;
@@ -1038,9 +1071,12 @@ send_connection_ack (struct CadetConnection *c, int fwd)
1038 msg.cid = c->id; 1071 msg.cid = c->id;
1039 1072
1040 GNUNET_assert (NULL == c->maintenance_q); 1073 GNUNET_assert (NULL == c->maintenance_q);
1041 c->maintenance_q = GCP_send (get_hop (c, fwd), &msg.header, 1074 c->maintenance_q = GCP_send (get_hop (c, fwd),
1042 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0, 1075 &msg.header,
1043 c, fwd, 1076 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1077 zero,
1078 c,
1079 fwd,
1044 &conn_message_sent, NULL); 1080 &conn_message_sent, NULL);
1045 LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (conn`ACK)\n", 1081 LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (conn`ACK)\n",
1046 c, c->pending_messages); 1082 c, c->pending_messages);
@@ -1068,17 +1104,23 @@ send_broken (struct CadetConnection *c,
1068 const struct GNUNET_PeerIdentity *id2, 1104 const struct GNUNET_PeerIdentity *id2,
1069 int fwd) 1105 int fwd)
1070{ 1106{
1071 struct GNUNET_CADET_ConnectionBroken msg; 1107 static struct CadetEncryptedMessageIdentifier zero;
1108 struct GNUNET_CADET_ConnectionBrokenMessage msg;
1072 1109
1073 GCC_check_connections (); 1110 GCC_check_connections ();
1074 msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken)); 1111 msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage));
1075 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); 1112 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
1076 msg.cid = c->id; 1113 msg.cid = c->id;
1077 msg.reserved = htonl (0); 1114 msg.reserved = htonl (0);
1078 msg.peer1 = *id1; 1115 msg.peer1 = *id1;
1079 msg.peer2 = *id2; 1116 msg.peer2 = *id2;
1080 (void) GCC_send_prebuilt_message (&msg.header, UINT16_MAX, 0, c, fwd, 1117 (void) GCC_send_prebuilt_message (&msg.header,
1081 GNUNET_YES, NULL, NULL); 1118 UINT16_MAX,
1119 zero,
1120 c,
1121 fwd,
1122 GNUNET_YES,
1123 NULL, NULL);
1082 GCC_check_connections (); 1124 GCC_check_connections ();
1083} 1125}
1084 1126
@@ -1093,18 +1135,19 @@ send_broken (struct CadetConnection *c,
1093 * @param neighbor Peer to notify (neighbor who sent the connection). 1135 * @param neighbor Peer to notify (neighbor who sent the connection).
1094 */ 1136 */
1095static void 1137static void
1096send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id, 1138send_broken_unknown (const struct GNUNET_CADET_ConnectionTunnelIdentifier *connection_id,
1097 const struct GNUNET_PeerIdentity *id1, 1139 const struct GNUNET_PeerIdentity *id1,
1098 const struct GNUNET_PeerIdentity *id2, 1140 const struct GNUNET_PeerIdentity *id2,
1099 struct CadetPeer *neighbor) 1141 struct CadetPeer *neighbor)
1100{ 1142{
1101 struct GNUNET_CADET_ConnectionBroken msg; 1143 static struct CadetEncryptedMessageIdentifier zero;
1144 struct GNUNET_CADET_ConnectionBrokenMessage msg;
1102 1145
1103 GCC_check_connections (); 1146 GCC_check_connections ();
1104 LOG (GNUNET_ERROR_TYPE_INFO, "--> BROKEN on unknown connection %s\n", 1147 LOG (GNUNET_ERROR_TYPE_INFO, "--> BROKEN on unknown connection %s\n",
1105 GNUNET_h2s (GC_h2hc (connection_id))); 1148 GNUNET_sh2s (&connection_id->connection_of_tunnel));
1106 1149
1107 msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken)); 1150 msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage));
1108 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); 1151 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
1109 msg.cid = *connection_id; 1152 msg.cid = *connection_id;
1110 msg.reserved = htonl (0); 1153 msg.reserved = htonl (0);
@@ -1113,9 +1156,12 @@ send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id,
1113 msg.peer2 = *id2; 1156 msg.peer2 = *id2;
1114 else 1157 else
1115 memset (&msg.peer2, 0, sizeof (msg.peer2)); 1158 memset (&msg.peer2, 0, sizeof (msg.peer2));
1116 GNUNET_assert (NULL != GCP_send (neighbor, &msg.header, 1159 GNUNET_assert (NULL != GCP_send (neighbor,
1117 UINT16_MAX, 2, 1160 &msg.header,
1118 NULL, GNUNET_SYSERR, /* connection, fwd */ 1161 UINT16_MAX,
1162 zero,
1163 NULL,
1164 GNUNET_SYSERR, /* connection, fwd */
1119 NULL, NULL)); /* continuation */ 1165 NULL, NULL)); /* continuation */
1120 GCC_check_connections (); 1166 GCC_check_connections ();
1121} 1167}
@@ -1153,7 +1199,7 @@ send_connection_keepalive (struct CadetConnection *c, int fwd)
1153 1199
1154 GNUNET_assert (NULL != c->t); 1200 GNUNET_assert (NULL != c->t);
1155 msg.size = htons (sizeof (msg)); 1201 msg.size = htons (sizeof (msg));
1156 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE); 1202 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
1157 1203
1158 GNUNET_assert (NULL == 1204 GNUNET_assert (NULL ==
1159 GCT_send_prebuilt_message (&msg, c->t, c, 1205 GCT_send_prebuilt_message (&msg, c->t, c,
@@ -1410,8 +1456,9 @@ connection_cancel_queues (struct CadetConnection *c,
1410static void 1456static void
1411send_poll (void *cls) 1457send_poll (void *cls)
1412{ 1458{
1459 static struct CadetEncryptedMessageIdentifier zero;
1413 struct CadetFlowControl *fc = cls; 1460 struct CadetFlowControl *fc = cls;
1414 struct GNUNET_CADET_Poll msg; 1461 struct GNUNET_CADET_ConnectionHopByHopPollMessage msg;
1415 struct CadetConnection *c; 1462 struct CadetConnection *c;
1416 int fwd; 1463 int fwd;
1417 1464
@@ -1422,14 +1469,20 @@ send_poll (void *cls)
1422 LOG (GNUNET_ERROR_TYPE_DEBUG, "Polling connection %s %s\n", 1469 LOG (GNUNET_ERROR_TYPE_DEBUG, "Polling connection %s %s\n",
1423 GCC_2s (c), GC_f2s (fwd)); 1470 GCC_2s (c), GC_f2s (fwd));
1424 1471
1425 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_POLL); 1472 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL);
1426 msg.header.size = htons (sizeof (msg)); 1473 msg.header.size = htons (sizeof (msg));
1427 msg.cid = c->id; 1474 msg.cid = c->id;
1428 msg.pid = htonl (fc->last_pid_sent); 1475 msg.cemi = fc->last_pid_sent;
1429 LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid sent: %u\n", fc->last_pid_sent); 1476 LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid sent: %u\n", ntohl (fc->last_pid_sent.pid));
1430 fc->poll_msg = 1477 fc->poll_msg
1431 GCC_send_prebuilt_message (&msg.header, UINT16_MAX, fc->last_pid_sent, c, 1478 = GCC_send_prebuilt_message (&msg.header,
1432 fc == &c->fwd_fc, GNUNET_YES, NULL, NULL); 1479 UINT16_MAX,
1480 zero,
1481 c,
1482 fc == &c->fwd_fc,
1483 GNUNET_YES,
1484 NULL,
1485 NULL);
1433 GNUNET_assert (NULL != fc->poll_msg); 1486 GNUNET_assert (NULL != fc->poll_msg);
1434 GCC_check_connections (); 1487 GCC_check_connections ();
1435} 1488}
@@ -1829,7 +1882,7 @@ add_to_peer (struct CadetConnection *c,
1829static void 1882static void
1830log_message (const struct GNUNET_MessageHeader *message, 1883log_message (const struct GNUNET_MessageHeader *message,
1831 const struct CadetPeer *peer, 1884 const struct CadetPeer *peer,
1832 const struct GNUNET_CADET_Hash *conn_id) 1885 const struct GNUNET_CADET_ConnectionTunnelIdentifier *conn_id)
1833{ 1886{
1834 uint16_t size; 1887 uint16_t size;
1835 uint16_t type; 1888 uint16_t type;
@@ -1840,7 +1893,7 @@ log_message (const struct GNUNET_MessageHeader *message,
1840 switch (type) 1893 switch (type)
1841 { 1894 {
1842 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: 1895 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
1843 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: 1896 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
1844 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: 1897 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
1845 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: 1898 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
1846 arrow = "=="; 1899 arrow = "==";
@@ -1848,9 +1901,13 @@ log_message (const struct GNUNET_MessageHeader *message,
1848 default: 1901 default:
1849 arrow = "--"; 1902 arrow = "--";
1850 } 1903 }
1851 LOG (GNUNET_ERROR_TYPE_INFO, "<%s %s on conn %s from %s, %6u bytes\n", 1904 LOG (GNUNET_ERROR_TYPE_INFO,
1852 arrow, GC_m2s (type), GNUNET_h2s (GC_h2hc (conn_id)), 1905 "<%s %s on conn %s from %s, %6u bytes\n",
1853 GCP_2s(peer), (unsigned int) size); 1906 arrow,
1907 GC_m2s (type),
1908 GNUNET_sh2s (&conn_id->connection_of_tunnel),
1909 GCP_2s(peer),
1910 (unsigned int) size);
1854} 1911}
1855 1912
1856/******************************************************************************/ 1913/******************************************************************************/
@@ -1865,9 +1922,10 @@ log_message (const struct GNUNET_MessageHeader *message,
1865 */ 1922 */
1866void 1923void
1867GCC_handle_create (struct CadetPeer *peer, 1924GCC_handle_create (struct CadetPeer *peer,
1868 const struct GNUNET_CADET_ConnectionCreate *msg) 1925 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
1869{ 1926{
1870 const struct GNUNET_CADET_Hash *cid; 1927 static struct CadetEncryptedMessageIdentifier zero;
1928 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid;
1871 struct GNUNET_PeerIdentity *id; 1929 struct GNUNET_PeerIdentity *id;
1872 struct CadetPeerPath *path; 1930 struct CadetPeerPath *path;
1873 struct CadetPeer *dest_peer; 1931 struct CadetPeer *dest_peer;
@@ -1880,7 +1938,7 @@ GCC_handle_create (struct CadetPeer *peer,
1880 size = ntohs (msg->header.size); 1938 size = ntohs (msg->header.size);
1881 1939
1882 /* Calculate hops */ 1940 /* Calculate hops */
1883 size -= sizeof (struct GNUNET_CADET_ConnectionCreate); 1941 size -= sizeof (struct GNUNET_CADET_ConnectionCreateMessage);
1884 if (0 != size % sizeof (struct GNUNET_PeerIdentity)) 1942 if (0 != size % sizeof (struct GNUNET_PeerIdentity))
1885 { 1943 {
1886 GNUNET_break_op (0); 1944 GNUNET_break_op (0);
@@ -1989,8 +2047,12 @@ GCC_handle_create (struct CadetPeer *peer,
1989 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); 2047 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1990 GCP_add_path (dest_peer, path_duplicate (path), GNUNET_NO); 2048 GCP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1991 GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO); 2049 GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
1992 (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, 2050 (void) GCC_send_prebuilt_message (&msg->header,
1993 GNUNET_YES, GNUNET_YES, NULL, NULL); 2051 0,
2052 zero,
2053 c,
2054 GNUNET_YES, GNUNET_YES,
2055 NULL, NULL);
1994 } 2056 }
1995 path_destroy (path); 2057 path_destroy (path);
1996 GCC_check_connections (); 2058 GCC_check_connections ();
@@ -2005,8 +2067,9 @@ GCC_handle_create (struct CadetPeer *peer,
2005 */ 2067 */
2006void 2068void
2007GCC_handle_confirm (struct CadetPeer *peer, 2069GCC_handle_confirm (struct CadetPeer *peer,
2008 const struct GNUNET_CADET_ConnectionACK *msg) 2070 const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
2009{ 2071{
2072 static struct CadetEncryptedMessageIdentifier zero;
2010 struct CadetConnection *c; 2073 struct CadetConnection *c;
2011 enum CadetConnectionState oldstate; 2074 enum CadetConnectionState oldstate;
2012 int fwd; 2075 int fwd;
@@ -2114,7 +2177,10 @@ GCC_handle_confirm (struct CadetPeer *peer,
2114 else 2177 else
2115 { 2178 {
2116 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); 2179 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2117 (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd, 2180 (void) GCC_send_prebuilt_message (&msg->header, 0,
2181 zero,
2182 c,
2183 fwd,
2118 GNUNET_YES, NULL, NULL); 2184 GNUNET_YES, NULL, NULL);
2119 } 2185 }
2120 GCC_check_connections (); 2186 GCC_check_connections ();
@@ -2129,8 +2195,9 @@ GCC_handle_confirm (struct CadetPeer *peer,
2129 */ 2195 */
2130void 2196void
2131GCC_handle_broken (struct CadetPeer *peer, 2197GCC_handle_broken (struct CadetPeer *peer,
2132 const struct GNUNET_CADET_ConnectionBroken *msg) 2198 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
2133{ 2199{
2200 static struct CadetEncryptedMessageIdentifier zero;
2134 struct CadetConnection *c; 2201 struct CadetConnection *c;
2135 struct CadetTunnel *t; 2202 struct CadetTunnel *t;
2136 int fwd; 2203 int fwd;
@@ -2183,7 +2250,8 @@ GCC_handle_broken (struct CadetPeer *peer,
2183 } 2250 }
2184 else 2251 else
2185 { 2252 {
2186 (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd, 2253 (void) GCC_send_prebuilt_message (&msg->header, 0,
2254 zero, c, fwd,
2187 GNUNET_YES, NULL, NULL); 2255 GNUNET_YES, NULL, NULL);
2188 connection_cancel_queues (c, !fwd); 2256 connection_cancel_queues (c, !fwd);
2189 } 2257 }
@@ -2200,8 +2268,9 @@ GCC_handle_broken (struct CadetPeer *peer,
2200 */ 2268 */
2201void 2269void
2202GCC_handle_destroy (struct CadetPeer *peer, 2270GCC_handle_destroy (struct CadetPeer *peer,
2203 const struct GNUNET_CADET_ConnectionDestroy *msg) 2271 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
2204{ 2272{
2273 static struct CadetEncryptedMessageIdentifier zero;
2205 struct CadetConnection *c; 2274 struct CadetConnection *c;
2206 int fwd; 2275 int fwd;
2207 2276
@@ -2233,7 +2302,8 @@ GCC_handle_destroy (struct CadetPeer *peer,
2233 2302
2234 if (GNUNET_NO == GCC_is_terminal (c, fwd)) 2303 if (GNUNET_NO == GCC_is_terminal (c, fwd))
2235 { 2304 {
2236 (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd, 2305 (void) GCC_send_prebuilt_message (&msg->header, 0,
2306 zero, c, fwd,
2237 GNUNET_YES, NULL, NULL); 2307 GNUNET_YES, NULL, NULL);
2238 } 2308 }
2239 else if (0 == c->pending_messages) 2309 else if (0 == c->pending_messages)
@@ -2262,11 +2332,11 @@ GCC_handle_destroy (struct CadetPeer *peer,
2262 */ 2332 */
2263void 2333void
2264GCC_handle_ack (struct CadetPeer *peer, 2334GCC_handle_ack (struct CadetPeer *peer,
2265 const struct GNUNET_CADET_ACK *msg) 2335 const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
2266{ 2336{
2267 struct CadetConnection *c; 2337 struct CadetConnection *c;
2268 struct CadetFlowControl *fc; 2338 struct CadetFlowControl *fc;
2269 uint32_t ack; 2339 struct CadetEncryptedMessageIdentifier ack;
2270 int fwd; 2340 int fwd;
2271 2341
2272 GCC_check_connections (); 2342 GCC_check_connections ();
@@ -2303,15 +2373,19 @@ GCC_handle_ack (struct CadetPeer *peer,
2303 return; 2373 return;
2304 } 2374 }
2305 2375
2306 ack = ntohl (msg->ack); 2376 ack = msg->cemi;
2307 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n", 2377 LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n",
2308 GC_f2s (fwd), ack, fc->last_ack_recv); 2378 GC_f2s (fwd),
2309 if (GC_is_pid_bigger (ack, fc->last_ack_recv)) 2379 ntohl (ack.pid),
2380 ntohl (fc->last_ack_recv.pid));
2381 if (GC_is_pid_bigger (ntohl (ack.pid),
2382 ntohl (fc->last_ack_recv.pid)))
2310 fc->last_ack_recv = ack; 2383 fc->last_ack_recv = ack;
2311 2384
2312 /* Cancel polling if the ACK is big enough. */ 2385 /* Cancel polling if the ACK is big enough. */
2313 if (NULL != fc->poll_task && 2386 if ( (NULL != fc->poll_task) &
2314 GC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) 2387 GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid),
2388 ntohl (fc->last_pid_sent.pid)))
2315 { 2389 {
2316 LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n"); 2390 LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
2317 GNUNET_SCHEDULER_cancel (fc->poll_task); 2391 GNUNET_SCHEDULER_cancel (fc->poll_task);
@@ -2331,11 +2405,11 @@ GCC_handle_ack (struct CadetPeer *peer,
2331 */ 2405 */
2332void 2406void
2333GCC_handle_poll (struct CadetPeer *peer, 2407GCC_handle_poll (struct CadetPeer *peer,
2334 const struct GNUNET_CADET_Poll *msg) 2408 const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
2335{ 2409{
2336 struct CadetConnection *c; 2410 struct CadetConnection *c;
2337 struct CadetFlowControl *fc; 2411 struct CadetFlowControl *fc;
2338 uint32_t pid; 2412 struct CadetEncryptedMessageIdentifier pid;
2339 int fwd; 2413 int fwd;
2340 2414
2341 GCC_check_connections (); 2415 GCC_check_connections ();
@@ -2347,7 +2421,7 @@ GCC_handle_poll (struct CadetPeer *peer,
2347 GNUNET_NO); 2421 GNUNET_NO);
2348 LOG (GNUNET_ERROR_TYPE_DEBUG, 2422 LOG (GNUNET_ERROR_TYPE_DEBUG,
2349 "POLL message on unknown connection %s!\n", 2423 "POLL message on unknown connection %s!\n",
2350 GNUNET_h2s (GC_h2hc (&msg->cid))); 2424 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
2351 send_broken_unknown (&msg->cid, 2425 send_broken_unknown (&msg->cid,
2352 &my_full_id, 2426 &my_full_id,
2353 NULL, 2427 NULL,
@@ -2377,8 +2451,11 @@ GCC_handle_poll (struct CadetPeer *peer,
2377 return; 2451 return;
2378 } 2452 }
2379 2453
2380 pid = ntohl (msg->pid); 2454 pid = msg->cemi;
2381 LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n", pid, fc->last_pid_recv); 2455 LOG (GNUNET_ERROR_TYPE_DEBUG,
2456 " PID %u, OLD %u\n",
2457 ntohl (pid.pid),
2458 ntohl (fc->last_pid_recv.pid));
2382 fc->last_pid_recv = pid; 2459 fc->last_pid_recv = pid;
2383 fwd = fc == &c->bck_fc; 2460 fwd = fc == &c->bck_fc;
2384 GCC_send_ack (c, fwd, GNUNET_YES); 2461 GCC_send_ack (c, fwd, GNUNET_YES);
@@ -2402,10 +2479,10 @@ GCC_handle_poll (struct CadetPeer *peer,
2402 */ 2479 */
2403static int 2480static int
2404check_message (const struct GNUNET_MessageHeader *message, 2481check_message (const struct GNUNET_MessageHeader *message,
2405 const struct GNUNET_CADET_Hash* cid, 2482 const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid,
2406 struct CadetConnection *c, 2483 struct CadetConnection *c,
2407 struct CadetPeer *sender, 2484 struct CadetPeer *sender,
2408 uint32_t pid) 2485 struct CadetEncryptedMessageIdentifier pid)
2409{ 2486{
2410 struct CadetFlowControl *fc; 2487 struct CadetFlowControl *fc;
2411 struct CadetPeer *hop; 2488 struct CadetPeer *hop;
@@ -2421,7 +2498,8 @@ check_message (const struct GNUNET_MessageHeader *message,
2421 LOG (GNUNET_ERROR_TYPE_DEBUG, 2498 LOG (GNUNET_ERROR_TYPE_DEBUG,
2422 "%s on unknown connection %s\n", 2499 "%s on unknown connection %s\n",
2423 GC_m2s (ntohs (message->type)), 2500 GC_m2s (ntohs (message->type)),
2424 GNUNET_h2s (GC_h2hc (cid))); 2501 GNUNET_sh2s (&cid->connection_of_tunnel));
2502 GNUNET_break_op (0);
2425 send_broken_unknown (cid, 2503 send_broken_unknown (cid,
2426 &my_full_id, 2504 &my_full_id,
2427 NULL, 2505 NULL,
@@ -2453,43 +2531,59 @@ check_message (const struct GNUNET_MessageHeader *message,
2453 2531
2454 /* Check PID for payload messages */ 2532 /* Check PID for payload messages */
2455 type = ntohs (message->type); 2533 type = ntohs (message->type);
2456 if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type) 2534 if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type)
2457 { 2535 {
2458 fc = fwd ? &c->bck_fc : &c->fwd_fc; 2536 fc = fwd ? &c->bck_fc : &c->fwd_fc;
2459 LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u - %u)\n", 2537 LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected in interval [%u,%u])\n",
2460 pid, fc->last_pid_recv + 1, fc->last_ack_sent); 2538 ntohl (pid.pid),
2461 if (GC_is_pid_bigger (pid, fc->last_ack_sent)) 2539 ntohl (fc->last_pid_recv.pid) + 1,
2540 ntohl (fc->last_ack_sent.pid));
2541 if (GC_is_pid_bigger (ntohl (pid.pid),
2542 ntohl (fc->last_ack_sent.pid)))
2462 { 2543 {
2463 GNUNET_break_op (0); 2544 GNUNET_STATISTICS_update (stats,
2464 GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO); 2545 "# unsolicited message",
2465 LOG (GNUNET_ERROR_TYPE_WARNING, "Received PID %u, (prev %u), ACK %u\n", 2546 1,
2466 pid, fc->last_pid_recv, fc->last_ack_sent); 2547 GNUNET_NO);
2548 LOG (GNUNET_ERROR_TYPE_WARNING,
2549 "Received PID %u, (prev %u), ACK %u\n",
2550 pid, fc->last_pid_recv, fc->last_ack_sent);
2467 return GNUNET_SYSERR; 2551 return GNUNET_SYSERR;
2468 } 2552 }
2469 if (GC_is_pid_bigger (pid, fc->last_pid_recv)) 2553 if (GC_is_pid_bigger (ntohl (pid.pid),
2554 ntohl (fc->last_pid_recv.pid)))
2470 { 2555 {
2471 unsigned int delta; 2556 unsigned int delta;
2472 2557
2473 delta = pid - fc->last_pid_recv; 2558 delta = ntohl (pid.pid) - ntohl (fc->last_pid_recv.pid);
2474 fc->last_pid_recv = pid; 2559 fc->last_pid_recv = pid;
2475 fc->recv_bitmap <<= delta; 2560 fc->recv_bitmap <<= delta;
2476 fc->recv_bitmap |= 1; 2561 fc->recv_bitmap |= 1;
2477 } 2562 }
2478 else 2563 else
2479 { 2564 {
2480 GNUNET_STATISTICS_update (stats, "# out of order PID", 1, GNUNET_NO); 2565 GNUNET_STATISTICS_update (stats,
2481 if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv, pid, fc->recv_bitmap)) 2566 "# out of order PID",
2567 1,
2568 GNUNET_NO);
2569 if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv,
2570 pid,
2571 fc->recv_bitmap))
2482 { 2572 {
2483 LOG (GNUNET_ERROR_TYPE_WARNING, "PID %u unexpected (%u+), dropping!\n", 2573 LOG (GNUNET_ERROR_TYPE_WARNING,
2484 pid, fc->last_pid_recv - 31); 2574 "PID %u unexpected (%u+), dropping!\n",
2575 ntohl (pid.pid),
2576 ntohl (fc->last_pid_recv.pid) - 31);
2485 return GNUNET_SYSERR; 2577 return GNUNET_SYSERR;
2486 } 2578 }
2487 fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv, pid); 2579 fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv,
2580 pid);
2488 } 2581 }
2489 } 2582 }
2490 2583
2491 /* Count as connection confirmation. */ 2584 /* Count as connection confirmation. */
2492 if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state) 2585 if ( (CADET_CONNECTION_SENT == c->state) ||
2586 (CADET_CONNECTION_ACK == c->state) )
2493 { 2587 {
2494 connection_change_state (c, CADET_CONNECTION_READY); 2588 connection_change_state (c, CADET_CONNECTION_READY);
2495 if (NULL != c->t) 2589 if (NULL != c->t)
@@ -2512,9 +2606,10 @@ check_message (const struct GNUNET_MessageHeader *message,
2512 */ 2606 */
2513void 2607void
2514GCC_handle_kx (struct CadetPeer *peer, 2608GCC_handle_kx (struct CadetPeer *peer,
2515 const struct GNUNET_CADET_KX *msg) 2609 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
2516{ 2610{
2517 const struct GNUNET_CADET_Hash* cid; 2611 static struct CadetEncryptedMessageIdentifier zero;
2612 const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid;
2518 struct CadetConnection *c; 2613 struct CadetConnection *c;
2519 int fwd; 2614 int fwd;
2520 2615
@@ -2527,7 +2622,7 @@ GCC_handle_kx (struct CadetPeer *peer,
2527 cid, 2622 cid,
2528 c, 2623 c,
2529 peer, 2624 peer,
2530 0); 2625 zero);
2531 2626
2532 /* If something went wrong, discard message. */ 2627 /* If something went wrong, discard message. */
2533 if (GNUNET_SYSERR == fwd) 2628 if (GNUNET_SYSERR == fwd)
@@ -2555,7 +2650,8 @@ GCC_handle_kx (struct CadetPeer *peer,
2555 /* Message not for us: forward to next hop */ 2650 /* Message not for us: forward to next hop */
2556 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); 2651 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2557 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); 2652 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
2558 (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd, 2653 (void) GCC_send_prebuilt_message (&msg->header, 0,
2654 zero, c, fwd,
2559 GNUNET_NO, NULL, NULL); 2655 GNUNET_NO, NULL, NULL);
2560 GCC_check_connections (); 2656 GCC_check_connections ();
2561} 2657}
@@ -2569,16 +2665,17 @@ GCC_handle_kx (struct CadetPeer *peer,
2569 */ 2665 */
2570void 2666void
2571GCC_handle_encrypted (struct CadetPeer *peer, 2667GCC_handle_encrypted (struct CadetPeer *peer,
2572 const struct GNUNET_CADET_Encrypted *msg) 2668 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
2573{ 2669{
2574 const struct GNUNET_CADET_Hash* cid; 2670 static struct CadetEncryptedMessageIdentifier zero;
2671 const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid;
2575 struct CadetConnection *c; 2672 struct CadetConnection *c;
2576 uint32_t pid; 2673 struct CadetEncryptedMessageIdentifier pid;
2577 int fwd; 2674 int fwd;
2578 2675
2579 GCC_check_connections (); 2676 GCC_check_connections ();
2580 cid = &msg->cid; 2677 cid = &msg->cid;
2581 pid = ntohl (msg->pid); 2678 pid = msg->cemi;
2582 log_message (&msg->header, peer, cid); 2679 log_message (&msg->header, peer, cid);
2583 2680
2584 c = connection_get (cid); 2681 c = connection_get (cid);
@@ -2591,7 +2688,6 @@ GCC_handle_encrypted (struct CadetPeer *peer,
2591 /* If something went wrong, discard message. */ 2688 /* If something went wrong, discard message. */
2592 if (GNUNET_SYSERR == fwd) 2689 if (GNUNET_SYSERR == fwd)
2593 { 2690 {
2594 GNUNET_break_op (0);
2595 GCC_check_connections (); 2691 GCC_check_connections ();
2596 return; 2692 return;
2597 } 2693 }
@@ -2615,7 +2711,8 @@ GCC_handle_encrypted (struct CadetPeer *peer,
2615 /* Message not for us: forward to next hop */ 2711 /* Message not for us: forward to next hop */
2616 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); 2712 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2617 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); 2713 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
2618 (void) GCC_send_prebuilt_message (&msg->header, 0, 0, c, fwd, 2714 (void) GCC_send_prebuilt_message (&msg->header, 0,
2715 zero, c, fwd,
2619 GNUNET_NO, NULL, NULL); 2716 GNUNET_NO, NULL, NULL);
2620 GCC_check_connections (); 2717 GCC_check_connections ();
2621} 2718}
@@ -2661,7 +2758,8 @@ GCC_init (const struct GNUNET_CONFIGURATION_Handle *c)
2661 } 2758 }
2662 create_connection_time = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, 2759 create_connection_time = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
2663 refresh_connection_time); 2760 refresh_connection_time);
2664 connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); 2761 connections = GNUNET_CONTAINER_multishortmap_create (1024,
2762 GNUNET_YES);
2665} 2763}
2666 2764
2667 2765
@@ -2676,7 +2774,7 @@ GCC_init (const struct GNUNET_CONFIGURATION_Handle *c)
2676 */ 2774 */
2677static int 2775static int
2678shutdown_iterator (void *cls, 2776shutdown_iterator (void *cls,
2679 const struct GNUNET_HashCode *key, 2777 const struct GNUNET_ShortHashCode *key,
2680 void *value) 2778 void *value)
2681{ 2779{
2682 struct CadetConnection *c = value; 2780 struct CadetConnection *c = value;
@@ -2695,10 +2793,10 @@ GCC_shutdown (void)
2695{ 2793{
2696 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connections\n"); 2794 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connections\n");
2697 GCC_check_connections (); 2795 GCC_check_connections ();
2698 GNUNET_CONTAINER_multihashmap_iterate (connections, 2796 GNUNET_CONTAINER_multishortmap_iterate (connections,
2699 &shutdown_iterator, 2797 &shutdown_iterator,
2700 NULL); 2798 NULL);
2701 GNUNET_CONTAINER_multihashmap_destroy (connections); 2799 GNUNET_CONTAINER_multishortmap_destroy (connections);
2702 connections = NULL; 2800 connections = NULL;
2703} 2801}
2704 2802
@@ -2715,7 +2813,7 @@ GCC_shutdown (void)
2715 * NULL in case of error: own id not in path, wrong neighbors, ... 2813 * NULL in case of error: own id not in path, wrong neighbors, ...
2716*/ 2814*/
2717struct CadetConnection * 2815struct CadetConnection *
2718GCC_new (const struct GNUNET_CADET_Hash *cid, 2816GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
2719 struct CadetTunnel *t, 2817 struct CadetTunnel *t,
2720 struct CadetPeerPath *path, 2818 struct CadetPeerPath *path,
2721 unsigned int own_pos) 2819 unsigned int own_pos)
@@ -2729,9 +2827,10 @@ GCC_new (const struct GNUNET_CADET_Hash *cid,
2729 c = GNUNET_new (struct CadetConnection); 2827 c = GNUNET_new (struct CadetConnection);
2730 c->id = *cid; 2828 c->id = *cid;
2731 GNUNET_assert (GNUNET_OK == 2829 GNUNET_assert (GNUNET_OK ==
2732 GNUNET_CONTAINER_multihashmap_put (connections, 2830 GNUNET_CONTAINER_multishortmap_put (connections,
2733 GCC_get_h (c), c, 2831 &c->id.connection_of_tunnel,
2734 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 2832 c,
2833 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2735 fc_init (&c->fwd_fc); 2834 fc_init (&c->fwd_fc);
2736 fc_init (&c->bck_fc); 2835 fc_init (&c->bck_fc);
2737 c->fwd_fc.c = c; 2836 c->fwd_fc.c = c;
@@ -2832,9 +2931,9 @@ GCC_destroy (struct CadetConnection *c)
2832 if (GNUNET_NO == c->was_removed) 2931 if (GNUNET_NO == c->was_removed)
2833 { 2932 {
2834 GNUNET_break (GNUNET_YES == 2933 GNUNET_break (GNUNET_YES ==
2835 GNUNET_CONTAINER_multihashmap_remove (connections, 2934 GNUNET_CONTAINER_multishortmap_remove (connections,
2836 GCC_get_h (c), 2935 &c->id.connection_of_tunnel,
2837 c)); 2936 c));
2838 } 2937 }
2839 GNUNET_STATISTICS_update (stats, 2938 GNUNET_STATISTICS_update (stats,
2840 "# connections", 2939 "# connections",
@@ -2852,7 +2951,7 @@ GCC_destroy (struct CadetConnection *c)
2852 * 2951 *
2853 * @return ID of the connection. 2952 * @return ID of the connection.
2854 */ 2953 */
2855const struct GNUNET_CADET_Hash * 2954const struct GNUNET_CADET_ConnectionTunnelIdentifier *
2856GCC_get_id (const struct CadetConnection *c) 2955GCC_get_id (const struct CadetConnection *c)
2857{ 2956{
2858 return &c->id; 2957 return &c->id;
@@ -2860,20 +2959,6 @@ GCC_get_id (const struct CadetConnection *c)
2860 2959
2861 2960
2862/** 2961/**
2863 * Get the connection ID.
2864 *
2865 * @param c Connection to get the ID from.
2866 *
2867 * @return ID of the connection.
2868 */
2869const struct GNUNET_HashCode *
2870GCC_get_h (const struct CadetConnection *c)
2871{
2872 return GC_h2hc (&c->id);
2873}
2874
2875
2876/**
2877 * Get the connection path. 2962 * Get the connection path.
2878 * 2963 *
2879 * @param c Connection to get the path from. 2964 * @param c Connection to get the path from.
@@ -2953,12 +3038,13 @@ GCC_get_allowed (struct CadetConnection *c, int fwd)
2953 struct CadetFlowControl *fc; 3038 struct CadetFlowControl *fc;
2954 3039
2955 fc = fwd ? &c->fwd_fc : &c->bck_fc; 3040 fc = fwd ? &c->fwd_fc : &c->bck_fc;
2956 if (CADET_CONNECTION_READY != c->state 3041 if ( (CADET_CONNECTION_READY != c->state) ||
2957 || GC_is_pid_bigger (fc->last_pid_recv, fc->last_ack_sent)) 3042 GC_is_pid_bigger (ntohl (fc->last_pid_recv.pid),
3043 ntohl (fc->last_ack_sent.pid)) )
2958 { 3044 {
2959 return 0; 3045 return 0;
2960 } 3046 }
2961 return (fc->last_ack_sent - fc->last_pid_recv); 3047 return (ntohl (fc->last_ack_sent.pid) - ntohl (fc->last_pid_recv.pid));
2962} 3048}
2963 3049
2964 3050
@@ -2986,18 +3072,17 @@ GCC_get_qn (struct CadetConnection *c, int fwd)
2986 * 3072 *
2987 * @param c Connection. 3073 * @param c Connection.
2988 * @param fwd Is query about FWD traffic? 3074 * @param fwd Is query about FWD traffic?
2989 *
2990 * @return Next PID to use. 3075 * @return Next PID to use.
2991 */ 3076 */
2992uint32_t 3077struct CadetEncryptedMessageIdentifier
2993GCC_get_pid (struct CadetConnection *c, int fwd) 3078GCC_get_pid (struct CadetConnection *c, int fwd)
2994{ 3079{
2995 struct CadetFlowControl *fc; 3080 struct CadetFlowControl *fc;
2996 uint32_t pid; 3081 struct CadetEncryptedMessageIdentifier pid;
2997 3082
2998 fc = fwd ? &c->fwd_fc : &c->bck_fc; 3083 fc = fwd ? &c->fwd_fc : &c->bck_fc;
2999 pid = fc->next_pid; 3084 pid = fc->next_pid;
3000 fc->next_pid++; 3085 fc->next_pid.pid = htonl (1 + ntohl (pid.pid));
3001 return pid; 3086 return pid;
3002} 3087}
3003 3088
@@ -3072,9 +3157,9 @@ GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer)
3072 GNUNET_assert (GNUNET_NO == c->was_removed); 3157 GNUNET_assert (GNUNET_NO == c->was_removed);
3073 c->was_removed = GNUNET_YES; 3158 c->was_removed = GNUNET_YES;
3074 GNUNET_break (GNUNET_YES == 3159 GNUNET_break (GNUNET_YES ==
3075 GNUNET_CONTAINER_multihashmap_remove (connections, 3160 GNUNET_CONTAINER_multishortmap_remove (connections,
3076 GCC_get_h (c), 3161 &c->id.connection_of_tunnel,
3077 c)); 3162 c));
3078 /* Cancel queue in the direction that just died. */ 3163 /* Cancel queue in the direction that just died. */
3079 connection_cancel_queues (c, ! fwd); 3164 connection_cancel_queues (c, ! fwd);
3080 GCC_stop_poll (c, ! fwd); 3165 GCC_stop_poll (c, ! fwd);
@@ -3142,8 +3227,10 @@ GCC_is_sendable (struct CadetConnection *c, int fwd)
3142 fc = fwd ? &c->fwd_fc : &c->bck_fc; 3227 fc = fwd ? &c->fwd_fc : &c->bck_fc;
3143 LOG (GNUNET_ERROR_TYPE_DEBUG, 3228 LOG (GNUNET_ERROR_TYPE_DEBUG,
3144 " last ack recv: %u, last pid sent: %u\n", 3229 " last ack recv: %u, last pid sent: %u\n",
3145 fc->last_ack_recv, fc->last_pid_sent); 3230 ntohl (fc->last_ack_recv.pid),
3146 if (GC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) 3231 ntohl (fc->last_pid_sent.pid));
3232 if (GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid),
3233 ntohl (fc->last_pid_sent.pid)))
3147 { 3234 {
3148 LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n"); 3235 LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n");
3149 return GNUNET_YES; 3236 return GNUNET_YES;
@@ -3188,7 +3275,8 @@ GCC_is_direct (struct CadetConnection *c)
3188 */ 3275 */
3189struct CadetConnectionQueue * 3276struct CadetConnectionQueue *
3190GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, 3277GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
3191 uint16_t payload_type, uint32_t payload_id, 3278 uint16_t payload_type,
3279 struct CadetEncryptedMessageIdentifier payload_id,
3192 struct CadetConnection *c, int fwd, int force, 3280 struct CadetConnection *c, int fwd, int force,
3193 GCC_sent cont, void *cont_cls) 3281 GCC_sent cont, void *cont_cls)
3194{ 3282{
@@ -3214,27 +3302,30 @@ GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
3214 GC_f2s(fwd), size); 3302 GC_f2s(fwd), size);
3215 switch (type) 3303 switch (type)
3216 { 3304 {
3217 case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: 3305 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
3218 LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u, PIDsnt: %u, ACKrcv: %u\n", 3306 LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u, PIDsnt: %u, ACKrcv: %u\n",
3219 fc, fc->queue_n, fc->last_pid_sent, fc->last_ack_recv); 3307 fc,
3308 fc->queue_n,
3309 ntohl (fc->last_pid_sent.pid),
3310 ntohl (fc->last_ack_recv.pid));
3220 if (GNUNET_NO == force) 3311 if (GNUNET_NO == force)
3221 { 3312 {
3222 fc->queue_n++; 3313 fc->queue_n++;
3223 } 3314 }
3224 break; 3315 break;
3225 3316
3226 case GNUNET_MESSAGE_TYPE_CADET_KX: 3317 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
3227 /* nothing to do here */ 3318 /* nothing to do here */
3228 break; 3319 break;
3229 3320
3230 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: 3321 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
3231 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: 3322 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
3232 /* Should've only be used for restransmissions. */ 3323 /* Should've only be used for restransmissions. */
3233 GNUNET_break (0 == payload_type); 3324 GNUNET_break (0 == payload_type);
3234 break; 3325 break;
3235 3326
3236 case GNUNET_MESSAGE_TYPE_CADET_ACK: 3327 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
3237 case GNUNET_MESSAGE_TYPE_CADET_POLL: 3328 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
3238 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: 3329 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
3239 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: 3330 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
3240 GNUNET_assert (GNUNET_YES == force); 3331 GNUNET_assert (GNUNET_YES == force);
@@ -3252,7 +3343,7 @@ GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
3252 GNUNET_break (0); 3343 GNUNET_break (0);
3253 LOG (GNUNET_ERROR_TYPE_DEBUG, "queue full: %u/%u\n", 3344 LOG (GNUNET_ERROR_TYPE_DEBUG, "queue full: %u/%u\n",
3254 fc->queue_n, fc->queue_max); 3345 fc->queue_n, fc->queue_max);
3255 if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type) 3346 if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type)
3256 { 3347 {
3257 fc->queue_n--; 3348 fc->queue_n--;
3258 } 3349 }
@@ -3264,21 +3355,25 @@ GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
3264 c->pending_messages++; 3355 c->pending_messages++;
3265 3356
3266 q = GNUNET_new (struct CadetConnectionQueue); 3357 q = GNUNET_new (struct CadetConnectionQueue);
3358 q->cont = cont;
3359 q->cont_cls = cont_cls;
3267 q->forced = force; 3360 q->forced = force;
3268 q->peer_q = GCP_send (get_hop (c, fwd), message, 3361 GNUNET_CONTAINER_DLL_insert (fc->q_head, fc->q_tail, q);
3269 payload_type, payload_id, 3362 q->peer_q = GCP_send (get_hop (c, fwd),
3270 c, fwd, 3363 message,
3364 payload_type,
3365 payload_id,
3366 c,
3367 fwd,
3271 &conn_message_sent, q); 3368 &conn_message_sent, q);
3272 if (NULL == q->peer_q) 3369 if (NULL == q->peer_q)
3273 { 3370 {
3274 LOG (GNUNET_ERROR_TYPE_DEBUG, "dropping msg on %s, NULL q\n", GCC_2s (c)); 3371 LOG (GNUNET_ERROR_TYPE_DEBUG, "dropping msg on %s, NULL q\n", GCC_2s (c));
3372 GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q);
3275 GNUNET_free (q); 3373 GNUNET_free (q);
3276 GCC_check_connections (); 3374 GCC_check_connections ();
3277 return NULL; 3375 return NULL;
3278 } 3376 }
3279 q->cont = cont;
3280 q->cont_cls = cont_cls;
3281 GNUNET_CONTAINER_DLL_insert (fc->q_head, fc->q_tail, q);
3282 GCC_check_connections (); 3377 GCC_check_connections ();
3283 return q; 3378 return q;
3284} 3379}
@@ -3313,19 +3408,21 @@ GCC_cancel (struct CadetConnectionQueue *q)
3313void 3408void
3314GCC_send_create (struct CadetConnection *c) 3409GCC_send_create (struct CadetConnection *c)
3315{ 3410{
3411 static struct CadetEncryptedMessageIdentifier zero;
3316 enum CadetTunnelCState state; 3412 enum CadetTunnelCState state;
3317 size_t size; 3413 size_t size;
3318 3414
3319 GCC_check_connections (); 3415 GCC_check_connections ();
3320 size = sizeof (struct GNUNET_CADET_ConnectionCreate); 3416 size = sizeof (struct GNUNET_CADET_ConnectionCreateMessage);
3321 size += c->path->length * sizeof (struct GNUNET_PeerIdentity); 3417 size += c->path->length * sizeof (struct GNUNET_PeerIdentity);
3322 { 3418 {
3323 /* Allocate message on the stack */ 3419 /* Allocate message on the stack */
3324 unsigned char cbuf[size]; 3420 unsigned char cbuf[size];
3325 struct GNUNET_CADET_ConnectionCreate *msg; 3421 struct GNUNET_CADET_ConnectionCreateMessage *msg;
3326 struct GNUNET_PeerIdentity *peers; 3422 struct GNUNET_PeerIdentity *peers;
3327 3423
3328 msg = (struct GNUNET_CADET_ConnectionCreate *) cbuf; 3424
3425 msg = (struct GNUNET_CADET_ConnectionCreateMessage *) cbuf;
3329 msg->header.size = htons (size); 3426 msg->header.size = htons (size);
3330 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); 3427 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
3331 msg->reserved = htonl (0); 3428 msg->reserved = htonl (0);
@@ -3338,7 +3435,8 @@ GCC_send_create (struct CadetConnection *c)
3338 GNUNET_assert (NULL == c->maintenance_q); 3435 GNUNET_assert (NULL == c->maintenance_q);
3339 c->maintenance_q = GCP_send (get_next_hop (c), 3436 c->maintenance_q = GCP_send (get_next_hop (c),
3340 &msg->header, 3437 &msg->header,
3341 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0, 3438 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
3439 zero,
3342 c, GNUNET_YES, 3440 c, GNUNET_YES,
3343 &conn_message_sent, NULL); 3441 &conn_message_sent, NULL);
3344 } 3442 }
@@ -3435,7 +3533,8 @@ GCC_send_ack (struct CadetConnection *c, int fwd, int force)
3435void 3533void
3436GCC_send_destroy (struct CadetConnection *c) 3534GCC_send_destroy (struct CadetConnection *c)
3437{ 3535{
3438 struct GNUNET_CADET_ConnectionDestroy msg; 3536 static struct CadetEncryptedMessageIdentifier zero;
3537 struct GNUNET_CADET_ConnectionDestroyMessage msg;
3439 3538
3440 if (GNUNET_YES == c->destroy) 3539 if (GNUNET_YES == c->destroy)
3441 return; 3540 return;
@@ -3449,10 +3548,16 @@ GCC_send_destroy (struct CadetConnection *c)
3449 GCC_2s (c)); 3548 GCC_2s (c));
3450 3549
3451 if (GNUNET_NO == GCC_is_terminal (c, GNUNET_YES)) 3550 if (GNUNET_NO == GCC_is_terminal (c, GNUNET_YES))
3452 (void) GCC_send_prebuilt_message (&msg.header, UINT16_MAX, 0, c, 3551 (void) GCC_send_prebuilt_message (&msg.header,
3552 UINT16_MAX,
3553 zero,
3554 c,
3453 GNUNET_YES, GNUNET_YES, NULL, NULL); 3555 GNUNET_YES, GNUNET_YES, NULL, NULL);
3454 if (GNUNET_NO == GCC_is_terminal (c, GNUNET_NO)) 3556 if (GNUNET_NO == GCC_is_terminal (c, GNUNET_NO))
3455 (void) GCC_send_prebuilt_message (&msg.header, UINT16_MAX, 0, c, 3557 (void) GCC_send_prebuilt_message (&msg.header,
3558 UINT16_MAX,
3559 zero,
3560 c,
3456 GNUNET_NO, GNUNET_YES, NULL, NULL); 3561 GNUNET_NO, GNUNET_YES, NULL, NULL);
3457 mark_destroyed (c); 3562 mark_destroyed (c);
3458 GCC_check_connections (); 3563 GCC_check_connections ();
@@ -3538,10 +3643,11 @@ GCC_2s (const struct CadetConnection *c)
3538 static char buf[128]; 3643 static char buf[128];
3539 3644
3540 SPRINTF (buf, "%s (->%s)", 3645 SPRINTF (buf, "%s (->%s)",
3541 GNUNET_h2s (GC_h2hc (GCC_get_id (c))), GCT_2s (c->t)); 3646 GNUNET_sh2s (&GCC_get_id (c)->connection_of_tunnel),
3647 GCT_2s (c->t));
3542 return buf; 3648 return buf;
3543 } 3649 }
3544 return GNUNET_h2s (GC_h2hc (&c->id)); 3650 return GNUNET_sh2s (&c->id.connection_of_tunnel);
3545} 3651}
3546 3652
3547 3653
@@ -3582,9 +3688,11 @@ GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level)
3582 LOG2 (level, "CCC FWD flow control:\n"); 3688 LOG2 (level, "CCC FWD flow control:\n");
3583 LOG2 (level, "CCC queue: %u/%u\n", c->fwd_fc.queue_n, c->fwd_fc.queue_max); 3689 LOG2 (level, "CCC queue: %u/%u\n", c->fwd_fc.queue_n, c->fwd_fc.queue_max);
3584 LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n", 3690 LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n",
3585 c->fwd_fc.last_pid_sent, c->fwd_fc.last_pid_recv); 3691 ntohl (c->fwd_fc.last_pid_sent.pid),
3692 ntohl (c->fwd_fc.last_pid_recv.pid));
3586 LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n", 3693 LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n",
3587 c->fwd_fc.last_ack_sent, c->fwd_fc.last_ack_recv); 3694 ntohl (c->fwd_fc.last_ack_sent.pid),
3695 ntohl (c->fwd_fc.last_ack_recv.pid));
3588 LOG2 (level, "CCC recv PID bitmap: %X\n", c->fwd_fc.recv_bitmap); 3696 LOG2 (level, "CCC recv PID bitmap: %X\n", c->fwd_fc.recv_bitmap);
3589 LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n", 3697 LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n",
3590 c->fwd_fc.poll_task, c->fwd_fc.poll_msg, c->fwd_fc.ack_msg); 3698 c->fwd_fc.poll_task, c->fwd_fc.poll_msg, c->fwd_fc.ack_msg);
@@ -3592,9 +3700,11 @@ GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level)
3592 LOG2 (level, "CCC BCK flow control:\n"); 3700 LOG2 (level, "CCC BCK flow control:\n");
3593 LOG2 (level, "CCC queue: %u/%u\n", c->bck_fc.queue_n, c->bck_fc.queue_max); 3701 LOG2 (level, "CCC queue: %u/%u\n", c->bck_fc.queue_n, c->bck_fc.queue_max);
3594 LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n", 3702 LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n",
3595 c->bck_fc.last_pid_sent, c->bck_fc.last_pid_recv); 3703 ntohl (c->bck_fc.last_pid_sent.pid),
3704 ntohl (c->bck_fc.last_pid_recv.pid));
3596 LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n", 3705 LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n",
3597 c->bck_fc.last_ack_sent, c->bck_fc.last_ack_recv); 3706 ntohl (c->bck_fc.last_ack_sent.pid),
3707 ntohl (c->bck_fc.last_ack_recv.pid));
3598 LOG2 (level, "CCC recv PID bitmap: %X\n", c->bck_fc.recv_bitmap); 3708 LOG2 (level, "CCC recv PID bitmap: %X\n", c->bck_fc.recv_bitmap);
3599 LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n", 3709 LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n",
3600 c->bck_fc.poll_task, c->bck_fc.poll_msg, c->bck_fc.ack_msg); 3710 c->bck_fc.poll_task, c->bck_fc.poll_msg, c->bck_fc.ack_msg);
diff --git a/src/cadet/gnunet-service-cadet_connection.h b/src/cadet/gnunet-service-cadet_connection.h
index 18f33ce7c..1c3160dfd 100644
--- a/src/cadet/gnunet-service-cadet_connection.h
+++ b/src/cadet/gnunet-service-cadet_connection.h
@@ -125,7 +125,7 @@ typedef void
125 */ 125 */
126void 126void
127GCC_handle_create (struct CadetPeer *peer, 127GCC_handle_create (struct CadetPeer *peer,
128 const struct GNUNET_CADET_ConnectionCreate *msg); 128 const struct GNUNET_CADET_ConnectionCreateMessage *msg);
129 129
130 130
131/** 131/**
@@ -136,7 +136,7 @@ GCC_handle_create (struct CadetPeer *peer,
136 */ 136 */
137void 137void
138GCC_handle_confirm (struct CadetPeer *peer, 138GCC_handle_confirm (struct CadetPeer *peer,
139 const struct GNUNET_CADET_ConnectionACK *msg); 139 const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg);
140 140
141 141
142/** 142/**
@@ -147,7 +147,7 @@ GCC_handle_confirm (struct CadetPeer *peer,
147 */ 147 */
148void 148void
149GCC_handle_broken (struct CadetPeer *peer, 149GCC_handle_broken (struct CadetPeer *peer,
150 const struct GNUNET_CADET_ConnectionBroken *msg); 150 const struct GNUNET_CADET_ConnectionBrokenMessage *msg);
151 151
152/** 152/**
153 * Handler for notifications of destroyed connections. 153 * Handler for notifications of destroyed connections.
@@ -157,7 +157,7 @@ GCC_handle_broken (struct CadetPeer *peer,
157 */ 157 */
158void 158void
159GCC_handle_destroy (struct CadetPeer *peer, 159GCC_handle_destroy (struct CadetPeer *peer,
160 const struct GNUNET_CADET_ConnectionDestroy *msg); 160 const struct GNUNET_CADET_ConnectionDestroyMessage *msg);
161 161
162/** 162/**
163 * Handler for cadet network traffic hop-by-hop acks. 163 * Handler for cadet network traffic hop-by-hop acks.
@@ -167,7 +167,7 @@ GCC_handle_destroy (struct CadetPeer *peer,
167 */ 167 */
168void 168void
169GCC_handle_ack (struct CadetPeer *peer, 169GCC_handle_ack (struct CadetPeer *peer,
170 const struct GNUNET_CADET_ACK *msg); 170 const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg);
171 171
172/** 172/**
173 * Handler for cadet network traffic hop-by-hop data counter polls. 173 * Handler for cadet network traffic hop-by-hop data counter polls.
@@ -177,7 +177,7 @@ GCC_handle_ack (struct CadetPeer *peer,
177 */ 177 */
178void 178void
179GCC_handle_poll (struct CadetPeer *peer, 179GCC_handle_poll (struct CadetPeer *peer,
180 const struct GNUNET_CADET_Poll *msg); 180 const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg);
181 181
182/** 182/**
183 * Handler for key exchange traffic (Axolotl KX). 183 * Handler for key exchange traffic (Axolotl KX).
@@ -187,7 +187,7 @@ GCC_handle_poll (struct CadetPeer *peer,
187 */ 187 */
188void 188void
189GCC_handle_kx (struct CadetPeer *peer, 189GCC_handle_kx (struct CadetPeer *peer,
190 const struct GNUNET_CADET_KX *msg); 190 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
191 191
192/** 192/**
193 * Handler for encrypted cadet network traffic (channel mgmt, data). 193 * Handler for encrypted cadet network traffic (channel mgmt, data).
@@ -197,7 +197,7 @@ GCC_handle_kx (struct CadetPeer *peer,
197 */ 197 */
198void 198void
199GCC_handle_encrypted (struct CadetPeer *peer, 199GCC_handle_encrypted (struct CadetPeer *peer,
200 const struct GNUNET_CADET_Encrypted *msg); 200 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
201 201
202/** 202/**
203 * Core handler for axolotl key exchange traffic. 203 * Core handler for axolotl key exchange traffic.
@@ -277,7 +277,7 @@ GCC_shutdown (void);
277 * NULL in case of error: own id not in path, wrong neighbors, ... 277 * NULL in case of error: own id not in path, wrong neighbors, ...
278 */ 278 */
279struct CadetConnection * 279struct CadetConnection *
280GCC_new (const struct GNUNET_CADET_Hash *cid, 280GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
281 struct CadetTunnel *t, 281 struct CadetTunnel *t,
282 struct CadetPeerPath *path, 282 struct CadetPeerPath *path,
283 unsigned int own_pos); 283 unsigned int own_pos);
@@ -300,22 +300,11 @@ GCC_destroy (struct CadetConnection *c);
300 * 300 *
301 * @return ID of the connection. 301 * @return ID of the connection.
302 */ 302 */
303const struct GNUNET_CADET_Hash * 303const struct GNUNET_CADET_ConnectionTunnelIdentifier *
304GCC_get_id (const struct CadetConnection *c); 304GCC_get_id (const struct CadetConnection *c);
305 305
306 306
307/** 307/**
308 * Get a hash for the connection ID.
309 *
310 * @param c Connection to get the hash.
311 *
312 * @return Hash expanded from the ID of the connection.
313 */
314const struct GNUNET_HashCode *
315GCC_get_h (const struct CadetConnection *c);
316
317
318/**
319 * Get the connection path. 308 * Get the connection path.
320 * 309 *
321 * @param c Connection to get the path from. 310 * @param c Connection to get the path from.
@@ -383,10 +372,9 @@ GCC_get_qn (struct CadetConnection *c, int fwd);
383 * 372 *
384 * @param c Connection. 373 * @param c Connection.
385 * @param fwd Is query about FWD traffic? 374 * @param fwd Is query about FWD traffic?
386 *
387 * @return Next PID to use. 375 * @return Next PID to use.
388 */ 376 */
389uint32_t 377struct CadetEncryptedMessageIdentifier
390GCC_get_pid (struct CadetConnection *c, int fwd); 378GCC_get_pid (struct CadetConnection *c, int fwd);
391 379
392/** 380/**
@@ -508,7 +496,8 @@ GCC_cancel (struct CadetConnectionQueue *q);
508 */ 496 */
509struct CadetConnectionQueue * 497struct CadetConnectionQueue *
510GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, 498GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
511 uint16_t payload_type, uint32_t payload_id, 499 uint16_t payload_type,
500 struct CadetEncryptedMessageIdentifier payload_id,
512 struct CadetConnection *c, int fwd, int force, 501 struct CadetConnection *c, int fwd, int force,
513 GCC_sent cont, void *cont_cls); 502 GCC_sent cont, void *cont_cls);
514 503
diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c
index 9b11ebf18..22673b167 100644
--- a/src/cadet/gnunet-service-cadet_dht.c
+++ b/src/cadet/gnunet-service-cadet_dht.c
@@ -42,16 +42,24 @@
42 */ 42 */
43struct GCD_search_handle 43struct GCD_search_handle
44{ 44{
45 /** DHT_GET handle. */ 45 /**
46 * DHT_GET handle.
47 */
46 struct GNUNET_DHT_GetHandle *dhtget; 48 struct GNUNET_DHT_GetHandle *dhtget;
47 49
48 /** Provided callback to call when a path is found. */ 50 /**
51 * Provided callback to call when a path is found.
52 */
49 GCD_search_callback callback; 53 GCD_search_callback callback;
50 54
51 /** Provided closure. */ 55 /**
56 * Provided closure.
57 */
52 void *cls; 58 void *cls;
53 59
54 /** Peer ID searched for */ 60 /**
61 * Peer ID searched for
62 */
55 GNUNET_PEER_Id peer_id; 63 GNUNET_PEER_Id peer_id;
56}; 64};
57 65
@@ -224,13 +232,16 @@ announce_id (void *cls)
224 announce_id_task = NULL; 232 announce_id_task = NULL;
225 LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n"); 233 LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n");
226 hello = GCH_get_mine (); 234 hello = GCH_get_mine ();
227 size = NULL != hello ? GNUNET_HELLO_size (hello) : 0; 235 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
228 if (NULL == hello || 0 == size) 236 if ( (NULL == hello) || (0 == size) )
229 { 237 {
230 /* Peerinfo gave us no hello yet, try again soon. */ 238 /* Peerinfo gave us no hello yet, try again soon. */
231 LOG (GNUNET_ERROR_TYPE_INFO, " no hello, waiting!\n"); 239 LOG (GNUNET_ERROR_TYPE_INFO,
232 GNUNET_STATISTICS_update (stats, "# DHT announce skipped (no hello)", 240 " no hello, waiting!\n");
233 1, GNUNET_NO); 241 GNUNET_STATISTICS_update (stats,
242 "# DHT announce skipped (no hello)",
243 1,
244 GNUNET_NO);
234 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), 245 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
235 announce_delay); 246 announce_delay);
236 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); 247 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
@@ -241,29 +252,43 @@ announce_id (void *cls)
241 announce_delay = GNUNET_TIME_UNIT_SECONDS; 252 announce_delay = GNUNET_TIME_UNIT_SECONDS;
242 } 253 }
243 254
244 LOG (GNUNET_ERROR_TYPE_DEBUG, "Hello %p size: %u\n", hello, size); 255 LOG (GNUNET_ERROR_TYPE_DEBUG,
245 GNUNET_STATISTICS_update (stats, "# DHT announce", 256 "Hello %p size: %u\n",
246 1, GNUNET_NO); 257 hello,
247 memset (&phash, 0, sizeof (phash)); 258 size);
248 GNUNET_memcpy (&phash, &my_full_id, sizeof (my_full_id)); 259 if (NULL != hello)
249 GNUNET_DHT_put (dht_handle, /* DHT handle */ 260 {
250 &phash, /* Key to use */ 261 GNUNET_STATISTICS_update (stats,
251 dht_replication_level, /* Replication level */ 262 "# DHT announce",
252 GNUNET_DHT_RO_RECORD_ROUTE 263 1, GNUNET_NO);
253 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ 264 memset (&phash,
254 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ 265 0,
255 size, /* Size of the data */ 266 sizeof (phash));
256 (const char *) hello, /* Data itself */ 267 GNUNET_memcpy (&phash,
257 expiration, /* Data expiration */ 268 &my_full_id,
258 NULL, /* Continuation */ 269 sizeof (my_full_id));
259 NULL); /* Continuation closure */ 270 GNUNET_DHT_put (dht_handle, /* DHT handle */
260 271 &phash, /* Key to use */
272 dht_replication_level, /* Replication level */
273 GNUNET_DHT_RO_RECORD_ROUTE
274 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
275 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
276 size, /* Size of the data */
277 (const char *) hello, /* Data itself */
278 expiration, /* Data expiration */
279 NULL, /* Continuation */
280 NULL); /* Continuation closure */
281 }
261 /* Call again in id_announce_time, unless HELLO expires first, 282 /* Call again in id_announce_time, unless HELLO expires first,
262 * but wait at least 1s. */ 283 * but wait at least 1s. */
263 next_put = GNUNET_TIME_absolute_get_remaining (expiration); 284 next_put = GNUNET_TIME_absolute_get_remaining (expiration);
264 next_put = GNUNET_TIME_relative_min (next_put, id_announce_time); 285 next_put = GNUNET_TIME_relative_min (next_put,
265 next_put = GNUNET_TIME_relative_max (next_put, GNUNET_TIME_UNIT_SECONDS); 286 id_announce_time);
266 announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put, &announce_id, cls); 287 next_put = GNUNET_TIME_relative_max (next_put,
288 GNUNET_TIME_UNIT_SECONDS);
289 announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put,
290 &announce_id,
291 cls);
267} 292}
268 293
269/** 294/**
@@ -378,8 +403,11 @@ GCD_search (const struct GNUNET_PeerIdentity *peer_id,
378 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, 403 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
379 NULL, /* xquery */ 404 NULL, /* xquery */
380 0, /* xquery bits */ 405 0, /* xquery bits */
381 &dht_get_id_handler, h); 406 &dht_get_id_handler,
382 GNUNET_CONTAINER_multihashmap32_put (get_requests, h->peer_id, h, 407 h);
408 GNUNET_CONTAINER_multihashmap32_put (get_requests,
409 h->peer_id,
410 h,
383 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 411 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
384 return h; 412 return h;
385} 413}
diff --git a/src/cadet/gnunet-service-cadet_hello.h b/src/cadet/gnunet-service-cadet_hello.h
index 5f535b496..34121e1e0 100644
--- a/src/cadet/gnunet-service-cadet_hello.h
+++ b/src/cadet/gnunet-service-cadet_hello.h
@@ -50,11 +50,13 @@ extern "C"
50void 50void
51GCH_init (const struct GNUNET_CONFIGURATION_Handle *c); 51GCH_init (const struct GNUNET_CONFIGURATION_Handle *c);
52 52
53
53/** 54/**
54 * Shut down the hello subsystem. 55 * Shut down the hello subsystem.
55 */ 56 */
56void 57void
57GCH_shutdown (); 58GCH_shutdown (void);
59
58 60
59/** 61/**
60 * Get own hello message. 62 * Get own hello message.
@@ -64,6 +66,7 @@ GCH_shutdown ();
64const struct GNUNET_HELLO_Message * 66const struct GNUNET_HELLO_Message *
65GCH_get_mine (void); 67GCH_get_mine (void);
66 68
69
67#if 0 /* keep Emacsens' auto-indent happy */ 70#if 0 /* keep Emacsens' auto-indent happy */
68{ 71{
69#endif 72#endif
diff --git a/src/cadet/gnunet-service-cadet_local.c b/src/cadet/gnunet-service-cadet_local.c
index 9be1224c1..e1f6ac4c3 100644
--- a/src/cadet/gnunet-service-cadet_local.c
+++ b/src/cadet/gnunet-service-cadet_local.c
@@ -61,7 +61,7 @@ struct CadetClient
61 * Tunnels that belong to this client, indexed by local id 61 * Tunnels that belong to this client, indexed by local id
62 */ 62 */
63 struct GNUNET_CONTAINER_MultiHashMap32 *own_channels; 63 struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
64 64
65 /** 65 /**
66 * Tunnels this client has accepted, indexed by incoming local id 66 * Tunnels this client has accepted, indexed by incoming local id
67 */ 67 */
@@ -70,7 +70,7 @@ struct CadetClient
70 /** 70 /**
71 * Channel ID for the next incoming channel. 71 * Channel ID for the next incoming channel.
72 */ 72 */
73 CADET_ChannelNumber next_chid; 73 struct GNUNET_CADET_ClientChannelNumber next_chid;
74 74
75 /** 75 /**
76 * Handle to communicate with the client 76 * Handle to communicate with the client
@@ -188,7 +188,9 @@ channel_destroy_iterator (void *cls,
188 " Channel %s destroy, due to client %s shutdown.\n", 188 " Channel %s destroy, due to client %s shutdown.\n",
189 GCCH_2s (ch), GML_2s (c)); 189 GCCH_2s (ch), GML_2s (c));
190 190
191 GCCH_handle_local_destroy (ch, c, key < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV); 191 GCCH_handle_local_destroy (ch,
192 c,
193 key < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
192 return GNUNET_OK; 194 return GNUNET_OK;
193} 195}
194 196
@@ -247,7 +249,6 @@ client_new (struct GNUNET_SERVER_Client *client)
247 c = GNUNET_new (struct CadetClient); 249 c = GNUNET_new (struct CadetClient);
248 c->handle = client; 250 c->handle = client;
249 c->id = next_client_id++; /* overflow not important: just for debug */ 251 c->id = next_client_id++; /* overflow not important: just for debug */
250 c->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
251 252
252 c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32); 253 c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32);
253 c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32); 254 c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32);
@@ -439,7 +440,7 @@ handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
439 LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); 440 LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
440 441
441 /* Message size sanity check */ 442 /* Message size sanity check */
442 if (sizeof (struct GNUNET_CADET_ChannelCreateMessage) 443 if (sizeof (struct GNUNET_CADET_ChannelOpenMessageMessage)
443 != ntohs (message->size)) 444 != ntohs (message->size))
444 { 445 {
445 GNUNET_break (0); 446 GNUNET_break (0);
@@ -449,7 +450,7 @@ handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
449 450
450 if (GNUNET_OK != 451 if (GNUNET_OK !=
451 GCCH_handle_local_create (c, 452 GCCH_handle_local_create (c,
452 (struct GNUNET_CADET_ChannelCreateMessage *) 453 (struct GNUNET_CADET_ChannelOpenMessageMessage *)
453 message)) 454 message))
454 { 455 {
455 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 456 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
@@ -474,7 +475,7 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
474 struct GNUNET_CADET_ChannelDestroyMessage *msg; 475 struct GNUNET_CADET_ChannelDestroyMessage *msg;
475 struct CadetClient *c; 476 struct CadetClient *c;
476 struct CadetChannel *ch; 477 struct CadetChannel *ch;
477 CADET_ChannelNumber chid; 478 struct GNUNET_CADET_ClientChannelNumber chid;
478 479
479 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n"); 480 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n");
480 481
@@ -499,7 +500,7 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
499 msg = (struct GNUNET_CADET_ChannelDestroyMessage *) message; 500 msg = (struct GNUNET_CADET_ChannelDestroyMessage *) message;
500 501
501 /* Retrieve tunnel */ 502 /* Retrieve tunnel */
502 chid = ntohl (msg->channel_id); 503 chid = msg->channel_id;
503 ch = GML_channel_get (c, chid); 504 ch = GML_channel_get (c, chid);
504 505
505 LOG (GNUNET_ERROR_TYPE_INFO, "Client %u is destroying channel %X\n", 506 LOG (GNUNET_ERROR_TYPE_INFO, "Client %u is destroying channel %X\n",
@@ -515,7 +516,9 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
515 return; 516 return;
516 } 517 }
517 518
518 GCCH_handle_local_destroy (ch, c, chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV); 519 GCCH_handle_local_destroy (ch,
520 c,
521 ntohl (chid.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
519 522
520 GNUNET_SERVER_receive_done (client, GNUNET_OK); 523 GNUNET_SERVER_receive_done (client, GNUNET_OK);
521 return; 524 return;
@@ -537,7 +540,7 @@ handle_data (void *cls, struct GNUNET_SERVER_Client *client,
537 struct GNUNET_CADET_LocalData *msg; 540 struct GNUNET_CADET_LocalData *msg;
538 struct CadetClient *c; 541 struct CadetClient *c;
539 struct CadetChannel *ch; 542 struct CadetChannel *ch;
540 CADET_ChannelNumber chid; 543 struct GNUNET_CADET_ClientChannelNumber chid;
541 size_t message_size; 544 size_t message_size;
542 size_t payload_size; 545 size_t payload_size;
543 size_t payload_claimed_size; 546 size_t payload_claimed_size;
@@ -583,12 +586,12 @@ handle_data (void *cls, struct GNUNET_SERVER_Client *client,
583 return; 586 return;
584 } 587 }
585 588
586 chid = ntohl (msg->id); 589 chid = msg->id;
587 LOG (GNUNET_ERROR_TYPE_DEBUG, " %u bytes (%u payload) by client %u\n", 590 LOG (GNUNET_ERROR_TYPE_DEBUG, " %u bytes (%u payload) by client %u\n",
588 payload_size, payload_claimed_size, c->id); 591 payload_size, payload_claimed_size, c->id);
589 592
590 /* Channel exists? */ 593 /* Channel exists? */
591 fwd = chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; 594 fwd = ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
592 ch = GML_channel_get (c, chid); 595 ch = GML_channel_get (c, chid);
593 if (NULL == ch) 596 if (NULL == ch)
594 { 597 {
@@ -626,7 +629,7 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
626 struct GNUNET_CADET_LocalAck *msg; 629 struct GNUNET_CADET_LocalAck *msg;
627 struct CadetChannel *ch; 630 struct CadetChannel *ch;
628 struct CadetClient *c; 631 struct CadetClient *c;
629 CADET_ChannelNumber chid; 632 struct GNUNET_CADET_ClientChannelNumber chid;
630 int fwd; 633 int fwd;
631 634
632 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); 635 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
@@ -644,13 +647,16 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
644 msg = (struct GNUNET_CADET_LocalAck *) message; 647 msg = (struct GNUNET_CADET_LocalAck *) message;
645 648
646 /* Channel exists? */ 649 /* Channel exists? */
647 chid = ntohl (msg->channel_id); 650 chid = msg->channel_id;
648 LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid); 651 LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n",
652 ntohl (chid.channel_of_client));
649 ch = GML_channel_get (c, chid); 653 ch = GML_channel_get (c, chid);
650 LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch); 654 LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch);
651 if (NULL == ch) 655 if (NULL == ch)
652 { 656 {
653 LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X unknown.\n", chid); 657 LOG (GNUNET_ERROR_TYPE_DEBUG,
658 "Channel %X unknown.\n",
659 ntohl (chid.channel_of_client));
654 LOG (GNUNET_ERROR_TYPE_DEBUG, " for client %u.\n", c->id); 660 LOG (GNUNET_ERROR_TYPE_DEBUG, " for client %u.\n", c->id);
655 GNUNET_STATISTICS_update (stats, 661 GNUNET_STATISTICS_update (stats,
656 "# client ack messages on unknown channel", 662 "# client ack messages on unknown channel",
@@ -661,12 +667,10 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
661 667
662 /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */ 668 /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */
663 /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */ 669 /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */
664 fwd = chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; 670 fwd = ntohl (chid.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
665 671
666 GCCH_handle_local_ack (ch, fwd); 672 GCCH_handle_local_ack (ch, fwd);
667 GNUNET_SERVER_receive_done (client, GNUNET_OK); 673 GNUNET_SERVER_receive_done (client, GNUNET_OK);
668
669 return;
670} 674}
671 675
672 676
@@ -961,8 +965,9 @@ static void
961iter_connection (void *cls, struct CadetConnection *c) 965iter_connection (void *cls, struct CadetConnection *c)
962{ 966{
963 struct GNUNET_CADET_LocalInfoTunnel *msg = cls; 967 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
964 struct GNUNET_CADET_Hash *h = (struct GNUNET_CADET_Hash *) &msg[1]; 968 struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
965 969
970 h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
966 h[msg->connections] = *(GCC_get_id (c)); 971 h[msg->connections] = *(GCC_get_id (c));
967 msg->connections++; 972 msg->connections++;
968} 973}
@@ -971,10 +976,10 @@ static void
971iter_channel (void *cls, struct CadetChannel *ch) 976iter_channel (void *cls, struct CadetChannel *ch)
972{ 977{
973 struct GNUNET_CADET_LocalInfoTunnel *msg = cls; 978 struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
974 struct GNUNET_CADET_Hash *h = (struct GNUNET_CADET_Hash *) &msg[1]; 979 struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
975 CADET_ChannelNumber *chn = (CADET_ChannelNumber *) &h[msg->connections]; 980 struct GNUNET_CADET_ChannelTunnelNumber *chn = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections];
976 981
977 chn[msg->channels] = htonl (GCCH_get_id (ch)); 982 chn[msg->channels] = GCCH_get_id (ch);
978 msg->channels++; 983 msg->channels++;
979} 984}
980 985
@@ -1039,8 +1044,8 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
1039 c_n = GCT_count_any_connections (t); 1044 c_n = GCT_count_any_connections (t);
1040 1045
1041 size = sizeof (struct GNUNET_CADET_LocalInfoTunnel); 1046 size = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
1042 size += c_n * sizeof (struct GNUNET_CADET_Hash); 1047 size += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
1043 size += ch_n * sizeof (CADET_ChannelNumber); 1048 size += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
1044 1049
1045 resp = GNUNET_malloc (size); 1050 resp = GNUNET_malloc (size);
1046 resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); 1051 resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
@@ -1123,8 +1128,8 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
1123 sizeof (struct GNUNET_CADET_PortMessage)}, 1128 sizeof (struct GNUNET_CADET_PortMessage)},
1124 {&handle_port_close, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE, 1129 {&handle_port_close, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
1125 sizeof (struct GNUNET_CADET_PortMessage)}, 1130 sizeof (struct GNUNET_CADET_PortMessage)},
1126 {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE, 1131 {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
1127 sizeof (struct GNUNET_CADET_ChannelCreateMessage)}, 1132 sizeof (struct GNUNET_CADET_ChannelOpenMessageMessage)},
1128 {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY, 1133 {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
1129 sizeof (struct GNUNET_CADET_ChannelDestroyMessage)}, 1134 sizeof (struct GNUNET_CADET_ChannelDestroyMessage)},
1130 {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0}, 1135 {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0},
@@ -1214,26 +1219,16 @@ GML_shutdown (void)
1214 * @return non-NULL if channel exists in the clients lists 1219 * @return non-NULL if channel exists in the clients lists
1215 */ 1220 */
1216struct CadetChannel * 1221struct CadetChannel *
1217GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid) 1222GML_channel_get (struct CadetClient *c,
1223 struct GNUNET_CADET_ClientChannelNumber chid)
1218{ 1224{
1219 struct GNUNET_CONTAINER_MultiHashMap32 *map; 1225 struct GNUNET_CONTAINER_MultiHashMap32 *map;
1220 1226
1221 if (0 == (chid & GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)) 1227 if (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1222 {
1223 GNUNET_break_op (0);
1224 LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid);
1225 return NULL;
1226 }
1227
1228 if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
1229 map = c->incoming_channels;
1230 else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1231 map = c->own_channels; 1228 map = c->own_channels;
1232 else 1229 else
1233 { 1230 map = c->incoming_channels;
1234 GNUNET_break (0); 1231
1235 map = NULL;
1236 }
1237 if (NULL == map) 1232 if (NULL == map)
1238 { 1233 {
1239 GNUNET_break (0); 1234 GNUNET_break (0);
@@ -1242,7 +1237,8 @@ GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid)
1242 GML_2s (c), chid); 1237 GML_2s (c), chid);
1243 return NULL; 1238 return NULL;
1244 } 1239 }
1245 return GNUNET_CONTAINER_multihashmap32_get (map, chid); 1240 return GNUNET_CONTAINER_multihashmap32_get (map,
1241 chid.channel_of_client);
1246} 1242}
1247 1243
1248 1244
@@ -1255,17 +1251,19 @@ GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid)
1255 */ 1251 */
1256void 1252void
1257GML_channel_add (struct CadetClient *client, 1253GML_channel_add (struct CadetClient *client,
1258 uint32_t chid, 1254 struct GNUNET_CADET_ClientChannelNumber chid,
1259 struct CadetChannel *ch) 1255 struct CadetChannel *ch)
1260{ 1256{
1261 if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) 1257 if (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1262 GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch, 1258 GNUNET_CONTAINER_multihashmap32_put (client->own_channels,
1263 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 1259 chid.channel_of_client,
1264 else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) 1260 ch,
1265 GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch,
1266 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 1261 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1267 else 1262 else
1268 GNUNET_break (0); 1263 GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels,
1264 chid.channel_of_client,
1265 ch,
1266 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1269} 1267}
1270 1268
1271 1269
@@ -1278,19 +1276,17 @@ GML_channel_add (struct CadetClient *client,
1278 */ 1276 */
1279void 1277void
1280GML_channel_remove (struct CadetClient *client, 1278GML_channel_remove (struct CadetClient *client,
1281 uint32_t chid, 1279 struct GNUNET_CADET_ClientChannelNumber chid,
1282 struct CadetChannel *ch) 1280 struct CadetChannel *ch)
1283{ 1281{
1284 if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= chid) 1282 if (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1285 GNUNET_break (GNUNET_YES == 1283 GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
1286 GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels, 1284 chid.channel_of_client,
1287 chid, ch)); 1285 ch);
1288 else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= chid)
1289 GNUNET_break (GNUNET_YES ==
1290 GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
1291 chid, ch));
1292 else 1286 else
1293 GNUNET_break (0); 1287 GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels,
1288 chid.channel_of_client,
1289 ch);
1294} 1290}
1295 1291
1296 1292
@@ -1301,18 +1297,26 @@ GML_channel_remove (struct CadetClient *client,
1301 * 1297 *
1302 * @return LID of a channel free to use. 1298 * @return LID of a channel free to use.
1303 */ 1299 */
1304CADET_ChannelNumber 1300struct GNUNET_CADET_ClientChannelNumber
1305GML_get_next_chid (struct CadetClient *c) 1301GML_get_next_chid (struct CadetClient *c)
1306{ 1302{
1307 CADET_ChannelNumber chid; 1303 struct GNUNET_CADET_ClientChannelNumber chid;
1308 1304
1309 while (NULL != GML_channel_get (c, c->next_chid)) 1305 while (NULL != GML_channel_get (c,
1306 c->next_chid))
1310 { 1307 {
1311 LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid); 1308 LOG (GNUNET_ERROR_TYPE_DEBUG,
1312 c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; 1309 "Channel %u exists...\n",
1310 c->next_chid);
1311 c->next_chid.channel_of_client
1312 = htonl (1 + (ntohl (c->next_chid.channel_of_client)));
1313 if (ntohl (c->next_chid.channel_of_client) >=
1314 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1315 c->next_chid.channel_of_client = htonl (0);
1313 } 1316 }
1314 chid = c->next_chid; 1317 chid = c->next_chid;
1315 c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; 1318 c->next_chid.channel_of_client
1319 = htonl (1 + (ntohl (c->next_chid.channel_of_client)));
1316 1320
1317 return chid; 1321 return chid;
1318} 1322}
@@ -1330,9 +1334,11 @@ GML_client_get (struct GNUNET_SERVER_Client *client)
1330{ 1334{
1331 if (NULL == client) 1335 if (NULL == client)
1332 return NULL; 1336 return NULL;
1333 return GNUNET_SERVER_client_get_user_context (client, struct CadetClient); 1337 return GNUNET_SERVER_client_get_user_context (client,
1338 struct CadetClient);
1334} 1339}
1335 1340
1341
1336/** 1342/**
1337 * Find a client that has opened a port 1343 * Find a client that has opened a port
1338 * 1344 *
@@ -1357,27 +1363,25 @@ GML_client_get_by_port (const struct GNUNET_HashCode *port)
1357void 1363void
1358GML_client_delete_channel (struct CadetClient *c, 1364GML_client_delete_channel (struct CadetClient *c,
1359 struct CadetChannel *ch, 1365 struct CadetChannel *ch,
1360 CADET_ChannelNumber id) 1366 struct GNUNET_CADET_ClientChannelNumber id)
1361{ 1367{
1362 int res; 1368 int res;
1363 1369
1364 if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= id) 1370 if (ntohl (id.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1365 {
1366 res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
1367 id, ch);
1368 if (GNUNET_YES != res)
1369 LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
1370 }
1371 else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= id)
1372 { 1371 {
1373 res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels, 1372 res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
1374 id, ch); 1373 id.channel_of_client,
1374 ch);
1375 if (GNUNET_YES != res) 1375 if (GNUNET_YES != res)
1376 LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n"); 1376 LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n");
1377 } 1377 }
1378 else 1378 else
1379 { 1379 {
1380 GNUNET_break (0); 1380 res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
1381 id.channel_of_client,
1382 ch);
1383 if (GNUNET_YES != res)
1384 LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
1381 } 1385 }
1382} 1386}
1383 1387
@@ -1390,17 +1394,21 @@ GML_client_delete_channel (struct CadetClient *c,
1390 * @param id Channel ID to use 1394 * @param id Channel ID to use
1391 */ 1395 */
1392void 1396void
1393GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id) 1397GML_send_ack (struct CadetClient *c,
1398 struct GNUNET_CADET_ClientChannelNumber id)
1394{ 1399{
1395 struct GNUNET_CADET_LocalAck msg; 1400 struct GNUNET_CADET_LocalAck msg;
1396 1401
1397 LOG (GNUNET_ERROR_TYPE_DEBUG, 1402 LOG (GNUNET_ERROR_TYPE_DEBUG,
1398 "send local %s ack on %X towards %p\n", 1403 "send local %s ack on %X towards %p\n",
1399 id < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c); 1404 ntohl (id.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI
1405 ? "FWD" : "BCK",
1406 ntohl (id.channel_of_client),
1407 c);
1400 1408
1401 msg.header.size = htons (sizeof (msg)); 1409 msg.header.size = htons (sizeof (msg));
1402 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); 1410 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
1403 msg.channel_id = htonl (id); 1411 msg.channel_id = id;
1404 GNUNET_SERVER_notification_context_unicast (nc, 1412 GNUNET_SERVER_notification_context_unicast (nc,
1405 c->handle, 1413 c->handle,
1406 &msg.header, 1414 &msg.header,
@@ -1421,14 +1429,16 @@ GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id)
1421 */ 1429 */
1422void 1430void
1423GML_send_channel_create (struct CadetClient *c, 1431GML_send_channel_create (struct CadetClient *c,
1424 uint32_t id, struct GNUNET_HashCode *port, 1432 struct GNUNET_CADET_ClientChannelNumber id,
1425 uint32_t opt, const struct GNUNET_PeerIdentity *peer) 1433 const struct GNUNET_HashCode *port,
1434 uint32_t opt,
1435 const struct GNUNET_PeerIdentity *peer)
1426{ 1436{
1427 struct GNUNET_CADET_ChannelCreateMessage msg; 1437 struct GNUNET_CADET_ChannelOpenMessageMessage msg;
1428 1438
1429 msg.header.size = htons (sizeof (msg)); 1439 msg.header.size = htons (sizeof (msg));
1430 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE); 1440 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
1431 msg.channel_id = htonl (id); 1441 msg.channel_id = id;
1432 msg.port = *port; 1442 msg.port = *port;
1433 msg.opt = htonl (opt); 1443 msg.opt = htonl (opt);
1434 msg.peer = *peer; 1444 msg.peer = *peer;
@@ -1444,17 +1454,19 @@ GML_send_channel_create (struct CadetClient *c,
1444 * @param id Channel ID to use 1454 * @param id Channel ID to use
1445 */ 1455 */
1446void 1456void
1447GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id) 1457GML_send_channel_nack (struct CadetClient *c,
1458 struct GNUNET_CADET_ClientChannelNumber id)
1448{ 1459{
1449 struct GNUNET_CADET_LocalAck msg; 1460 struct GNUNET_CADET_LocalAck msg;
1450 1461
1451 LOG (GNUNET_ERROR_TYPE_DEBUG, 1462 LOG (GNUNET_ERROR_TYPE_DEBUG,
1452 "send local nack on %X towards %p\n", 1463 "send local nack on %X towards %p\n",
1453 id, c); 1464 ntohl (id.channel_of_client),
1465 c);
1454 1466
1455 msg.header.size = htons (sizeof (msg)); 1467 msg.header.size = htons (sizeof (msg));
1456 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK); 1468 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED);
1457 msg.channel_id = htonl (id); 1469 msg.channel_id = id;
1458 GNUNET_SERVER_notification_context_unicast (nc, 1470 GNUNET_SERVER_notification_context_unicast (nc,
1459 c->handle, 1471 c->handle,
1460 &msg.header, 1472 &msg.header,
@@ -1469,7 +1481,8 @@ GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id)
1469 * @param id ID of the channel that is destroyed. 1481 * @param id ID of the channel that is destroyed.
1470 */ 1482 */
1471void 1483void
1472GML_send_channel_destroy (struct CadetClient *c, uint32_t id) 1484GML_send_channel_destroy (struct CadetClient *c,
1485 struct GNUNET_CADET_ClientChannelNumber id)
1473{ 1486{
1474 struct GNUNET_CADET_ChannelDestroyMessage msg; 1487 struct GNUNET_CADET_ChannelDestroyMessage msg;
1475 1488
@@ -1482,7 +1495,7 @@ GML_send_channel_destroy (struct CadetClient *c, uint32_t id)
1482 return; 1495 return;
1483 msg.header.size = htons (sizeof (msg)); 1496 msg.header.size = htons (sizeof (msg));
1484 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); 1497 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
1485 msg.channel_id = htonl (id); 1498 msg.channel_id = id;
1486 GNUNET_SERVER_notification_context_unicast (nc, c->handle, 1499 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1487 &msg.header, GNUNET_NO); 1500 &msg.header, GNUNET_NO);
1488} 1501}
@@ -1497,11 +1510,11 @@ GML_send_channel_destroy (struct CadetClient *c, uint32_t id)
1497 */ 1510 */
1498void 1511void
1499GML_send_data (struct CadetClient *c, 1512GML_send_data (struct CadetClient *c,
1500 const struct GNUNET_CADET_Data *msg, 1513 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
1501 CADET_ChannelNumber id) 1514 struct GNUNET_CADET_ClientChannelNumber id)
1502{ 1515{
1503 struct GNUNET_CADET_LocalData *copy; 1516 struct GNUNET_CADET_LocalData *copy;
1504 uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_Data); 1517 uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_ChannelAppDataMessage);
1505 char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)]; 1518 char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)];
1506 1519
1507 if (size < sizeof (struct GNUNET_MessageHeader)) 1520 if (size < sizeof (struct GNUNET_MessageHeader))
@@ -1518,7 +1531,7 @@ GML_send_data (struct CadetClient *c,
1518 GNUNET_memcpy (&copy[1], &msg[1], size); 1531 GNUNET_memcpy (&copy[1], &msg[1], size);
1519 copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size); 1532 copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size);
1520 copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); 1533 copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1521 copy->id = htonl (id); 1534 copy->id = id;
1522 GNUNET_SERVER_notification_context_unicast (nc, c->handle, 1535 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1523 &copy->header, GNUNET_NO); 1536 &copy->header, GNUNET_NO);
1524} 1537}
diff --git a/src/cadet/gnunet-service-cadet_local.h b/src/cadet/gnunet-service-cadet_local.h
index f89745092..bf691f9c3 100644
--- a/src/cadet/gnunet-service-cadet_local.h
+++ b/src/cadet/gnunet-service-cadet_local.h
@@ -80,7 +80,8 @@ GML_shutdown (void);
80 * @return non-NULL if channel exists in the clients lists 80 * @return non-NULL if channel exists in the clients lists
81 */ 81 */
82struct CadetChannel * 82struct CadetChannel *
83GML_channel_get (struct CadetClient *c, uint32_t chid); 83GML_channel_get (struct CadetClient *c,
84 struct GNUNET_CADET_ClientChannelNumber chid);
84 85
85/** 86/**
86 * Add a channel to a client 87 * Add a channel to a client
@@ -91,7 +92,7 @@ GML_channel_get (struct CadetClient *c, uint32_t chid);
91 */ 92 */
92void 93void
93GML_channel_add (struct CadetClient *client, 94GML_channel_add (struct CadetClient *client,
94 uint32_t chid, 95 struct GNUNET_CADET_ClientChannelNumber chid,
95 struct CadetChannel *ch); 96 struct CadetChannel *ch);
96 97
97/** 98/**
@@ -103,7 +104,7 @@ GML_channel_add (struct CadetClient *client,
103 */ 104 */
104void 105void
105GML_channel_remove (struct CadetClient *client, 106GML_channel_remove (struct CadetClient *client,
106 uint32_t chid, 107 struct GNUNET_CADET_ClientChannelNumber chid,
107 struct CadetChannel *ch); 108 struct CadetChannel *ch);
108 109
109/** 110/**
@@ -113,7 +114,7 @@ GML_channel_remove (struct CadetClient *client,
113 * 114 *
114 * @return LID of a channel free to use. 115 * @return LID of a channel free to use.
115 */ 116 */
116CADET_ChannelNumber 117struct GNUNET_CADET_ClientChannelNumber
117GML_get_next_chid (struct CadetClient *c); 118GML_get_next_chid (struct CadetClient *c);
118 119
119/** 120/**
@@ -146,7 +147,7 @@ GML_client_get_by_port (const struct GNUNET_HashCode *port);
146void 147void
147GML_client_delete_channel (struct CadetClient *c, 148GML_client_delete_channel (struct CadetClient *c,
148 struct CadetChannel *ch, 149 struct CadetChannel *ch,
149 CADET_ChannelNumber id); 150 struct GNUNET_CADET_ClientChannelNumber id);
150 151
151/** 152/**
152 * Build a local ACK message and send it to a local client, if needed. 153 * Build a local ACK message and send it to a local client, if needed.
@@ -157,7 +158,8 @@ GML_client_delete_channel (struct CadetClient *c,
157 * @param id Channel ID to use 158 * @param id Channel ID to use
158 */ 159 */
159void 160void
160GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id); 161GML_send_ack (struct CadetClient *c,
162 struct GNUNET_CADET_ClientChannelNumber id);
161 163
162/** 164/**
163 * Notify the appropriate client that a new incoming channel was created. 165 * Notify the appropriate client that a new incoming channel was created.
@@ -170,8 +172,10 @@ GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id);
170 */ 172 */
171void 173void
172GML_send_channel_create (struct CadetClient *c, 174GML_send_channel_create (struct CadetClient *c,
173 uint32_t id, struct GNUNET_HashCode *port, 175 struct GNUNET_CADET_ClientChannelNumber id,
174 uint32_t opt, const struct GNUNET_PeerIdentity *peer); 176 const struct GNUNET_HashCode *port,
177 uint32_t opt,
178 const struct GNUNET_PeerIdentity *peer);
175 179
176/** 180/**
177 * Build a local channel NACK message and send it to a local client. 181 * Build a local channel NACK message and send it to a local client.
@@ -180,7 +184,9 @@ GML_send_channel_create (struct CadetClient *c,
180 * @param id Channel ID to use 184 * @param id Channel ID to use
181 */ 185 */
182void 186void
183GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id); 187GML_send_channel_nack (struct CadetClient *c,
188 struct GNUNET_CADET_ClientChannelNumber id);
189
184 190
185/** 191/**
186 * Notify a client that a channel is no longer valid. 192 * Notify a client that a channel is no longer valid.
@@ -189,7 +195,9 @@ GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id);
189 * @param id ID of the channel that is destroyed. 195 * @param id ID of the channel that is destroyed.
190 */ 196 */
191void 197void
192GML_send_channel_destroy (struct CadetClient *c, uint32_t id); 198GML_send_channel_destroy (struct CadetClient *c,
199 struct GNUNET_CADET_ClientChannelNumber id);
200
193 201
194/** 202/**
195 * Modify the cadet message ID from global to local and send to client. 203 * Modify the cadet message ID from global to local and send to client.
@@ -200,8 +208,8 @@ GML_send_channel_destroy (struct CadetClient *c, uint32_t id);
200 */ 208 */
201void 209void
202GML_send_data (struct CadetClient *c, 210GML_send_data (struct CadetClient *c,
203 const struct GNUNET_CADET_Data *msg, 211 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
204 CADET_ChannelNumber id); 212 struct GNUNET_CADET_ClientChannelNumber id);
205 213
206/** 214/**
207 * Get the static string to represent a client. 215 * Get the static string to represent a client.
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
index c312d56bf..3f8b7bbb8 100644
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ b/src/cadet/gnunet-service-cadet_peer.c
@@ -73,6 +73,11 @@ struct CadetPeerQueue {
73 void *cont_cls; 73 void *cont_cls;
74 74
75 /** 75 /**
76 * Task to asynchronously run the drop continuation.
77 */
78 struct GNUNET_SCHEDULER_Task *drop_task;
79
80 /**
76 * Time when message was queued for sending. 81 * Time when message was queued for sending.
77 */ 82 */
78 struct GNUNET_TIME_Absolute queue_timestamp; 83 struct GNUNET_TIME_Absolute queue_timestamp;
@@ -98,9 +103,9 @@ struct CadetPeerQueue {
98 uint16_t payload_type; 103 uint16_t payload_type;
99 104
100 /** 105 /**
101 *ID of the payload (PID, ACK #, ...). 106 * ID of the payload (PID, ACK #, ...).
102 */ 107 */
103 uint16_t payload_id; 108 struct CadetEncryptedMessageIdentifier payload_id;
104 109
105 /** 110 /**
106 * Connection this message was sent on. 111 * Connection this message was sent on.
@@ -160,7 +165,7 @@ struct CadetPeer
160 /** 165 /**
161 * Connections that go through this peer; indexed by tid. 166 * Connections that go through this peer; indexed by tid.
162 */ 167 */
163 struct GNUNET_CONTAINER_MultiHashMap *connections; 168 struct GNUNET_CONTAINER_MultiShortmap *connections;
164 169
165 /** 170 /**
166 * Handle for core transmissions. 171 * Handle for core transmissions.
@@ -263,7 +268,7 @@ static int in_shutdown;
263 */ 268 */
264static int 269static int
265notify_broken (void *cls, 270notify_broken (void *cls,
266 const struct GNUNET_HashCode *key, 271 const struct GNUNET_ShortHashCode *key,
267 void *value) 272 void *value)
268{ 273{
269 struct CadetPeer *peer = cls; 274 struct CadetPeer *peer = cls;
@@ -368,7 +373,8 @@ core_connect_handler (void *cls,
368 373
369 /* Create the connections hashmap */ 374 /* Create the connections hashmap */
370 GNUNET_assert (NULL == neighbor->connections); 375 GNUNET_assert (NULL == neighbor->connections);
371 neighbor->connections = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO); 376 neighbor->connections = GNUNET_CONTAINER_multishortmap_create (16,
377 GNUNET_YES);
372 GNUNET_STATISTICS_update (stats, 378 GNUNET_STATISTICS_update (stats,
373 "# peers", 379 "# peers",
374 1, 380 1,
@@ -420,11 +426,11 @@ core_disconnect_handler (void *cls,
420 direct_path = pop_direct_path (p); 426 direct_path = pop_direct_path (p);
421 if (NULL != p->connections) 427 if (NULL != p->connections)
422 { 428 {
423 GNUNET_CONTAINER_multihashmap_iterate (p->connections, 429 GNUNET_CONTAINER_multishortmap_iterate (p->connections,
424 &notify_broken, 430 &notify_broken,
425 p); 431 p);
426 GNUNET_CONTAINER_multihashmap_destroy (p->connections); 432 GNUNET_CONTAINER_multishortmap_destroy (p->connections);
427 p->connections = NULL; 433 p->connections = NULL;
428 } 434 }
429 GNUNET_STATISTICS_update (stats, 435 GNUNET_STATISTICS_update (stats,
430 "# peers", 436 "# peers",
@@ -450,7 +456,7 @@ core_disconnect_handler (void *cls,
450 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. 456 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
451 */ 457 */
452static int 458static int
453check_create (void *cls, const struct GNUNET_CADET_ConnectionCreate *msg) 459check_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
454{ 460{
455 uint16_t size; 461 uint16_t size;
456 462
@@ -470,7 +476,7 @@ check_create (void *cls, const struct GNUNET_CADET_ConnectionCreate *msg)
470 * @param msg Message itself. 476 * @param msg Message itself.
471 */ 477 */
472static void 478static void
473handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreate *msg) 479handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
474{ 480{
475 struct CadetPeer *peer = cls; 481 struct CadetPeer *peer = cls;
476 GCC_handle_create (peer, msg); 482 GCC_handle_create (peer, msg);
@@ -478,13 +484,13 @@ handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreate *msg)
478 484
479 485
480/** 486/**
481 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK 487 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
482 * 488 *
483 * @param cls Closure (CadetPeer for neighbor that sent the message). 489 * @param cls Closure (CadetPeer for neighbor that sent the message).
484 * @param msg Message itself. 490 * @param msg Message itself.
485 */ 491 */
486static void 492static void
487handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionACK *msg) 493handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
488{ 494{
489 struct CadetPeer *peer = cls; 495 struct CadetPeer *peer = cls;
490 GCC_handle_confirm (peer, msg); 496 GCC_handle_confirm (peer, msg);
@@ -498,7 +504,7 @@ handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionACK *msg)
498 * @param msg Message itself. 504 * @param msg Message itself.
499 */ 505 */
500static void 506static void
501handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBroken *msg) 507handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
502{ 508{
503 struct CadetPeer *peer = cls; 509 struct CadetPeer *peer = cls;
504 GCC_handle_broken (peer, msg); 510 GCC_handle_broken (peer, msg);
@@ -512,7 +518,7 @@ handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBroken *msg)
512 * @param msg Message itself. 518 * @param msg Message itself.
513 */ 519 */
514static void 520static void
515handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroy *msg) 521handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
516{ 522{
517 struct CadetPeer *peer = cls; 523 struct CadetPeer *peer = cls;
518 GCC_handle_destroy (peer, msg); 524 GCC_handle_destroy (peer, msg);
@@ -520,13 +526,13 @@ handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroy *msg)
520 526
521 527
522/** 528/**
523 * Handle for #GNUNET_MESSAGE_TYPE_CADET_ACK 529 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
524 * 530 *
525 * @param cls Closure (CadetPeer for neighbor that sent the message). 531 * @param cls Closure (CadetPeer for neighbor that sent the message).
526 * @param msg Message itself. 532 * @param msg Message itself.
527 */ 533 */
528static void 534static void
529handle_ack (void *cls, const struct GNUNET_CADET_ACK *msg) 535handle_ack (void *cls, const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
530{ 536{
531 struct CadetPeer *peer = cls; 537 struct CadetPeer *peer = cls;
532 GCC_handle_ack (peer, msg); 538 GCC_handle_ack (peer, msg);
@@ -534,13 +540,13 @@ handle_ack (void *cls, const struct GNUNET_CADET_ACK *msg)
534 540
535 541
536/** 542/**
537 * Handle for #GNUNET_MESSAGE_TYPE_CADET_POLL 543 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
538 * 544 *
539 * @param cls Closure (CadetPeer for neighbor that sent the message). 545 * @param cls Closure (CadetPeer for neighbor that sent the message).
540 * @param msg Message itself. 546 * @param msg Message itself.
541 */ 547 */
542static void 548static void
543handle_poll (void *cls, const struct GNUNET_CADET_Poll *msg) 549handle_poll (void *cls, const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
544{ 550{
545 struct CadetPeer *peer = cls; 551 struct CadetPeer *peer = cls;
546 GCC_handle_poll (peer, msg); 552 GCC_handle_poll (peer, msg);
@@ -548,13 +554,13 @@ handle_poll (void *cls, const struct GNUNET_CADET_Poll *msg)
548 554
549 555
550/** 556/**
551 * Handle for #GNUNET_MESSAGE_TYPE_CADET_KX 557 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
552 * 558 *
553 * @param cls Closure (CadetPeer for neighbor that sent the message). 559 * @param cls Closure (CadetPeer for neighbor that sent the message).
554 * @param msg Message itself. 560 * @param msg Message itself.
555 */ 561 */
556static void 562static void
557handle_kx (void *cls, const struct GNUNET_CADET_KX *msg) 563handle_kx (void *cls, const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
558{ 564{
559 struct CadetPeer *peer = cls; 565 struct CadetPeer *peer = cls;
560 GCC_handle_kx (peer, msg); 566 GCC_handle_kx (peer, msg);
@@ -570,13 +576,13 @@ handle_kx (void *cls, const struct GNUNET_CADET_KX *msg)
570 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. 576 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
571 */ 577 */
572static int 578static int
573check_encrypted (void *cls, const struct GNUNET_CADET_Encrypted *msg) 579check_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
574{ 580{
575 uint16_t size; 581 uint16_t size;
576 uint16_t minimum_size; 582 uint16_t minimum_size;
577 583
578 size = ntohs (msg->header.size); 584 size = ntohs (msg->header.size);
579 minimum_size = sizeof (struct GNUNET_CADET_Encrypted) 585 minimum_size = sizeof (struct GNUNET_CADET_TunnelEncryptedMessage)
580 + sizeof (struct GNUNET_MessageHeader); 586 + sizeof (struct GNUNET_MessageHeader);
581 587
582 if (size < minimum_size) 588 if (size < minimum_size)
@@ -588,13 +594,13 @@ check_encrypted (void *cls, const struct GNUNET_CADET_Encrypted *msg)
588} 594}
589 595
590/** 596/**
591 * Handle for #GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED. 597 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
592 * 598 *
593 * @param cls Closure (CadetPeer for neighbor that sent the message). 599 * @param cls Closure (CadetPeer for neighbor that sent the message).
594 * @param msg Message itself. 600 * @param msg Message itself.
595 */ 601 */
596static void 602static void
597handle_encrypted (void *cls, const struct GNUNET_CADET_Encrypted *msg) 603handle_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
598{ 604{
599 struct CadetPeer *peer = cls; 605 struct CadetPeer *peer = cls;
600 GCC_handle_encrypted (peer, msg); 606 GCC_handle_encrypted (peer, msg);
@@ -618,39 +624,39 @@ connect_to_core (const struct GNUNET_CONFIGURATION_Handle *c)
618 struct GNUNET_MQ_MessageHandler core_handlers[] = { 624 struct GNUNET_MQ_MessageHandler core_handlers[] = {
619 GNUNET_MQ_hd_var_size (create, 625 GNUNET_MQ_hd_var_size (create,
620 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 626 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
621 struct GNUNET_CADET_ConnectionCreate, 627 struct GNUNET_CADET_ConnectionCreateMessage,
622 NULL), 628 NULL),
623 GNUNET_MQ_hd_fixed_size (confirm, 629 GNUNET_MQ_hd_fixed_size (confirm,
624 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 630 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
625 struct GNUNET_CADET_ConnectionACK, 631 struct GNUNET_CADET_ConnectionCreateMessageAckMessage,
626 NULL), 632 NULL),
627 GNUNET_MQ_hd_fixed_size (broken, 633 GNUNET_MQ_hd_fixed_size (broken,
628 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 634 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
629 struct GNUNET_CADET_ConnectionBroken, 635 struct GNUNET_CADET_ConnectionBrokenMessage,
630 NULL), 636 NULL),
631 GNUNET_MQ_hd_fixed_size (destroy, 637 GNUNET_MQ_hd_fixed_size (destroy,
632 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 638 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
633 struct GNUNET_CADET_ConnectionDestroy, 639 struct GNUNET_CADET_ConnectionDestroyMessage,
634 NULL), 640 NULL),
635 GNUNET_MQ_hd_fixed_size (ack, 641 GNUNET_MQ_hd_fixed_size (ack,
636 GNUNET_MESSAGE_TYPE_CADET_ACK, 642 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
637 struct GNUNET_CADET_ACK, 643 struct GNUNET_CADET_ConnectionEncryptedAckMessage,
638 NULL), 644 NULL),
639 GNUNET_MQ_hd_fixed_size (poll, 645 GNUNET_MQ_hd_fixed_size (poll,
640 GNUNET_MESSAGE_TYPE_CADET_POLL, 646 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
641 struct GNUNET_CADET_Poll, 647 struct GNUNET_CADET_ConnectionHopByHopPollMessage,
642 NULL), 648 NULL),
643 GNUNET_MQ_hd_fixed_size (kx, 649 GNUNET_MQ_hd_fixed_size (kx,
644 GNUNET_MESSAGE_TYPE_CADET_KX, 650 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
645 struct GNUNET_CADET_KX, 651 struct GNUNET_CADET_TunnelKeyExchangeMessage,
646 NULL), 652 NULL),
647 GNUNET_MQ_hd_var_size (encrypted, 653 GNUNET_MQ_hd_var_size (encrypted,
648 GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 654 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
649 struct GNUNET_CADET_Encrypted, 655 struct GNUNET_CADET_TunnelEncryptedMessage,
650 NULL), 656 NULL),
651 GNUNET_MQ_handler_end () 657 GNUNET_MQ_handler_end ()
652 }; 658 };
653 core_handle = GNUNET_CORE_connecT (c, NULL, 659 core_handle = GNUNET_CORE_connect (c, NULL,
654 &core_init_notify, 660 &core_init_notify,
655 &core_connect_handler, 661 &core_connect_handler,
656 &core_disconnect_handler, 662 &core_disconnect_handler,
@@ -681,7 +687,7 @@ core_init_notify (void *cls,
681 LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); 687 LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
682 LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (core_identity)); 688 LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (core_identity));
683 LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id)); 689 LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id));
684 GNUNET_CORE_disconnecT (core_handle); 690 GNUNET_CORE_disconnect (core_handle);
685 connect_to_core (c); 691 connect_to_core (c);
686 return; 692 return;
687 } 693 }
@@ -729,7 +735,7 @@ get_priority (struct CadetPeerQueue *q)
729 } 735 }
730 736
731 /* Bulky payload has lower priority, control traffic has higher. */ 737 /* Bulky payload has lower priority, control traffic has higher. */
732 if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == q->type) 738 if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == q->type)
733 return low; 739 return low;
734 return high; 740 return high;
735} 741}
@@ -795,8 +801,8 @@ peer_destroy (struct CadetPeer *peer)
795 GCT_destroy_empty (peer->tunnel); 801 GCT_destroy_empty (peer->tunnel);
796 if (NULL != peer->connections) 802 if (NULL != peer->connections)
797 { 803 {
798 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (peer->connections)); 804 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (peer->connections));
799 GNUNET_CONTAINER_multihashmap_destroy (peer->connections); 805 GNUNET_CONTAINER_multishortmap_destroy (peer->connections);
800 peer->connections = NULL; 806 peer->connections = NULL;
801 } 807 }
802 if (NULL != peer->hello_offer) 808 if (NULL != peer->hello_offer)
@@ -1053,8 +1059,8 @@ search_handler (void *cls, const struct CadetPeerPath *path)
1053static int 1059static int
1054is_connection_management (uint16_t type) 1060is_connection_management (uint16_t type)
1055{ 1061{
1056 return type == GNUNET_MESSAGE_TYPE_CADET_ACK || 1062 return type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK ||
1057 type == GNUNET_MESSAGE_TYPE_CADET_POLL; 1063 type == GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL;
1058} 1064}
1059 1065
1060 1066
@@ -1104,8 +1110,11 @@ call_peer_cont (struct CadetPeerQueue *q, int sent)
1104 GNUNET_STRINGS_relative_time_to_string (wait_time, GNUNET_NO)); 1110 GNUNET_STRINGS_relative_time_to_string (wait_time, GNUNET_NO));
1105 q->cont (q->cont_cls, 1111 q->cont (q->cont_cls,
1106 q->c, q->c_fwd, sent, 1112 q->c, q->c_fwd, sent,
1107 q->type, q->payload_type, q->payload_id, 1113 q->type,
1114 q->payload_type,
1115 q->payload_id,
1108 q->size, wait_time); 1116 q->size, wait_time);
1117 q->cont = NULL;
1109 } 1118 }
1110 GNUNET_CONTAINER_DLL_remove (q->peer->q_head, q->peer->q_tail, q); 1119 GNUNET_CONTAINER_DLL_remove (q->peer->q_head, q->peer->q_tail, q);
1111} 1120}
@@ -1131,6 +1140,22 @@ mq_sent (void *cls)
1131 1140
1132 1141
1133/** 1142/**
1143 * Finish the drop operation.
1144 *
1145 * @param cls queue entry to finish drop for
1146 */
1147static void
1148drop_cb (void *cls)
1149{
1150 struct CadetPeerQueue *q = cls;
1151
1152 GNUNET_MQ_discard (q->env);
1153 call_peer_cont (q, GNUNET_YES);
1154 GNUNET_free (q);
1155}
1156
1157
1158/**
1134 * @brief Send a message to another peer (using CORE). 1159 * @brief Send a message to another peer (using CORE).
1135 * 1160 *
1136 * @param peer Peer towards which to queue the message. 1161 * @param peer Peer towards which to queue the message.
@@ -1150,7 +1175,7 @@ struct CadetPeerQueue *
1150GCP_send (struct CadetPeer *peer, 1175GCP_send (struct CadetPeer *peer,
1151 const struct GNUNET_MessageHeader *message, 1176 const struct GNUNET_MessageHeader *message,
1152 uint16_t payload_type, 1177 uint16_t payload_type,
1153 uint32_t payload_id, 1178 struct CadetEncryptedMessageIdentifier payload_id,
1154 struct CadetConnection *c, 1179 struct CadetConnection *c,
1155 int fwd, 1180 int fwd,
1156 GCP_sent cont, 1181 GCP_sent cont,
@@ -1165,7 +1190,8 @@ GCP_send (struct CadetPeer *peer,
1165 size = ntohs (message->size); 1190 size = ntohs (message->size);
1166 LOG (GNUNET_ERROR_TYPE_DEBUG, 1191 LOG (GNUNET_ERROR_TYPE_DEBUG,
1167 "que %s (%s %4u) on conn %s (%p) %s towards %s (size %u)\n", 1192 "que %s (%s %4u) on conn %s (%p) %s towards %s (size %u)\n",
1168 GC_m2s (type), GC_m2s (payload_type), payload_id, 1193 GC_m2s (type), GC_m2s (payload_type),
1194 ntohl (payload_id.pid),
1169 GCC_2s (c), c, GC_f2s (fwd), GCP_2s (peer), size); 1195 GCC_2s (c), c, GC_f2s (fwd), GCP_2s (peer), size);
1170 1196
1171 if (NULL == peer->connections) 1197 if (NULL == peer->connections)
@@ -1191,7 +1217,8 @@ GCP_send (struct CadetPeer *peer,
1191 q->payload_id = payload_id; 1217 q->payload_id = payload_id;
1192 q->c = c; 1218 q->c = c;
1193 q->c_fwd = fwd; 1219 q->c_fwd = fwd;
1194 GNUNET_MQ_notify_sent (q->env, mq_sent, q); 1220 GNUNET_MQ_notify_sent (q->env, &mq_sent, q);
1221 GNUNET_CONTAINER_DLL_insert (peer->q_head, peer->q_tail, q);
1195 1222
1196 if (GNUNET_YES == q->management_traffic) 1223 if (GNUNET_YES == q->management_traffic)
1197 { 1224 {
@@ -1201,19 +1228,21 @@ GCP_send (struct CadetPeer *peer,
1201 { 1228 {
1202 if (GNUNET_YES == should_I_drop ()) 1229 if (GNUNET_YES == should_I_drop ())
1203 { 1230 {
1204 LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s (%s %u) on conn %s %s\n", 1231 LOG (GNUNET_ERROR_TYPE_WARNING,
1205 GC_m2s (q->type), GC_m2s (q->payload_type), 1232 "DD %s (%s %u) on conn %s %s (random drop for testing)\n",
1206 q->payload_id, GCC_2s (c), GC_f2s (q->c_fwd)); 1233 GC_m2s (q->type),
1207 GNUNET_MQ_discard (q->env); 1234 GC_m2s (q->payload_type),
1208 call_peer_cont (q, GNUNET_YES); 1235 ntohl (q->payload_id.pid),
1209 GNUNET_free (q); 1236 GCC_2s (c),
1210 return NULL; 1237 GC_f2s (q->c_fwd));
1238 q->drop_task = GNUNET_SCHEDULER_add_now (&drop_cb,
1239 q);
1240 return q;
1211 } 1241 }
1212 GNUNET_MQ_send (peer->core_mq, q->env); 1242 GNUNET_MQ_send (peer->core_mq, q->env);
1213 peer->queue_n++; 1243 peer->queue_n++;
1214 } 1244 }
1215 1245
1216 GNUNET_CONTAINER_DLL_insert (peer->q_head, peer->q_tail, q);
1217 GCC_check_connections (); 1246 GCC_check_connections ();
1218 return q; 1247 return q;
1219} 1248}
@@ -1231,9 +1260,18 @@ GCP_send (struct CadetPeer *peer,
1231void 1260void
1232GCP_send_cancel (struct CadetPeerQueue *q) 1261GCP_send_cancel (struct CadetPeerQueue *q)
1233{ 1262{
1234 call_peer_cont (q, GNUNET_NO); 1263 if (NULL != q->drop_task)
1264 {
1265 GNUNET_SCHEDULER_cancel (q->drop_task);
1266 q->drop_task = NULL;
1267 GNUNET_MQ_discard (q->env);
1268 }
1269 else
1270 {
1235 GNUNET_MQ_send_cancel (q->env); 1271 GNUNET_MQ_send_cancel (q->env);
1236 GNUNET_free (q); 1272 }
1273 call_peer_cont (q, GNUNET_NO);
1274 GNUNET_free (q);
1237} 1275}
1238 1276
1239 1277
@@ -1294,12 +1332,12 @@ GCP_shutdown (void)
1294 in_shutdown = GNUNET_YES; 1332 in_shutdown = GNUNET_YES;
1295 if (NULL != core_handle) 1333 if (NULL != core_handle)
1296 { 1334 {
1297 GNUNET_CORE_disconnecT (core_handle); 1335 GNUNET_CORE_disconnect (core_handle);
1298 core_handle = NULL; 1336 core_handle = NULL;
1299 } 1337 }
1300 GNUNET_PEER_change_rc (myid, -1); 1338 GNUNET_PEER_change_rc (myid, -1);
1301 /* With MQ API, CORE calls the disconnect handler for every peer 1339 /* With MQ API, CORE calls the disconnect handler for every peer
1302 * after calling GNUNET_CORE_disconnecT, shutdown must occur *after* that. 1340 * after calling GNUNET_CORE_disconnect, shutdown must occur *after* that.
1303 */ 1341 */
1304 GNUNET_CONTAINER_multipeermap_iterate (peers, 1342 GNUNET_CONTAINER_multipeermap_iterate (peers,
1305 &shutdown_peer, 1343 &shutdown_peer,
@@ -1543,14 +1581,14 @@ GCP_add_connection (struct CadetPeer *peer,
1543 GCP_2s (peer)); 1581 GCP_2s (peer));
1544 GNUNET_assert (NULL != peer->connections); 1582 GNUNET_assert (NULL != peer->connections);
1545 GNUNET_assert (GNUNET_OK == 1583 GNUNET_assert (GNUNET_OK ==
1546 GNUNET_CONTAINER_multihashmap_put (peer->connections, 1584 GNUNET_CONTAINER_multishortmap_put (peer->connections,
1547 GCC_get_h (c), 1585 &GCC_get_id (c)->connection_of_tunnel,
1548 c, 1586 c,
1549 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 1587 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1550 LOG (GNUNET_ERROR_TYPE_DEBUG, 1588 LOG (GNUNET_ERROR_TYPE_DEBUG,
1551 "Peer %s has now %u connections.\n", 1589 "Peer %s has now %u connections.\n",
1552 GCP_2s (peer), 1590 GCP_2s (peer),
1553 GNUNET_CONTAINER_multihashmap_size (peer->connections)); 1591 GNUNET_CONTAINER_multishortmap_size (peer->connections));
1554} 1592}
1555 1593
1556 1594
@@ -1761,13 +1799,13 @@ void
1761GCP_check_connection (const struct CadetPeer *peer, 1799GCP_check_connection (const struct CadetPeer *peer,
1762 const struct CadetConnection *c) 1800 const struct CadetConnection *c)
1763{ 1801{
1764 GNUNET_assert (NULL != peer); 1802 GNUNET_assert (NULL != peer);
1765 GNUNET_assert (NULL != peer->connections); 1803 GNUNET_assert (NULL != peer->connections);
1766 return; 1804 return; // ????
1767 GNUNET_assert (GNUNET_YES == 1805 GNUNET_assert (GNUNET_YES ==
1768 GNUNET_CONTAINER_multihashmap_contains_value (peer->connections, 1806 GNUNET_CONTAINER_multishortmap_contains_value (peer->connections,
1769 GCC_get_h (c), 1807 &GCC_get_id (c)->connection_of_tunnel,
1770 c)); 1808 c));
1771} 1809}
1772 1810
1773 1811
@@ -1791,13 +1829,13 @@ GCP_remove_connection (struct CadetPeer *peer,
1791 (NULL == peer->connections) ) 1829 (NULL == peer->connections) )
1792 return; 1830 return;
1793 GNUNET_assert (GNUNET_YES == 1831 GNUNET_assert (GNUNET_YES ==
1794 GNUNET_CONTAINER_multihashmap_remove (peer->connections, 1832 GNUNET_CONTAINER_multishortmap_remove (peer->connections,
1795 GCC_get_h (c), 1833 &GCC_get_id (c)->connection_of_tunnel,
1796 c)); 1834 c));
1797 LOG (GNUNET_ERROR_TYPE_DEBUG, 1835 LOG (GNUNET_ERROR_TYPE_DEBUG,
1798 "Peer %s remains with %u connections.\n", 1836 "Peer %s remains with %u connections.\n",
1799 GCP_2s (peer), 1837 GCP_2s (peer),
1800 GNUNET_CONTAINER_multihashmap_size (peer->connections)); 1838 GNUNET_CONTAINER_multishortmap_size (peer->connections));
1801} 1839}
1802 1840
1803 1841
diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h
index 093cfa21a..1e206e10f 100644
--- a/src/cadet/gnunet-service-cadet_peer.h
+++ b/src/cadet/gnunet-service-cadet_peer.h
@@ -69,8 +69,12 @@ struct CadetPeerQueue;
69 */ 69 */
70typedef void 70typedef void
71(*GCP_sent) (void *cls, 71(*GCP_sent) (void *cls,
72 struct CadetConnection *c, int fwd, int sent, 72 struct CadetConnection *c,
73 uint16_t type, uint16_t payload_type, uint32_t pid, 73 int fwd,
74 int sent,
75 uint16_t type,
76 uint16_t payload_type,
77 struct CadetEncryptedMessageIdentifier pid,
74 size_t size, 78 size_t size,
75 struct GNUNET_TIME_Relative wait); 79 struct GNUNET_TIME_Relative wait);
76 80
@@ -122,6 +126,7 @@ GCP_shutdown (void);
122struct CadetPeer * 126struct CadetPeer *
123GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create); 127GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create);
124 128
129
125/** 130/**
126 * Retrieve the CadetPeer stucture associated with the peer. Optionally create 131 * Retrieve the CadetPeer stucture associated with the peer. Optionally create
127 * one and insert it in the appropriate structures if the peer is not known yet. 132 * one and insert it in the appropriate structures if the peer is not known yet.
@@ -136,6 +141,7 @@ GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create);
136struct CadetPeer * 141struct CadetPeer *
137GCP_get_short (const GNUNET_PEER_Id peer, int create); 142GCP_get_short (const GNUNET_PEER_Id peer, int create);
138 143
144
139/** 145/**
140 * Try to establish a new connection to this peer (in its tunnel). 146 * Try to establish a new connection to this peer (in its tunnel).
141 * If the peer doesn't have any path to it yet, try to get one. 147 * If the peer doesn't have any path to it yet, try to get one.
@@ -164,7 +170,7 @@ struct CadetPeerQueue *
164GCP_send (struct CadetPeer *peer, 170GCP_send (struct CadetPeer *peer,
165 const struct GNUNET_MessageHeader *message, 171 const struct GNUNET_MessageHeader *message,
166 uint16_t payload_type, 172 uint16_t payload_type,
167 uint32_t payload_id, 173 struct CadetEncryptedMessageIdentifier payload_id,
168 struct CadetConnection *c, 174 struct CadetConnection *c,
169 int fwd, 175 int fwd,
170 GCP_sent cont, 176 GCP_sent cont,
@@ -440,7 +446,8 @@ GCP_iterate_paths (struct CadetPeer *peer,
440 * @param cls Closure for @c iter. 446 * @param cls Closure for @c iter.
441 */ 447 */
442void 448void
443GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls); 449GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
450 void *cls);
444 451
445 452
446/** 453/**
diff --git a/src/cadet/gnunet-service-cadet_tunnel.c b/src/cadet/gnunet-service-cadet_tunnel.c
index 5b07e42c0..65775ce66 100644
--- a/src/cadet/gnunet-service-cadet_tunnel.c
+++ b/src/cadet/gnunet-service-cadet_tunnel.c
@@ -63,7 +63,7 @@ struct CadetTChannel
63 63
64 64
65/** 65/**
66 * Connection list and metadata. 66 * Entry in list of connections used by tunnel, with metadata.
67 */ 67 */
68struct CadetTConnection 68struct CadetTConnection
69{ 69{
@@ -243,6 +243,7 @@ struct CadetTunnelAxolotl
243 struct GNUNET_TIME_Absolute ratchet_expiration; 243 struct GNUNET_TIME_Absolute ratchet_expiration;
244}; 244};
245 245
246
246/** 247/**
247 * Struct containing all information regarding a tunnel to a peer. 248 * Struct containing all information regarding a tunnel to a peer.
248 */ 249 */
@@ -309,7 +310,7 @@ struct CadetTunnel
309 /** 310 /**
310 * Channel ID for the next created channel. 311 * Channel ID for the next created channel.
311 */ 312 */
312 CADET_ChannelNumber next_chid; 313 struct GNUNET_CADET_ChannelTunnelNumber next_chid;
313 314
314 /** 315 /**
315 * Destroy flag: if true, destroy on last message. 316 * Destroy flag: if true, destroy on last message.
@@ -648,7 +649,7 @@ new_ephemeral (struct CadetTunnel *t)
648static void 649static void
649t_hmac (const void *plaintext, size_t size, 650t_hmac (const void *plaintext, size_t size,
650 uint32_t iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *key, 651 uint32_t iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
651 struct GNUNET_CADET_Hash *hmac) 652 struct GNUNET_ShortHashCode *hmac)
652{ 653{
653 static const char ctx[] = "cadet authentication key"; 654 static const char ctx[] = "cadet authentication key";
654 struct GNUNET_CRYPTO_AuthKey auth_key; 655 struct GNUNET_CRYPTO_AuthKey auth_key;
@@ -842,7 +843,7 @@ t_ax_decrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size)
842 * @param msg Message whose header to encrypt. 843 * @param msg Message whose header to encrypt.
843 */ 844 */
844static void 845static void
845t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_Encrypted *msg) 846t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_TunnelEncryptedMessage *msg)
846{ 847{
847 struct GNUNET_CRYPTO_SymmetricInitializationVector iv; 848 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
848 struct CadetTunnelAxolotl *ax; 849 struct CadetTunnelAxolotl *ax;
@@ -873,8 +874,8 @@ t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_Encrypted *msg)
873 * @param dst Where to decrypt header to. 874 * @param dst Where to decrypt header to.
874 */ 875 */
875static void 876static void
876t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_Encrypted *src, 877t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_TunnelEncryptedMessage *src,
877 struct GNUNET_CADET_Encrypted *dst) 878 struct GNUNET_CADET_TunnelEncryptedMessage *dst)
878{ 879{
879 struct GNUNET_CRYPTO_SymmetricInitializationVector iv; 880 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
880 struct CadetTunnelAxolotl *ax; 881 struct CadetTunnelAxolotl *ax;
@@ -912,12 +913,12 @@ t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_Encrypted *src,
912 */ 913 */
913static int 914static int
914try_old_ax_keys (struct CadetTunnel *t, void *dst, 915try_old_ax_keys (struct CadetTunnel *t, void *dst,
915 const struct GNUNET_CADET_Encrypted *src, size_t size) 916 const struct GNUNET_CADET_TunnelEncryptedMessage *src, size_t size)
916{ 917{
917 struct CadetTunnelSkippedKey *key; 918 struct CadetTunnelSkippedKey *key;
918 struct GNUNET_CADET_Hash *hmac; 919 struct GNUNET_ShortHashCode *hmac;
919 struct GNUNET_CRYPTO_SymmetricInitializationVector iv; 920 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
920 struct GNUNET_CADET_Encrypted plaintext_header; 921 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
921 struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK; 922 struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
922 size_t esize; 923 size_t esize;
923 size_t res; 924 size_t res;
@@ -926,7 +927,7 @@ try_old_ax_keys (struct CadetTunnel *t, void *dst,
926 927
927 LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying old keys\n"); 928 LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying old keys\n");
928 hmac = &plaintext_header.hmac; 929 hmac = &plaintext_header.hmac;
929 esize = size - sizeof (struct GNUNET_CADET_Encrypted); 930 esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
930 931
931 /* Find a correct Header Key */ 932 /* Find a correct Header Key */
932 for (key = t->ax->skipped_head; NULL != key; key = key->next) 933 for (key = t->ax->skipped_head; NULL != key; key = key->next)
@@ -947,8 +948,8 @@ try_old_ax_keys (struct CadetTunnel *t, void *dst,
947 return -1; 948 return -1;
948 949
949 /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */ 950 /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
950 GNUNET_assert (size > sizeof (struct GNUNET_CADET_Encrypted)); 951 GNUNET_assert (size > sizeof (struct GNUNET_CADET_TunnelEncryptedMessage));
951 len = size - sizeof (struct GNUNET_CADET_Encrypted); 952 len = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
952 GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader)); 953 GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader));
953 954
954 /* Decrypt header */ 955 /* Decrypt header */
@@ -1091,19 +1092,19 @@ store_ax_keys (struct CadetTunnel *t,
1091 */ 1092 */
1092static int 1093static int
1093t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst, 1094t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst,
1094 const struct GNUNET_CADET_Encrypted *src, 1095 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
1095 size_t size) 1096 size_t size)
1096{ 1097{
1097 struct CadetTunnelAxolotl *ax; 1098 struct CadetTunnelAxolotl *ax;
1098 struct GNUNET_CADET_Hash msg_hmac; 1099 struct GNUNET_ShortHashCode msg_hmac;
1099 struct GNUNET_HashCode hmac; 1100 struct GNUNET_HashCode hmac;
1100 struct GNUNET_CADET_Encrypted plaintext_header; 1101 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
1101 uint32_t Np; 1102 uint32_t Np;
1102 uint32_t PNp; 1103 uint32_t PNp;
1103 size_t esize; /* Size of encryped payload */ 1104 size_t esize; /* Size of encryped payload */
1104 size_t osize; /* Size of output (decrypted payload) */ 1105 size_t osize; /* Size of output (decrypted payload) */
1105 1106
1106 esize = size - sizeof (struct GNUNET_CADET_Encrypted); 1107 esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
1107 ax = t->ax; 1108 ax = t->ax;
1108 if (NULL == ax) 1109 if (NULL == ax)
1109 return -1; 1110 return -1;
@@ -1321,12 +1322,11 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1321 struct CadetTunnelQueue *existing_q) 1322 struct CadetTunnelQueue *existing_q)
1322{ 1323{
1323 struct GNUNET_MessageHeader *msg; 1324 struct GNUNET_MessageHeader *msg;
1324 struct GNUNET_CADET_Encrypted *ax_msg; 1325 struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
1325 struct CadetTunnelQueue *tq; 1326 struct CadetTunnelQueue *tq;
1326 size_t size = ntohs (message->size); 1327 size_t size = ntohs (message->size);
1327 char cbuf[sizeof (struct GNUNET_CADET_Encrypted) + size] GNUNET_ALIGN; 1328 char cbuf[sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size] GNUNET_ALIGN;
1328 size_t esize; 1329 size_t esize;
1329 uint32_t mid;
1330 uint16_t type; 1330 uint16_t type;
1331 int fwd; 1331 int fwd;
1332 1332
@@ -1352,10 +1352,10 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1352 1352
1353 GNUNET_assert (GNUNET_NO == GCT_is_loopback (t)); 1353 GNUNET_assert (GNUNET_NO == GCT_is_loopback (t));
1354 1354
1355 ax_msg = (struct GNUNET_CADET_Encrypted *) cbuf; 1355 ax_msg = (struct GNUNET_CADET_TunnelEncryptedMessage *) cbuf;
1356 msg = &ax_msg->header; 1356 msg = &ax_msg->header;
1357 msg->size = htons (sizeof (struct GNUNET_CADET_Encrypted) + size); 1357 msg->size = htons (sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size);
1358 msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED); 1358 msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
1359 esize = t_ax_encrypt (t, &ax_msg[1], message, size); 1359 esize = t_ax_encrypt (t, &ax_msg[1], message, size);
1360 ax_msg->Ns = htonl (t->ax->Ns++); 1360 ax_msg->Ns = htonl (t->ax->Ns++);
1361 ax_msg->PNs = htonl (t->ax->PNs); 1361 ax_msg->PNs = htonl (t->ax->PNs);
@@ -1378,34 +1378,22 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1378 } 1378 }
1379 fwd = GCC_is_origin (c, GNUNET_YES); 1379 fwd = GCC_is_origin (c, GNUNET_YES);
1380 ax_msg->cid = *GCC_get_id (c); 1380 ax_msg->cid = *GCC_get_id (c);
1381 ax_msg->pid = htonl (GCC_get_pid (c, fwd)); 1381 ax_msg->cemi = GCC_get_pid (c, fwd);
1382 1382
1383 mid = 0; 1383 type = htons (message->type);
1384 type = ntohs (message->type); 1384 LOG (GNUNET_ERROR_TYPE_DEBUG,
1385 switch (type) 1385 "Sending message of type %s with CEMI %u and CID %s\n",
1386 { 1386 GC_m2s (type),
1387 case GNUNET_MESSAGE_TYPE_CADET_DATA: 1387 htonl (ax_msg->cemi.pid),
1388 case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: 1388 GNUNET_sh2s (&ax_msg->cid.connection_of_tunnel));
1389 if (GNUNET_MESSAGE_TYPE_CADET_DATA == type)
1390 mid = ntohl (((struct GNUNET_CADET_Data *) message)->mid);
1391 else
1392 mid = ntohl (((struct GNUNET_CADET_DataACK *) message)->mid);
1393 /* Fall thru */
1394 case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
1395 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
1396 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
1397 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
1398 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
1399 break;
1400 default:
1401 GNUNET_break (0);
1402 LOG (GNUNET_ERROR_TYPE_ERROR, "type %s not valid\n", GC_m2s (type));
1403 }
1404 LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s\n", GC_m2s (type));
1405 1389
1406 if (NULL == cont) 1390 if (NULL == cont)
1407 { 1391 {
1408 (void) GCC_send_prebuilt_message (msg, type, mid, c, fwd, 1392 (void) GCC_send_prebuilt_message (msg,
1393 type,
1394 ax_msg->cemi,
1395 c,
1396 fwd,
1409 force, NULL, NULL); 1397 force, NULL, NULL);
1410 return NULL; 1398 return NULL;
1411 } 1399 }
@@ -1418,11 +1406,16 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1418 tq = existing_q; 1406 tq = existing_q;
1419 tq->tqd = NULL; 1407 tq->tqd = NULL;
1420 } 1408 }
1421 tq->cq = GCC_send_prebuilt_message (msg, type, mid, c, fwd, force,
1422 &tun_message_sent, tq);
1423 GNUNET_assert (NULL != tq->cq);
1424 tq->cont = cont; 1409 tq->cont = cont;
1425 tq->cont_cls = cont_cls; 1410 tq->cont_cls = cont_cls;
1411 tq->cq = GCC_send_prebuilt_message (msg,
1412 type,
1413 ax_msg->cemi,
1414 c,
1415 fwd,
1416 force,
1417 &tun_message_sent, tq);
1418 GNUNET_assert (NULL != tq->cq);
1426 1419
1427 return tq; 1420 return tq;
1428} 1421}
@@ -1562,17 +1555,19 @@ destroy_iterator (void *cls,
1562 * @param gid ID of the channel. 1555 * @param gid ID of the channel.
1563 */ 1556 */
1564static void 1557static void
1565send_channel_destroy (struct CadetTunnel *t, unsigned int gid) 1558send_channel_destroy (struct CadetTunnel *t,
1559 struct GNUNET_CADET_ChannelTunnelNumber gid)
1566{ 1560{
1567 struct GNUNET_CADET_ChannelManage msg; 1561 struct GNUNET_CADET_ChannelManageMessage msg;
1568 1562
1569 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); 1563 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
1570 msg.header.size = htons (sizeof (msg)); 1564 msg.header.size = htons (sizeof (msg));
1571 msg.chid = htonl (gid); 1565 msg.chid = gid;
1572 1566
1573 LOG (GNUNET_ERROR_TYPE_DEBUG, 1567 LOG (GNUNET_ERROR_TYPE_DEBUG,
1574 "WARNING destroying unknown channel %u on tunnel %s\n", 1568 "WARNING destroying unknown channel %u on tunnel %s\n",
1575 gid, GCT_2s (t)); 1569 ntohl (gid.cn),
1570 GCT_2s (t));
1576 send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL); 1571 send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL);
1577} 1572}
1578 1573
@@ -1589,7 +1584,7 @@ send_channel_destroy (struct CadetTunnel *t, unsigned int gid)
1589 */ 1584 */
1590static void 1585static void
1591handle_data (struct CadetTunnel *t, 1586handle_data (struct CadetTunnel *t,
1592 const struct GNUNET_CADET_Data *msg, 1587 const struct GNUNET_CADET_ChannelAppDataMessage *msg,
1593 int fwd) 1588 int fwd)
1594{ 1589{
1595 struct CadetChannel *ch; 1590 struct CadetChannel *ch;
@@ -1600,7 +1595,7 @@ handle_data (struct CadetTunnel *t,
1600 /* Check size */ 1595 /* Check size */
1601 size = ntohs (msg->header.size); 1596 size = ntohs (msg->header.size);
1602 if (size < 1597 if (size <
1603 sizeof (struct GNUNET_CADET_Data) + 1598 sizeof (struct GNUNET_CADET_ChannelAppDataMessage) +
1604 sizeof (struct GNUNET_MessageHeader)) 1599 sizeof (struct GNUNET_MessageHeader))
1605 { 1600 {
1606 GNUNET_break (0); 1601 GNUNET_break (0);
@@ -1613,13 +1608,17 @@ handle_data (struct CadetTunnel *t,
1613 1608
1614 1609
1615 /* Check channel */ 1610 /* Check channel */
1616 ch = GCT_get_channel (t, ntohl (msg->chid)); 1611 ch = GCT_get_channel (t, msg->chid);
1617 if (NULL == ch) 1612 if (NULL == ch)
1618 { 1613 {
1619 GNUNET_STATISTICS_update (stats, "# data on unknown channel", 1614 GNUNET_STATISTICS_update (stats,
1620 1, GNUNET_NO); 1615 "# data on unknown channel",
1621 LOG (GNUNET_ERROR_TYPE_DEBUG, "channel 0x%X unknown\n", ntohl (msg->chid)); 1616 1,
1622 send_channel_destroy (t, ntohl (msg->chid)); 1617 GNUNET_NO);
1618 LOG (GNUNET_ERROR_TYPE_DEBUG,
1619 "channel 0x%X unknown\n",
1620 ntohl (msg->chid.cn));
1621 send_channel_destroy (t, msg->chid);
1623 return; 1622 return;
1624 } 1623 }
1625 1624
@@ -1639,7 +1638,7 @@ handle_data (struct CadetTunnel *t,
1639 */ 1638 */
1640static void 1639static void
1641handle_data_ack (struct CadetTunnel *t, 1640handle_data_ack (struct CadetTunnel *t,
1642 const struct GNUNET_CADET_DataACK *msg, 1641 const struct GNUNET_CADET_ChannelDataAckMessage *msg,
1643 int fwd) 1642 int fwd)
1644{ 1643{
1645 struct CadetChannel *ch; 1644 struct CadetChannel *ch;
@@ -1647,20 +1646,20 @@ handle_data_ack (struct CadetTunnel *t,
1647 1646
1648 /* Check size */ 1647 /* Check size */
1649 size = ntohs (msg->header.size); 1648 size = ntohs (msg->header.size);
1650 if (size != sizeof (struct GNUNET_CADET_DataACK)) 1649 if (size != sizeof (struct GNUNET_CADET_ChannelDataAckMessage))
1651 { 1650 {
1652 GNUNET_break (0); 1651 GNUNET_break (0);
1653 return; 1652 return;
1654 } 1653 }
1655 1654
1656 /* Check channel */ 1655 /* Check channel */
1657 ch = GCT_get_channel (t, ntohl (msg->chid)); 1656 ch = GCT_get_channel (t, msg->chid);
1658 if (NULL == ch) 1657 if (NULL == ch)
1659 { 1658 {
1660 GNUNET_STATISTICS_update (stats, "# data ack on unknown channel", 1659 GNUNET_STATISTICS_update (stats, "# data ack on unknown channel",
1661 1, GNUNET_NO); 1660 1, GNUNET_NO);
1662 LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", 1661 LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
1663 ntohl (msg->chid)); 1662 ntohl (msg->chid.cn));
1664 return; 1663 return;
1665 } 1664 }
1666 1665
@@ -1676,21 +1675,21 @@ handle_data_ack (struct CadetTunnel *t,
1676 */ 1675 */
1677static void 1676static void
1678handle_ch_create (struct CadetTunnel *t, 1677handle_ch_create (struct CadetTunnel *t,
1679 const struct GNUNET_CADET_ChannelCreate *msg) 1678 const struct GNUNET_CADET_ChannelOpenMessage *msg)
1680{ 1679{
1681 struct CadetChannel *ch; 1680 struct CadetChannel *ch;
1682 size_t size; 1681 size_t size;
1683 1682
1684 /* Check size */ 1683 /* Check size */
1685 size = ntohs (msg->header.size); 1684 size = ntohs (msg->header.size);
1686 if (size != sizeof (struct GNUNET_CADET_ChannelCreate)) 1685 if (size != sizeof (struct GNUNET_CADET_ChannelOpenMessage))
1687 { 1686 {
1688 GNUNET_break_op (0); 1687 GNUNET_break_op (0);
1689 return; 1688 return;
1690 } 1689 }
1691 1690
1692 /* Check channel */ 1691 /* Check channel */
1693 ch = GCT_get_channel (t, ntohl (msg->chid)); 1692 ch = GCT_get_channel (t, msg->chid);
1694 if (NULL != ch && ! GCT_is_loopback (t)) 1693 if (NULL != ch && ! GCT_is_loopback (t))
1695 { 1694 {
1696 /* Probably a retransmission, safe to ignore */ 1695 /* Probably a retransmission, safe to ignore */
@@ -1711,27 +1710,28 @@ handle_ch_create (struct CadetTunnel *t,
1711 */ 1710 */
1712static void 1711static void
1713handle_ch_nack (struct CadetTunnel *t, 1712handle_ch_nack (struct CadetTunnel *t,
1714 const struct GNUNET_CADET_ChannelManage *msg) 1713 const struct GNUNET_CADET_ChannelManageMessage *msg)
1715{ 1714{
1716 struct CadetChannel *ch; 1715 struct CadetChannel *ch;
1717 size_t size; 1716 size_t size;
1718 1717
1719 /* Check size */ 1718 /* Check size */
1720 size = ntohs (msg->header.size); 1719 size = ntohs (msg->header.size);
1721 if (size != sizeof (struct GNUNET_CADET_ChannelManage)) 1720 if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
1722 { 1721 {
1723 GNUNET_break (0); 1722 GNUNET_break (0);
1724 return; 1723 return;
1725 } 1724 }
1726 1725
1727 /* Check channel */ 1726 /* Check channel */
1728 ch = GCT_get_channel (t, ntohl (msg->chid)); 1727 ch = GCT_get_channel (t, msg->chid);
1729 if (NULL == ch) 1728 if (NULL == ch)
1730 { 1729 {
1731 GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel", 1730 GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel",
1732 1, GNUNET_NO); 1731 1, GNUNET_NO);
1733 LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", 1732 LOG (GNUNET_ERROR_TYPE_DEBUG,
1734 ntohl (msg->chid)); 1733 "WARNING channel %u unknown\n",
1734 ntohl (msg->chid.cn));
1735 return; 1735 return;
1736 } 1736 }
1737 1737
@@ -1751,7 +1751,7 @@ handle_ch_nack (struct CadetTunnel *t,
1751 */ 1751 */
1752static void 1752static void
1753handle_ch_ack (struct CadetTunnel *t, 1753handle_ch_ack (struct CadetTunnel *t,
1754 const struct GNUNET_CADET_ChannelManage *msg, 1754 const struct GNUNET_CADET_ChannelManageMessage *msg,
1755 int fwd) 1755 int fwd)
1756{ 1756{
1757 struct CadetChannel *ch; 1757 struct CadetChannel *ch;
@@ -1759,20 +1759,23 @@ handle_ch_ack (struct CadetTunnel *t,
1759 1759
1760 /* Check size */ 1760 /* Check size */
1761 size = ntohs (msg->header.size); 1761 size = ntohs (msg->header.size);
1762 if (size != sizeof (struct GNUNET_CADET_ChannelManage)) 1762 if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
1763 { 1763 {
1764 GNUNET_break (0); 1764 GNUNET_break (0);
1765 return; 1765 return;
1766 } 1766 }
1767 1767
1768 /* Check channel */ 1768 /* Check channel */
1769 ch = GCT_get_channel (t, ntohl (msg->chid)); 1769 ch = GCT_get_channel (t, msg->chid);
1770 if (NULL == ch) 1770 if (NULL == ch)
1771 { 1771 {
1772 GNUNET_STATISTICS_update (stats, "# channel ack on unknown channel", 1772 GNUNET_STATISTICS_update (stats,
1773 1, GNUNET_NO); 1773 "# channel ack on unknown channel",
1774 LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", 1774 1,
1775 ntohl (msg->chid)); 1775 GNUNET_NO);
1776 LOG (GNUNET_ERROR_TYPE_DEBUG,
1777 "WARNING channel %u unknown\n",
1778 ntohl (msg->chid.cn));
1776 return; 1779 return;
1777 } 1780 }
1778 1781
@@ -1792,7 +1795,7 @@ handle_ch_ack (struct CadetTunnel *t,
1792 */ 1795 */
1793static void 1796static void
1794handle_ch_destroy (struct CadetTunnel *t, 1797handle_ch_destroy (struct CadetTunnel *t,
1795 const struct GNUNET_CADET_ChannelManage *msg, 1798 const struct GNUNET_CADET_ChannelManageMessage *msg,
1796 int fwd) 1799 int fwd)
1797{ 1800{
1798 struct CadetChannel *ch; 1801 struct CadetChannel *ch;
@@ -1800,14 +1803,14 @@ handle_ch_destroy (struct CadetTunnel *t,
1800 1803
1801 /* Check size */ 1804 /* Check size */
1802 size = ntohs (msg->header.size); 1805 size = ntohs (msg->header.size);
1803 if (size != sizeof (struct GNUNET_CADET_ChannelManage)) 1806 if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
1804 { 1807 {
1805 GNUNET_break (0); 1808 GNUNET_break (0);
1806 return; 1809 return;
1807 } 1810 }
1808 1811
1809 /* Check channel */ 1812 /* Check channel */
1810 ch = GCT_get_channel (t, ntohl (msg->chid)); 1813 ch = GCT_get_channel (t, msg->chid);
1811 if (NULL == ch) 1814 if (NULL == ch)
1812 { 1815 {
1813 /* Probably a retransmission, safe to ignore */ 1816 /* Probably a retransmission, safe to ignore */
@@ -1877,34 +1880,34 @@ handle_decrypted (struct CadetTunnel *t,
1877 1880
1878 switch (type) 1881 switch (type)
1879 { 1882 {
1880 case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: 1883 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE:
1881 /* Do nothing, connection aleady got updated. */ 1884 /* Do nothing, connection aleady got updated. */
1882 GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO); 1885 GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO);
1883 break; 1886 break;
1884 1887
1885 case GNUNET_MESSAGE_TYPE_CADET_DATA: 1888 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
1886 /* Don't send hop ACK, wait for client to ACK */ 1889 /* Don't send hop ACK, wait for client to ACK */
1887 handle_data (t, (struct GNUNET_CADET_Data *) msgh, fwd); 1890 handle_data (t, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd);
1888 break; 1891 break;
1889 1892
1890 case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: 1893 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
1891 handle_data_ack (t, (struct GNUNET_CADET_DataACK *) msgh, fwd); 1894 handle_data_ack (t, (struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd);
1892 break; 1895 break;
1893 1896
1894 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: 1897 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
1895 handle_ch_create (t, (struct GNUNET_CADET_ChannelCreate *) msgh); 1898 handle_ch_create (t, (struct GNUNET_CADET_ChannelOpenMessage *) msgh);
1896 break; 1899 break;
1897 1900
1898 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: 1901 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
1899 handle_ch_nack (t, (struct GNUNET_CADET_ChannelManage *) msgh); 1902 handle_ch_nack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh);
1900 break; 1903 break;
1901 1904
1902 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: 1905 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
1903 handle_ch_ack (t, (struct GNUNET_CADET_ChannelManage *) msgh, fwd); 1906 handle_ch_ack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd);
1904 break; 1907 break;
1905 1908
1906 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: 1909 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
1907 handle_ch_destroy (t, (struct GNUNET_CADET_ChannelManage *) msgh, fwd); 1910 handle_ch_destroy (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd);
1908 break; 1911 break;
1909 1912
1910 default: 1913 default:
@@ -1931,7 +1934,7 @@ handle_decrypted (struct CadetTunnel *t,
1931 */ 1934 */
1932void 1935void
1933GCT_handle_encrypted (struct CadetTunnel *t, 1936GCT_handle_encrypted (struct CadetTunnel *t,
1934 const struct GNUNET_CADET_Encrypted *msg) 1937 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1935{ 1938{
1936 uint16_t size = ntohs (msg->header.size); 1939 uint16_t size = ntohs (msg->header.size);
1937 char cbuf [size]; 1940 char cbuf [size];
@@ -1990,7 +1993,7 @@ GCT_handle_encrypted (struct CadetTunnel *t,
1990 */ 1993 */
1991void 1994void
1992GCT_handle_kx (struct CadetTunnel *t, 1995GCT_handle_kx (struct CadetTunnel *t,
1993 const struct GNUNET_CADET_KX *msg) 1996 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1994{ 1997{
1995 struct CadetTunnelAxolotl *ax; 1998 struct CadetTunnelAxolotl *ax;
1996 struct GNUNET_HashCode key_material[3]; 1999 struct GNUNET_HashCode key_material[3];
@@ -2143,9 +2146,9 @@ GCT_init (const struct GNUNET_CONFIGURATION_Handle *c,
2143 LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); 2146 LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
2144 2147
2145 expected_overhead = 0; 2148 expected_overhead = 0;
2146 expected_overhead += sizeof (struct GNUNET_CADET_Encrypted); 2149 expected_overhead += sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
2147 expected_overhead += sizeof (struct GNUNET_CADET_Data); 2150 expected_overhead += sizeof (struct GNUNET_CADET_ChannelAppDataMessage);
2148 expected_overhead += sizeof (struct GNUNET_CADET_ACK); 2151 expected_overhead += sizeof (struct GNUNET_CADET_ConnectionEncryptedAckMessage);
2149 GNUNET_assert (GNUNET_CONSTANTS_CADET_P2P_OVERHEAD == expected_overhead); 2152 GNUNET_assert (GNUNET_CONSTANTS_CADET_P2P_OVERHEAD == expected_overhead);
2150 2153
2151 if (GNUNET_OK != 2154 if (GNUNET_OK !=
@@ -2200,7 +2203,7 @@ GCT_new (struct CadetPeer *destination)
2200 struct CadetTunnel *t; 2203 struct CadetTunnel *t;
2201 2204
2202 t = GNUNET_new (struct CadetTunnel); 2205 t = GNUNET_new (struct CadetTunnel);
2203 t->next_chid = 0; 2206 t->next_chid.cn = 0;
2204 t->peer = destination; 2207 t->peer = destination;
2205 2208
2206 if (GNUNET_OK != 2209 if (GNUNET_OK !=
@@ -2442,7 +2445,8 @@ GCT_remove_connection (struct CadetTunnel *t,
2442 * @param ch Channel. 2445 * @param ch Channel.
2443 */ 2446 */
2444void 2447void
2445GCT_add_channel (struct CadetTunnel *t, struct CadetChannel *ch) 2448GCT_add_channel (struct CadetTunnel *t,
2449 struct CadetChannel *ch)
2446{ 2450{
2447 struct CadetTChannel *aux; 2451 struct CadetTChannel *aux;
2448 2452
@@ -2510,7 +2514,8 @@ GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch)
2510 * @return channel handler, NULL if doesn't exist 2514 * @return channel handler, NULL if doesn't exist
2511 */ 2515 */
2512struct CadetChannel * 2516struct CadetChannel *
2513GCT_get_channel (struct CadetTunnel *t, CADET_ChannelNumber chid) 2517GCT_get_channel (struct CadetTunnel *t,
2518 struct GNUNET_CADET_ChannelTunnelNumber chid)
2514{ 2519{
2515 struct CadetTChannel *iter; 2520 struct CadetTChannel *iter;
2516 2521
@@ -2519,7 +2524,7 @@ GCT_get_channel (struct CadetTunnel *t, CADET_ChannelNumber chid)
2519 2524
2520 for (iter = t->channel_head; NULL != iter; iter = iter->next) 2525 for (iter = t->channel_head; NULL != iter; iter = iter->next)
2521 { 2526 {
2522 if (GCCH_get_id (iter->ch) == chid) 2527 if (GCCH_get_id (iter->ch).cn == chid.cn)
2523 break; 2528 break;
2524 } 2529 }
2525 2530
@@ -2659,7 +2664,7 @@ GCT_destroy (struct CadetTunnel *t)
2659 2664
2660 mh = (struct GNUNET_MessageHeader *) &t->tq_head[1]; 2665 mh = (struct GNUNET_MessageHeader *) &t->tq_head[1];
2661 type = ntohs (mh->type); 2666 type = ntohs (mh->type);
2662 if (0 == keepalives_queued && GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE == type) 2667 if (0 == keepalives_queued && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE == type)
2663 { 2668 {
2664 keepalives_queued = 1; 2669 keepalives_queued = 1;
2665 LOG (GNUNET_ERROR_TYPE_DEBUG, 2670 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -2727,7 +2732,7 @@ struct CadetConnection *
2727GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *path) 2732GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *path)
2728{ 2733{
2729 struct CadetConnection *c; 2734 struct CadetConnection *c;
2730 struct GNUNET_CADET_Hash cid; 2735 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
2731 unsigned int own_pos; 2736 unsigned int own_pos;
2732 2737
2733 if (NULL == t || NULL == path) 2738 if (NULL == t || NULL == path)
@@ -2966,11 +2971,11 @@ GCT_get_destination (struct CadetTunnel *t)
2966 * 2971 *
2967 * @return GID of a channel free to use. 2972 * @return GID of a channel free to use.
2968 */ 2973 */
2969CADET_ChannelNumber 2974struct GNUNET_CADET_ChannelTunnelNumber
2970GCT_get_next_chid (struct CadetTunnel *t) 2975GCT_get_next_chid (struct CadetTunnel *t)
2971{ 2976{
2972 CADET_ChannelNumber chid; 2977 struct GNUNET_CADET_ChannelTunnelNumber chid;
2973 CADET_ChannelNumber mask; 2978 struct GNUNET_CADET_ChannelTunnelNumber mask;
2974 int result; 2979 int result;
2975 2980
2976 /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID. 2981 /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID.
@@ -2979,20 +2984,22 @@ GCT_get_next_chid (struct CadetTunnel *t)
2979 */ 2984 */
2980 result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GCP_get_id (t->peer)); 2985 result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GCP_get_id (t->peer));
2981 if (0 > result) 2986 if (0 > result)
2982 mask = 0x40000000; 2987 mask.cn = htonl (0x40000000);
2983 else 2988 else
2984 mask = 0x0; 2989 mask.cn = 0x0;
2985 t->next_chid |= mask; 2990 t->next_chid.cn |= mask.cn;
2986 2991
2987 while (NULL != GCT_get_channel (t, t->next_chid)) 2992 while (NULL != GCT_get_channel (t, t->next_chid))
2988 { 2993 {
2989 LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", t->next_chid); 2994 LOG (GNUNET_ERROR_TYPE_DEBUG,
2990 t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; 2995 "Channel %u exists...\n",
2991 t->next_chid |= mask; 2996 t->next_chid.cn);
2997 t->next_chid.cn = htonl ((ntohl (t->next_chid.cn) + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
2998 t->next_chid.cn |= mask.cn;
2992 } 2999 }
2993 chid = t->next_chid; 3000 chid = t->next_chid;
2994 t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; 3001 t->next_chid.cn = (t->next_chid.cn + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
2995 t->next_chid |= mask; 3002 t->next_chid.cn |= mask.cn;
2996 3003
2997 return chid; 3004 return chid;
2998} 3005}
@@ -3185,7 +3192,8 @@ GCT_has_queued_traffic (struct CadetTunnel *t)
3185 */ 3192 */
3186struct CadetTunnelQueue * 3193struct CadetTunnelQueue *
3187GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, 3194GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
3188 struct CadetTunnel *t, struct CadetConnection *c, 3195 struct CadetTunnel *t,
3196 struct CadetConnection *c,
3189 int force, GCT_sent cont, void *cont_cls) 3197 int force, GCT_sent cont, void *cont_cls)
3190{ 3198{
3191 return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL); 3199 return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL);
@@ -3201,8 +3209,9 @@ GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
3201void 3209void
3202GCT_send_kx (struct CadetTunnel *t, int force_reply) 3210GCT_send_kx (struct CadetTunnel *t, int force_reply)
3203{ 3211{
3212 static struct CadetEncryptedMessageIdentifier zero;
3204 struct CadetConnection *c; 3213 struct CadetConnection *c;
3205 struct GNUNET_CADET_KX msg; 3214 struct GNUNET_CADET_TunnelKeyExchangeMessage msg;
3206 enum GNUNET_CADET_KX_Flags flags; 3215 enum GNUNET_CADET_KX_Flags flags;
3207 3216
3208 LOG (GNUNET_ERROR_TYPE_INFO, "==> { KX} on %s\n", GCT_2s (t)); 3217 LOG (GNUNET_ERROR_TYPE_INFO, "==> { KX} on %s\n", GCT_2s (t));
@@ -3225,7 +3234,7 @@ GCT_send_kx (struct CadetTunnel *t, int force_reply)
3225 } 3234 }
3226 3235
3227 msg.header.size = htons (sizeof (msg)); 3236 msg.header.size = htons (sizeof (msg));
3228 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX); 3237 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
3229 flags = GNUNET_CADET_KX_FLAG_NONE; 3238 flags = GNUNET_CADET_KX_FLAG_NONE;
3230 if (GNUNET_YES == force_reply) 3239 if (GNUNET_YES == force_reply)
3231 flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY; 3240 flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
@@ -3234,8 +3243,11 @@ GCT_send_kx (struct CadetTunnel *t, int force_reply)
3234 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->kx_0, &msg.ephemeral_key); 3243 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->kx_0, &msg.ephemeral_key);
3235 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &msg.ratchet_key); 3244 GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &msg.ratchet_key);
3236 3245
3237 t->ephm_h = GCC_send_prebuilt_message (&msg.header, UINT16_MAX, 0, 3246 t->ephm_h = GCC_send_prebuilt_message (&msg.header,
3238 c, GCC_is_origin (c, GNUNET_YES), 3247 UINT16_MAX,
3248 zero,
3249 c,
3250 GCC_is_origin (c, GNUNET_YES),
3239 GNUNET_YES, &ephm_sent, t); 3251 GNUNET_YES, &ephm_sent, t);
3240 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) 3252 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
3241 GCT_change_estate (t, CADET_TUNNEL_KEY_SENT); 3253 GCT_change_estate (t, CADET_TUNNEL_KEY_SENT);
@@ -3486,4 +3498,3 @@ GCT_iterate_channels (struct CadetTunnel *t, GCT_chan_iter iter, void *cls)
3486 for (cht = t->channel_head; NULL != cht; cht = cht->next) 3498 for (cht = t->channel_head; NULL != cht; cht = cht->next)
3487 iter (cls, cht->ch); 3499 iter (cls, cht->ch);
3488} 3500}
3489
diff --git a/src/cadet/gnunet-service-cadet_tunnel.h b/src/cadet/gnunet-service-cadet_tunnel.h
index e3ca57e9c..c10815a3b 100644
--- a/src/cadet/gnunet-service-cadet_tunnel.h
+++ b/src/cadet/gnunet-service-cadet_tunnel.h
@@ -291,7 +291,7 @@ GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch);
291 * @return channel handler, NULL if doesn't exist 291 * @return channel handler, NULL if doesn't exist
292 */ 292 */
293struct CadetChannel * 293struct CadetChannel *
294GCT_get_channel (struct CadetTunnel *t, CADET_ChannelNumber chid); 294GCT_get_channel (struct CadetTunnel *t, struct GNUNET_CADET_ChannelTunnelNumber chid);
295 295
296 296
297/** 297/**
@@ -304,7 +304,7 @@ GCT_get_channel (struct CadetTunnel *t, CADET_ChannelNumber chid);
304 */ 304 */
305void 305void
306GCT_handle_encrypted (struct CadetTunnel *t, 306GCT_handle_encrypted (struct CadetTunnel *t,
307 const struct GNUNET_CADET_Encrypted *msg); 307 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
308 308
309 309
310/** 310/**
@@ -315,7 +315,7 @@ GCT_handle_encrypted (struct CadetTunnel *t,
315 */ 315 */
316void 316void
317GCT_handle_kx (struct CadetTunnel *t, 317GCT_handle_kx (struct CadetTunnel *t,
318 const struct GNUNET_CADET_KX *msg); 318 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
319 319
320 320
321/** 321/**
@@ -427,7 +427,7 @@ GCT_get_destination (struct CadetTunnel *t);
427 * 427 *
428 * @return ID of a channel free to use. 428 * @return ID of a channel free to use.
429 */ 429 */
430CADET_ChannelNumber 430struct GNUNET_CADET_ChannelTunnelNumber
431GCT_get_next_chid (struct CadetTunnel *t); 431GCT_get_next_chid (struct CadetTunnel *t);
432 432
433 433
diff --git a/src/cadet/test_cadet.conf b/src/cadet/test_cadet.conf
index b6ed64c58..e0c00858e 100644
--- a/src/cadet/test_cadet.conf
+++ b/src/cadet/test_cadet.conf
@@ -59,11 +59,6 @@ USE_EPHEMERAL_KEYS = NO
59[PATHS] 59[PATHS]
60GNUNET_TEST_HOME = /tmp/test-cadet/ 60GNUNET_TEST_HOME = /tmp/test-cadet/
61 61
62[nat]
63RETURN_LOCAL_ADDRESSES = YES
64DISABLEV6 = YES
65USE_LOCALADDR = YES
66
67[peerinfo] 62[peerinfo]
68NO_IO = YES 63NO_IO = YES
69 64
diff --git a/src/cadet/test_cadet_local.c b/src/cadet/test_cadet_local.c
index c226563d5..d15785cb0 100644
--- a/src/cadet/test_cadet_local.c
+++ b/src/cadet/test_cadet_local.c
@@ -178,7 +178,8 @@ inbound_channel (void *cls,
178 * with the channel is stored 178 * with the channel is stored
179 */ 179 */
180static void 180static void
181channel_end (void *cls, const struct GNUNET_CADET_Channel *channel, 181channel_end (void *cls,
182 const struct GNUNET_CADET_Channel *channel,
182 void *channel_ctx) 183 void *channel_ctx)
183{ 184{
184 long id = (long) cls; 185 long id = (long) cls;
@@ -191,6 +192,8 @@ channel_end (void *cls, const struct GNUNET_CADET_Channel *channel,
191 GNUNET_CADET_notify_transmit_ready_cancel (mth); 192 GNUNET_CADET_notify_transmit_ready_cancel (mth);
192 mth = NULL; 193 mth = NULL;
193 } 194 }
195 if (channel == ch)
196 ch = NULL;
194 if (GNUNET_NO == got_data) 197 if (GNUNET_NO == got_data)
195 { 198 {
196 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( 199 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
diff --git a/src/consensus/consensus_api.c b/src/consensus/consensus_api.c
index 18898bebd..d5ed8db80 100644
--- a/src/consensus/consensus_api.c
+++ b/src/consensus/consensus_api.c
@@ -222,7 +222,7 @@ GNUNET_CONSENSUS_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
222 consensus->new_element_cb = new_element_cb; 222 consensus->new_element_cb = new_element_cb;
223 consensus->new_element_cls = new_element_cls; 223 consensus->new_element_cls = new_element_cls;
224 consensus->session_id = *session_id; 224 consensus->session_id = *session_id;
225 consensus->mq = GNUNET_CLIENT_connecT (cfg, 225 consensus->mq = GNUNET_CLIENT_connect (cfg,
226 "consensus", 226 "consensus",
227 mq_handlers, 227 mq_handlers,
228 &mq_error_handler, 228 &mq_error_handler,
diff --git a/src/conversation/conversation_api.c b/src/conversation/conversation_api.c
index 8a74f0ca6..0b3920633 100644
--- a/src/conversation/conversation_api.c
+++ b/src/conversation/conversation_api.c
@@ -584,7 +584,7 @@ reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
584 phone->mq = NULL; 584 phone->mq = NULL;
585 } 585 }
586 phone->state = PS_REGISTER; 586 phone->state = PS_REGISTER;
587 phone->mq = GNUNET_CLIENT_connecT (phone->cfg, 587 phone->mq = GNUNET_CLIENT_connect (phone->cfg,
588 "conversation", 588 "conversation",
589 handlers, 589 handlers,
590 &phone_error_handler, 590 &phone_error_handler,
diff --git a/src/conversation/conversation_api_call.c b/src/conversation/conversation_api_call.c
index 17e26465e..a6bc506bc 100644
--- a/src/conversation/conversation_api_call.c
+++ b/src/conversation/conversation_api_call.c
@@ -570,7 +570,7 @@ GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
570 }; 570 };
571 struct GNUNET_CRYPTO_EcdsaPublicKey my_zone; 571 struct GNUNET_CRYPTO_EcdsaPublicKey my_zone;
572 572
573 call->mq = GNUNET_CLIENT_connecT (cfg, 573 call->mq = GNUNET_CLIENT_connect (cfg,
574 "conversation", 574 "conversation",
575 handlers, 575 handlers,
576 &call_error_handler, 576 &call_error_handler,
diff --git a/src/core/.gitignore b/src/core/.gitignore
index 42b7030b3..cdd1f93c2 100644
--- a/src/core/.gitignore
+++ b/src/core/.gitignore
@@ -1,2 +1,9 @@
1gnunet-service-core 1gnunet-service-core
2gnunet-core 2gnunet-core
3test_core_api
4test_core_api_reliability
5test_core_api_send_to_self
6test_core_api_start_only
7test_core_quota_compliance_asymmetric_recv_limited
8test_core_quota_compliance_asymmetric_send_limited
9test_core_quota_compliance_symmetric
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index aea64fa34..ed80bae73 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -23,7 +23,6 @@ lib_LTLIBRARIES = \
23 23
24libgnunetcore_la_SOURCES = \ 24libgnunetcore_la_SOURCES = \
25 core_api.c core.h \ 25 core_api.c core.h \
26 core_api_2.c \
27 core_api_monitor_peers.c 26 core_api_monitor_peers.c
28libgnunetcore_la_LIBADD = \ 27libgnunetcore_la_LIBADD = \
29 $(top_builddir)/src/util/libgnunetutil.la \ 28 $(top_builddir)/src/util/libgnunetutil.la \
diff --git a/src/core/core_api.c b/src/core/core_api.c
index fda49e259..ace80b952 100644
--- a/src/core/core_api.c
+++ b/src/core/core_api.c
@@ -33,79 +33,32 @@
33 33
34 34
35/** 35/**
36 * Handle for a transmission request. 36 * Information we track for each peer.
37 */ 37 */
38struct GNUNET_CORE_TransmitHandle 38struct PeerRecord
39{ 39{
40 40
41 /** 41 /**
42 * Corresponding peer record. 42 * Corresponding CORE handle.
43 */
44 struct PeerRecord *peer;
45
46 /**
47 * Function that will be called to get the actual request
48 * (once we are ready to transmit this request to the core).
49 * The function will be called with a NULL buffer to signal
50 * timeout.
51 */
52 GNUNET_CONNECTION_TransmitReadyNotify get_message;
53
54 /**
55 * Closure for @e get_message.
56 */
57 void *get_message_cls;
58
59 /**
60 * Deadline for the transmission (the request does not get cancelled
61 * at this time, this is merely how soon the application wants this out).
62 */
63 struct GNUNET_TIME_Absolute deadline;
64
65 /**
66 * When did this request get queued?
67 */
68 struct GNUNET_TIME_Absolute request_time;
69
70 /**
71 * How important is this message?
72 */
73 enum GNUNET_CORE_Priority priority;
74
75 /**
76 * Is corking allowed?
77 */
78 int cork;
79
80 /**
81 * Size of this request.
82 */ 43 */
83 uint16_t msize; 44 struct GNUNET_CORE_Handle *h;
84 45
85 /** 46 /**
86 * Send message request ID for this request. 47 * Message queue for the peer.
87 */ 48 */
88 uint16_t smr_id; 49 struct GNUNET_MQ_Handle *mq;
89
90};
91
92
93/**
94 * Information we track for each peer.
95 */
96struct PeerRecord
97{
98 50
99 /** 51 /**
100 * Corresponding CORE handle. 52 * Message we are currently trying to pass to the CORE service
53 * for this peer (from @e mq).
101 */ 54 */
102 struct GNUNET_CORE_Handle *ch; 55 struct GNUNET_MQ_Envelope *env;
103 56
104 /** 57 /**
105 * Pending request, if any. 'th->peer' is set to NULL if the 58 * Value the client returned when we connected, used
106 * request is not active. 59 * as the closure in various places.
107 */ 60 */
108 struct GNUNET_CORE_TransmitHandle th; 61 void *client_cls;
109 62
110 /** 63 /**
111 * Peer the record is about. 64 * Peer the record is about.
@@ -152,19 +105,9 @@ struct GNUNET_CORE_Handle
152 GNUNET_CORE_DisconnectEventHandler disconnects; 105 GNUNET_CORE_DisconnectEventHandler disconnects;
153 106
154 /** 107 /**
155 * Function to call whenever we receive an inbound message.
156 */
157 GNUNET_CORE_MessageCallback inbound_notify;
158
159 /**
160 * Function to call whenever we receive an outbound message.
161 */
162 GNUNET_CORE_MessageCallback outbound_notify;
163
164 /**
165 * Function handlers for messages of particular type. 108 * Function handlers for messages of particular type.
166 */ 109 */
167 struct GNUNET_CORE_MessageHandler *handlers; 110 struct GNUNET_MQ_MessageHandler *handlers;
168 111
169 /** 112 /**
170 * Our message queue for transmissions to the service. 113 * Our message queue for transmissions to the service.
@@ -198,24 +141,6 @@ struct GNUNET_CORE_Handle
198 unsigned int hcnt; 141 unsigned int hcnt;
199 142
200 /** 143 /**
201 * For inbound notifications without a specific handler, do
202 * we expect to only receive headers?
203 */
204 int inbound_hdr_only;
205
206 /**
207 * For outbound notifications without a specific handler, do
208 * we expect to only receive headers?
209 */
210 int outbound_hdr_only;
211
212 /**
213 * Are we currently disconnected and hence unable to forward
214 * requests?
215 */
216 int currently_down;
217
218 /**
219 * Did we ever get INIT? 144 * Did we ever get INIT?
220 */ 145 */
221 int have_init; 146 int have_init;
@@ -266,25 +191,19 @@ disconnect_and_free_peer_entry (void *cls,
266 void *value) 191 void *value)
267{ 192{
268 struct GNUNET_CORE_Handle *h = cls; 193 struct GNUNET_CORE_Handle *h = cls;
269 struct GNUNET_CORE_TransmitHandle *th;
270 struct PeerRecord *pr = value; 194 struct PeerRecord *pr = value;
271 195
196 GNUNET_assert (pr->h == h);
272 if (NULL != h->disconnects) 197 if (NULL != h->disconnects)
273 h->disconnects (h->cls, 198 h->disconnects (h->cls,
274 &pr->peer); 199 &pr->peer,
275 /* all requests should have been cancelled, clean up anyway, just in case */ 200 pr->client_cls);
276 th = &pr->th;
277 if (NULL != th->peer)
278 {
279 GNUNET_break (0);
280 th->peer = NULL;
281 }
282 /* done with 'voluntary' cleanups, now on to normal freeing */
283 GNUNET_assert (GNUNET_YES == 201 GNUNET_assert (GNUNET_YES ==
284 GNUNET_CONTAINER_multipeermap_remove (h->peers, 202 GNUNET_CONTAINER_multipeermap_remove (h->peers,
285 key, 203 key,
286 pr)); 204 pr));
287 GNUNET_assert (pr->ch == h); 205 GNUNET_MQ_destroy (pr->mq);
206 GNUNET_assert (NULL == pr->mq);
288 GNUNET_free (pr); 207 GNUNET_free (pr);
289 return GNUNET_YES; 208 return GNUNET_YES;
290} 209}
@@ -305,8 +224,7 @@ reconnect_later (struct GNUNET_CORE_Handle *h)
305 GNUNET_MQ_destroy (h->mq); 224 GNUNET_MQ_destroy (h->mq);
306 h->mq = NULL; 225 h->mq = NULL;
307 } 226 }
308 h->currently_down = GNUNET_YES; 227 GNUNET_assert (NULL == h->reconnect_task);
309 GNUNET_assert (h->reconnect_task == NULL);
310 h->reconnect_task = 228 h->reconnect_task =
311 GNUNET_SCHEDULER_add_delayed (h->retry_backoff, 229 GNUNET_SCHEDULER_add_delayed (h->retry_backoff,
312 &reconnect_task, 230 &reconnect_task,
@@ -319,9 +237,8 @@ reconnect_later (struct GNUNET_CORE_Handle *h)
319 237
320 238
321/** 239/**
322 * Generic error handler, called with the appropriate error code and 240 * Error handler for the message queue to the CORE service.
323 * the same closure specified at the creation of the message queue. 241 * On errors, we reconnect.
324 * Not every message queue implementation supports an error handler.
325 * 242 *
326 * @param cls closure, a `struct GNUNET_CORE_Handle *` 243 * @param cls closure, a `struct GNUNET_CORE_Handle *`
327 * @param error error code 244 * @param error error code
@@ -340,6 +257,209 @@ handle_mq_error (void *cls,
340 257
341 258
342/** 259/**
260 * Inquire with CORE what options should be set for a message
261 * so that it is transmitted with the given @a priority and
262 * the given @a cork value.
263 *
264 * @param cork desired corking
265 * @param priority desired message priority
266 * @param[out] flags set to `flags` value for #GNUNET_MQ_set_options()
267 * @return `extra` argument to give to #GNUNET_MQ_set_options()
268 */
269const void *
270GNUNET_CORE_get_mq_options (int cork,
271 enum GNUNET_CORE_Priority priority,
272 uint64_t *flags)
273{
274 *flags = ((uint64_t) priority) + (((uint64_t) cork) << 32);
275 return NULL;
276}
277
278
279/**
280 * Implement sending functionality of a message queue for
281 * us sending messages to a peer.
282 *
283 * @param mq the message queue
284 * @param msg the message to send
285 * @param impl_state state of the implementation
286 */
287static void
288core_mq_send_impl (struct GNUNET_MQ_Handle *mq,
289 const struct GNUNET_MessageHeader *msg,
290 void *impl_state)
291{
292 struct PeerRecord *pr = impl_state;
293 struct GNUNET_CORE_Handle *h = pr->h;
294 struct SendMessageRequest *smr;
295 struct SendMessage *sm;
296 struct GNUNET_MQ_Envelope *env;
297 uint16_t msize;
298 uint64_t flags;
299 int cork;
300 enum GNUNET_CORE_Priority priority;
301
302 if (NULL == h->mq)
303 {
304 /* We're currently reconnecting, pretend this worked */
305 GNUNET_MQ_impl_send_continue (mq);
306 return;
307 }
308 GNUNET_assert (NULL == pr->env);
309 /* extract options from envelope */
310 env = GNUNET_MQ_get_current_envelope (mq);
311 GNUNET_break (NULL ==
312 GNUNET_MQ_env_get_options (env,
313 &flags));
314 cork = (int) (flags >> 32);
315 priority = (uint32_t) flags;
316
317 /* check message size for sanity */
318 msize = ntohs (msg->size);
319 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct SendMessage))
320 {
321 GNUNET_break (0);
322 GNUNET_MQ_impl_send_continue (mq);
323 return;
324 }
325
326 /* ask core for transmission */
327 LOG (GNUNET_ERROR_TYPE_DEBUG,
328 "Asking core for transmission of %u bytes to `%s'\n",
329 (unsigned int) msize,
330 GNUNET_i2s (&pr->peer));
331 env = GNUNET_MQ_msg (smr,
332 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
333 smr->priority = htonl ((uint32_t) priority);
334 // smr->deadline = GNUNET_TIME_absolute_hton (deadline);
335 smr->peer = pr->peer;
336 smr->reserved = htonl (0);
337 smr->size = htons (msize);
338 smr->smr_id = htons (++pr->smr_id_gen);
339 GNUNET_MQ_send (h->mq,
340 env);
341
342 /* prepare message with actual transmission data */
343 pr->env = GNUNET_MQ_msg_nested_mh (sm,
344 GNUNET_MESSAGE_TYPE_CORE_SEND,
345 msg);
346 sm->priority = htonl ((uint32_t) priority);
347 // sm->deadline = GNUNET_TIME_absolute_hton (deadline);
348 sm->peer = pr->peer;
349 sm->cork = htonl ((uint32_t) cork);
350 sm->reserved = htonl (0);
351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
352 "Calling get_message with buffer of %u bytes (%s)\n",
353 (unsigned int) msize,
354 cork ? "corked" : "uncorked");
355}
356
357
358/**
359 * Handle destruction of a message queue. Implementations must not
360 * free @a mq, but should take care of @a impl_state.
361 *
362 * @param mq the message queue to destroy
363 * @param impl_state state of the implementation
364 */
365static void
366core_mq_destroy_impl (struct GNUNET_MQ_Handle *mq,
367 void *impl_state)
368{
369 struct PeerRecord *pr = impl_state;
370
371 GNUNET_assert (mq == pr->mq);
372 pr->mq = NULL;
373}
374
375
376/**
377 * Implementation function that cancels the currently sent message.
378 * Should basically undo whatever #mq_send_impl() did.
379 *
380 * @param mq message queue
381 * @param impl_state state specific to the implementation
382 */
383static void
384core_mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
385 void *impl_state)
386{
387 struct PeerRecord *pr = impl_state;
388
389 GNUNET_assert (NULL != pr->env);
390 GNUNET_MQ_discard (pr->env);
391 pr->env = NULL;
392}
393
394
395/**
396 * We had an error processing a message we forwarded from a peer to
397 * the CORE service. We should just complain about it but otherwise
398 * continue processing.
399 *
400 * @param cls closure
401 * @param error error code
402 */
403static void
404core_mq_error_handler (void *cls,
405 enum GNUNET_MQ_Error error)
406{
407 /* struct PeerRecord *pr = cls; */
408
409 GNUNET_break_op (0);
410}
411
412
413/**
414 * Add the given peer to the list of our connected peers
415 * and create the respective data structures and notify
416 * the application.
417 *
418 * @param h the core handle
419 * @param peer the peer that is connecting to us
420 */
421static void
422connect_peer (struct GNUNET_CORE_Handle *h,
423 const struct GNUNET_PeerIdentity *peer)
424{
425 struct PeerRecord *pr;
426 uint64_t flags;
427 const void *extra;
428
429 pr = GNUNET_new (struct PeerRecord);
430 pr->peer = *peer;
431 pr->h = h;
432 GNUNET_assert (GNUNET_YES ==
433 GNUNET_CONTAINER_multipeermap_put (h->peers,
434 &pr->peer,
435 pr,
436 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
437 pr->mq = GNUNET_MQ_queue_for_callbacks (&core_mq_send_impl,
438 &core_mq_destroy_impl,
439 &core_mq_cancel_impl,
440 pr,
441 h->handlers,
442 &core_mq_error_handler,
443 pr);
444 /* get our default options */
445 extra = GNUNET_CORE_get_mq_options (GNUNET_NO,
446 GNUNET_CORE_PRIO_BEST_EFFORT,
447 &flags);
448 GNUNET_MQ_set_options (pr->mq,
449 flags,
450 extra);
451 if (NULL != h->connects)
452 {
453 pr->client_cls = h->connects (h->cls,
454 &pr->peer,
455 pr->mq);
456 GNUNET_MQ_set_handlers_closure (pr->mq,
457 pr->client_cls);
458 }
459}
460
461
462/**
343 * Handle init reply message received from CORE service. Notify 463 * Handle init reply message received from CORE service. Notify
344 * application that we are now connected to the CORE. Also fake 464 * application that we are now connected to the CORE. Also fake
345 * loopback connection. 465 * loopback connection.
@@ -353,11 +473,8 @@ handle_init_reply (void *cls,
353{ 473{
354 struct GNUNET_CORE_Handle *h = cls; 474 struct GNUNET_CORE_Handle *h = cls;
355 GNUNET_CORE_StartupCallback init; 475 GNUNET_CORE_StartupCallback init;
356 struct PeerRecord *pr;
357 476
358 GNUNET_break (0 == ntohl (m->reserved)); 477 GNUNET_break (0 == ntohl (m->reserved));
359 GNUNET_break (GNUNET_YES == h->currently_down);
360 h->currently_down = GNUNET_NO;
361 h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS; 478 h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
362 if (NULL != (init = h->init)) 479 if (NULL != (init = h->init))
363 { 480 {
@@ -388,17 +505,8 @@ handle_init_reply (void *cls,
388 } 505 }
389 } 506 }
390 /* fake 'connect to self' */ 507 /* fake 'connect to self' */
391 pr = GNUNET_new (struct PeerRecord); 508 connect_peer (h,
392 pr->peer = h->me; 509 &h->me);
393 pr->ch = h;
394 GNUNET_assert (GNUNET_YES ==
395 GNUNET_CONTAINER_multipeermap_put (h->peers,
396 &h->me,
397 pr,
398 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
399 if (NULL != h->connects)
400 h->connects (h->cls,
401 &pr->peer);
402} 510}
403 511
404 512
@@ -416,7 +524,6 @@ handle_connect_notify (void *cls,
416 struct GNUNET_CORE_Handle *h = cls; 524 struct GNUNET_CORE_Handle *h = cls;
417 struct PeerRecord *pr; 525 struct PeerRecord *pr;
418 526
419 GNUNET_break (GNUNET_NO == h->currently_down);
420 LOG (GNUNET_ERROR_TYPE_DEBUG, 527 LOG (GNUNET_ERROR_TYPE_DEBUG,
421 "Received notification about connection from `%s'.\n", 528 "Received notification about connection from `%s'.\n",
422 GNUNET_i2s (&cnm->peer)); 529 GNUNET_i2s (&cnm->peer));
@@ -436,17 +543,8 @@ handle_connect_notify (void *cls,
436 reconnect_later (h); 543 reconnect_later (h);
437 return; 544 return;
438 } 545 }
439 pr = GNUNET_new (struct PeerRecord); 546 connect_peer (h,
440 pr->peer = cnm->peer; 547 &cnm->peer);
441 pr->ch = h;
442 GNUNET_assert (GNUNET_YES ==
443 GNUNET_CONTAINER_multipeermap_put (h->peers,
444 &cnm->peer,
445 pr,
446 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
447 if (NULL != h->connects)
448 h->connects (h->cls,
449 &pr->peer);
450} 548}
451 549
452 550
@@ -459,17 +557,16 @@ handle_connect_notify (void *cls,
459 */ 557 */
460static void 558static void
461handle_disconnect_notify (void *cls, 559handle_disconnect_notify (void *cls,
462 const struct DisconnectNotifyMessage * dnm) 560 const struct DisconnectNotifyMessage *dnm)
463{ 561{
464 struct GNUNET_CORE_Handle *h = cls; 562 struct GNUNET_CORE_Handle *h = cls;
465 struct PeerRecord *pr; 563 struct PeerRecord *pr;
466 564
467 GNUNET_break (GNUNET_NO == h->currently_down);
468 if (0 == memcmp (&h->me, 565 if (0 == memcmp (&h->me,
469 &dnm->peer, 566 &dnm->peer,
470 sizeof (struct GNUNET_PeerIdentity))) 567 sizeof (struct GNUNET_PeerIdentity)))
471 { 568 {
472 /* connection to self!? */ 569 /* disconnect from self!? */
473 GNUNET_break (0); 570 GNUNET_break (0);
474 return; 571 return;
475 } 572 }
@@ -486,7 +583,7 @@ handle_disconnect_notify (void *cls,
486 return; 583 return;
487 } 584 }
488 disconnect_and_free_peer_entry (h, 585 disconnect_and_free_peer_entry (h,
489 &dnm->peer, 586 &pr->peer,
490 pr); 587 pr);
491} 588}
492 589
@@ -502,11 +599,9 @@ static int
502check_notify_inbound (void *cls, 599check_notify_inbound (void *cls,
503 const struct NotifyTrafficMessage *ntm) 600 const struct NotifyTrafficMessage *ntm)
504{ 601{
505 struct GNUNET_CORE_Handle *h = cls;
506 uint16_t msize; 602 uint16_t msize;
507 const struct GNUNET_MessageHeader *em; 603 const struct GNUNET_MessageHeader *em;
508 604
509 GNUNET_break (GNUNET_NO == h->currently_down);
510 msize = ntohs (ntm->header.size) - sizeof (struct NotifyTrafficMessage); 605 msize = ntohs (ntm->header.size) - sizeof (struct NotifyTrafficMessage);
511 if (msize < sizeof (struct GNUNET_MessageHeader)) 606 if (msize < sizeof (struct GNUNET_MessageHeader))
512 { 607 {
@@ -514,8 +609,7 @@ check_notify_inbound (void *cls,
514 return GNUNET_SYSERR; 609 return GNUNET_SYSERR;
515 } 610 }
516 em = (const struct GNUNET_MessageHeader *) &ntm[1]; 611 em = (const struct GNUNET_MessageHeader *) &ntm[1];
517 if ( (GNUNET_NO == h->inbound_hdr_only) && 612 if (msize != ntohs (em->size))
518 (msize != ntohs (em->size)) )
519 { 613 {
520 GNUNET_break (0); 614 GNUNET_break (0);
521 return GNUNET_SYSERR; 615 return GNUNET_SYSERR;
@@ -538,120 +632,21 @@ handle_notify_inbound (void *cls,
538 struct GNUNET_CORE_Handle *h = cls; 632 struct GNUNET_CORE_Handle *h = cls;
539 const struct GNUNET_MessageHeader *em; 633 const struct GNUNET_MessageHeader *em;
540 struct PeerRecord *pr; 634 struct PeerRecord *pr;
541 uint16_t et;
542 635
543 GNUNET_break (GNUNET_NO == h->currently_down);
544 em = (const struct GNUNET_MessageHeader *) &ntm[1];
545 et = ntohs (em->type);
546 LOG (GNUNET_ERROR_TYPE_DEBUG, 636 LOG (GNUNET_ERROR_TYPE_DEBUG,
547 "Received inbound message of type %d from `%s'.\n", 637 "Received inbound message from `%s'.\n",
548 (int) et,
549 GNUNET_i2s (&ntm->peer)); 638 GNUNET_i2s (&ntm->peer));
550 for (unsigned int hpos = 0; NULL != h->handlers[hpos].callback; hpos++)
551 {
552 const struct GNUNET_CORE_MessageHandler *mh;
553
554 mh = &h->handlers[hpos];
555 if (mh->type != et)
556 continue;
557 if ( (mh->expected_size != ntohs (em->size)) &&
558 (0 != mh->expected_size) )
559 {
560 LOG (GNUNET_ERROR_TYPE_ERROR,
561 "Unexpected message size %u for message of type %u from peer `%s'\n",
562 htons (em->size),
563 mh->type,
564 GNUNET_i2s (&ntm->peer));
565 GNUNET_break_op (0);
566 continue;
567 }
568 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
569 &ntm->peer);
570 if (NULL == pr)
571 {
572 GNUNET_break (0);
573 reconnect_later (h);
574 return;
575 }
576 if (GNUNET_OK !=
577 h->handlers[hpos].callback (h->cls,
578 &ntm->peer,
579 em))
580 {
581 /* error in processing, do not process other messages! */
582 break;
583 }
584 }
585 if (NULL != h->inbound_notify)
586 h->inbound_notify (h->cls,
587 &ntm->peer,
588 em);
589}
590
591
592/**
593 * Check that message received from CORE service is well-formed.
594 *
595 * @param cls the `struct GNUNET_CORE_Handle`
596 * @param ntm the message we got
597 * @return #GNUNET_OK if the message is well-formed
598 */
599static int
600check_notify_outbound (void *cls,
601 const struct NotifyTrafficMessage *ntm)
602{
603 struct GNUNET_CORE_Handle *h = cls;
604 uint16_t msize;
605 const struct GNUNET_MessageHeader *em;
606
607 GNUNET_break (GNUNET_NO == h->currently_down);
608 LOG (GNUNET_ERROR_TYPE_DEBUG,
609 "Received outbound message from `%s'.\n",
610 GNUNET_i2s (&ntm->peer));
611 msize = ntohs (ntm->header.size) - sizeof (struct NotifyTrafficMessage);
612 if (msize < sizeof (struct GNUNET_MessageHeader))
613 {
614 GNUNET_break (0);
615 return GNUNET_SYSERR;
616 }
617 em = (const struct GNUNET_MessageHeader *) &ntm[1];
618 if ( (GNUNET_NO == h->outbound_hdr_only) &&
619 (msize != ntohs (em->size)) )
620 {
621 GNUNET_break (0);
622 return GNUNET_SYSERR;
623 }
624 return GNUNET_OK;
625}
626
627
628/**
629 * Handle outbound message received from CORE service. If applicable,
630 * notify the application.
631 *
632 * @param cls the `struct GNUNET_CORE_Handle`
633 * @param ntm the message we got
634 */
635static void
636handle_notify_outbound (void *cls,
637 const struct NotifyTrafficMessage *ntm)
638{
639 struct GNUNET_CORE_Handle *h = cls;
640 const struct GNUNET_MessageHeader *em;
641
642 GNUNET_break (GNUNET_NO == h->currently_down);
643 em = (const struct GNUNET_MessageHeader *) &ntm[1]; 639 em = (const struct GNUNET_MessageHeader *) &ntm[1];
644 LOG (GNUNET_ERROR_TYPE_DEBUG, 640 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
645 "Received notification about transmission to `%s'.\n", 641 &ntm->peer);
646 GNUNET_i2s (&ntm->peer)); 642 if (NULL == pr)
647 if (NULL == h->outbound_notify)
648 { 643 {
649 GNUNET_break (0); 644 GNUNET_break (0);
645 reconnect_later (h);
650 return; 646 return;
651 } 647 }
652 h->outbound_notify (h->cls, 648 GNUNET_MQ_inject_message (pr->mq,
653 &ntm->peer, 649 em);
654 em);
655} 650}
656 651
657 652
@@ -661,7 +656,7 @@ handle_notify_outbound (void *cls,
661 * pending, put it into the queue to be transmitted. 656 * pending, put it into the queue to be transmitted.
662 * 657 *
663 * @param cls the `struct GNUNET_CORE_Handle` 658 * @param cls the `struct GNUNET_CORE_Handle`
664 * @param ntm the message we got 659 * @param smr the message we got
665 */ 660 */
666static void 661static void
667handle_send_ready (void *cls, 662handle_send_ready (void *cls,
@@ -669,16 +664,7 @@ handle_send_ready (void *cls,
669{ 664{
670 struct GNUNET_CORE_Handle *h = cls; 665 struct GNUNET_CORE_Handle *h = cls;
671 struct PeerRecord *pr; 666 struct PeerRecord *pr;
672 struct GNUNET_CORE_TransmitHandle *th;
673 struct SendMessage *sm;
674 struct GNUNET_MQ_Envelope *env;
675 struct GNUNET_TIME_Relative delay;
676 struct GNUNET_TIME_Relative overdue;
677 unsigned int ret;
678 unsigned int priority;
679 int cork;
680 667
681 GNUNET_break (GNUNET_NO == h->currently_down);
682 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, 668 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
683 &smr->peer); 669 &smr->peer);
684 if (NULL == pr) 670 if (NULL == pr)
@@ -690,72 +676,24 @@ handle_send_ready (void *cls,
690 LOG (GNUNET_ERROR_TYPE_DEBUG, 676 LOG (GNUNET_ERROR_TYPE_DEBUG,
691 "Received notification about transmission readiness to `%s'.\n", 677 "Received notification about transmission readiness to `%s'.\n",
692 GNUNET_i2s (&smr->peer)); 678 GNUNET_i2s (&smr->peer));
693 if (NULL == pr->th.peer) 679 if (NULL == pr->env)
694 { 680 {
695 /* request must have been cancelled between the original request 681 /* request must have been cancelled between the original request
696 * and the response from CORE, ignore CORE's readiness */ 682 * and the response from CORE, ignore CORE's readiness */
697 return; 683 return;
698 } 684 }
699 th = &pr->th; 685 if (ntohs (smr->smr_id) != pr->smr_id_gen)
700 if (ntohs (smr->smr_id) != th->smr_id)
701 { 686 {
702 /* READY message is for expired or cancelled message, 687 /* READY message is for expired or cancelled message,
703 * ignore! (we should have already sent another request) */ 688 * ignore! (we should have already sent another request) */
704 return; 689 return;
705 } 690 }
691
706 /* ok, all good, send message out! */ 692 /* ok, all good, send message out! */
707 th->peer = NULL;
708 env = GNUNET_MQ_msg_extra (sm,
709 th->msize,
710 GNUNET_MESSAGE_TYPE_CORE_SEND);
711 sm->priority = htonl ((uint32_t) th->priority);
712 sm->deadline = GNUNET_TIME_absolute_hton (th->deadline);
713 sm->peer = pr->peer;
714 sm->cork = htonl ((uint32_t) (cork = th->cork));
715 sm->reserved = htonl (0);
716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
717 "Calling get_message with buffer of %u bytes (%s)\n",
718 (unsigned int) th->msize,
719 cork ? "corked" : "uncorked");
720 /* FIXME: this is ugly and a bit brutal, but "get_message"
721 may call GNUNET_CORE_notify_transmit_ready() which
722 may call GNUNET_MQ_send() as well, and we MUST get this
723 message out before the next SEND_REQUEST. So we queue
724 it (even though incomplete) and then---relying on MQ being
725 nice and not actually touching 'env' until much later---
726 fill it afterwards. This is horrible style, and once
727 the core_api abandons GNUNET_CORE_notify_transmit_ready
728 in favor of an MQ-style API, this hack should no longer
729 be required */
730 GNUNET_MQ_send (h->mq, 693 GNUNET_MQ_send (h->mq,
731 env); 694 pr->env);
732 delay = GNUNET_TIME_absolute_get_duration (th->request_time); 695 pr->env = NULL;
733 overdue = GNUNET_TIME_absolute_get_duration (th->deadline); 696 GNUNET_MQ_impl_send_continue (pr->mq);
734 priority = th->priority;
735 ret = th->get_message (th->get_message_cls,
736 th->msize,
737 &sm[1]);
738 /* after this point, 'th' should not be used anymore, it
739 may now be about another message! */
740 sm->header.size = htons (ret + sizeof (struct SendMessage));
741 if (overdue.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
742 LOG (GNUNET_ERROR_TYPE_WARNING,
743 "Transmitting overdue %u bytes to `%s' at priority %u with %s delay %s\n",
744 ret,
745 GNUNET_i2s (&pr->peer),
746 priority,
747 GNUNET_STRINGS_relative_time_to_string (delay,
748 GNUNET_YES),
749 (cork) ? " (corked)" : " (uncorked)");
750 else
751 LOG (GNUNET_ERROR_TYPE_DEBUG,
752 "Transmitting %u bytes to `%s' at priority %u with %s delay %s\n",
753 ret,
754 GNUNET_i2s (&pr->peer),
755 priority,
756 GNUNET_STRINGS_relative_time_to_string (delay,
757 GNUNET_YES),
758 (cork) ? " (corked)" : " (uncorked)");
759} 697}
760 698
761 699
@@ -785,10 +723,6 @@ reconnect (struct GNUNET_CORE_Handle *h)
785 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND, 723 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND,
786 struct NotifyTrafficMessage, 724 struct NotifyTrafficMessage,
787 h), 725 h),
788 GNUNET_MQ_hd_var_size (notify_outbound,
789 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND,
790 struct NotifyTrafficMessage,
791 h),
792 GNUNET_MQ_hd_fixed_size (send_ready, 726 GNUNET_MQ_hd_fixed_size (send_ready,
793 GNUNET_MESSAGE_TYPE_CORE_SEND_READY, 727 GNUNET_MESSAGE_TYPE_CORE_SEND_READY,
794 struct SendMessageReady, 728 struct SendMessageReady,
@@ -797,12 +731,10 @@ reconnect (struct GNUNET_CORE_Handle *h)
797 }; 731 };
798 struct InitMessage *init; 732 struct InitMessage *init;
799 struct GNUNET_MQ_Envelope *env; 733 struct GNUNET_MQ_Envelope *env;
800 uint32_t opt;
801 uint16_t *ts; 734 uint16_t *ts;
802 735
803 GNUNET_assert (NULL == h->mq); 736 GNUNET_assert (NULL == h->mq);
804 GNUNET_assert (GNUNET_YES == h->currently_down); 737 h->mq = GNUNET_CLIENT_connect (h->cfg,
805 h->mq = GNUNET_CLIENT_connecT (h->cfg,
806 "core", 738 "core",
807 handlers, 739 handlers,
808 &handle_mq_error, 740 &handle_mq_error,
@@ -815,25 +747,9 @@ reconnect (struct GNUNET_CORE_Handle *h)
815 env = GNUNET_MQ_msg_extra (init, 747 env = GNUNET_MQ_msg_extra (init,
816 sizeof (uint16_t) * h->hcnt, 748 sizeof (uint16_t) * h->hcnt,
817 GNUNET_MESSAGE_TYPE_CORE_INIT); 749 GNUNET_MESSAGE_TYPE_CORE_INIT);
818 opt = GNUNET_CORE_OPTION_NOTHING;
819 if (NULL != h->inbound_notify)
820 {
821 if (h->inbound_hdr_only)
822 opt |= GNUNET_CORE_OPTION_SEND_HDR_INBOUND;
823 else
824 opt |= GNUNET_CORE_OPTION_SEND_FULL_INBOUND;
825 }
826 if (NULL != h->outbound_notify)
827 {
828 if (h->outbound_hdr_only)
829 opt |= GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND;
830 else
831 opt |= GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND;
832 }
833 LOG (GNUNET_ERROR_TYPE_INFO, 750 LOG (GNUNET_ERROR_TYPE_INFO,
834 "(Re)connecting to CORE service, monitoring messages of type %u\n", 751 "(Re)connecting to CORE service\n");
835 opt); 752 init->options = htonl (0);
836 init->options = htonl (opt);
837 ts = (uint16_t *) &init[1]; 753 ts = (uint16_t *) &init[1];
838 for (unsigned int hpos = 0; hpos < h->hcnt; hpos++) 754 for (unsigned int hpos = 0; hpos < h->hcnt; hpos++)
839 ts[hpos] = htons (h->handlers[hpos].type); 755 ts[hpos] = htons (h->handlers[hpos].type);
@@ -852,14 +768,6 @@ reconnect (struct GNUNET_CORE_Handle *h)
852 * connected to the core service 768 * connected to the core service
853 * @param connects function to call on peer connect, can be NULL 769 * @param connects function to call on peer connect, can be NULL
854 * @param disconnects function to call on peer disconnect / timeout, can be NULL 770 * @param disconnects function to call on peer disconnect / timeout, can be NULL
855 * @param inbound_notify function to call for all inbound messages, can be NULL
856 * @param inbound_hdr_only set to #GNUNET_YES if inbound_notify will only read the
857 * GNUNET_MessageHeader and hence we do not need to give it the full message;
858 * can be used to improve efficiency, ignored if @a inbound_notify is NULL
859 * @param outbound_notify function to call for all outbound messages, can be NULL
860 * @param outbound_hdr_only set to #GNUNET_YES if outbound_notify will only read the
861 * GNUNET_MessageHeader and hence we do not need to give it the full message
862 * can be used to improve efficiency, ignored if @a outbound_notify is NULL
863 * @param handlers callbacks for messages we care about, NULL-terminated 771 * @param handlers callbacks for messages we care about, NULL-terminated
864 * @return handle to the core service (only useful for disconnect until @a init is called); 772 * @return handle to the core service (only useful for disconnect until @a init is called);
865 * NULL on error (in this case, init is never called) 773 * NULL on error (in this case, init is never called)
@@ -870,11 +778,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
870 GNUNET_CORE_StartupCallback init, 778 GNUNET_CORE_StartupCallback init,
871 GNUNET_CORE_ConnectEventHandler connects, 779 GNUNET_CORE_ConnectEventHandler connects,
872 GNUNET_CORE_DisconnectEventHandler disconnects, 780 GNUNET_CORE_DisconnectEventHandler disconnects,
873 GNUNET_CORE_MessageCallback inbound_notify, 781 const struct GNUNET_MQ_MessageHandler *handlers)
874 int inbound_hdr_only,
875 GNUNET_CORE_MessageCallback outbound_notify,
876 int outbound_hdr_only,
877 const struct GNUNET_CORE_MessageHandler *handlers)
878{ 782{
879 struct GNUNET_CORE_Handle *h; 783 struct GNUNET_CORE_Handle *h;
880 unsigned int hcnt; 784 unsigned int hcnt;
@@ -885,22 +789,18 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
885 h->init = init; 789 h->init = init;
886 h->connects = connects; 790 h->connects = connects;
887 h->disconnects = disconnects; 791 h->disconnects = disconnects;
888 h->inbound_notify = inbound_notify; 792 h->peers = GNUNET_CONTAINER_multipeermap_create (128,
889 h->outbound_notify = outbound_notify; 793 GNUNET_NO);
890 h->inbound_hdr_only = inbound_hdr_only;
891 h->outbound_hdr_only = outbound_hdr_only;
892 h->currently_down = GNUNET_YES;
893 h->peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
894 hcnt = 0; 794 hcnt = 0;
895 if (NULL != handlers) 795 if (NULL != handlers)
896 while (NULL != handlers[hcnt].callback) 796 while (NULL != handlers[hcnt].cb)
897 hcnt++; 797 hcnt++;
898 h->handlers = GNUNET_new_array (hcnt + 1, 798 h->handlers = GNUNET_new_array (hcnt + 1,
899 struct GNUNET_CORE_MessageHandler); 799 struct GNUNET_MQ_MessageHandler);
900 if (NULL != handlers) 800 if (NULL != handlers)
901 GNUNET_memcpy (h->handlers, 801 GNUNET_memcpy (h->handlers,
902 handlers, 802 handlers,
903 hcnt * sizeof (struct GNUNET_CORE_MessageHandler)); 803 hcnt * sizeof (struct GNUNET_MQ_MessageHandler));
904 h->hcnt = hcnt; 804 h->hcnt = hcnt;
905 GNUNET_assert (hcnt < 805 GNUNET_assert (hcnt <
906 (GNUNET_SERVER_MAX_MESSAGE_SIZE - 806 (GNUNET_SERVER_MAX_MESSAGE_SIZE -
@@ -918,9 +818,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
918 818
919 819
920/** 820/**
921 * Disconnect from the core service. This function can only 821 * Disconnect from the core service.
922 * be called *after* all pending #GNUNET_CORE_notify_transmit_ready()
923 * requests have been explicitly canceled.
924 * 822 *
925 * @param handle connection to core to disconnect 823 * @param handle connection to core to disconnect
926 */ 824 */
@@ -950,148 +848,23 @@ GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
950 848
951 849
952/** 850/**
953 * Ask the core to call @a notify once it is ready to transmit the 851 * Obtain the message queue for a connected peer.
954 * given number of bytes to the specified @a target. Must only be
955 * called after a connection to the respective peer has been
956 * established (and the client has been informed about this). You may
957 * have one request of this type pending for each connected peer at
958 * any time. If a peer disconnects, the application MUST call
959 * #GNUNET_CORE_notify_transmit_ready_cancel on the respective
960 * transmission request, if one such request is pending.
961 * 852 *
962 * @param handle connection to core service 853 * @param h the core handle
963 * @param cork is corking allowed for this transmission? 854 * @param pid the identity of the peer to check if it has been connected to us
964 * @param priority how important is the message? 855 * @return NULL if peer is not connected
965 * @param maxdelay how long can the message wait? Only effective if @a cork is #GNUNET_YES
966 * @param target who should receive the message, never NULL (can be this peer's identity for loopback)
967 * @param notify_size how many bytes of buffer space does @a notify want?
968 * @param notify function to call when buffer space is available;
969 * will be called with NULL on timeout; clients MUST cancel
970 * all pending transmission requests DURING the disconnect
971 * handler
972 * @param notify_cls closure for @a notify
973 * @return non-NULL if the notify callback was queued,
974 * NULL if we can not even queue the request (request already pending);
975 * if NULL is returned, @a notify will NOT be called.
976 */ 856 */
977struct GNUNET_CORE_TransmitHandle * 857struct GNUNET_MQ_Handle *
978GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, 858GNUNET_CORE_get_mq (const struct GNUNET_CORE_Handle *h,
979 int cork, 859 const struct GNUNET_PeerIdentity *pid)
980 enum GNUNET_CORE_Priority priority,
981 struct GNUNET_TIME_Relative maxdelay,
982 const struct GNUNET_PeerIdentity *target,
983 size_t notify_size,
984 GNUNET_CONNECTION_TransmitReadyNotify notify,
985 void *notify_cls)
986{ 860{
987 struct PeerRecord *pr; 861 struct PeerRecord *pr;
988 struct GNUNET_CORE_TransmitHandle *th;
989 struct SendMessageRequest *smr;
990 struct GNUNET_MQ_Envelope *env;
991 862
992 if (NULL == handle->mq) 863 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
993 { 864 pid);
994 GNUNET_break (0); /* SEE #4588: do not call NTR from disconnect notification! */
995 return NULL;
996 }
997 GNUNET_assert (NULL != notify);
998 if ( (notify_size > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) ||
999 (notify_size + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) )
1000 {
1001 GNUNET_break (0);
1002 return NULL;
1003 }
1004 LOG (GNUNET_ERROR_TYPE_DEBUG,
1005 "Asking core for transmission of %u bytes to `%s'%s\n",
1006 (unsigned int) notify_size,
1007 GNUNET_i2s (target),
1008 cork ? " (corked)" : "");
1009 pr = GNUNET_CONTAINER_multipeermap_get (handle->peers,
1010 target);
1011 if (NULL == pr) 865 if (NULL == pr)
1012 {
1013 /* attempt to send to peer that is not connected */
1014 GNUNET_break (0);
1015 return NULL; 866 return NULL;
1016 } 867 return pr->mq;
1017 if (NULL != pr->th.peer)
1018 {
1019 /* attempting to queue a second request for the same destination */
1020 GNUNET_break (0);
1021 return NULL;
1022 }
1023 th = &pr->th;
1024 memset (th,
1025 0,
1026 sizeof (struct GNUNET_CORE_TransmitHandle));
1027 th->peer = pr;
1028 th->get_message = notify;
1029 th->get_message_cls = notify_cls;
1030 th->request_time = GNUNET_TIME_absolute_get ();
1031 if (GNUNET_YES == cork)
1032 th->deadline = GNUNET_TIME_relative_to_absolute (maxdelay);
1033 else
1034 th->deadline = th->request_time;
1035 th->priority = priority;
1036 th->msize = notify_size;
1037 th->cork = cork;
1038 if (NULL == handle->mq)
1039 return th; /* see #4588 (hack until we transition core fully to MQ) */
1040 env = GNUNET_MQ_msg (smr,
1041 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
1042 smr->priority = htonl ((uint32_t) th->priority);
1043 smr->deadline = GNUNET_TIME_absolute_hton (th->deadline);
1044 smr->peer = pr->peer;
1045 smr->reserved = htonl (0);
1046 smr->size = htons (th->msize);
1047 smr->smr_id = htons (th->smr_id = pr->smr_id_gen++);
1048 GNUNET_MQ_send (handle->mq,
1049 env);
1050 LOG (GNUNET_ERROR_TYPE_DEBUG,
1051 "Transmission request added to queue\n");
1052 return th;
1053}
1054
1055
1056/**
1057 * Cancel the specified transmission-ready notification.
1058 *
1059 * @param th handle that was returned by #GNUNET_CORE_notify_transmit_ready().
1060 */
1061void
1062GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle *th)
1063{
1064 struct PeerRecord *pr = th->peer;
1065
1066 LOG (GNUNET_ERROR_TYPE_DEBUG,
1067 "Aborting transmission request to core for %u bytes to `%s'\n",
1068 (unsigned int) th->msize,
1069 GNUNET_i2s (&pr->peer));
1070 th->peer = NULL;
1071}
1072
1073
1074/**
1075 * Check if the given peer is currently connected. This function is for special
1076 * cirumstances (GNUNET_TESTBED uses it), normal users of the CORE API are
1077 * expected to track which peers are connected based on the connect/disconnect
1078 * callbacks from #GNUNET_CORE_connect(). This function is NOT part of the
1079 * 'versioned', 'official' API. The difference between this function and the
1080 * function GNUNET_CORE_is_peer_connected() is that this one returns
1081 * synchronously after looking in the CORE API cache. The function
1082 * GNUNET_CORE_is_peer_connected() sends a message to the CORE service and hence
1083 * its response is given asynchronously.
1084 *
1085 * @param h the core handle
1086 * @param pid the identity of the peer to check if it has been connected to us
1087 * @return #GNUNET_YES if the peer is connected to us; #GNUNET_NO if not
1088 */
1089int
1090GNUNET_CORE_is_peer_connected_sync (const struct GNUNET_CORE_Handle *h,
1091 const struct GNUNET_PeerIdentity *pid)
1092{
1093 return GNUNET_CONTAINER_multipeermap_contains (h->peers,
1094 pid);
1095} 868}
1096 869
1097 870
diff --git a/src/core/core_api_2.c b/src/core/core_api_2.c
deleted file mode 100644
index d810bf2ec..000000000
--- a/src/core/core_api_2.c
+++ /dev/null
@@ -1,865 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file core/core_api_2.c
22 * @brief core service; this is the main API for encrypted P2P
23 * communications
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_core_service.h"
30#include "core.h"
31
32#define LOG(kind,...) GNUNET_log_from (kind, "core-api",__VA_ARGS__)
33
34
35/**
36 * Information we track for each peer.
37 */
38struct PeerRecord
39{
40
41 /**
42 * Corresponding CORE handle.
43 */
44 struct GNUNET_CORE_Handle *h;
45
46 /**
47 * Message queue for the peer.
48 */
49 struct GNUNET_MQ_Handle *mq;
50
51 /**
52 * Message we are currently trying to pass to the CORE service
53 * for this peer (from @e mq).
54 */
55 struct GNUNET_MQ_Envelope *env;
56
57 /**
58 * Value the client returned when we connected, used
59 * as the closure in various places.
60 */
61 void *client_cls;
62
63 /**
64 * Peer the record is about.
65 */
66 struct GNUNET_PeerIdentity peer;
67
68 /**
69 * SendMessageRequest ID generator for this peer.
70 */
71 uint16_t smr_id_gen;
72
73};
74
75
76/**
77 * Context for the core service connection.
78 */
79struct GNUNET_CORE_Handle
80{
81
82 /**
83 * Configuration we're using.
84 */
85 const struct GNUNET_CONFIGURATION_Handle *cfg;
86
87 /**
88 * Closure for the various callbacks.
89 */
90 void *cls;
91
92 /**
93 * Function to call once we've handshaked with the core service.
94 */
95 GNUNET_CORE_StartupCallback init;
96
97 /**
98 * Function to call whenever we're notified about a peer connecting.
99 */
100 GNUNET_CORE_ConnecTEventHandler connects;
101
102 /**
103 * Function to call whenever we're notified about a peer disconnecting.
104 */
105 GNUNET_CORE_DisconnecTEventHandler disconnects;
106
107 /**
108 * Function handlers for messages of particular type.
109 */
110 struct GNUNET_MQ_MessageHandler *handlers;
111
112 /**
113 * Our message queue for transmissions to the service.
114 */
115 struct GNUNET_MQ_Handle *mq;
116
117 /**
118 * Hash map listing all of the peers that we are currently
119 * connected to.
120 */
121 struct GNUNET_CONTAINER_MultiPeerMap *peers;
122
123 /**
124 * Identity of this peer.
125 */
126 struct GNUNET_PeerIdentity me;
127
128 /**
129 * ID of reconnect task (if any).
130 */
131 struct GNUNET_SCHEDULER_Task *reconnect_task;
132
133 /**
134 * Current delay we use for re-trying to connect to core.
135 */
136 struct GNUNET_TIME_Relative retry_backoff;
137
138 /**
139 * Number of entries in the handlers array.
140 */
141 unsigned int hcnt;
142
143 /**
144 * Did we ever get INIT?
145 */
146 int have_init;
147
148};
149
150
151/**
152 * Our current client connection went down. Clean it up
153 * and try to reconnect!
154 *
155 * @param h our handle to the core service
156 */
157static void
158reconnect (struct GNUNET_CORE_Handle *h);
159
160
161/**
162 * Task schedule to try to re-connect to core.
163 *
164 * @param cls the `struct GNUNET_CORE_Handle`
165 * @param tc task context
166 */
167static void
168reconnect_task (void *cls)
169{
170 struct GNUNET_CORE_Handle *h = cls;
171
172 h->reconnect_task = NULL;
173 LOG (GNUNET_ERROR_TYPE_DEBUG,
174 "Connecting to CORE service after delay\n");
175 reconnect (h);
176}
177
178
179/**
180 * Notify clients about disconnect and free the entry for connected
181 * peer.
182 *
183 * @param cls the `struct GNUNET_CORE_Handle *`
184 * @param key the peer identity (not used)
185 * @param value the `struct PeerRecord` to free.
186 * @return #GNUNET_YES (continue)
187 */
188static int
189disconnect_and_free_peer_entry (void *cls,
190 const struct GNUNET_PeerIdentity *key,
191 void *value)
192{
193 struct GNUNET_CORE_Handle *h = cls;
194 struct PeerRecord *pr = value;
195
196 GNUNET_assert (pr->h == h);
197 if (NULL != h->disconnects)
198 h->disconnects (h->cls,
199 &pr->peer,
200 pr->client_cls);
201 GNUNET_assert (GNUNET_YES ==
202 GNUNET_CONTAINER_multipeermap_remove (h->peers,
203 key,
204 pr));
205 GNUNET_MQ_destroy (pr->mq);
206 GNUNET_assert (NULL == pr->mq);
207 GNUNET_free (pr);
208 return GNUNET_YES;
209}
210
211
212/**
213 * Close down any existing connection to the CORE service and
214 * try re-establishing it later.
215 *
216 * @param h our handle
217 */
218static void
219reconnect_later (struct GNUNET_CORE_Handle *h)
220{
221 GNUNET_assert (NULL == h->reconnect_task);
222 if (NULL != h->mq)
223 {
224 GNUNET_MQ_destroy (h->mq);
225 h->mq = NULL;
226 }
227 GNUNET_assert (NULL == h->reconnect_task);
228 h->reconnect_task =
229 GNUNET_SCHEDULER_add_delayed (h->retry_backoff,
230 &reconnect_task,
231 h);
232 GNUNET_CONTAINER_multipeermap_iterate (h->peers,
233 &disconnect_and_free_peer_entry,
234 h);
235 h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff);
236}
237
238
239/**
240 * Error handler for the message queue to the CORE service.
241 * On errors, we reconnect.
242 *
243 * @param cls closure, a `struct GNUNET_CORE_Handle *`
244 * @param error error code
245 */
246static void
247handle_mq_error (void *cls,
248 enum GNUNET_MQ_Error error)
249{
250 struct GNUNET_CORE_Handle *h = cls;
251
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "MQ ERROR: %d\n",
254 error);
255 reconnect_later (h);
256}
257
258
259/**
260 * Inquire with CORE what options should be set for a message
261 * so that it is transmitted with the given @a priority and
262 * the given @a cork value.
263 *
264 * @param cork desired corking
265 * @param priority desired message priority
266 * @param[out] flags set to `flags` value for #GNUNET_MQ_set_options()
267 * @return `extra` argument to give to #GNUNET_MQ_set_options()
268 */
269const void *
270GNUNET_CORE_get_mq_options (int cork,
271 enum GNUNET_CORE_Priority priority,
272 uint64_t *flags)
273{
274 *flags = ((uint64_t) priority) + (((uint64_t) cork) << 32);
275 return NULL;
276}
277
278
279/**
280 * Implement sending functionality of a message queue for
281 * us sending messages to a peer.
282 *
283 * @param mq the message queue
284 * @param msg the message to send
285 * @param impl_state state of the implementation
286 */
287static void
288core_mq_send_impl (struct GNUNET_MQ_Handle *mq,
289 const struct GNUNET_MessageHeader *msg,
290 void *impl_state)
291{
292 struct PeerRecord *pr = impl_state;
293 struct GNUNET_CORE_Handle *h = pr->h;
294 struct SendMessageRequest *smr;
295 struct SendMessage *sm;
296 struct GNUNET_MQ_Envelope *env;
297 uint16_t msize;
298 uint64_t flags;
299 int cork;
300 enum GNUNET_CORE_Priority priority;
301
302 GNUNET_assert (NULL == pr->env);
303 /* extract options from envelope */
304 env = GNUNET_MQ_get_current_envelope (mq);
305 GNUNET_break (NULL ==
306 GNUNET_MQ_env_get_options (env,
307 &flags));
308 cork = (int) (flags >> 32);
309 priority = (uint32_t) flags;
310
311 /* check message size for sanity */
312 msize = ntohs (msg->size);
313 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct SendMessage))
314 {
315 GNUNET_break (0);
316 GNUNET_MQ_impl_send_continue (mq);
317 return;
318 }
319
320 /* ask core for transmission */
321 LOG (GNUNET_ERROR_TYPE_DEBUG,
322 "Asking core for transmission of %u bytes to `%s'\n",
323 (unsigned int) msize,
324 GNUNET_i2s (&pr->peer));
325 env = GNUNET_MQ_msg (smr,
326 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
327 smr->priority = htonl ((uint32_t) priority);
328 // smr->deadline = GNUNET_TIME_absolute_hton (deadline);
329 smr->peer = pr->peer;
330 smr->reserved = htonl (0);
331 smr->size = htons (msize);
332 smr->smr_id = htons (++pr->smr_id_gen);
333 GNUNET_MQ_send (h->mq,
334 env);
335
336 /* prepare message with actual transmission data */
337 pr->env = GNUNET_MQ_msg_nested_mh (sm,
338 GNUNET_MESSAGE_TYPE_CORE_SEND,
339 msg);
340 sm->priority = htonl ((uint32_t) priority);
341 // sm->deadline = GNUNET_TIME_absolute_hton (deadline);
342 sm->peer = pr->peer;
343 sm->cork = htonl ((uint32_t) cork);
344 sm->reserved = htonl (0);
345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
346 "Calling get_message with buffer of %u bytes (%s)\n",
347 (unsigned int) msize,
348 cork ? "corked" : "uncorked");
349}
350
351
352/**
353 * Handle destruction of a message queue. Implementations must not
354 * free @a mq, but should take care of @a impl_state.
355 *
356 * @param mq the message queue to destroy
357 * @param impl_state state of the implementation
358 */
359static void
360core_mq_destroy_impl (struct GNUNET_MQ_Handle *mq,
361 void *impl_state)
362{
363 struct PeerRecord *pr = impl_state;
364
365 GNUNET_assert (mq == pr->mq);
366 pr->mq = NULL;
367}
368
369
370/**
371 * Implementation function that cancels the currently sent message.
372 * Should basically undo whatever #mq_send_impl() did.
373 *
374 * @param mq message queue
375 * @param impl_state state specific to the implementation
376 */
377static void
378core_mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
379 void *impl_state)
380{
381 struct PeerRecord *pr = impl_state;
382
383 GNUNET_assert (NULL != pr->env);
384 GNUNET_MQ_discard (pr->env);
385 pr->env = NULL;
386}
387
388
389/**
390 * We had an error processing a message we forwarded from a peer to
391 * the CORE service. We should just complain about it but otherwise
392 * continue processing.
393 *
394 * @param cls closure
395 * @param error error code
396 */
397static void
398core_mq_error_handler (void *cls,
399 enum GNUNET_MQ_Error error)
400{
401 /* struct PeerRecord *pr = cls; */
402
403 GNUNET_break_op (0);
404}
405
406
407/**
408 * Add the given peer to the list of our connected peers
409 * and create the respective data structures and notify
410 * the application.
411 *
412 * @param h the core handle
413 * @param peer the peer that is connecting to us
414 */
415static void
416connect_peer (struct GNUNET_CORE_Handle *h,
417 const struct GNUNET_PeerIdentity *peer)
418{
419 struct PeerRecord *pr;
420 uint64_t flags;
421 const void *extra;
422
423 pr = GNUNET_new (struct PeerRecord);
424 pr->peer = *peer;
425 pr->h = h;
426 GNUNET_assert (GNUNET_YES ==
427 GNUNET_CONTAINER_multipeermap_put (h->peers,
428 &pr->peer,
429 pr,
430 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
431 pr->mq = GNUNET_MQ_queue_for_callbacks (&core_mq_send_impl,
432 &core_mq_destroy_impl,
433 &core_mq_cancel_impl,
434 pr,
435 h->handlers,
436 &core_mq_error_handler,
437 pr);
438 /* get our default options */
439 extra = GNUNET_CORE_get_mq_options (GNUNET_NO,
440 GNUNET_CORE_PRIO_BEST_EFFORT,
441 &flags);
442 GNUNET_MQ_set_options (pr->mq,
443 flags,
444 extra);
445 if (NULL != h->connects)
446 {
447 pr->client_cls = h->connects (h->cls,
448 &pr->peer,
449 pr->mq);
450 GNUNET_MQ_set_handlers_closure (pr->mq,
451 pr->client_cls);
452 }
453}
454
455
456/**
457 * Handle init reply message received from CORE service. Notify
458 * application that we are now connected to the CORE. Also fake
459 * loopback connection.
460 *
461 * @param cls the `struct GNUNET_CORE_Handle`
462 * @param m the init reply
463 */
464static void
465handle_init_reply (void *cls,
466 const struct InitReplyMessage *m)
467{
468 struct GNUNET_CORE_Handle *h = cls;
469 GNUNET_CORE_StartupCallback init;
470
471 GNUNET_break (0 == ntohl (m->reserved));
472 h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
473 if (NULL != (init = h->init))
474 {
475 /* mark so we don't call init on reconnect */
476 h->init = NULL;
477 h->me = m->my_identity;
478 LOG (GNUNET_ERROR_TYPE_DEBUG,
479 "Connected to core service of peer `%s'.\n",
480 GNUNET_i2s (&h->me));
481 h->have_init = GNUNET_YES;
482 init (h->cls,
483 &h->me);
484 }
485 else
486 {
487 LOG (GNUNET_ERROR_TYPE_DEBUG,
488 "Successfully reconnected to core service.\n");
489 if (GNUNET_NO == h->have_init)
490 {
491 h->me = m->my_identity;
492 h->have_init = GNUNET_YES;
493 }
494 else
495 {
496 GNUNET_break (0 == memcmp (&h->me,
497 &m->my_identity,
498 sizeof (struct GNUNET_PeerIdentity)));
499 }
500 }
501 /* fake 'connect to self' */
502 connect_peer (h,
503 &h->me);
504}
505
506
507/**
508 * Handle connect message received from CORE service.
509 * Notify the application about the new connection.
510 *
511 * @param cls the `struct GNUNET_CORE_Handle`
512 * @param cnm the connect message
513 */
514static void
515handle_connect_notify (void *cls,
516 const struct ConnectNotifyMessage *cnm)
517{
518 struct GNUNET_CORE_Handle *h = cls;
519 struct PeerRecord *pr;
520
521 LOG (GNUNET_ERROR_TYPE_DEBUG,
522 "Received notification about connection from `%s'.\n",
523 GNUNET_i2s (&cnm->peer));
524 if (0 == memcmp (&h->me,
525 &cnm->peer,
526 sizeof (struct GNUNET_PeerIdentity)))
527 {
528 /* connect to self!? */
529 GNUNET_break (0);
530 return;
531 }
532 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
533 &cnm->peer);
534 if (NULL != pr)
535 {
536 GNUNET_break (0);
537 reconnect_later (h);
538 return;
539 }
540 connect_peer (h,
541 &cnm->peer);
542}
543
544
545/**
546 * Handle disconnect message received from CORE service.
547 * Notify the application about the lost connection.
548 *
549 * @param cls the `struct GNUNET_CORE_Handle`
550 * @param dnm message about the disconnect event
551 */
552static void
553handle_disconnect_notify (void *cls,
554 const struct DisconnectNotifyMessage *dnm)
555{
556 struct GNUNET_CORE_Handle *h = cls;
557 struct PeerRecord *pr;
558
559 if (0 == memcmp (&h->me,
560 &dnm->peer,
561 sizeof (struct GNUNET_PeerIdentity)))
562 {
563 /* disconnect from self!? */
564 GNUNET_break (0);
565 return;
566 }
567 GNUNET_break (0 == ntohl (dnm->reserved));
568 LOG (GNUNET_ERROR_TYPE_DEBUG,
569 "Received notification about disconnect from `%s'.\n",
570 GNUNET_i2s (&dnm->peer));
571 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
572 &dnm->peer);
573 if (NULL == pr)
574 {
575 GNUNET_break (0);
576 reconnect_later (h);
577 return;
578 }
579 disconnect_and_free_peer_entry (h,
580 &pr->peer,
581 pr);
582}
583
584
585/**
586 * Check that message received from CORE service is well-formed.
587 *
588 * @param cls the `struct GNUNET_CORE_Handle`
589 * @param ntm the message we got
590 * @return #GNUNET_OK if the message is well-formed
591 */
592static int
593check_notify_inbound (void *cls,
594 const struct NotifyTrafficMessage *ntm)
595{
596 uint16_t msize;
597 const struct GNUNET_MessageHeader *em;
598
599 msize = ntohs (ntm->header.size) - sizeof (struct NotifyTrafficMessage);
600 if (msize < sizeof (struct GNUNET_MessageHeader))
601 {
602 GNUNET_break (0);
603 return GNUNET_SYSERR;
604 }
605 em = (const struct GNUNET_MessageHeader *) &ntm[1];
606 if (msize != ntohs (em->size))
607 {
608 GNUNET_break (0);
609 return GNUNET_SYSERR;
610 }
611 return GNUNET_OK;
612}
613
614
615/**
616 * Handle inbound message received from CORE service. If applicable,
617 * notify the application.
618 *
619 * @param cls the `struct GNUNET_CORE_Handle`
620 * @param ntm the message we got from CORE.
621 */
622static void
623handle_notify_inbound (void *cls,
624 const struct NotifyTrafficMessage *ntm)
625{
626 struct GNUNET_CORE_Handle *h = cls;
627 const struct GNUNET_MessageHeader *em;
628 struct PeerRecord *pr;
629
630 LOG (GNUNET_ERROR_TYPE_DEBUG,
631 "Received inbound message from `%s'.\n",
632 GNUNET_i2s (&ntm->peer));
633 em = (const struct GNUNET_MessageHeader *) &ntm[1];
634 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
635 &ntm->peer);
636 if (NULL == pr)
637 {
638 GNUNET_break (0);
639 reconnect_later (h);
640 return;
641 }
642 GNUNET_MQ_inject_message (pr->mq,
643 em);
644}
645
646
647/**
648 * Handle message received from CORE service notifying us that we are
649 * now allowed to send a message to a peer. If that message is still
650 * pending, put it into the queue to be transmitted.
651 *
652 * @param cls the `struct GNUNET_CORE_Handle`
653 * @param smr the message we got
654 */
655static void
656handle_send_ready (void *cls,
657 const struct SendMessageReady *smr)
658{
659 struct GNUNET_CORE_Handle *h = cls;
660 struct PeerRecord *pr;
661
662 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
663 &smr->peer);
664 if (NULL == pr)
665 {
666 GNUNET_break (0);
667 reconnect_later (h);
668 return;
669 }
670 LOG (GNUNET_ERROR_TYPE_DEBUG,
671 "Received notification about transmission readiness to `%s'.\n",
672 GNUNET_i2s (&smr->peer));
673 if (NULL == pr->env)
674 {
675 /* request must have been cancelled between the original request
676 * and the response from CORE, ignore CORE's readiness */
677 return;
678 }
679 if (ntohs (smr->smr_id) != pr->smr_id_gen)
680 {
681 /* READY message is for expired or cancelled message,
682 * ignore! (we should have already sent another request) */
683 return;
684 }
685
686 /* ok, all good, send message out! */
687 GNUNET_MQ_send (h->mq,
688 pr->env);
689 pr->env = NULL;
690 GNUNET_MQ_impl_send_continue (pr->mq);
691}
692
693
694/**
695 * Our current client connection went down. Clean it up and try to
696 * reconnect!
697 *
698 * @param h our handle to the core service
699 */
700static void
701reconnect (struct GNUNET_CORE_Handle *h)
702{
703 struct GNUNET_MQ_MessageHandler handlers[] = {
704 GNUNET_MQ_hd_fixed_size (init_reply,
705 GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY,
706 struct InitReplyMessage,
707 h),
708 GNUNET_MQ_hd_fixed_size (connect_notify,
709 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT,
710 struct ConnectNotifyMessage,
711 h),
712 GNUNET_MQ_hd_fixed_size (disconnect_notify,
713 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT,
714 struct DisconnectNotifyMessage,
715 h),
716 GNUNET_MQ_hd_var_size (notify_inbound,
717 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND,
718 struct NotifyTrafficMessage,
719 h),
720 GNUNET_MQ_hd_fixed_size (send_ready,
721 GNUNET_MESSAGE_TYPE_CORE_SEND_READY,
722 struct SendMessageReady,
723 h),
724 GNUNET_MQ_handler_end ()
725 };
726 struct InitMessage *init;
727 struct GNUNET_MQ_Envelope *env;
728 uint16_t *ts;
729
730 GNUNET_assert (NULL == h->mq);
731 h->mq = GNUNET_CLIENT_connecT (h->cfg,
732 "core",
733 handlers,
734 &handle_mq_error,
735 h);
736 if (NULL == h->mq)
737 {
738 reconnect_later (h);
739 return;
740 }
741 env = GNUNET_MQ_msg_extra (init,
742 sizeof (uint16_t) * h->hcnt,
743 GNUNET_MESSAGE_TYPE_CORE_INIT);
744 LOG (GNUNET_ERROR_TYPE_INFO,
745 "(Re)connecting to CORE service\n");
746 init->options = htonl (0);
747 ts = (uint16_t *) &init[1];
748 for (unsigned int hpos = 0; hpos < h->hcnt; hpos++)
749 ts[hpos] = htons (h->handlers[hpos].type);
750 GNUNET_MQ_send (h->mq,
751 env);
752}
753
754
755/**
756 * Connect to the core service. Note that the connection may complete
757 * (or fail) asynchronously.
758 *
759 * @param cfg configuration to use
760 * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
761 * @param init callback to call once we have successfully
762 * connected to the core service
763 * @param connects function to call on peer connect, can be NULL
764 * @param disconnects function to call on peer disconnect / timeout, can be NULL
765 * @param handlers callbacks for messages we care about, NULL-terminated
766 * @return handle to the core service (only useful for disconnect until @a init is called);
767 * NULL on error (in this case, init is never called)
768 */
769struct GNUNET_CORE_Handle *
770GNUNET_CORE_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
771 void *cls,
772 GNUNET_CORE_StartupCallback init,
773 GNUNET_CORE_ConnecTEventHandler connects,
774 GNUNET_CORE_DisconnecTEventHandler disconnects,
775 const struct GNUNET_MQ_MessageHandler *handlers)
776{
777 struct GNUNET_CORE_Handle *h;
778 unsigned int hcnt;
779
780 h = GNUNET_new (struct GNUNET_CORE_Handle);
781 h->cfg = cfg;
782 h->cls = cls;
783 h->init = init;
784 h->connects = connects;
785 h->disconnects = disconnects;
786 h->peers = GNUNET_CONTAINER_multipeermap_create (128,
787 GNUNET_NO);
788 hcnt = 0;
789 if (NULL != handlers)
790 while (NULL != handlers[hcnt].cb)
791 hcnt++;
792 h->handlers = GNUNET_new_array (hcnt + 1,
793 struct GNUNET_MQ_MessageHandler);
794 if (NULL != handlers)
795 GNUNET_memcpy (h->handlers,
796 handlers,
797 hcnt * sizeof (struct GNUNET_MQ_MessageHandler));
798 h->hcnt = hcnt;
799 GNUNET_assert (hcnt <
800 (GNUNET_SERVER_MAX_MESSAGE_SIZE -
801 sizeof (struct InitMessage)) / sizeof (uint16_t));
802 LOG (GNUNET_ERROR_TYPE_DEBUG,
803 "Connecting to CORE service\n");
804 reconnect (h);
805 if (NULL == h->mq)
806 {
807 GNUNET_CORE_disconnect (h);
808 return NULL;
809 }
810 return h;
811}
812
813
814/**
815 * Disconnect from the core service.
816 *
817 * @param handle connection to core to disconnect
818 */
819void
820GNUNET_CORE_disconnecT (struct GNUNET_CORE_Handle *handle)
821{
822 LOG (GNUNET_ERROR_TYPE_DEBUG,
823 "Disconnecting from CORE service\n");
824 GNUNET_CONTAINER_multipeermap_iterate (handle->peers,
825 &disconnect_and_free_peer_entry,
826 handle);
827 GNUNET_CONTAINER_multipeermap_destroy (handle->peers);
828 handle->peers = NULL;
829 if (NULL != handle->reconnect_task)
830 {
831 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
832 handle->reconnect_task = NULL;
833 }
834 if (NULL != handle->mq)
835 {
836 GNUNET_MQ_destroy (handle->mq);
837 handle->mq = NULL;
838 }
839 GNUNET_free (handle->handlers);
840 GNUNET_free (handle);
841}
842
843
844/**
845 * Obtain the message queue for a connected peer.
846 *
847 * @param h the core handle
848 * @param pid the identity of the peer to check if it has been connected to us
849 * @return NULL if peer is not connected
850 */
851struct GNUNET_MQ_Handle *
852GNUNET_CORE_get_mq (const struct GNUNET_CORE_Handle *h,
853 const struct GNUNET_PeerIdentity *pid)
854{
855 struct PeerRecord *pr;
856
857 pr = GNUNET_CONTAINER_multipeermap_get (h->peers,
858 pid);
859 if (NULL == pr)
860 return NULL;
861 return pr->mq;
862}
863
864
865/* end of core_api.c */
diff --git a/src/core/core_api_monitor_peers.c b/src/core/core_api_monitor_peers.c
index 1455eb2b0..796fdb9d5 100644
--- a/src/core/core_api_monitor_peers.c
+++ b/src/core/core_api_monitor_peers.c
@@ -127,7 +127,7 @@ reconnect (struct GNUNET_CORE_MonitorHandle *mh)
127 if (NULL != mh->mq) 127 if (NULL != mh->mq)
128 GNUNET_MQ_destroy (mh->mq); 128 GNUNET_MQ_destroy (mh->mq);
129 /* FIXME: use backoff? */ 129 /* FIXME: use backoff? */
130 mh->mq = GNUNET_CLIENT_connecT (mh->cfg, 130 mh->mq = GNUNET_CLIENT_connect (mh->cfg,
131 "core", 131 "core",
132 handlers, 132 handlers,
133 &handle_mq_error, 133 &handle_mq_error,
diff --git a/src/core/core_api_mq.c b/src/core/core_api_mq.c
deleted file mode 100644
index 12c7a3bdd..000000000
--- a/src/core/core_api_mq.c
+++ /dev/null
@@ -1,191 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2014 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file core/core_api_mq.c
22 * @brief MQ support for core service
23 * @author Christian Grothoff
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_core_service.h"
30#include "core.h"
31
32#define LOG(kind,...) GNUNET_log_from (kind, "core-api",__VA_ARGS__)
33
34
35/**
36 * Internal state of a GNUNET-MQ queue for CORE.
37 */
38struct CoreMQState
39{
40 /**
41 * Which peer does this queue target?
42 */
43 struct GNUNET_PeerIdentity target;
44
45 /**
46 * Handle to the CORE service used by this MQ.
47 */
48 struct GNUNET_CORE_Handle *core;
49
50 /**
51 * Transmission handle (if in use).
52 */
53 struct GNUNET_CORE_TransmitHandle *th;
54};
55
56
57/**
58 * Function called to notify a client about the connection
59 * begin ready to queue more data. @a buf will be
60 * NULL and @a size zero if the connection was closed for
61 * writing in the meantime.
62 *
63 * @param cls closure
64 * @param size number of bytes available in @a buf
65 * @param buf where the callee should write the message
66 * @return number of bytes written to @a buf
67 */
68static size_t
69core_mq_ntr (void *cls, size_t size,
70 void *buf)
71{
72 struct GNUNET_MQ_Handle *mq = cls;
73 struct CoreMQState *mqs = GNUNET_MQ_impl_state (mq);
74 const struct GNUNET_MessageHeader *mh = GNUNET_MQ_impl_current (mq);
75 size_t msg_size = ntohs (mh->size);
76
77 LOG (GNUNET_ERROR_TYPE_DEBUG,
78 "ntr called (size %u, type %u)\n",
79 msg_size,
80 ntohs (mh->type));
81 mqs->th = NULL;
82 if (NULL == buf)
83 {
84 LOG (GNUNET_ERROR_TYPE_DEBUG,
85 "send error\n");
86 GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
87 return 0;
88 }
89 GNUNET_memcpy (buf, mh, msg_size);
90 GNUNET_MQ_impl_send_continue (mq);
91 return msg_size;
92}
93
94
95/**
96 * Signature of functions implementing the
97 * sending functionality of a message queue.
98 *
99 * @param mq the message queue
100 * @param msg the message to send
101 * @param impl_state state of the implementation
102 */
103static void
104core_mq_send (struct GNUNET_MQ_Handle *mq,
105 const struct GNUNET_MessageHeader *msg,
106 void *impl_state)
107{
108 struct CoreMQState *mqs = impl_state;
109
110 GNUNET_assert (NULL == mqs->th);
111 LOG (GNUNET_ERROR_TYPE_DEBUG,
112 "Sending queued message (size %u)\n",
113 ntohs (msg->size));
114 mqs->th = GNUNET_CORE_notify_transmit_ready (mqs->core, GNUNET_YES, 0,
115 GNUNET_TIME_UNIT_FOREVER_REL,
116 &mqs->target,
117 ntohs (msg->size),
118 &core_mq_ntr, mq);
119}
120
121
122/**
123 * Signature of functions implementing the
124 * destruction of a message queue.
125 * Implementations must not free @a mq, but should
126 * take care of @a impl_state.
127 *
128 * @param mq the message queue to destroy
129 * @param impl_state state of the implementation
130 */
131static void
132core_mq_destroy (struct GNUNET_MQ_Handle *mq,
133 void *impl_state)
134{
135 struct CoreMQState *mqs = impl_state;
136
137 if (NULL != mqs->th)
138 {
139 GNUNET_CORE_notify_transmit_ready_cancel (mqs->th);
140 mqs->th = NULL;
141 }
142 GNUNET_free (mqs);
143}
144
145
146/**
147 * Implementation function that cancels the currently sent message.
148 *
149 * @param mq message queue
150 * @param impl_state state specific to the implementation
151 */
152static void
153core_mq_cancel (struct GNUNET_MQ_Handle *mq,
154 void *impl_state)
155{
156 struct CoreMQState *mqs = impl_state;
157
158 GNUNET_assert (NULL != mqs->th);
159 GNUNET_CORE_notify_transmit_ready_cancel (mqs->th);
160}
161
162
163/**
164 * Create a message queue for sending messages to a peer with CORE.
165 * Messages may only be queued with #GNUNET_MQ_send once the init callback has
166 * been called for the given handle.
167 * There must only be one queue per peer for each core handle.
168 * The message queue can only be used to transmit messages,
169 * not to receive them.
170 *
171 * @param h the core handle
172 * @param target the target peer for this queue, may not be NULL
173 * @return a message queue for sending messages over the core handle
174 * to the target peer
175 */
176struct GNUNET_MQ_Handle *
177GNUNET_CORE_mq_create (struct GNUNET_CORE_Handle *h,
178 const struct GNUNET_PeerIdentity *target)
179{
180 struct CoreMQState *mqs = GNUNET_new (struct CoreMQState);
181
182 mqs->core = h;
183 mqs->target = *target;
184 return GNUNET_MQ_queue_for_callbacks (&core_mq_send,
185 &core_mq_destroy,
186 &core_mq_cancel,
187 mqs,
188 NULL, NULL, NULL);
189}
190
191/* end of core_api_mq.c */
diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c
index e6a113b52..847ba6e75 100644
--- a/src/core/test_core_api.c
+++ b/src/core/test_core_api.c
@@ -92,7 +92,7 @@ terminate_peer (struct PeerContext *p)
92{ 92{
93 if (NULL != p->ch) 93 if (NULL != p->ch)
94 { 94 {
95 GNUNET_CORE_disconnecT (p->ch); 95 GNUNET_CORE_disconnect (p->ch);
96 p->ch = NULL; 96 p->ch = NULL;
97 } 97 }
98 if (NULL != p->ghh) 98 if (NULL != p->ghh)
@@ -243,7 +243,7 @@ init_notify (void *cls,
243 GNUNET_assert (ok == 2); 243 GNUNET_assert (ok == 2);
244 OKPP; 244 OKPP;
245 /* connect p2 */ 245 /* connect p2 */
246 p2.ch = GNUNET_CORE_connecT (p2.cfg, 246 p2.ch = GNUNET_CORE_connect (p2.cfg,
247 &p2, 247 &p2,
248 &init_notify, 248 &init_notify,
249 &connect_notify, 249 &connect_notify,
@@ -317,7 +317,7 @@ run (void *cls,
317 (GNUNET_TIME_UNIT_SECONDS, 300), 317 (GNUNET_TIME_UNIT_SECONDS, 300),
318 &terminate_task_error, NULL); 318 &terminate_task_error, NULL);
319 p1.ch = 319 p1.ch =
320 GNUNET_CORE_connecT (p1.cfg, 320 GNUNET_CORE_connect (p1.cfg,
321 &p1, 321 &p1,
322 &init_notify, 322 &init_notify,
323 &connect_notify, 323 &connect_notify,
diff --git a/src/core/test_core_api_reliability.c b/src/core/test_core_api_reliability.c
index cd2bcad83..900c9f732 100644
--- a/src/core/test_core_api_reliability.c
+++ b/src/core/test_core_api_reliability.c
@@ -103,7 +103,7 @@ terminate_peer (struct PeerContext *p)
103{ 103{
104 if (NULL != p->ch) 104 if (NULL != p->ch)
105 { 105 {
106 GNUNET_CORE_disconnecT (p->ch); 106 GNUNET_CORE_disconnect (p->ch);
107 p->ch = NULL; 107 p->ch = NULL;
108 } 108 }
109 if (NULL != p->ghh) 109 if (NULL != p->ghh)
@@ -341,7 +341,7 @@ init_notify (void *cls,
341 OKPP; 341 OKPP;
342 /* connect p2 */ 342 /* connect p2 */
343 GNUNET_assert (NULL != 343 GNUNET_assert (NULL !=
344 (p2.ch = GNUNET_CORE_connecT (p2.cfg, 344 (p2.ch = GNUNET_CORE_connect (p2.cfg,
345 &p2, 345 &p2,
346 &init_notify, 346 &init_notify,
347 &connect_notify, 347 &connect_notify,
@@ -464,7 +464,7 @@ run (void *cls,
464 NULL); 464 NULL);
465 465
466 GNUNET_assert (NULL != 466 GNUNET_assert (NULL !=
467 (p1.ch = GNUNET_CORE_connecT (p1.cfg, 467 (p1.ch = GNUNET_CORE_connect (p1.cfg,
468 &p1, 468 &p1,
469 &init_notify, 469 &init_notify,
470 &connect_notify, 470 &connect_notify,
diff --git a/src/core/test_core_api_send_to_self.c b/src/core/test_core_api_send_to_self.c
index d29da651b..5cfc8b35f 100644
--- a/src/core/test_core_api_send_to_self.c
+++ b/src/core/test_core_api_send_to_self.c
@@ -65,7 +65,7 @@ cleanup (void *cls)
65 } 65 }
66 if (NULL != core) 66 if (NULL != core)
67 { 67 {
68 GNUNET_CORE_disconnecT (core); 68 GNUNET_CORE_disconnect (core);
69 core = NULL; 69 core = NULL;
70 } 70 }
71 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 71 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -159,7 +159,7 @@ run (void *cls,
159 }; 159 };
160 160
161 core = 161 core =
162 GNUNET_CORE_connecT (cfg, 162 GNUNET_CORE_connect (cfg,
163 NULL, 163 NULL,
164 &init, 164 &init,
165 &connect_cb, 165 &connect_cb,
diff --git a/src/core/test_core_api_start_only.c b/src/core/test_core_api_start_only.c
index 6abc3cc89..31e300b14 100644
--- a/src/core/test_core_api_start_only.c
+++ b/src/core/test_core_api_start_only.c
@@ -74,9 +74,9 @@ static struct GNUNET_MQ_MessageHandler handlers[] = {
74static void 74static void
75shutdown_task (void *cls) 75shutdown_task (void *cls)
76{ 76{
77 GNUNET_CORE_disconnecT (p1.ch); 77 GNUNET_CORE_disconnect (p1.ch);
78 p1.ch = NULL; 78 p1.ch = NULL;
79 GNUNET_CORE_disconnecT (p2.ch); 79 GNUNET_CORE_disconnect (p2.ch);
80 p2.ch = NULL; 80 p2.ch = NULL;
81 ok = 0; 81 ok = 0;
82} 82}
@@ -91,7 +91,7 @@ init_notify (void *cls,
91 if (p == &p1) 91 if (p == &p1)
92 { 92 {
93 /* connect p2 */ 93 /* connect p2 */
94 p2.ch = GNUNET_CORE_connecT (p2.cfg, 94 p2.ch = GNUNET_CORE_connect (p2.cfg,
95 &p2, 95 &p2,
96 &init_notify, 96 &init_notify,
97 &connect_notify, 97 &connect_notify,
@@ -140,12 +140,12 @@ timeout_task (void *cls)
140 "Timeout.\n"); 140 "Timeout.\n");
141 if (NULL != p1.ch) 141 if (NULL != p1.ch)
142 { 142 {
143 GNUNET_CORE_disconnecT (p1.ch); 143 GNUNET_CORE_disconnect (p1.ch);
144 p1.ch = NULL; 144 p1.ch = NULL;
145 } 145 }
146 if (NULL != p2.ch) 146 if (NULL != p2.ch)
147 { 147 {
148 GNUNET_CORE_disconnecT (p2.ch); 148 GNUNET_CORE_disconnect (p2.ch);
149 p2.ch = NULL; 149 p2.ch = NULL;
150 } 150 }
151 ok = 42; 151 ok = 42;
@@ -168,7 +168,7 @@ run (void *cls,
168 TIMEOUT), 168 TIMEOUT),
169 &timeout_task, 169 &timeout_task,
170 NULL); 170 NULL);
171 p1.ch = GNUNET_CORE_connecT (p1.cfg, 171 p1.ch = GNUNET_CORE_connect (p1.cfg,
172 &p1, 172 &p1,
173 &init_notify, 173 &init_notify,
174 &connect_notify, 174 &connect_notify,
diff --git a/src/core/test_core_defaults.conf b/src/core/test_core_defaults.conf
index eb9a1c379..4c956987c 100644
--- a/src/core/test_core_defaults.conf
+++ b/src/core/test_core_defaults.conf
@@ -5,13 +5,7 @@
5GNUNET_TEST_HOME = /tmp/test-gnunet-core/ 5GNUNET_TEST_HOME = /tmp/test-gnunet-core/
6 6
7[nat] 7[nat]
8DISABLEV6 = YES
9ENABLE_UPNP = NO 8ENABLE_UPNP = NO
10BEHIND_NAT = NO
11ALLOW_NAT = NO
12INTERNAL_ADDRESS = 127.0.0.1
13EXTERNAL_ADDRESS = 127.0.0.1
14USE_LOCALADDR = NO
15 9
16[ats] 10[ats]
17WAN_QUOTA_IN = 1 GB 11WAN_QUOTA_IN = 1 GB
diff --git a/src/core/test_core_quota_compliance.c b/src/core/test_core_quota_compliance.c
index 4dee958f2..dcc33288d 100644
--- a/src/core/test_core_quota_compliance.c
+++ b/src/core/test_core_quota_compliance.c
@@ -117,7 +117,7 @@ terminate_peer (struct PeerContext *p)
117{ 117{
118 if (NULL != p->ch) 118 if (NULL != p->ch)
119 { 119 {
120 GNUNET_CORE_disconnecT (p->ch); 120 GNUNET_CORE_disconnect (p->ch);
121 p->ch = NULL; 121 p->ch = NULL;
122 } 122 }
123 if (NULL != p->ghh) 123 if (NULL != p->ghh)
@@ -480,7 +480,7 @@ init_notify (void *cls,
480 GNUNET_assert (ok == 2); 480 GNUNET_assert (ok == 2);
481 OKPP; 481 OKPP;
482 /* connect p2 */ 482 /* connect p2 */
483 p2.ch = GNUNET_CORE_connecT (p2.cfg, 483 p2.ch = GNUNET_CORE_connect (p2.cfg,
484 &p2, 484 &p2,
485 &init_notify, 485 &init_notify,
486 &connect_notify, 486 &connect_notify,
@@ -653,7 +653,7 @@ run (void *cls,
653 "WAN_QUOTA_OUT", 653 "WAN_QUOTA_OUT",
654 &current_quota_p2_out)); 654 &current_quota_p2_out));
655 655
656 p1.ch = GNUNET_CORE_connecT (p1.cfg, 656 p1.ch = GNUNET_CORE_connect (p1.cfg,
657 &p1, 657 &p1,
658 &init_notify, 658 &init_notify,
659 &connect_notify, 659 &connect_notify,
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
index b201d4d9c..f90bf9630 100644
--- a/src/credential/credential_api.c
+++ b/src/credential/credential_api.c
@@ -283,7 +283,7 @@ reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
283 GNUNET_assert (NULL == handle->mq); 283 GNUNET_assert (NULL == handle->mq);
284 LOG (GNUNET_ERROR_TYPE_DEBUG, 284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Trying to connect to CREDENTIAL\n"); 285 "Trying to connect to CREDENTIAL\n");
286 handle->mq = GNUNET_CLIENT_connecT (handle->cfg, 286 handle->mq = GNUNET_CLIENT_connect (handle->cfg,
287 "credential", 287 "credential",
288 handlers, 288 handlers,
289 &mq_error_handler, 289 &mq_error_handler,
diff --git a/src/datacache/.gitignore b/src/datacache/.gitignore
new file mode 100644
index 000000000..8e42aa103
--- /dev/null
+++ b/src/datacache/.gitignore
@@ -0,0 +1,6 @@
1test_datacache_heap
2test_datacache_postgres
3test_datacache_quota_heap
4test_datacache_quota_postgres
5test_datacache_quota_sqlite
6test_datacache_sqlite
diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c
index 185d54f2f..49e60bca1 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -180,8 +180,7 @@ put_cb (void *cls,
180 GNUNET_memcpy (val->path_info, 180 GNUNET_memcpy (val->path_info,
181 put_ctx->path_info, 181 put_ctx->path_info,
182 put_ctx->path_info_len * sizeof (struct GNUNET_PeerIdentity)); 182 put_ctx->path_info_len * sizeof (struct GNUNET_PeerIdentity));
183 GNUNET_CONTAINER_heap_update_cost (put_ctx->heap, 183 GNUNET_CONTAINER_heap_update_cost (val->hn,
184 val->hn,
185 val->discard_time.abs_value_us); 184 val->discard_time.abs_value_us);
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 "Got same value for key %s and type %d (size %u vs %u)\n", 186 "Got same value for key %s and type %d (size %u vs %u)\n",
diff --git a/src/datastore/.gitignore b/src/datastore/.gitignore
index 38dff9993..51d3391b9 100644
--- a/src/datastore/.gitignore
+++ b/src/datastore/.gitignore
@@ -1,2 +1,16 @@
1gnunet-service-datastore 1gnunet-service-datastore
2gnunet-datastore 2gnunet-datastore
3perf_datastore_api_heap
4perf_plugin_datastore_heap
5test_datastore_api_heap
6test_datastore_api_management_heap
7test_datastore_api_management_mysql
8test_datastore_api_management_postgres
9test_datastore_api_management_sqlite
10test_datastore_api_mysql
11test_datastore_api_postgres
12test_datastore_api_sqlite
13test_plugin_datastore_heap
14test_plugin_datastore_mysql
15test_plugin_datastore_postgres
16test_plugin_datastore_sqlite
diff --git a/src/datastore/datastore_api.c b/src/datastore/datastore_api.c
index d75a58552..db485364e 100644
--- a/src/datastore/datastore_api.c
+++ b/src/datastore/datastore_api.c
@@ -443,7 +443,7 @@ GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
443 LOG (GNUNET_ERROR_TYPE_DEBUG, 443 LOG (GNUNET_ERROR_TYPE_DEBUG,
444 "Re-connecting to issue DROP!\n"); 444 "Re-connecting to issue DROP!\n");
445 GNUNET_assert (NULL == h->mq); 445 GNUNET_assert (NULL == h->mq);
446 h->mq = GNUNET_CLIENT_connecT (h->cfg, 446 h->mq = GNUNET_CLIENT_connect (h->cfg,
447 "datastore", 447 "datastore",
448 NULL, 448 NULL,
449 &disconnect_on_mq_error, 449 &disconnect_on_mq_error,
@@ -868,7 +868,7 @@ try_reconnect (void *cls)
868 h->retry_time = GNUNET_TIME_STD_BACKOFF (h->retry_time); 868 h->retry_time = GNUNET_TIME_STD_BACKOFF (h->retry_time);
869 h->reconnect_task = NULL; 869 h->reconnect_task = NULL;
870 GNUNET_assert (NULL == h->mq); 870 GNUNET_assert (NULL == h->mq);
871 h->mq = GNUNET_CLIENT_connecT (h->cfg, 871 h->mq = GNUNET_CLIENT_connect (h->cfg,
872 "datastore", 872 "datastore",
873 handlers, 873 handlers,
874 &mq_error_handler, 874 &mq_error_handler,
diff --git a/src/datastore/plugin_datastore_heap.c b/src/datastore/plugin_datastore_heap.c
index 51f61764c..977d599d2 100644
--- a/src/datastore/plugin_datastore_heap.c
+++ b/src/datastore/plugin_datastore_heap.c
@@ -331,7 +331,7 @@ struct GetContext
331 * The plugin. 331 * The plugin.
332 */ 332 */
333 struct Plugin *plugin; 333 struct Plugin *plugin;
334 334
335 /** 335 /**
336 * Requested value hash. 336 * Requested value hash.
337 */ 337 */
@@ -608,7 +608,7 @@ heap_plugin_get_expiration (void *cls, PluginDatumProcessor proc,
608 * priority should be added to the existing priority, ignoring the 608 * priority should be added to the existing priority, ignoring the
609 * priority in value. 609 * priority in value.
610 * 610 *
611 * @param cls our "struct Plugin*" 611 * @param cls our `struct Plugin *`
612 * @param uid unique identifier of the datum 612 * @param uid unique identifier of the datum
613 * @param delta by how much should the priority 613 * @param delta by how much should the priority
614 * change? If priority + delta < 0 the 614 * change? If priority + delta < 0 the
@@ -628,7 +628,6 @@ heap_plugin_update (void *cls,
628 PluginUpdateCont cont, 628 PluginUpdateCont cont,
629 void *cont_cls) 629 void *cont_cls)
630{ 630{
631 struct Plugin *plugin = cls;
632 struct Value *value; 631 struct Value *value;
633 632
634 value = (struct Value*) (long) uid; 633 value = (struct Value*) (long) uid;
@@ -636,8 +635,7 @@ heap_plugin_update (void *cls,
636 if (value->expiration.abs_value_us != expire.abs_value_us) 635 if (value->expiration.abs_value_us != expire.abs_value_us)
637 { 636 {
638 value->expiration = expire; 637 value->expiration = expire;
639 GNUNET_CONTAINER_heap_update_cost (plugin->by_expiration, 638 GNUNET_CONTAINER_heap_update_cost (value->expire_heap,
640 value->expire_heap,
641 expire.abs_value_us); 639 expire.abs_value_us);
642 } 640 }
643 if ( (delta < 0) && (value->priority < - delta) ) 641 if ( (delta < 0) && (value->priority < - delta) )
diff --git a/src/dht/.gitignore b/src/dht/.gitignore
index b8b0ff7d4..e7f3c2a86 100644
--- a/src/dht/.gitignore
+++ b/src/dht/.gitignore
@@ -5,3 +5,10 @@ gnunet-dht-profiler
5gnunet-dht-put 5gnunet-dht-put
6gnunet-service-dht 6gnunet-service-dht
7gnunet-service-dht-whanau 7gnunet-service-dht-whanau
8test_dht_2dtorus
9test_dht_api
10test_dht_line
11test_dht_monitor
12test_dht_multipeer
13test_dht_tools.py
14test_dht_twopeer
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index f91917768..1a174165c 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -58,8 +58,12 @@ endif
58noinst_PROGRAMS = \ 58noinst_PROGRAMS = \
59 gnunet-dht-monitor \ 59 gnunet-dht-monitor \
60 gnunet-dht-get \ 60 gnunet-dht-get \
61 gnunet-dht-put \ 61 gnunet-dht-put
62
63if HAVE_TESTING
64noinst_PROGRAMS += \
62 gnunet-dht-profiler 65 gnunet-dht-profiler
66endif
63 67
64gnunet_service_dht_SOURCES = \ 68gnunet_service_dht_SOURCES = \
65 gnunet-service-dht.c gnunet-service-dht.h \ 69 gnunet-service-dht.c gnunet-service-dht.h \
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c
index 57880165e..66eaf1064 100644
--- a/src/dht/dht_api.c
+++ b/src/dht/dht_api.c
@@ -867,7 +867,7 @@ try_connect (struct GNUNET_DHT_Handle *h)
867 }; 867 };
868 if (NULL != h->mq) 868 if (NULL != h->mq)
869 return GNUNET_OK; 869 return GNUNET_OK;
870 h->mq = GNUNET_CLIENT_connecT (h->cfg, 870 h->mq = GNUNET_CLIENT_connect (h->cfg,
871 "dht", 871 "dht",
872 handlers, 872 handlers,
873 &mq_error_handler, 873 &mq_error_handler,
diff --git a/src/dht/gnunet-service-dht_hello.c b/src/dht/gnunet-service-dht_hello.c
index 3716ea3af..5a5c41567 100644
--- a/src/dht/gnunet-service-dht_hello.c
+++ b/src/dht/gnunet-service-dht_hello.c
@@ -69,13 +69,15 @@ GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
69 * FIXME this is called once per address. Merge instead of replacing? 69 * FIXME this is called once per address. Merge instead of replacing?
70 */ 70 */
71static void 71static void
72process_hello (void *cls, const struct GNUNET_PeerIdentity *peer, 72process_hello (void *cls,
73 const struct GNUNET_HELLO_Message *hello, const char *err_msg) 73 const struct GNUNET_PeerIdentity *peer,
74 const struct GNUNET_HELLO_Message *hello,
75 const char *err_msg)
74{ 76{
75 struct GNUNET_TIME_Absolute ex; 77 struct GNUNET_TIME_Absolute ex;
76 struct GNUNET_HELLO_Message *hm; 78 struct GNUNET_HELLO_Message *hm;
77 79
78 if (hello == NULL) 80 if (NULL == hello)
79 return; 81 return;
80 ex = GNUNET_HELLO_get_last_expiration (hello); 82 ex = GNUNET_HELLO_get_last_expiration (hello);
81 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us) 83 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
@@ -100,8 +102,12 @@ process_hello (void *cls, const struct GNUNET_PeerIdentity *peer,
100void 102void
101GDS_HELLO_init () 103GDS_HELLO_init ()
102{ 104{
103 pnc = GNUNET_PEERINFO_notify (GDS_cfg, GNUNET_NO, &process_hello, NULL); 105 pnc = GNUNET_PEERINFO_notify (GDS_cfg,
104 peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO); 106 GNUNET_NO,
107 &process_hello,
108 NULL);
109 peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256,
110 GNUNET_NO);
105} 111}
106 112
107 113
@@ -131,7 +137,9 @@ GDS_HELLO_done ()
131 } 137 }
132 if (NULL != peer_to_hello) 138 if (NULL != peer_to_hello)
133 { 139 {
134 GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello, &free_hello, NULL); 140 GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello,
141 &free_hello,
142 NULL);
135 GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello); 143 GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
136 } 144 }
137} 145}
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index 574ed9ad0..20bdc0ce4 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -1830,10 +1830,16 @@ handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1830 /* first, check about our own HELLO */ 1830 /* first, check about our own HELLO */
1831 if (NULL != GDS_my_hello) 1831 if (NULL != GDS_my_hello)
1832 { 1832 {
1833 GNUNET_BLOCK_mingle_hash (&my_identity_hash, bf_mutator, &mhash); 1833 GNUNET_BLOCK_mingle_hash (&my_identity_hash,
1834 bf_mutator,
1835 &mhash);
1834 if ((NULL == bf) || 1836 if ((NULL == bf) ||
1835 (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (bf, &mhash))) 1837 (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (bf, &mhash)))
1836 { 1838 {
1839 size_t hello_size;
1840
1841 hello_size = GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message *) GDS_my_hello);
1842 GNUNET_break (hello_size >= sizeof (struct GNUNET_MessageHeader));
1837 GDS_NEIGHBOURS_handle_reply (sender, 1843 GDS_NEIGHBOURS_handle_reply (sender,
1838 GNUNET_BLOCK_TYPE_DHT_HELLO, 1844 GNUNET_BLOCK_TYPE_DHT_HELLO,
1839 GNUNET_TIME_relative_to_absolute 1845 GNUNET_TIME_relative_to_absolute
@@ -1844,9 +1850,7 @@ handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1844 0, 1850 0,
1845 NULL, 1851 NULL,
1846 GDS_my_hello, 1852 GDS_my_hello,
1847 GNUNET_HELLO_size ((const struct 1853 hello_size);
1848 GNUNET_HELLO_Message *)
1849 GDS_my_hello));
1850 } 1854 }
1851 else 1855 else
1852 { 1856 {
@@ -2377,7 +2381,7 @@ GDS_NEIGHBOURS_init ()
2377 log_route_details_stderr = 2381 log_route_details_stderr =
2378 (NULL != getenv("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO; 2382 (NULL != getenv("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO;
2379 ats_ch = GNUNET_ATS_connectivity_init (GDS_cfg); 2383 ats_ch = GNUNET_ATS_connectivity_init (GDS_cfg);
2380 core_api = GNUNET_CORE_connecT (GDS_cfg, 2384 core_api = GNUNET_CORE_connect (GDS_cfg,
2381 NULL, 2385 NULL,
2382 &core_init, 2386 &core_init,
2383 &handle_core_connect, 2387 &handle_core_connect,
@@ -2401,7 +2405,7 @@ GDS_NEIGHBOURS_done ()
2401{ 2405{
2402 if (NULL == core_api) 2406 if (NULL == core_api)
2403 return; 2407 return;
2404 GNUNET_CORE_disconnecT (core_api); 2408 GNUNET_CORE_disconnect (core_api);
2405 core_api = NULL; 2409 core_api = NULL;
2406 GNUNET_assert (0 == 2410 GNUNET_assert (0 ==
2407 GNUNET_CONTAINER_multipeermap_size (all_connected_peers)); 2411 GNUNET_CONTAINER_multipeermap_size (all_connected_peers));
diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c
index 48bece35e..978c46d73 100644
--- a/src/dht/gnunet-service-dht_routing.c
+++ b/src/dht/gnunet-service-dht_routing.c
@@ -160,7 +160,9 @@ struct ProcessContext
160 * #GNUNET_SYSERR if the result is malformed or type unsupported 160 * #GNUNET_SYSERR if the result is malformed or type unsupported
161 */ 161 */
162static int 162static int
163process (void *cls, const struct GNUNET_HashCode * key, void *value) 163process (void *cls,
164 const struct GNUNET_HashCode *key,
165 void *value)
164{ 166{
165 struct ProcessContext *pc = cls; 167 struct ProcessContext *pc = cls;
166 struct RecentRequest *rr = value; 168 struct RecentRequest *rr = value;
@@ -170,7 +172,8 @@ process (void *cls, const struct GNUNET_HashCode * key, void *value)
170 struct GNUNET_HashCode hc; 172 struct GNUNET_HashCode hc;
171 const struct GNUNET_HashCode *eval_key; 173 const struct GNUNET_HashCode *eval_key;
172 174
173 if ((rr->type != GNUNET_BLOCK_TYPE_ANY) && (rr->type != pc->type)) 175 if ( (rr->type != GNUNET_BLOCK_TYPE_ANY) &&
176 (rr->type != pc->type) )
174 return GNUNET_OK; /* type missmatch */ 177 return GNUNET_OK; /* type missmatch */
175 178
176 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE)) 179 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE))
@@ -183,23 +186,26 @@ process (void *cls, const struct GNUNET_HashCode * key, void *value)
183 gpl = 0; 186 gpl = 0;
184 ppl = 0; 187 ppl = 0;
185 } 188 }
186 if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) && 189 if ( (0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
187 (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO)) 190 (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO) )
188 { 191 {
189 /* key may not match HELLO, which is OK since 192 /* key may not match HELLO, which is OK since
190 * the search is approximate. Still, the evaluation 193 * the search is approximate. Still, the evaluation
191 * would fail since the match is not exact. So 194 * would fail since the match is not exact. So
192 * we fake it by changing the key to the actual PID ... */ 195 * we fake it by changing the key to the actual PID ... */
193 GNUNET_BLOCK_get_key (GDS_block_context, GNUNET_BLOCK_TYPE_DHT_HELLO, 196 GNUNET_BLOCK_get_key (GDS_block_context,
194 pc->data, pc->data_size, &hc); 197 GNUNET_BLOCK_TYPE_DHT_HELLO,
198 pc->data,
199 pc->data_size,
200 &hc);
195 eval_key = &hc; 201 eval_key = &hc;
196 } 202 }
197 else 203 else
198 { 204 {
199 eval_key = key; 205 eval_key = key;
200 } 206 }
201 eval = 207 eval
202 GNUNET_BLOCK_evaluate (GDS_block_context, 208 = GNUNET_BLOCK_evaluate (GDS_block_context,
203 pc->type, 209 pc->type,
204 GNUNET_BLOCK_EO_NONE, 210 GNUNET_BLOCK_EO_NONE,
205 eval_key, 211 eval_key,
@@ -308,7 +314,10 @@ GDS_ROUTING_process (void *cls,
308 pc.data_size = 0; 314 pc.data_size = 0;
309 pc.data = ""; /* something not null */ 315 pc.data = ""; /* something not null */
310 } 316 }
311 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, &process, &pc); 317 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map,
318 key,
319 &process,
320 &pc);
312} 321}
313 322
314 323
@@ -345,11 +354,13 @@ expire_oldest_entry ()
345 * @param cls the new 'struct RecentRequest' (to discard upon successful combination) 354 * @param cls the new 'struct RecentRequest' (to discard upon successful combination)
346 * @param key the query 355 * @param key the query
347 * @param value the existing 'struct RecentRequest' (to update upon successful combination) 356 * @param value the existing 'struct RecentRequest' (to update upon successful combination)
348 * @return GNUNET_OK (continue to iterate), 357 * @return #GNUNET_OK (continue to iterate),
349 * GNUNET_SYSERR if the request was successfully combined 358 * #GNUNET_SYSERR if the request was successfully combined
350 */ 359 */
351static int 360static int
352try_combine_recent (void *cls, const struct GNUNET_HashCode * key, void *value) 361try_combine_recent (void *cls,
362 const struct GNUNET_HashCode *key,
363 void *value)
353{ 364{
354 struct RecentRequest *in = cls; 365 struct RecentRequest *in = cls;
355 struct RecentRequest *rr = value; 366 struct RecentRequest *rr = value;
@@ -396,7 +407,8 @@ void
396GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender, 407GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
397 enum GNUNET_BLOCK_Type type, 408 enum GNUNET_BLOCK_Type type,
398 enum GNUNET_DHT_RouteOption options, 409 enum GNUNET_DHT_RouteOption options,
399 const struct GNUNET_HashCode * key, const void *xquery, 410 const struct GNUNET_HashCode *key,
411 const void *xquery,
400 size_t xquery_size, 412 size_t xquery_size,
401 const struct GNUNET_CONTAINER_BloomFilter *reply_bf, 413 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
402 uint32_t reply_bf_mutator) 414 uint32_t reply_bf_mutator)
@@ -419,8 +431,10 @@ GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
419 recent_req->xquery_size = xquery_size; 431 recent_req->xquery_size = xquery_size;
420 recent_req->reply_bf_mutator = reply_bf_mutator; 432 recent_req->reply_bf_mutator = reply_bf_mutator;
421 if (GNUNET_SYSERR == 433 if (GNUNET_SYSERR ==
422 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, 434 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map,
423 &try_combine_recent, recent_req)) 435 key,
436 &try_combine_recent,
437 recent_req))
424 { 438 {
425 GNUNET_STATISTICS_update (GDS_stats, 439 GNUNET_STATISTICS_update (GDS_stats,
426 gettext_noop 440 gettext_noop
diff --git a/src/dht/gnunet-service-wdht_neighbours.c b/src/dht/gnunet-service-wdht_neighbours.c
index d3b92585b..78a04d66d 100644
--- a/src/dht/gnunet-service-wdht_neighbours.c
+++ b/src/dht/gnunet-service-wdht_neighbours.c
@@ -1712,7 +1712,7 @@ GDS_NEIGHBOURS_init (void)
1712 GNUNET_MQ_handler_end () 1712 GNUNET_MQ_handler_end ()
1713 }; 1713 };
1714 1714
1715 core_api = GNUNET_CORE_connecT (GDS_cfg, NULL, 1715 core_api = GNUNET_CORE_connect (GDS_cfg, NULL,
1716 &core_init, 1716 &core_init,
1717 &handle_core_connect, 1717 &handle_core_connect,
1718 &handle_core_disconnect, 1718 &handle_core_disconnect,
@@ -1736,7 +1736,7 @@ GDS_NEIGHBOURS_done (void)
1736{ 1736{
1737 if (NULL == core_api) 1737 if (NULL == core_api)
1738 return; 1738 return;
1739 GNUNET_CORE_disconnecT (core_api); 1739 GNUNET_CORE_disconnect (core_api);
1740 core_api = NULL; 1740 core_api = NULL;
1741 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friends_peermap)); 1741 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friends_peermap));
1742 GNUNET_CONTAINER_multipeermap_destroy (friends_peermap); 1742 GNUNET_CONTAINER_multipeermap_destroy (friends_peermap);
diff --git a/src/dht/gnunet-service-xdht_neighbours.c b/src/dht/gnunet-service-xdht_neighbours.c
index e3462f618..d41eb1900 100644
--- a/src/dht/gnunet-service-xdht_neighbours.c
+++ b/src/dht/gnunet-service-xdht_neighbours.c
@@ -6150,7 +6150,7 @@ GDS_NEIGHBOURS_init (void)
6150 GNUNET_MQ_handler_end () 6150 GNUNET_MQ_handler_end ()
6151 }; 6151 };
6152 6152
6153 core_api = GNUNET_CORE_connecT (GDS_cfg, 6153 core_api = GNUNET_CORE_connect (GDS_cfg,
6154 NULL, 6154 NULL,
6155 &core_init, 6155 &core_init,
6156 &handle_core_connect, 6156 &handle_core_connect,
@@ -6212,7 +6212,7 @@ GDS_NEIGHBOURS_done (void)
6212 if (NULL == core_api) 6212 if (NULL == core_api)
6213 return; 6213 return;
6214 6214
6215 GNUNET_CORE_disconnecT (core_api); 6215 GNUNET_CORE_disconnect (core_api);
6216 core_api = NULL; 6216 core_api = NULL;
6217 6217
6218 delete_finger_table_entries(); 6218 delete_finger_table_entries();
diff --git a/src/dht/plugin_block_dht.c b/src/dht/plugin_block_dht.c
index 17594efcb..8bb533961 100644
--- a/src/dht/plugin_block_dht.c
+++ b/src/dht/plugin_block_dht.c
@@ -70,12 +70,13 @@ block_plugin_dht_evaluate (void *cls,
70 70
71 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO) 71 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
72 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; 72 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
73 if (xquery_size != 0) 73 if (0 != xquery_size)
74 { 74 {
75 GNUNET_break_op (0); 75 GNUNET_break_op (0);
76 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; 76 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
77 } 77 }
78 if (NULL == reply_block) 78 if ( (NULL == reply_block) ||
79 (0 == reply_block_size) )
79 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; 80 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
80 if (reply_block_size < sizeof (struct GNUNET_MessageHeader)) 81 if (reply_block_size < sizeof (struct GNUNET_MessageHeader))
81 { 82 {
@@ -121,14 +122,16 @@ block_plugin_dht_evaluate (void *cls,
121 * @param type block type 122 * @param type block type
122 * @param block block to get the key for 123 * @param block block to get the key for
123 * @param block_size number of bytes @a block 124 * @param block_size number of bytes @a block
124 * @param key set to the key (query) for the given block 125 * @param[out] key set to the key (query) for the given block
125 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 126 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
126 * (or if extracting a key from a block of this type does not work) 127 * (or if extracting a key from a block of this type does not work)
127 */ 128 */
128static int 129static int
129block_plugin_dht_get_key (void *cls, enum GNUNET_BLOCK_Type type, 130block_plugin_dht_get_key (void *cls,
130 const void *block, size_t block_size, 131 enum GNUNET_BLOCK_Type type,
131 struct GNUNET_HashCode * key) 132 const void *block,
133 size_t block_size,
134 struct GNUNET_HashCode *key)
132{ 135{
133 const struct GNUNET_MessageHeader *msg; 136 const struct GNUNET_MessageHeader *msg;
134 const struct GNUNET_HELLO_Message *hello; 137 const struct GNUNET_HELLO_Message *hello;
diff --git a/src/dns/.gitignore b/src/dns/.gitignore
index ef9125c50..952f6fb9a 100644
--- a/src/dns/.gitignore
+++ b/src/dns/.gitignore
@@ -2,3 +2,4 @@ gnunet-service-dns
2gnunet-dns-monitor 2gnunet-dns-monitor
3gnunet-dns-redirector 3gnunet-dns-redirector
4gnunet-helper-dns 4gnunet-helper-dns
5test_hexcoder
diff --git a/src/dns/dns_api.c b/src/dns/dns_api.c
index 4803fe3fc..e7450a1d4 100644
--- a/src/dns/dns_api.c
+++ b/src/dns/dns_api.c
@@ -217,7 +217,7 @@ reconnect (void *cls)
217 struct GNUNET_DNS_Register *msg; 217 struct GNUNET_DNS_Register *msg;
218 218
219 dh->reconnect_task = NULL; 219 dh->reconnect_task = NULL;
220 dh->mq = GNUNET_CLIENT_connecT (dh->cfg, 220 dh->mq = GNUNET_CLIENT_connect (dh->cfg,
221 "dns", 221 "dns",
222 handlers, 222 handlers,
223 &mq_error_handler, 223 &mq_error_handler,
diff --git a/src/dv/dv_api.c b/src/dv/dv_api.c
index 43b6c7db1..062f9a95f 100644
--- a/src/dv/dv_api.c
+++ b/src/dv/dv_api.c
@@ -346,7 +346,7 @@ reconnect (struct GNUNET_DV_ServiceHandle *sh)
346 sh); 346 sh);
347 LOG (GNUNET_ERROR_TYPE_DEBUG, 347 LOG (GNUNET_ERROR_TYPE_DEBUG,
348 "Connecting to DV service\n"); 348 "Connecting to DV service\n");
349 sh->mq = GNUNET_CLIENT_connecT (sh->cfg, 349 sh->mq = GNUNET_CLIENT_connect (sh->cfg,
350 "dv", 350 "dv",
351 handlers, 351 handlers,
352 &mq_error_handler, 352 &mq_error_handler,
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c
index fdd871bbd..6adaa04d9 100644
--- a/src/dv/gnunet-service-dv.c
+++ b/src/dv/gnunet-service-dv.c
@@ -1936,7 +1936,7 @@ shutdown_task (void *cls)
1936 1936
1937 in_shutdown = GNUNET_YES; 1937 in_shutdown = GNUNET_YES;
1938 GNUNET_assert (NULL != core_api); 1938 GNUNET_assert (NULL != core_api);
1939 GNUNET_CORE_disconnecT (core_api); 1939 GNUNET_CORE_disconnect (core_api);
1940 core_api = NULL; 1940 core_api = NULL;
1941 GNUNET_ATS_performance_done (ats); 1941 GNUNET_ATS_performance_done (ats);
1942 ats = NULL; 1942 ats = NULL;
@@ -2059,7 +2059,7 @@ run (void *cls,
2059 GNUNET_NO); 2059 GNUNET_NO);
2060 all_routes = GNUNET_CONTAINER_multipeermap_create (65536, 2060 all_routes = GNUNET_CONTAINER_multipeermap_create (65536,
2061 GNUNET_NO); 2061 GNUNET_NO);
2062 core_api = GNUNET_CORE_connecT (cfg, 2062 core_api = GNUNET_CORE_connect (cfg,
2063 NULL, 2063 NULL,
2064 &core_init, 2064 &core_init,
2065 &handle_core_connect, 2065 &handle_core_connect,
@@ -2073,7 +2073,7 @@ run (void *cls,
2073 NULL); 2073 NULL);
2074 if (NULL == ats) 2074 if (NULL == ats)
2075 { 2075 {
2076 GNUNET_CORE_disconnecT (core_api); 2076 GNUNET_CORE_disconnect (core_api);
2077 core_api = NULL; 2077 core_api = NULL;
2078 return; 2078 return;
2079 } 2079 }
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 1b129c643..68699db71 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -747,9 +747,8 @@ get_redirect_state (int af,
747 return NULL; 747 return NULL;
748 /* Mark this connection as freshly used */ 748 /* Mark this connection as freshly used */
749 if (NULL == state_key) 749 if (NULL == state_key)
750 GNUNET_CONTAINER_heap_update_cost (connections_heap, 750 GNUNET_CONTAINER_heap_update_cost (state->specifics.tcp_udp.heap_node,
751 state->specifics.tcp_udp.heap_node, 751 GNUNET_TIME_absolute_get ().abs_value_us);
752 GNUNET_TIME_absolute_get ().abs_value_us);
753 return state; 752 return state;
754} 753}
755 754
diff --git a/src/fragmentation/.gitignore b/src/fragmentation/.gitignore
new file mode 100644
index 000000000..c3293ab69
--- /dev/null
+++ b/src/fragmentation/.gitignore
@@ -0,0 +1,2 @@
1test_fragmentation
2test_fragmentation_parallel
diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c
index eacc3c2df..53b836f22 100644
--- a/src/fs/fs_download.c
+++ b/src/fs/fs_download.c
@@ -1335,7 +1335,7 @@ do_reconnect (void *cls)
1335 }; 1335 };
1336 1336
1337 dc->task = NULL; 1337 dc->task = NULL;
1338 dc->mq = GNUNET_CLIENT_connecT (dc->h->cfg, 1338 dc->mq = GNUNET_CLIENT_connect (dc->h->cfg,
1339 "fs", 1339 "fs",
1340 handlers, 1340 handlers,
1341 &download_mq_error_handler, 1341 &download_mq_error_handler,
diff --git a/src/fs/fs_list_indexed.c b/src/fs/fs_list_indexed.c
index 67183fce2..eec125a10 100644
--- a/src/fs/fs_list_indexed.c
+++ b/src/fs/fs_list_indexed.c
@@ -185,7 +185,7 @@ GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
185 struct GNUNET_MQ_Envelope *env; 185 struct GNUNET_MQ_Envelope *env;
186 struct GNUNET_MessageHeader *msg; 186 struct GNUNET_MessageHeader *msg;
187 187
188 gic->mq = GNUNET_CLIENT_connecT (h->cfg, 188 gic->mq = GNUNET_CLIENT_connect (h->cfg,
189 "fs", 189 "fs",
190 handlers, 190 handlers,
191 &mq_error_handler, 191 &mq_error_handler,
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c
index 5820c3d0c..86a58a58b 100644
--- a/src/fs/fs_publish.c
+++ b/src/fs/fs_publish.c
@@ -863,7 +863,7 @@ hash_for_index_cb (void *cls,
863 GNUNET_free (fn); 863 GNUNET_free (fn);
864 return; 864 return;
865 } 865 }
866 pc->mq = GNUNET_CLIENT_connecT (pc->h->cfg, 866 pc->mq = GNUNET_CLIENT_connect (pc->h->cfg,
867 "fs", 867 "fs",
868 handlers, 868 handlers,
869 &index_mq_error_handler, 869 &index_mq_error_handler,
@@ -1016,7 +1016,7 @@ create_loc_uri (struct GNUNET_FS_PublishContext *pc)
1016 1016
1017 if (NULL != pc->mq) 1017 if (NULL != pc->mq)
1018 GNUNET_MQ_destroy (pc->mq); 1018 GNUNET_MQ_destroy (pc->mq);
1019 pc->mq = GNUNET_CLIENT_connecT (pc->h->cfg, 1019 pc->mq = GNUNET_CLIENT_connect (pc->h->cfg,
1020 "fs", 1020 "fs",
1021 handlers, 1021 handlers,
1022 &loc_mq_error_handler, 1022 &loc_mq_error_handler,
diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c
index 198577b08..75ce4b54f 100644
--- a/src/fs/fs_search.c
+++ b/src/fs/fs_search.c
@@ -1244,7 +1244,7 @@ do_reconnect (void *cls)
1244 }; 1244 };
1245 1245
1246 sc->task = NULL; 1246 sc->task = NULL;
1247 sc->mq = GNUNET_CLIENT_connecT (sc->h->cfg, 1247 sc->mq = GNUNET_CLIENT_connect (sc->h->cfg,
1248 "fs", 1248 "fs",
1249 handlers, 1249 handlers,
1250 &search_mq_error_handler, 1250 &search_mq_error_handler,
diff --git a/src/fs/fs_unindex.c b/src/fs/fs_unindex.c
index 2a024ecbb..a672b84d5 100644
--- a/src/fs/fs_unindex.c
+++ b/src/fs/fs_unindex.c
@@ -316,7 +316,7 @@ unindex_finish (struct GNUNET_FS_UnindexContext *uc)
316 uc->seen_dh = NULL; 316 uc->seen_dh = NULL;
317 uc->state = UNINDEX_STATE_FS_NOTIFY; 317 uc->state = UNINDEX_STATE_FS_NOTIFY;
318 GNUNET_FS_unindex_sync_ (uc); 318 GNUNET_FS_unindex_sync_ (uc);
319 uc->mq = GNUNET_CLIENT_connecT (uc->h->cfg, 319 uc->mq = GNUNET_CLIENT_connect (uc->h->cfg,
320 "fs", 320 "fs",
321 handlers, 321 handlers,
322 &unindex_mq_error_handler, 322 &unindex_mq_error_handler,
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index c83d73555..e38fdb032 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -1181,7 +1181,7 @@ shutdown_task (void *cls)
1181 GSF_cadet_stop_server (); 1181 GSF_cadet_stop_server ();
1182 if (NULL != GSF_core) 1182 if (NULL != GSF_core)
1183 { 1183 {
1184 GNUNET_CORE_disconnecT (GSF_core); 1184 GNUNET_CORE_disconnect (GSF_core);
1185 GSF_core = NULL; 1185 GSF_core = NULL;
1186 } 1186 }
1187 if (NULL != GSF_ats) 1187 if (NULL != GSF_ats)
@@ -1219,7 +1219,7 @@ shutdown_task (void *cls)
1219 1219
1220 1220
1221/** 1221/**
1222 * Function called after GNUNET_CORE_connecT has succeeded 1222 * Function called after GNUNET_CORE_connect has succeeded
1223 * (or failed for good). Note that the private key of the 1223 * (or failed for good). Note that the private key of the
1224 * peer is intentionally not exposed here; if you need it, 1224 * peer is intentionally not exposed here; if you need it,
1225 * your process should try to read the private key file 1225 * your process should try to read the private key file
@@ -1299,7 +1299,7 @@ main_init (const struct GNUNET_CONFIGURATION_Handle *c)
1299 "I am peer %s\n", 1299 "I am peer %s\n",
1300 GNUNET_i2s (&GSF_my_id)); 1300 GNUNET_i2s (&GSF_my_id));
1301 GSF_core 1301 GSF_core
1302 = GNUNET_CORE_connecT (GSF_cfg, 1302 = GNUNET_CORE_connect (GSF_cfg,
1303 NULL, 1303 NULL,
1304 &peer_init_handler, 1304 &peer_init_handler,
1305 &GSF_peer_connect_handler, 1305 &GSF_peer_connect_handler,
diff --git a/src/gns/gns.conf.in b/src/gns/gns.conf.in
index bf59cac15..b34246cef 100644
--- a/src/gns/gns.conf.in
+++ b/src/gns/gns.conf.in
@@ -5,7 +5,6 @@ HOSTNAME = localhost
5BINARY = gnunet-service-gns 5BINARY = gnunet-service-gns
6UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-gns.sock 6UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-gns.sock
7@JAVAPORT@PORT = 2102 7@JAVAPORT@PORT = 2102
8USER_SERVICE = YES
9 8
10# Do we require users that want to access GNS to run this process 9# Do we require users that want to access GNS to run this process
11# (usually not a good idea) 10# (usually not a good idea)
@@ -17,9 +16,6 @@ UNIX_MATCH_GID = YES
17# How many queries is GNS allowed to perform in the background at the same time? 16# How many queries is GNS allowed to perform in the background at the same time?
18MAX_PARALLEL_BACKGROUND_QUERIES = 1000 17MAX_PARALLEL_BACKGROUND_QUERIES = 1000
19 18
20# How frequently do we try to publish our full zone?
21ZONE_PUBLISH_TIME_WINDOW = 4 h
22
23# Using caching or always ask DHT 19# Using caching or always ask DHT
24# USE_CACHE = YES 20# USE_CACHE = YES
25 21
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index 5ad7b4fae..f6f9889ac 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -397,7 +397,7 @@ reconnect (struct GNUNET_GNS_Handle *handle)
397 GNUNET_assert (NULL == handle->mq); 397 GNUNET_assert (NULL == handle->mq);
398 LOG (GNUNET_ERROR_TYPE_DEBUG, 398 LOG (GNUNET_ERROR_TYPE_DEBUG,
399 "Trying to connect to GNS\n"); 399 "Trying to connect to GNS\n");
400 handle->mq = GNUNET_CLIENT_connecT (handle->cfg, 400 handle->mq = GNUNET_CLIENT_connect (handle->cfg,
401 "gns", 401 "gns",
402 handlers, 402 handlers,
403 &mq_error_handler, 403 &mq_error_handler,
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
index 3e718dac8..cec31ff48 100644
--- a/src/gns/gnunet-service-gns.c
+++ b/src/gns/gnunet-service-gns.c
@@ -40,43 +40,6 @@
40#include "gnunet-service-gns_interceptor.h" 40#include "gnunet-service-gns_interceptor.h"
41#include "gnunet_protocols.h" 41#include "gnunet_protocols.h"
42 42
43/**
44 * The initial interval in milliseconds btween puts in
45 * a zone iteration
46 */
47#define INITIAL_PUT_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS
48
49/**
50 * The lower bound for the zone iteration interval
51 */
52#define MINIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_SECONDS
53
54/**
55 * The upper bound for the zone iteration interval
56 */
57#define MAXIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
58
59/**
60 * The default put interval for the zone iteration. In case
61 * no option is found
62 */
63#define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
64
65/**
66 * The factor the current zone iteration interval is divided by for each
67 * additional new record
68 */
69#define LATE_ITERATION_SPEEDUP_FACTOR 2
70
71/**
72 * How long until a DHT PUT attempt should time out?
73 */
74#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
75
76/**
77 * What replication level do we use for DHT PUT operations?
78 */
79#define DHT_GNS_REPLICATION_LEVEL 5
80 43
81/** 44/**
82 * GnsClient prototype 45 * GnsClient prototype
@@ -146,36 +109,14 @@ struct GnsClient
146 109
147 110
148/** 111/**
149 * Handle for DHT PUT activity triggered from the namestore monitor.
150 */
151struct MonitorActivity
152{
153 /**
154 * Kept in a DLL.
155 */
156 struct MonitorActivity *next;
157
158 /**
159 * Kept in a DLL.
160 */
161 struct MonitorActivity *prev;
162
163 /**
164 * Handle for the DHT PUT operation.
165 */
166 struct GNUNET_DHT_PutHandle *ph;
167};
168
169
170/**
171 * Our handle to the DHT 112 * Our handle to the DHT
172 */ 113 */
173static struct GNUNET_DHT_Handle *dht_handle; 114static struct GNUNET_DHT_Handle *dht_handle;
174 115
175/** 116/**
176 * Active DHT put operation (or NULL) 117 * Our handle to the namecache service
177 */ 118 */
178static struct GNUNET_DHT_PutHandle *active_put; 119static struct GNUNET_NAMECACHE_Handle *namecache_handle;
179 120
180/** 121/**
181 * Our handle to the namestore service 122 * Our handle to the namestore service
@@ -183,11 +124,6 @@ static struct GNUNET_DHT_PutHandle *active_put;
183static struct GNUNET_NAMESTORE_Handle *namestore_handle; 124static struct GNUNET_NAMESTORE_Handle *namestore_handle;
184 125
185/** 126/**
186 * Our handle to the namecache service
187 */
188static struct GNUNET_NAMECACHE_Handle *namecache_handle;
189
190/**
191 * Our handle to the identity service 127 * Our handle to the identity service
192 */ 128 */
193static struct GNUNET_IDENTITY_Handle *identity_handle; 129static struct GNUNET_IDENTITY_Handle *identity_handle;
@@ -199,68 +135,6 @@ static struct GNUNET_IDENTITY_Handle *identity_handle;
199static struct GNUNET_IDENTITY_Operation *identity_op; 135static struct GNUNET_IDENTITY_Operation *identity_op;
200 136
201/** 137/**
202 * Handle to iterate over our authoritative zone in namestore
203 */
204static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
205
206/**
207 * Handle to monitor namestore changes to instant propagation.
208 */
209static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
210
211/**
212 * Head of monitor activities; kept in a DLL.
213 */
214static struct MonitorActivity *ma_head;
215
216/**
217 * Tail of monitor activities; kept in a DLL.
218 */
219static struct MonitorActivity *ma_tail;
220
221/**
222 * Useful for zone update for DHT put
223 */
224static unsigned long long num_public_records;
225
226/**
227 * Last seen record count
228 */
229static unsigned long long last_num_public_records;
230
231/**
232 * Minimum relative expiration time of records seem during the current
233 * zone iteration.
234 */
235static struct GNUNET_TIME_Relative min_relative_record_time;
236
237/**
238 * Zone iteration PUT interval.
239 */
240static struct GNUNET_TIME_Relative put_interval;
241
242/**
243 * Default time window for zone iteration
244 */
245static struct GNUNET_TIME_Relative zone_publish_time_window_default;
246
247/**
248 * Time window for zone iteration, adjusted based on relative record
249 * expiration times in our zone.
250 */
251static struct GNUNET_TIME_Relative zone_publish_time_window;
252
253/**
254 * zone publish task
255 */
256static struct GNUNET_SCHEDULER_Task *zone_publish_task;
257
258/**
259 * #GNUNET_YES if zone has never been published before
260 */
261static int first_zone_iteration;
262
263/**
264 * #GNUNET_YES if ipv6 is supported 138 * #GNUNET_YES if ipv6 is supported
265 */ 139 */
266static int v6_enabled; 140static int v6_enabled;
@@ -285,8 +159,6 @@ static struct GNUNET_STATISTICS_Handle *statistics;
285static void 159static void
286shutdown_task (void *cls) 160shutdown_task (void *cls)
287{ 161{
288 struct MonitorActivity *ma;
289
290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 162 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
291 "Shutting down!\n"); 163 "Shutting down!\n");
292 GNS_interceptor_done (); 164 GNS_interceptor_done ();
@@ -303,35 +175,12 @@ shutdown_task (void *cls)
303 GNS_resolver_done (); 175 GNS_resolver_done ();
304 GNS_reverse_done (); 176 GNS_reverse_done ();
305 GNS_shorten_done (); 177 GNS_shorten_done ();
306 while (NULL != (ma = ma_head))
307 {
308 GNUNET_DHT_put_cancel (ma->ph);
309 GNUNET_CONTAINER_DLL_remove (ma_head,
310 ma_tail,
311 ma);
312 GNUNET_free (ma);
313 }
314 if (NULL != statistics) 178 if (NULL != statistics)
315 { 179 {
316 GNUNET_STATISTICS_destroy (statistics, 180 GNUNET_STATISTICS_destroy (statistics,
317 GNUNET_NO); 181 GNUNET_NO);
318 statistics = NULL; 182 statistics = NULL;
319 } 183 }
320 if (NULL != zone_publish_task)
321 {
322 GNUNET_SCHEDULER_cancel (zone_publish_task);
323 zone_publish_task = NULL;
324 }
325 if (NULL != namestore_iter)
326 {
327 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
328 namestore_iter = NULL;
329 }
330 if (NULL != zmon)
331 {
332 GNUNET_NAMESTORE_zone_monitor_stop (zmon);
333 zmon = NULL;
334 }
335 if (NULL != namestore_handle) 184 if (NULL != namestore_handle)
336 { 185 {
337 GNUNET_NAMESTORE_disconnect (namestore_handle); 186 GNUNET_NAMESTORE_disconnect (namestore_handle);
@@ -342,11 +191,6 @@ shutdown_task (void *cls)
342 GNUNET_NAMECACHE_disconnect (namecache_handle); 191 GNUNET_NAMECACHE_disconnect (namecache_handle);
343 namecache_handle = NULL; 192 namecache_handle = NULL;
344 } 193 }
345 if (NULL != active_put)
346 {
347 GNUNET_DHT_put_cancel (active_put);
348 active_put = NULL;
349 }
350 if (NULL != dht_handle) 194 if (NULL != dht_handle)
351 { 195 {
352 GNUNET_DHT_disconnect (dht_handle); 196 GNUNET_DHT_disconnect (dht_handle);
@@ -354,6 +198,7 @@ shutdown_task (void *cls)
354 } 198 }
355} 199}
356 200
201
357/** 202/**
358 * Called whenever a client is disconnected. 203 * Called whenever a client is disconnected.
359 * 204 *
@@ -413,408 +258,6 @@ client_connect_cb (void *cls,
413 258
414 259
415/** 260/**
416 * Method called periodically that triggers iteration over authoritative records
417 *
418 * @param cls closure
419 */
420static void
421publish_zone_dht_next (void *cls)
422{
423 zone_publish_task = NULL;
424 GNUNET_assert (NULL != namestore_iter);
425 GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
426}
427
428
429/**
430 * Periodically iterate over our zone and store everything in dht
431 *
432 * @param cls NULL
433 */
434static void
435publish_zone_dht_start (void *cls);
436
437
438/**
439 * Continuation called from DHT once the PUT operation is done.
440 *
441 * @param cls closure, NULL if called from regular iteration,
442 * `struct MonitorActivity` if called from #handle_monitor_event.
443 * @param success #GNUNET_OK on success
444 */
445static void
446dht_put_continuation (void *cls,
447 int success)
448{
449 struct MonitorActivity *ma = cls;
450 struct GNUNET_TIME_Relative next_put_interval;
451
452 num_public_records++;
453 if (NULL == ma)
454 {
455 active_put = NULL;
456 if ( (num_public_records > last_num_public_records) &&
457 (GNUNET_NO == first_zone_iteration) )
458 {
459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
460 "Last record count was lower than current record count. Reducing interval.\n");
461 put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
462 num_public_records);
463 next_put_interval = GNUNET_TIME_relative_divide (put_interval,
464 LATE_ITERATION_SPEEDUP_FACTOR);
465 }
466 else
467 next_put_interval = put_interval;
468 next_put_interval = GNUNET_TIME_relative_min (next_put_interval,
469 MAXIMUM_ZONE_ITERATION_INTERVAL);
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
471 "PUT complete, next PUT in %s!\n",
472 GNUNET_STRINGS_relative_time_to_string (next_put_interval,
473 GNUNET_YES));
474
475 GNUNET_STATISTICS_set (statistics,
476 "Current zone iteration interval (ms)",
477 next_put_interval.rel_value_us / 1000LL,
478 GNUNET_NO);
479 GNUNET_assert (NULL == zone_publish_task);
480 zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval,
481 &publish_zone_dht_next,
482 NULL);
483 }
484 else
485 {
486 GNUNET_CONTAINER_DLL_remove (ma_head,
487 ma_tail,
488 ma);
489 GNUNET_free (ma);
490 }
491}
492
493
494/**
495 * Convert namestore records from the internal format to that
496 * suitable for publication (removes private records, converts
497 * to absolute expiration time).
498 *
499 * @param rd input records
500 * @param rd_count size of the @a rd and @a rd_public arrays
501 * @param rd_public where to write the converted records
502 * @return number of records written to @a rd_public
503 */
504static unsigned int
505convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
506 unsigned int rd_count,
507 struct GNUNET_GNSRECORD_Data *rd_public)
508{
509 struct GNUNET_TIME_Absolute now;
510 unsigned int rd_public_count;
511 unsigned int i;
512
513 rd_public_count = 0;
514 now = GNUNET_TIME_absolute_get ();
515 for (i=0;i<rd_count;i++)
516 if (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
517 {
518 rd_public[rd_public_count] = rd[i];
519 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
520 {
521 /* GNUNET_GNSRECORD_block_create will convert to absolute time;
522 we just need to adjust our iteration frequency */
523 min_relative_record_time.rel_value_us =
524 GNUNET_MIN (rd_public[rd_public_count].expiration_time,
525 min_relative_record_time.rel_value_us);
526 }
527 else if (rd_public[rd_public_count].expiration_time < now.abs_value_us)
528 {
529 /* record already expired, skip it */
530 continue;
531 }
532 rd_public_count++;
533 }
534 return rd_public_count;
535}
536
537
538/**
539 * Store GNS records in the DHT.
540 *
541 * @param key key of the zone
542 * @param label label to store under
543 * @param rd_public public record data
544 * @param rd_public_count number of records in @a rd_public
545 * @param pc_arg closure argument to pass to the #dht_put_continuation
546 * @return DHT PUT handle, NULL on error
547 */
548static struct GNUNET_DHT_PutHandle *
549perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
550 const char *label,
551 const struct GNUNET_GNSRECORD_Data *rd_public,
552 unsigned int rd_public_count,
553 void *pc_arg)
554{
555 struct GNUNET_GNSRECORD_Block *block;
556 struct GNUNET_HashCode query;
557 struct GNUNET_TIME_Absolute expire;
558 size_t block_size;
559 struct GNUNET_DHT_PutHandle *ret;
560
561 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
562 rd_public);
563 block = GNUNET_GNSRECORD_block_create (key,
564 expire,
565 label,
566 rd_public,
567 rd_public_count);
568 if (NULL == block)
569 return NULL; /* whoops */
570 block_size = ntohl (block->purpose.size)
571 + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)
572 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
573 GNUNET_GNSRECORD_query_from_private_key (key,
574 label,
575 &query);
576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
577 "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n",
578 rd_public_count,
579 label,
580 GNUNET_STRINGS_absolute_time_to_string (expire),
581 GNUNET_h2s (&query));
582 ret = GNUNET_DHT_put (dht_handle,
583 &query,
584 DHT_GNS_REPLICATION_LEVEL,
585 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
586 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
587 block_size,
588 block,
589 expire,
590 &dht_put_continuation,
591 pc_arg);
592 GNUNET_free (block);
593 return ret;
594}
595
596
597/**
598 * We encountered an error in our zone iteration.
599 */
600static void
601zone_iteration_error (void *cls)
602{
603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
604 "Got disconnected from namestore database, retrying.\n");
605 namestore_iter = NULL;
606 /* We end up here on error/disconnect/shutdown, so potentially
607 while a zone publish task or a DHT put is still running; hence
608 we need to cancel those. */
609 if (NULL != zone_publish_task)
610 {
611 GNUNET_SCHEDULER_cancel (zone_publish_task);
612 zone_publish_task = NULL;
613 }
614 if (NULL != active_put)
615 {
616 GNUNET_DHT_put_cancel (active_put);
617 active_put = NULL;
618 }
619 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
620 NULL);
621}
622
623
624/**
625 * Zone iteration is completed.
626 */
627static void
628zone_iteration_finished (void *cls)
629{
630 /* we're done with one iteration, calculate when to do the next one */
631 namestore_iter = NULL;
632 last_num_public_records = num_public_records;
633 first_zone_iteration = GNUNET_NO;
634 if (0 == num_public_records)
635 {
636 /**
637 * If no records are known (startup) or none present
638 * we can safely set the interval to the value for a single
639 * record
640 */
641 put_interval = zone_publish_time_window;
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
643 "No records in namestore database.\n");
644 }
645 else
646 {
647 /* If records are present, next publication is based on the minimum
648 * relative expiration time of the records published divided by 4
649 */
650 zone_publish_time_window
651 = GNUNET_TIME_relative_min (GNUNET_TIME_relative_divide (min_relative_record_time, 4),
652 zone_publish_time_window_default);
653 put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
654 num_public_records);
655 }
656 /* reset for next iteration */
657 min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL;
658 put_interval = GNUNET_TIME_relative_max (MINIMUM_ZONE_ITERATION_INTERVAL,
659 put_interval);
660 put_interval = GNUNET_TIME_relative_min (put_interval,
661 MAXIMUM_ZONE_ITERATION_INTERVAL);
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
663 "Zone iteration finished. Adjusted zone iteration interval to %s\n",
664 GNUNET_STRINGS_relative_time_to_string (put_interval,
665 GNUNET_YES));
666 GNUNET_STATISTICS_set (statistics,
667 "Current zone iteration interval (in ms)",
668 put_interval.rel_value_us / 1000LL,
669 GNUNET_NO);
670 GNUNET_STATISTICS_update (statistics,
671 "Number of zone iterations",
672 1,
673 GNUNET_NO);
674 GNUNET_STATISTICS_set (statistics,
675 "Number of public records in DHT",
676 last_num_public_records,
677 GNUNET_NO);
678 GNUNET_assert (NULL == zone_publish_task);
679 if (0 == num_public_records)
680 zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval,
681 &publish_zone_dht_start,
682 NULL);
683 else
684 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
685 NULL);
686}
687
688
689/**
690 * Function used to put all records successively into the DHT.
691 *
692 * @param cls the closure (NULL)
693 * @param key the private key of the authority (ours)
694 * @param label the name of the records, NULL once the iteration is done
695 * @param rd_count the number of records in @a rd
696 * @param rd the record data
697 */
698static void
699put_gns_record (void *cls,
700 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
701 const char *label,
702 unsigned int rd_count,
703 const struct GNUNET_GNSRECORD_Data *rd)
704{
705 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
706 unsigned int rd_public_count;
707
708 rd_public_count = convert_records_for_export (rd,
709 rd_count,
710 rd_public);
711
712 if (0 == rd_public_count)
713 {
714 GNUNET_assert (NULL == zone_publish_task);
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
716 "Record set empty, moving to next record set\n");
717 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next,
718 NULL);
719 return;
720 }
721 /* We got a set of records to publish */
722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
723 "Starting DHT PUT\n");
724 active_put = perform_dht_put (key,
725 label,
726 rd_public,
727 rd_public_count,
728 NULL);
729 if (NULL == active_put)
730 {
731 GNUNET_break (0);
732 dht_put_continuation (NULL, GNUNET_NO);
733 }
734}
735
736
737/**
738 * Periodically iterate over all zones and store everything in DHT
739 *
740 * @param cls NULL
741 */
742static void
743publish_zone_dht_start (void *cls)
744{
745 zone_publish_task = NULL;
746
747 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
748 "Starting DHT zone update!\n");
749 /* start counting again */
750 num_public_records = 0;
751 GNUNET_assert (NULL == namestore_iter);
752 namestore_iter
753 = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
754 NULL, /* All zones */
755 &zone_iteration_error,
756 NULL,
757 &put_gns_record,
758 NULL,
759 &zone_iteration_finished,
760 NULL);
761}
762
763
764/**
765 * Process a record that was stored in the namestore
766 * (invoked by the monitor).
767 *
768 * @param cls closure, NULL
769 * @param zone private key of the zone; NULL on disconnect
770 * @param label label of the records; NULL on disconnect
771 * @param rd_count number of entries in @a rd array, 0 if label was deleted
772 * @param rd array of records with data to store
773 */
774static void
775handle_monitor_event (void *cls,
776 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
777 const char *label,
778 unsigned int rd_count,
779 const struct GNUNET_GNSRECORD_Data *rd)
780{
781 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
782 unsigned int rd_public_count;
783 struct MonitorActivity *ma;
784
785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
786 "Received %u records for label `%s' via namestore monitor\n",
787 rd_count,
788 label);
789 /* filter out records that are not public, and convert to
790 absolute expiration time. */
791 rd_public_count = convert_records_for_export (rd,
792 rd_count,
793 rd_public);
794 if (0 == rd_public_count)
795 return; /* nothing to do */
796 ma = GNUNET_new (struct MonitorActivity);
797 ma->ph = perform_dht_put (zone,
798 label,
799 rd,
800 rd_count,
801 ma);
802 if (NULL == ma->ph)
803 {
804 /* PUT failed, do not remember operation */
805 GNUNET_free (ma);
806 return;
807 }
808 GNUNET_CONTAINER_DLL_insert (ma_head,
809 ma_tail,
810 ma);
811}
812
813
814/* END DHT ZONE PROPAGATION */
815
816
817/**
818 * Reply to client with the result from our lookup. 261 * Reply to client with the result from our lookup.
819 * 262 *
820 * @param cls the closure (our client lookup handle) 263 * @param cls the closure (our client lookup handle)
@@ -1020,49 +463,6 @@ handle_rev_lookup (void *cls,
1020 463
1021 464
1022/** 465/**
1023 * The zone monitor is now in SYNC with the current state of the
1024 * name store. Start to perform periodic iterations.
1025 *
1026 * @param cls NULL
1027 */
1028static void
1029monitor_sync_event (void *cls)
1030{
1031 GNUNET_assert (NULL == zone_publish_task);
1032 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
1033 NULL);
1034}
1035
1036
1037/**
1038 * The zone monitor is now in SYNC with the current state of the
1039 * name store. Start to perform periodic iterations.
1040 *
1041 * @param cls NULL
1042 */
1043static void
1044handle_monitor_error (void *cls)
1045{
1046 if (NULL != zone_publish_task)
1047 {
1048 GNUNET_SCHEDULER_cancel (zone_publish_task);
1049 zone_publish_task = NULL;
1050 }
1051 if (NULL != namestore_iter)
1052 {
1053 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
1054 namestore_iter = NULL;
1055 }
1056 if (NULL != active_put)
1057 {
1058 GNUNET_DHT_put_cancel (active_put);
1059 active_put = NULL;
1060 }
1061 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
1062 NULL);
1063}
1064
1065/**
1066 * Method called to inform about the ego to be used for the master zone 466 * Method called to inform about the ego to be used for the master zone
1067 * for DNS interceptions. 467 * for DNS interceptions.
1068 * 468 *
@@ -1107,7 +507,6 @@ identity_reverse_cb (void *cls,
1107} 507}
1108 508
1109 509
1110
1111/** 510/**
1112 * Method called to inform about the ego to be used for the master zone 511 * Method called to inform about the ego to be used for the master zone
1113 * for DNS interceptions. 512 * for DNS interceptions.
@@ -1175,11 +574,10 @@ run (void *cls,
1175 const struct GNUNET_CONFIGURATION_Handle *c, 574 const struct GNUNET_CONFIGURATION_Handle *c,
1176 struct GNUNET_SERVICE_Handle *service) 575 struct GNUNET_SERVICE_Handle *service)
1177{ 576{
1178 unsigned long long max_parallel_bg_queries = 0; 577 unsigned long long max_parallel_bg_queries = 16;
1179 578
1180 v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6); 579 v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6);
1181 v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); 580 v4_enabled = GNUNET_NETWORK_test_pf (PF_INET);
1182 min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL;
1183 namestore_handle = GNUNET_NAMESTORE_connect (c); 581 namestore_handle = GNUNET_NAMESTORE_connect (c);
1184 if (NULL == namestore_handle) 582 if (NULL == namestore_handle)
1185 { 583 {
@@ -1188,7 +586,7 @@ run (void *cls,
1188 GNUNET_SCHEDULER_shutdown (); 586 GNUNET_SCHEDULER_shutdown ();
1189 return; 587 return;
1190 } 588 }
1191 namecache_handle = GNUNET_NAMECACHE_connect (c); 589 namecache_handle = GNUNET_NAMECACHE_connect (c);
1192 if (NULL == namecache_handle) 590 if (NULL == namecache_handle)
1193 { 591 {
1194 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 592 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1196,22 +594,9 @@ run (void *cls,
1196 GNUNET_SCHEDULER_shutdown (); 594 GNUNET_SCHEDULER_shutdown ();
1197 return; 595 return;
1198 } 596 }
1199
1200 put_interval = INITIAL_PUT_INTERVAL;
1201 zone_publish_time_window_default = DEFAULT_ZONE_PUBLISH_TIME_WINDOW;
1202 if (GNUNET_OK == 597 if (GNUNET_OK ==
1203 GNUNET_CONFIGURATION_get_value_time (c, "gns", 598 GNUNET_CONFIGURATION_get_value_number (c,
1204 "ZONE_PUBLISH_TIME_WINDOW", 599 "gns",
1205 &zone_publish_time_window_default))
1206 {
1207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1208 "Time window for zone iteration: %s\n",
1209 GNUNET_STRINGS_relative_time_to_string (zone_publish_time_window,
1210 GNUNET_YES));
1211 }
1212 zone_publish_time_window = zone_publish_time_window_default;
1213 if (GNUNET_OK ==
1214 GNUNET_CONFIGURATION_get_value_number (c, "gns",
1215 "MAX_PARALLEL_BACKGROUND_QUERIES", 600 "MAX_PARALLEL_BACKGROUND_QUERIES",
1216 &max_parallel_bg_queries)) 601 &max_parallel_bg_queries))
1217 { 602 {
@@ -1219,7 +604,6 @@ run (void *cls,
1219 "Number of allowed parallel background queries: %llu\n", 604 "Number of allowed parallel background queries: %llu\n",
1220 max_parallel_bg_queries); 605 max_parallel_bg_queries);
1221 } 606 }
1222
1223 dht_handle = GNUNET_DHT_connect (c, 607 dht_handle = GNUNET_DHT_connect (c,
1224 (unsigned int) max_parallel_bg_queries); 608 (unsigned int) max_parallel_bg_queries);
1225 if (NULL == dht_handle) 609 if (NULL == dht_handle)
@@ -1254,19 +638,7 @@ run (void *cls,
1254 GNS_shorten_init (namestore_handle, 638 GNS_shorten_init (namestore_handle,
1255 namecache_handle, 639 namecache_handle,
1256 dht_handle); 640 dht_handle);
1257 /* Schedule periodic put for our records. */
1258 first_zone_iteration = GNUNET_YES;
1259 statistics = GNUNET_STATISTICS_create ("gns", c); 641 statistics = GNUNET_STATISTICS_create ("gns", c);
1260 zmon = GNUNET_NAMESTORE_zone_monitor_start (c,
1261 NULL,
1262 GNUNET_NO,
1263 &handle_monitor_error,
1264 NULL,
1265 &handle_monitor_event,
1266 NULL,
1267 &monitor_sync_event,
1268 NULL);
1269 GNUNET_break (NULL != zmon);
1270 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); 642 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1271} 643}
1272 644
diff --git a/src/gns/gnunet-service-gns_reverser.c b/src/gns/gnunet-service-gns_reverser.c
index 931dc6809..b5b8b31b7 100644
--- a/src/gns/gnunet-service-gns_reverser.c
+++ b/src/gns/gnunet-service-gns_reverser.c
@@ -394,6 +394,7 @@ handle_gns_result_iter (void *cls,
394 it_task = GNUNET_SCHEDULER_add_now (&next_it, ith); 394 it_task = GNUNET_SCHEDULER_add_now (&next_it, ith);
395} 395}
396 396
397
397static void 398static void
398next_it (void *cls) 399next_it (void *cls)
399{ 400{
@@ -402,6 +403,7 @@ next_it (void *cls)
402 GNUNET_NAMESTORE_zone_iterator_next (namestore_iter); 403 GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
403} 404}
404 405
406
405static void 407static void
406iterator_cb (void *cls, 408iterator_cb (void *cls,
407 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, 409 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
@@ -487,6 +489,7 @@ store_reverse (void *cls,
487 GNUNET_free (ith); 489 GNUNET_free (ith);
488} 490}
489 491
492
490static void 493static void
491finished_cb (void *cls) 494finished_cb (void *cls)
492{ 495{
@@ -522,6 +525,7 @@ finished_cb (void *cls)
522 525
523} 526}
524 527
528
525static void 529static void
526it_error (void *cls) 530it_error (void *cls)
527{ 531{
@@ -529,6 +533,7 @@ it_error (void *cls)
529 "Error iterating for REVERSE\n"); 533 "Error iterating for REVERSE\n");
530} 534}
531 535
536
532static void 537static void
533check_reverse_records (void *cls) 538check_reverse_records (void *cls)
534{ 539{
diff --git a/src/gnsrecord/.gitignore b/src/gnsrecord/.gitignore
new file mode 100644
index 000000000..374abdb60
--- /dev/null
+++ b/src/gnsrecord/.gitignore
@@ -0,0 +1,4 @@
1test_gnsrecord_block_expiration
2test_gnsrecord_crypto
3test_gnsrecord_serialization
4zonefiles
diff --git a/src/hello/.gitignore b/src/hello/.gitignore
index 237e1a10e..bb49ceb20 100644
--- a/src/hello/.gitignore
+++ b/src/hello/.gitignore
@@ -1 +1,3 @@
1gnunet-hello 1gnunet-hello
2test_friend_hello
3test_hello
diff --git a/src/hostlist/.gitignore b/src/hostlist/.gitignore
index f20bc2d58..b16e3444a 100644
--- a/src/hostlist/.gitignore
+++ b/src/hostlist/.gitignore
@@ -1 +1,4 @@
1gnunet-daemon-hostlist 1gnunet-daemon-hostlist
2test_gnunet_daemon_hostlist
3test_gnunet_daemon_hostlist_learning
4test_gnunet_daemon_hostlist_reconnect
diff --git a/src/hostlist/gnunet-daemon-hostlist.c b/src/hostlist/gnunet-daemon-hostlist.c
index 7181a913b..a83d46e07 100644
--- a/src/hostlist/gnunet-daemon-hostlist.c
+++ b/src/hostlist/gnunet-daemon-hostlist.c
@@ -47,7 +47,7 @@ static int provide_hostlist;
47/** 47/**
48 * Handle to hostlist server's connect handler 48 * Handle to hostlist server's connect handler
49 */ 49 */
50static GNUNET_CORE_ConnecTEventHandler server_ch; 50static GNUNET_CORE_ConnectEventHandler server_ch;
51 51
52#endif 52#endif
53 53
@@ -81,12 +81,12 @@ static GNUNET_HOSTLIST_UriHandler client_adv_handler;
81/** 81/**
82 * Handle to hostlist client's connect handler 82 * Handle to hostlist client's connect handler
83 */ 83 */
84static GNUNET_CORE_ConnecTEventHandler client_ch; 84static GNUNET_CORE_ConnectEventHandler client_ch;
85 85
86/** 86/**
87 * Handle to hostlist client's disconnect handler 87 * Handle to hostlist client's disconnect handler
88 */ 88 */
89static GNUNET_CORE_DisconnecTEventHandler client_dh; 89static GNUNET_CORE_DisconnectEventHandler client_dh;
90 90
91GNUNET_NETWORK_STRUCT_BEGIN 91GNUNET_NETWORK_STRUCT_BEGIN
92 92
@@ -260,7 +260,7 @@ cleaning_task (void *cls)
260 "Hostlist daemon is shutting down\n"); 260 "Hostlist daemon is shutting down\n");
261 if (NULL != core) 261 if (NULL != core)
262 { 262 {
263 GNUNET_CORE_disconnecT (core); 263 GNUNET_CORE_disconnect (core);
264 core = NULL; 264 core = NULL;
265 } 265 }
266 if (bootstrapping) 266 if (bootstrapping)
@@ -330,7 +330,7 @@ run (void *cls,
330 &client_adv_handler, 330 &client_adv_handler,
331 learning); 331 learning);
332 core = 332 core =
333 GNUNET_CORE_connecT (cfg, 333 GNUNET_CORE_connect (cfg,
334 NULL, 334 NULL,
335 &core_init, 335 &core_init,
336 &connect_handler, 336 &connect_handler,
diff --git a/src/hostlist/gnunet-daemon-hostlist_client.c b/src/hostlist/gnunet-daemon-hostlist_client.c
index c1a2c2721..a973fcc28 100644
--- a/src/hostlist/gnunet-daemon-hostlist_client.c
+++ b/src/hostlist/gnunet-daemon-hostlist_client.c
@@ -1548,8 +1548,8 @@ save_hostlist_file (int shutdown)
1548int 1548int
1549GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c, 1549GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
1550 struct GNUNET_STATISTICS_Handle *st, 1550 struct GNUNET_STATISTICS_Handle *st,
1551 GNUNET_CORE_ConnecTEventHandler *ch, 1551 GNUNET_CORE_ConnectEventHandler *ch,
1552 GNUNET_CORE_DisconnecTEventHandler *dh, 1552 GNUNET_CORE_DisconnectEventHandler *dh,
1553 GNUNET_HOSTLIST_UriHandler *msgh, 1553 GNUNET_HOSTLIST_UriHandler *msgh,
1554 int learn) 1554 int learn)
1555{ 1555{
diff --git a/src/hostlist/gnunet-daemon-hostlist_client.h b/src/hostlist/gnunet-daemon-hostlist_client.h
index dd80d4a48..e41b90876 100644
--- a/src/hostlist/gnunet-daemon-hostlist_client.h
+++ b/src/hostlist/gnunet-daemon-hostlist_client.h
@@ -53,8 +53,8 @@ typedef void
53int 53int
54GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c, 54GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
55 struct GNUNET_STATISTICS_Handle *st, 55 struct GNUNET_STATISTICS_Handle *st,
56 GNUNET_CORE_ConnecTEventHandler *ch, 56 GNUNET_CORE_ConnectEventHandler *ch,
57 GNUNET_CORE_DisconnecTEventHandler *dh, 57 GNUNET_CORE_DisconnectEventHandler *dh,
58 GNUNET_HOSTLIST_UriHandler *msgh, 58 GNUNET_HOSTLIST_UriHandler *msgh,
59 int learn); 59 int learn);
60 60
diff --git a/src/hostlist/gnunet-daemon-hostlist_server.c b/src/hostlist/gnunet-daemon-hostlist_server.c
index b01dbc09e..48c1a5622 100644
--- a/src/hostlist/gnunet-daemon-hostlist_server.c
+++ b/src/hostlist/gnunet-daemon-hostlist_server.c
@@ -644,7 +644,7 @@ int
644GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c, 644GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
645 struct GNUNET_STATISTICS_Handle *st, 645 struct GNUNET_STATISTICS_Handle *st,
646 struct GNUNET_CORE_Handle *co, 646 struct GNUNET_CORE_Handle *co,
647 GNUNET_CORE_ConnecTEventHandler *server_ch, 647 GNUNET_CORE_ConnectEventHandler *server_ch,
648 int advertise) 648 int advertise)
649{ 649{
650 unsigned long long port; 650 unsigned long long port;
diff --git a/src/hostlist/gnunet-daemon-hostlist_server.h b/src/hostlist/gnunet-daemon-hostlist_server.h
index f18ad0ca2..d9f778a4b 100644
--- a/src/hostlist/gnunet-daemon-hostlist_server.h
+++ b/src/hostlist/gnunet-daemon-hostlist_server.h
@@ -46,7 +46,7 @@ int
46GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c, 46GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
47 struct GNUNET_STATISTICS_Handle *st, 47 struct GNUNET_STATISTICS_Handle *st,
48 struct GNUNET_CORE_Handle *core, 48 struct GNUNET_CORE_Handle *core,
49 GNUNET_CORE_ConnecTEventHandler *server_ch, 49 GNUNET_CORE_ConnectEventHandler *server_ch,
50 int advertise); 50 int advertise);
51 51
52 52
diff --git a/src/hostlist/test_gnunet_daemon_hostlist_learning.c b/src/hostlist/test_gnunet_daemon_hostlist_learning.c
index c39c57eb3..88ad22a1a 100644
--- a/src/hostlist/test_gnunet_daemon_hostlist_learning.c
+++ b/src/hostlist/test_gnunet_daemon_hostlist_learning.c
@@ -125,12 +125,12 @@ shutdown_testcase ()
125 } 125 }
126 if (NULL != adv_peer.core) 126 if (NULL != adv_peer.core)
127 { 127 {
128 GNUNET_CORE_disconnecT (adv_peer.core); 128 GNUNET_CORE_disconnect (adv_peer.core);
129 adv_peer.core = NULL; 129 adv_peer.core = NULL;
130 } 130 }
131 if (NULL != learn_peer.core) 131 if (NULL != learn_peer.core)
132 { 132 {
133 GNUNET_CORE_disconnecT (learn_peer.core); 133 GNUNET_CORE_disconnect (learn_peer.core);
134 learn_peer.core = NULL; 134 learn_peer.core = NULL;
135 } 135 }
136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -432,7 +432,7 @@ setup_learn_peer (struct PeerContext *p,
432 } 432 }
433 GNUNET_free (filename); 433 GNUNET_free (filename);
434 } 434 }
435 p->core = GNUNET_CORE_connecT (p->cfg, 435 p->core = GNUNET_CORE_connect (p->cfg,
436 NULL, 436 NULL,
437 NULL, 437 NULL,
438 NULL, 438 NULL,
@@ -567,13 +567,6 @@ main (int argc, char *argv[])
567 GNUNET_log_setup ("test-gnunet-daemon-hostlist", 567 GNUNET_log_setup ("test-gnunet-daemon-hostlist",
568 "WARNING", 568 "WARNING",
569 NULL); 569 NULL);
570#if !WINDOWS
571 system ("gnunet-peerinfo -s -c test_learning_adv_peer.conf > /dev/null");
572 system ("gnunet-peerinfo -s -c test_learning_learn_peer.conf > /dev/null");
573#else
574 system ("gnunet-peerinfo -s -c test_learning_adv_peer.conf > NUL");
575 system ("gnunet-peerinfo -s -c test_learning_learn_peer.conf > NUL");
576#endif
577 ret = check (); 570 ret = check ();
578 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1"); 571 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1");
579 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2"); 572 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2");
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c
index 220c36656..21ec235b6 100644
--- a/src/identity-provider/identity_provider_api.c
+++ b/src/identity-provider/identity_provider_api.c
@@ -380,7 +380,7 @@ reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
380 LOG (GNUNET_ERROR_TYPE_DEBUG, 380 LOG (GNUNET_ERROR_TYPE_DEBUG,
381 "Connecting to identity provider service.\n"); 381 "Connecting to identity provider service.\n");
382 382
383 h->mq = GNUNET_CLIENT_connecT (h->cfg, 383 h->mq = GNUNET_CLIENT_connect (h->cfg,
384 "identity-provider", 384 "identity-provider",
385 handlers, 385 handlers,
386 &mq_error_handler, 386 &mq_error_handler,
diff --git a/src/identity/.gitignore b/src/identity/.gitignore
index cbabc187e..634a0bdd6 100644
--- a/src/identity/.gitignore
+++ b/src/identity/.gitignore
@@ -1,2 +1,4 @@
1gnunet-service-identity 1gnunet-service-identity
2gnunet-identity 2gnunet-identity
3test_identity
4test_identity_defaults
diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c
index 10a64d1ba..905b3fd8b 100644
--- a/src/identity/identity_api.c
+++ b/src/identity/identity_api.c
@@ -575,7 +575,7 @@ reconnect (void *cls)
575 LOG (GNUNET_ERROR_TYPE_DEBUG, 575 LOG (GNUNET_ERROR_TYPE_DEBUG,
576 "Connecting to identity service.\n"); 576 "Connecting to identity service.\n");
577 GNUNET_assert (NULL == h->mq); 577 GNUNET_assert (NULL == h->mq);
578 h->mq = GNUNET_CLIENT_connecT (h->cfg, 578 h->mq = GNUNET_CLIENT_connect (h->cfg,
579 "identity", 579 "identity",
580 handlers, 580 handlers,
581 &mq_error_handler, 581 &mq_error_handler,
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index f27fd6e36..bf3ffe482 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -78,7 +78,7 @@ gnunetinclude_HEADERS = \
78 gnunet_namecache_service.h \ 78 gnunet_namecache_service.h \
79 gnunet_namestore_plugin.h \ 79 gnunet_namestore_plugin.h \
80 gnunet_namestore_service.h \ 80 gnunet_namestore_service.h \
81 gnunet_nat_lib.h \ 81 gnunet_nat_auto_service.h \
82 gnunet_nat_service.h \ 82 gnunet_nat_service.h \
83 gnunet_nc_lib.h \ 83 gnunet_nc_lib.h \
84 gnunet_network_lib.h \ 84 gnunet_network_lib.h \
diff --git a/src/include/gnunet_cadet_service.h b/src/include/gnunet_cadet_service.h
index c32311643..7090d4410 100644
--- a/src/include/gnunet_cadet_service.h
+++ b/src/include/gnunet_cadet_service.h
@@ -67,15 +67,6 @@ struct GNUNET_CADET_Channel;
67 */ 67 */
68struct GNUNET_CADET_Port; 68struct GNUNET_CADET_Port;
69 69
70/**
71 * Hash to be used in Cadet communication. Only 256 bits needed,
72 * instead of the 512 from `struct GNUNET_HashCode`.
73 */
74struct GNUNET_CADET_Hash
75{
76 unsigned char bits[256 / 8];
77};
78
79 70
80/** 71/**
81 * Channel options. Second line indicates filed in the 72 * Channel options. Second line indicates filed in the
@@ -102,9 +93,9 @@ enum GNUNET_CADET_ChannelOption
102 93
103 /** 94 /**
104 * Enable out of order delivery of messages. 95 * Enable out of order delivery of messages.
105 * Yes/No. 96 * Set bit for out-of-order delivery.
106 */ 97 */
107 GNUNET_CADET_OPTION_OOORDER = 0x4, 98 GNUNET_CADET_OPTION_OUT_OF_ORDER = 0x4,
108 99
109 /** 100 /**
110 * Who is the peer at the other end of the channel. 101 * Who is the peer at the other end of the channel.
@@ -255,8 +246,7 @@ GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle);
255struct GNUNET_CADET_Port * 246struct GNUNET_CADET_Port *
256GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h, 247GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
257 const struct GNUNET_HashCode *port, 248 const struct GNUNET_HashCode *port,
258 GNUNET_CADET_InboundChannelNotificationHandler 249 GNUNET_CADET_InboundChannelNotificationHandler new_channel,
259 new_channel,
260 void *new_channel_cls); 250 void *new_channel_cls);
261 251
262/** 252/**
@@ -332,7 +322,8 @@ union GNUNET_CADET_ChannelInfo
332 */ 322 */
333const union GNUNET_CADET_ChannelInfo * 323const union GNUNET_CADET_ChannelInfo *
334GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, 324GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
335 enum GNUNET_CADET_ChannelOption option, ...); 325 enum GNUNET_CADET_ChannelOption option,
326 ...);
336 327
337 328
338/** 329/**
@@ -421,10 +412,10 @@ typedef void
421(*GNUNET_CADET_ChannelCB) (void *cls, 412(*GNUNET_CADET_ChannelCB) (void *cls,
422 const struct GNUNET_PeerIdentity *root, 413 const struct GNUNET_PeerIdentity *root,
423 const struct GNUNET_PeerIdentity *dest, 414 const struct GNUNET_PeerIdentity *dest,
424 uint32_t port, 415 uint32_t /* UGH */ port,
425 uint32_t root_channel_number, 416 uint32_t /* ugh */ root_channel_number,
426 uint32_t dest_channel_number, 417 uint32_t /* ugh */ dest_channel_number,
427 uint32_t public_channel_number); 418 uint32_t /* ugh */ public_channel_number);
428 419
429/** 420/**
430 * Method called to retrieve information about all peers in CADET, called 421 * Method called to retrieve information about all peers in CADET, called
@@ -491,6 +482,28 @@ typedef void
491 482
492 483
493/** 484/**
485 * Hash uniquely identifying a connection below a tunnel.
486 */
487struct GNUNET_CADET_ConnectionTunnelIdentifier
488{
489 struct GNUNET_ShortHashCode connection_of_tunnel;
490};
491
492
493/**
494 * Number identifying a CADET channel within a tunnel.
495 */
496struct GNUNET_CADET_ChannelTunnelNumber
497{
498 /**
499 * Which number does this channel have that uniquely identfies
500 * it within its tunnel?
501 */
502 uint32_t cn GNUNET_PACKED;
503};
504
505
506/**
494 * Method called to retrieve information about a specific tunnel the cadet peer 507 * Method called to retrieve information about a specific tunnel the cadet peer
495 * has established, o`r is trying to establish. 508 * has established, o`r is trying to establish.
496 * 509 *
@@ -508,8 +521,8 @@ typedef void
508 const struct GNUNET_PeerIdentity *peer, 521 const struct GNUNET_PeerIdentity *peer,
509 unsigned int n_channels, 522 unsigned int n_channels,
510 unsigned int n_connections, 523 unsigned int n_connections,
511 uint32_t *channels, 524 const struct GNUNET_CADET_ChannelTunnelNumber *channels,
512 struct GNUNET_CADET_Hash *connections, 525 const struct GNUNET_CADET_ConnectionTunnelIdentifier *connections,
513 unsigned int estate, 526 unsigned int estate,
514 unsigned int cstate); 527 unsigned int cstate);
515 528
@@ -528,7 +541,7 @@ typedef void
528void 541void
529GNUNET_CADET_get_channel (struct GNUNET_CADET_Handle *h, 542GNUNET_CADET_get_channel (struct GNUNET_CADET_Handle *h,
530 struct GNUNET_PeerIdentity *peer, 543 struct GNUNET_PeerIdentity *peer,
531 uint32_t channel_number, 544 uint32_t /* UGH */ channel_number,
532 GNUNET_CADET_ChannelCB callback, 545 GNUNET_CADET_ChannelCB callback,
533 void *callback_cls); 546 void *callback_cls);
534 547
diff --git a/src/include/gnunet_client_lib.h b/src/include/gnunet_client_lib.h
index f98620dfa..613349fdd 100644
--- a/src/include/gnunet_client_lib.h
+++ b/src/include/gnunet_client_lib.h
@@ -57,7 +57,7 @@ extern "C"
57 * @return the message queue, NULL on error 57 * @return the message queue, NULL on error
58 */ 58 */
59struct GNUNET_MQ_Handle * 59struct GNUNET_MQ_Handle *
60GNUNET_CLIENT_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg, 60GNUNET_CLIENT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
61 const char *service_name, 61 const char *service_name,
62 const struct GNUNET_MQ_MessageHandler *handlers, 62 const struct GNUNET_MQ_MessageHandler *handlers,
63 GNUNET_MQ_ErrorHandler error_handler, 63 GNUNET_MQ_ErrorHandler error_handler,
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index 897502155..9ad604711 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -66,7 +66,7 @@ extern "C"
66/** 66/**
67 * Version of the API (for entire gnunetutil.so library). 67 * Version of the API (for entire gnunetutil.so library).
68 */ 68 */
69#define GNUNET_UTIL_VERSION 0x000A0101 69#define GNUNET_UTIL_VERSION 0x000A0102
70 70
71 71
72/** 72/**
@@ -558,6 +558,19 @@ GNUNET_logger_remove (GNUNET_Logger logger,
558 558
559/** 559/**
560 * @ingroup logging 560 * @ingroup logging
561 * Convert a short hash value to a string (for printing debug messages).
562 * This is one of the very few calls in the entire API that is
563 * NOT reentrant!
564 *
565 * @param shc the hash code
566 * @return string
567 */
568const char *
569GNUNET_sh2s (const struct GNUNET_ShortHashCode *shc);
570
571
572/**
573 * @ingroup logging
561 * Convert a hash value to a string (for printing debug messages). 574 * Convert a hash value to a string (for printing debug messages).
562 * This is one of the very few calls in the entire API that is 575 * This is one of the very few calls in the entire API that is
563 * NOT reentrant! 576 * NOT reentrant!
@@ -655,7 +668,7 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
655/** 668/**
656 * @ingroup logging 669 * @ingroup logging
657 * Use this for fatal errors that cannot be handled 670 * Use this for fatal errors that cannot be handled
658 * 671 *
659 * @param cond Condition to evaluate 672 * @param cond Condition to evaluate
660 * @param comp Component string to use for logging 673 * @param comp Component string to use for logging
661 */ 674 */
diff --git a/src/include/gnunet_constants.h b/src/include/gnunet_constants.h
index ef9b27318..1d0232cea 100644
--- a/src/include/gnunet_constants.h
+++ b/src/include/gnunet_constants.h
@@ -127,9 +127,9 @@ extern "C"
127 127
128/** 128/**
129 * Size of the CADET message overhead: 129 * Size of the CADET message overhead:
130 * = sizeof (struct GNUNET_CADET_Encrypted) 130 * = sizeof (struct GNUNET_CADET_TunnelEncryptedMessage)
131 * + sizeof (struct GNUNET_CADET_Data) 131 * + sizeof (struct GNUNET_CADET_ChannelAppDataMessage)
132 * + sizeof (struct GNUNET_CADET_ACK)) 132 * + sizeof (struct GNUNET_CADET_ConnectionEncryptedAckMessage))
133 * 133 *
134 * Checked for correcteness in gnunet-service-cadet_tunnel.c: GCT_init(). 134 * Checked for correcteness in gnunet-service-cadet_tunnel.c: GCT_init().
135 */ 135 */
diff --git a/src/include/gnunet_container_lib.h b/src/include/gnunet_container_lib.h
index 03c47c201..f3aaa943b 100644
--- a/src/include/gnunet_container_lib.h
+++ b/src/include/gnunet_container_lib.h
@@ -1285,6 +1285,275 @@ GNUNET_CONTAINER_multipeermap_get_random (const struct GNUNET_CONTAINER_MultiPee
1285 void *it_cls); 1285 void *it_cls);
1286 1286
1287 1287
1288/* ***************** Version of Multihashmap for short hashes ****************** */
1289
1290/**
1291 * @ingroup hashmap
1292 * Iterator over hash map entries.
1293 *
1294 * @param cls closure
1295 * @param key current public key
1296 * @param value value in the hash map
1297 * @return #GNUNET_YES if we should continue to
1298 * iterate,
1299 * #GNUNET_NO if not.
1300 */
1301typedef int
1302(*GNUNET_CONTAINER_ShortmapIterator) (void *cls,
1303 const struct GNUNET_ShortHashCode *key,
1304 void *value);
1305
1306
1307/**
1308 * Hash map from peer identities to values.
1309 */
1310struct GNUNET_CONTAINER_MultiShortmap;
1311
1312
1313/**
1314 * @ingroup hashmap
1315 * Create a multi peer map (hash map for public keys of peers).
1316 *
1317 * @param len initial size (map will grow as needed)
1318 * @param do_not_copy_keys #GNUNET_NO is always safe and should be used by default;
1319 * #GNUNET_YES means that on 'put', the 'key' does not have
1320 * to be copied as the destination of the pointer is
1321 * guaranteed to be life as long as the value is stored in
1322 * the hashmap. This can significantly reduce memory
1323 * consumption, but of course is also a recipie for
1324 * heap corruption if the assumption is not true. Only
1325 * use this if (1) memory use is important in this case and
1326 * (2) you have triple-checked that the invariant holds
1327 * @return NULL on error
1328 */
1329struct GNUNET_CONTAINER_MultiShortmap *
1330GNUNET_CONTAINER_multishortmap_create (unsigned int len,
1331 int do_not_copy_keys);
1332
1333
1334/**
1335 * @ingroup hashmap
1336 * Destroy a hash map. Will not free any values
1337 * stored in the hash map!
1338 *
1339 * @param map the map
1340 */
1341void
1342GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap *map);
1343
1344
1345/**
1346 * @ingroup hashmap
1347 * Given a key find a value in the map matching the key.
1348 *
1349 * @param map the map
1350 * @param key what to look for
1351 * @return NULL if no value was found; note that
1352 * this is indistinguishable from values that just
1353 * happen to be NULL; use "contains" to test for
1354 * key-value pairs with value NULL
1355 */
1356void *
1357GNUNET_CONTAINER_multishortmap_get (const struct GNUNET_CONTAINER_MultiShortmap *map,
1358 const struct GNUNET_ShortHashCode *key);
1359
1360
1361/**
1362 * @ingroup hashmap
1363 * Remove the given key-value pair from the map. Note that if the
1364 * key-value pair is in the map multiple times, only one of the pairs
1365 * will be removed.
1366 *
1367 * @param map the map
1368 * @param key key of the key-value pair
1369 * @param value value of the key-value pair
1370 * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair
1371 * is not in the map
1372 */
1373int
1374GNUNET_CONTAINER_multishortmap_remove (struct GNUNET_CONTAINER_MultiShortmap *map,
1375 const struct GNUNET_ShortHashCode * key,
1376 const void *value);
1377
1378/**
1379 * @ingroup hashmap
1380 * Remove all entries for the given key from the map.
1381 * Note that the values would not be "freed".
1382 *
1383 * @param map the map
1384 * @param key identifies values to be removed
1385 * @return number of values removed
1386 */
1387int
1388GNUNET_CONTAINER_multishortmap_remove_all (struct GNUNET_CONTAINER_MultiShortmap *map,
1389 const struct GNUNET_ShortHashCode *key);
1390
1391
1392/**
1393 * @ingroup hashmap
1394 * Check if the map contains any value under the given
1395 * key (including values that are NULL).
1396 *
1397 * @param map the map
1398 * @param key the key to test if a value exists for it
1399 * @return #GNUNET_YES if such a value exists,
1400 * #GNUNET_NO if not
1401 */
1402int
1403GNUNET_CONTAINER_multishortmap_contains (const struct GNUNET_CONTAINER_MultiShortmap *map,
1404 const struct GNUNET_ShortHashCode *key);
1405
1406
1407/**
1408 * @ingroup hashmap
1409 * Check if the map contains the given value under the given
1410 * key.
1411 *
1412 * @param map the map
1413 * @param key the key to test if a value exists for it
1414 * @param value value to test for
1415 * @return #GNUNET_YES if such a value exists,
1416 * #GNUNET_NO if not
1417 */
1418int
1419GNUNET_CONTAINER_multishortmap_contains_value (const struct GNUNET_CONTAINER_MultiShortmap *map,
1420 const struct GNUNET_ShortHashCode * key,
1421 const void *value);
1422
1423
1424/**
1425 * @ingroup hashmap
1426 * Store a key-value pair in the map.
1427 *
1428 * @param map the map
1429 * @param key key to use
1430 * @param value value to use
1431 * @param opt options for put
1432 * @return #GNUNET_OK on success,
1433 * #GNUNET_NO if a value was replaced (with REPLACE)
1434 * #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the
1435 * value already exists
1436 */
1437int
1438GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map,
1439 const struct GNUNET_ShortHashCode *key,
1440 void *value,
1441 enum GNUNET_CONTAINER_MultiHashMapOption opt);
1442
1443
1444/**
1445 * @ingroup hashmap
1446 * Get the number of key-value pairs in the map.
1447 *
1448 * @param map the map
1449 * @return the number of key value pairs
1450 */
1451unsigned int
1452GNUNET_CONTAINER_multishortmap_size (const struct GNUNET_CONTAINER_MultiShortmap *map);
1453
1454
1455/**
1456 * @ingroup hashmap
1457 * Iterate over all entries in the map.
1458 *
1459 * @param map the map
1460 * @param it function to call on each entry
1461 * @param it_cls extra argument to @a it
1462 * @return the number of key value pairs processed,
1463 * #GNUNET_SYSERR if it aborted iteration
1464 */
1465int
1466GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map,
1467 GNUNET_CONTAINER_ShortmapIterator it,
1468 void *it_cls);
1469
1470
1471struct GNUNET_CONTAINER_MultiShortmapIterator;
1472
1473
1474/**
1475 * @ingroup hashmap
1476 * Create an iterator for a multihashmap.
1477 * The iterator can be used to retrieve all the elements in the multihashmap
1478 * one by one, without having to handle all elements at once (in contrast to
1479 * #GNUNET_CONTAINER_multishortmap_iterate). Note that the iterator can not be
1480 * used anymore if elements have been removed from @a map after the creation of
1481 * the iterator, or 'map' has been destroyed. Adding elements to @a map may
1482 * result in skipped or repeated elements.
1483 *
1484 * @param map the map to create an iterator for
1485 * @return an iterator over the given multihashmap @a map
1486 */
1487struct GNUNET_CONTAINER_MultiShortmapIterator *
1488GNUNET_CONTAINER_multishortmap_iterator_create (const struct GNUNET_CONTAINER_MultiShortmap *map);
1489
1490
1491/**
1492 * @ingroup hashmap
1493 * Retrieve the next element from the hash map at the iterator's
1494 * position. If there are no elements left, #GNUNET_NO is returned,
1495 * and @a key and @a value are not modified. This operation is only
1496 * allowed if no elements have been removed from the multihashmap
1497 * since the creation of @a iter, and the map has not been destroyed.
1498 * Adding elements may result in repeating or skipping elements.
1499 *
1500 * @param iter the iterator to get the next element from
1501 * @param key pointer to store the key in, can be NULL
1502 * @param value pointer to store the value in, can be NULL
1503 * @return #GNUNET_YES we returned an element,
1504 * #GNUNET_NO if we are out of elements
1505 */
1506int
1507GNUNET_CONTAINER_multishortmap_iterator_next (struct GNUNET_CONTAINER_MultiShortmapIterator *iter,
1508 struct GNUNET_ShortHashCode *key,
1509 const void **value);
1510
1511
1512/**
1513 * @ingroup hashmap
1514 * Destroy a multishortmap iterator.
1515 *
1516 * @param iter the iterator to destroy
1517 */
1518void
1519GNUNET_CONTAINER_multishortmap_iterator_destroy (struct GNUNET_CONTAINER_MultiShortmapIterator *iter);
1520
1521
1522/**
1523 * @ingroup hashmap
1524 * Iterate over all entries in the map that match a particular key.
1525 *
1526 * @param map the map
1527 * @param key public key that the entries must correspond to
1528 * @param it function to call on each entry
1529 * @param it_cls extra argument to @a it
1530 * @return the number of key value pairs processed,
1531 * #GNUNET_SYSERR if it aborted iteration
1532 */
1533int
1534GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map,
1535 const struct GNUNET_ShortHashCode *key,
1536 GNUNET_CONTAINER_ShortmapIterator it,
1537 void *it_cls);
1538
1539
1540/**
1541 * @ingroup hashmap
1542 * Call @a it on a random value from the map, or not at all
1543 * if the map is empty. Note that this function has linear
1544 * complexity (in the size of the map).
1545 *
1546 * @param map the map
1547 * @param it function to call on a random entry
1548 * @param it_cls extra argument to @a it
1549 * @return the number of key value pairs processed, zero or one.
1550 */
1551unsigned int
1552GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiShortmap *map,
1553 GNUNET_CONTAINER_ShortmapIterator it,
1554 void *it_cls);
1555
1556
1288/* Version of multihashmap with 32 bit keys */ 1557/* Version of multihashmap with 32 bit keys */
1289 1558
1290/** 1559/**
@@ -1915,8 +2184,8 @@ GNUNET_CONTAINER_heap_get_size (const struct GNUNET_CONTAINER_Heap *heap);
1915 * @return cost of the node 2184 * @return cost of the node
1916 */ 2185 */
1917GNUNET_CONTAINER_HeapCostType 2186GNUNET_CONTAINER_HeapCostType
1918GNUNET_CONTAINER_heap_node_get_cost (const struct GNUNET_CONTAINER_HeapNode 2187GNUNET_CONTAINER_heap_node_get_cost (const struct GNUNET_CONTAINER_HeapNode *node);
1919 *node); 2188
1920 2189
1921/** 2190/**
1922 * @ingroup heap 2191 * @ingroup heap
@@ -2006,13 +2275,11 @@ GNUNET_CONTAINER_heap_remove_node (struct GNUNET_CONTAINER_HeapNode *node);
2006 * @ingroup heap 2275 * @ingroup heap
2007 * Updates the cost of any node in the tree 2276 * Updates the cost of any node in the tree
2008 * 2277 *
2009 * @param heap heap to modify
2010 * @param node node for which the cost is to be changed 2278 * @param node node for which the cost is to be changed
2011 * @param new_cost new cost for the node 2279 * @param new_cost new cost for the node
2012 */ 2280 */
2013void 2281void
2014GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_Heap *heap, 2282GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_HeapNode *node,
2015 struct GNUNET_CONTAINER_HeapNode *node,
2016 GNUNET_CONTAINER_HeapCostType new_cost); 2283 GNUNET_CONTAINER_HeapCostType new_cost);
2017 2284
2018 2285
diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h
index 6ec486b26..8136770b7 100644
--- a/src/include/gnunet_core_service.h
+++ b/src/include/gnunet_core_service.h
@@ -91,30 +91,8 @@ struct GNUNET_CORE_Handle;
91 * @param cls closure 91 * @param cls closure
92 * @param peer peer identity this notification is about 92 * @param peer peer identity this notification is about
93 */ 93 */
94typedef void
95(*GNUNET_CORE_ConnectEventHandler) (void *cls,
96 const struct GNUNET_PeerIdentity *peer);
97
98
99/**
100 * Method called whenever a peer disconnects.
101 *
102 * @param cls closure
103 * @param peer peer identity this notification is about
104 */
105typedef void
106(*GNUNET_CORE_DisconnectEventHandler) (void *cls,
107 const struct GNUNET_PeerIdentity *peer);
108
109
110/**
111 * Method called whenever a given peer connects.
112 *
113 * @param cls closure
114 * @param peer peer identity this notification is about
115 */
116typedef void * 94typedef void *
117(*GNUNET_CORE_ConnecTEventHandler) (void *cls, 95(*GNUNET_CORE_ConnectEventHandler) (void *cls,
118 const struct GNUNET_PeerIdentity *peer, 96 const struct GNUNET_PeerIdentity *peer,
119 struct GNUNET_MQ_Handle *mq); 97 struct GNUNET_MQ_Handle *mq);
120 98
@@ -126,55 +104,12 @@ typedef void *
126 * @param peer peer identity this notification is about 104 * @param peer peer identity this notification is about
127 */ 105 */
128typedef void 106typedef void
129(*GNUNET_CORE_DisconnecTEventHandler) (void *cls, 107(*GNUNET_CORE_DisconnectEventHandler) (void *cls,
130 const struct GNUNET_PeerIdentity *peer, 108 const struct GNUNET_PeerIdentity *peer,
131 void *peer_cls); 109 void *peer_cls);
132 110
133 111
134/** 112/**
135 * Functions with this signature are called whenever a message is
136 * received or transmitted.
137 *
138 * @param cls closure (set from #GNUNET_CORE_connect)
139 * @param peer the other peer involved (sender or receiver, NULL
140 * for loopback messages where we are both sender and receiver)
141 * @param message the actual message
142 * @return #GNUNET_OK to keep the connection open,
143 * #GNUNET_SYSERR to close connection to the peer (signal serious error)
144 */
145typedef int
146(*GNUNET_CORE_MessageCallback) (void *cls,
147 const struct GNUNET_PeerIdentity *other,
148 const struct GNUNET_MessageHeader *message);
149
150
151/**
152 * Message handler. Each struct specifies how to handle on particular
153 * type of message received.
154 */
155struct GNUNET_CORE_MessageHandler
156{
157 /**
158 * Function to call for messages of @e type.
159 */
160 GNUNET_CORE_MessageCallback callback;
161
162 /**
163 * Type of the message this handler covers.
164 */
165 uint16_t type;
166
167 /**
168 * Expected size of messages of this type. Use 0 for variable-size.
169 * If non-zero, messages of the given type will be discarded if they
170 * do not have the right size.
171 */
172 uint16_t expected_size;
173
174};
175
176
177/**
178 * Function called after #GNUNET_CORE_connect has succeeded (or failed 113 * Function called after #GNUNET_CORE_connect has succeeded (or failed
179 * for good). Note that the private key of the peer is intentionally 114 * for good). Note that the private key of the peer is intentionally
180 * not exposed here; if you need it, your process should try to read 115 * not exposed here; if you need it, your process should try to read
@@ -208,26 +143,6 @@ typedef void
208 * connected to the core service 143 * connected to the core service
209 * @param connects function to call on peer connect, can be NULL 144 * @param connects function to call on peer connect, can be NULL
210 * @param disconnects function to call on peer disconnect / timeout, can be NULL 145 * @param disconnects function to call on peer disconnect / timeout, can be NULL
211 * @param inbound_notify function to call for all inbound messages, can be NULL
212 * note that the core is allowed to drop notifications about inbound
213 * messages if the client does not process them fast enough (for this
214 * notification type, a bounded queue is used)
215 * @param inbound_hdr_only set to #GNUNET_YES if @a inbound_notify will only read the
216 * `struct GNUNET_MessageHeader` and hence we do not need to give it the full message;
217 * can be used to improve efficiency, ignored if inbound_notify is NULL
218 * note that the core is allowed to drop notifications about inbound
219 * messages if the client does not process them fast enough (for this
220 * notification type, a bounded queue is used)
221 * @param outbound_notify function to call for all outbound messages, can be NULL;
222 * note that the core is allowed to drop notifications about outbound
223 * messages if the client does not process them fast enough (for this
224 * notification type, a bounded queue is used)
225 * @param outbound_hdr_only set to #GNUNET_YES if @a outbound_notify will only read the
226 * `struct GNUNET_MessageHeader` and hence we do not need to give it the full message
227 * can be used to improve efficiency, ignored if outbound_notify is NULL
228 * note that the core is allowed to drop notifications about outbound
229 * messages if the client does not process them fast enough (for this
230 * notification type, a bounded queue is used)
231 * @param handlers callbacks for messages we care about, NULL-terminated 146 * @param handlers callbacks for messages we care about, NULL-terminated
232 * note that the core is allowed to drop notifications about inbound 147 * note that the core is allowed to drop notifications about inbound
233 * messages if the client does not process them fast enough (for this 148 * messages if the client does not process them fast enough (for this
@@ -241,53 +156,6 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
241 GNUNET_CORE_StartupCallback init, 156 GNUNET_CORE_StartupCallback init,
242 GNUNET_CORE_ConnectEventHandler connects, 157 GNUNET_CORE_ConnectEventHandler connects,
243 GNUNET_CORE_DisconnectEventHandler disconnects, 158 GNUNET_CORE_DisconnectEventHandler disconnects,
244 GNUNET_CORE_MessageCallback inbound_notify,
245 int inbound_hdr_only,
246 GNUNET_CORE_MessageCallback outbound_notify,
247 int outbound_hdr_only,
248 const struct GNUNET_CORE_MessageHandler *handlers);
249
250/**
251 * Disconnect from the core service. This function can only
252 * be called *after* all pending #GNUNET_CORE_notify_transmit_ready
253 * requests have been explicitly cancelled.
254 *
255 * @param handle connection to core to disconnect
256 */
257void
258GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle);
259
260
261/**
262 * Connect to the core service. Note that the connection may complete
263 * (or fail) asynchronously. This function primarily causes the given
264 * callback notification functions to be invoked whenever the
265 * specified event happens. The maximum number of queued
266 * notifications (queue length) is per client; the queue is shared
267 * across all types of notifications. So a slow client that registers
268 * for @a outbound_notify also risks missing @a inbound_notify messages.
269 * Certain events (such as connect/disconnect notifications) are not
270 * subject to queue size limitations.
271 *
272 * @param cfg configuration to use
273 * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
274 * @param init callback to call once we have successfully
275 * connected to the core service
276 * @param connects function to call on peer connect, can be NULL
277 * @param disconnects function to call on peer disconnect / timeout, can be NULL
278 * @param handlers callbacks for messages we care about, NULL-terminated
279 * note that the core is allowed to drop notifications about inbound
280 * messages if the client does not process them fast enough (for this
281 * notification type, a bounded queue is used)
282 * @return handle to the core service (only useful for disconnect until @a init is called),
283 * NULL on error (in this case, init is never called)
284 */
285struct GNUNET_CORE_Handle *
286GNUNET_CORE_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
287 void *cls,
288 GNUNET_CORE_StartupCallback init,
289 GNUNET_CORE_ConnecTEventHandler connects,
290 GNUNET_CORE_DisconnecTEventHandler disconnects,
291 const struct GNUNET_MQ_MessageHandler *handlers); 159 const struct GNUNET_MQ_MessageHandler *handlers);
292 160
293 161
@@ -297,7 +165,7 @@ GNUNET_CORE_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
297 * @param handle connection to core to disconnect 165 * @param handle connection to core to disconnect
298 */ 166 */
299void 167void
300GNUNET_CORE_disconnecT (struct GNUNET_CORE_Handle *handle); 168GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle);
301 169
302 170
303/** 171/**
@@ -305,7 +173,7 @@ GNUNET_CORE_disconnecT (struct GNUNET_CORE_Handle *handle);
305 * so that it is transmitted with the given @a priority and 173 * so that it is transmitted with the given @a priority and
306 * the given @a cork value. 174 * the given @a cork value.
307 * 175 *
308 * @param cork desired corking 176 * @param cork desired corking
309 * @param priority desired message priority 177 * @param priority desired message priority
310 * @param[out] flags set to `flags` value for #GNUNET_MQ_set_options() 178 * @param[out] flags set to `flags` value for #GNUNET_MQ_set_options()
311 * @return `extra` argument to give to #GNUNET_MQ_set_options() 179 * @return `extra` argument to give to #GNUNET_MQ_set_options()
@@ -320,7 +188,7 @@ GNUNET_CORE_get_mq_options (int cork,
320 * Obtain the message queue for a connected peer. 188 * Obtain the message queue for a connected peer.
321 * 189 *
322 * @param h the core handle 190 * @param h the core handle
323 * @param pid the identity of the peer 191 * @param pid the identity of the peer
324 * @return NULL if @a pid is not connected 192 * @return NULL if @a pid is not connected
325 */ 193 */
326struct GNUNET_MQ_Handle * 194struct GNUNET_MQ_Handle *
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 8002b7710..43fd32a58 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -52,9 +52,24 @@ extern "C"
52#endif 52#endif
53 53
54/** 54/**
55 * @brief A 512-bit hashcode 55 * @brief A 512-bit hashcode. These are the default length for GNUnet, using SHA-512.
56 */ 56 */
57struct GNUNET_HashCode; 57struct GNUNET_HashCode
58{
59 uint32_t bits[512 / 8 / sizeof (uint32_t)]; /* = 16 */
60};
61
62
63
64/**
65 * @brief A 256-bit hashcode. Used under special conditions, like when space
66 * is critical and security is not impacted by it.
67 */
68struct GNUNET_ShortHashCode
69{
70 uint32_t bits[256 / 8 / sizeof (uint32_t)]; /* = 8 */
71};
72
58 73
59/** 74/**
60 * The identity of the host (wraps the signing key of the peer). 75 * The identity of the host (wraps the signing key of the peer).
@@ -66,15 +81,6 @@ struct GNUNET_PeerIdentity;
66 81
67 82
68/** 83/**
69 * @brief A 512-bit hashcode
70 */
71struct GNUNET_HashCode
72{
73 uint32_t bits[512 / 8 / sizeof (uint32_t)]; /* = 16 */
74};
75
76
77/**
78 * Maximum length of an ECC signature. 84 * Maximum length of an ECC signature.
79 * Note: round up to multiple of 8 minus 2 for alignment. 85 * Note: round up to multiple of 8 minus 2 for alignment.
80 */ 86 */
diff --git a/src/include/gnunet_mq_lib.h b/src/include/gnunet_mq_lib.h
index d1a045b8b..108ba5d54 100644
--- a/src/include/gnunet_mq_lib.h
+++ b/src/include/gnunet_mq_lib.h
@@ -255,15 +255,6 @@ typedef void
255 255
256 256
257/** 257/**
258 * Callback used for notifications
259 *
260 * @param cls closure
261 */
262typedef void
263(*GNUNET_MQ_NotifyCallback) (void *cls);
264
265
266/**
267 * Generic error handler, called with the appropriate 258 * Generic error handler, called with the appropriate
268 * error code and the same closure specified at the creation of 259 * error code and the same closure specified at the creation of
269 * the message queue. 260 * the message queue.
@@ -402,7 +393,7 @@ struct GNUNET_MQ_MessageHandler
402 * @param ctx context for the callbacks 393 * @param ctx context for the callbacks
403 */ 394 */
404#define GNUNET_MQ_hd_var_size(name,code,str,ctx) \ 395#define GNUNET_MQ_hd_var_size(name,code,str,ctx) \
405 ({ \ 396 __extension__ ({ \
406 int (*_mv)(void *cls, const str *msg) = &check_##name; \ 397 int (*_mv)(void *cls, const str *msg) = &check_##name; \
407 void (*_cb)(void *cls, const str *msg) = &handle_##name; \ 398 void (*_cb)(void *cls, const str *msg) = &handle_##name; \
408 ((struct GNUNET_MQ_MessageHandler) \ 399 ((struct GNUNET_MQ_MessageHandler) \
@@ -634,7 +625,7 @@ GNUNET_MQ_set_handlers_closure (struct GNUNET_MQ_Handle *mq,
634 */ 625 */
635void 626void
636GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *ev, 627GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *ev,
637 GNUNET_MQ_NotifyCallback cb, 628 GNUNET_SCHEDULER_TaskCallback cb,
638 void *cb_cls); 629 void *cb_cls);
639 630
640 631
diff --git a/src/include/gnunet_nat_auto_service.h b/src/include/gnunet_nat_auto_service.h
new file mode 100644
index 000000000..a369c49e0
--- /dev/null
+++ b/src/include/gnunet_nat_auto_service.h
@@ -0,0 +1,135 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2007-2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @author Christian Grothoff
23 * @author Milan Bouchet-Valat
24 *
25 * @file
26 * Service for testing and autoconfiguration of
27 * NAT traversal functionality
28 *
29 * @defgroup nat NAT testing library
30 *
31 * @{
32 */
33
34#ifndef GNUNET_NAT_AUTO_SERVICE_H
35#define GNUNET_NAT_AUTO_SERVICE_H
36
37#include "gnunet_util_lib.h"
38#include "gnunet_nat_service.h"
39
40
41/**
42 * Handle to a NAT test.
43 */
44struct GNUNET_NAT_AUTO_Test;
45
46
47/**
48 * Start testing if NAT traversal works using the given configuration.
49 * The transport adapters should be down while using this function.
50 *
51 * @param cfg configuration for the NAT traversal
52 * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
53 * @param section_name configuration section to use for configuration
54 * @param report function to call with the result of the test
55 * @param report_cls closure for @a report
56 * @return handle to cancel NAT test
57 */
58struct GNUNET_NAT_AUTO_Test *
59GNUNET_NAT_AUTO_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
60 uint8_t proto,
61 const char *section_name,
62 GNUNET_NAT_TestCallback report,
63 void *report_cls);
64
65
66/**
67 * Stop an active NAT test.
68 *
69 * @param tst test to stop.
70 */
71void
72GNUNET_NAT_AUTO_test_stop (struct GNUNET_NAT_AUTO_Test *tst);
73
74
75/**
76 * Handle to auto-configuration in progress.
77 */
78struct GNUNET_NAT_AUTO_AutoHandle;
79
80
81/**
82 * Converts `enum GNUNET_NAT_StatusCode` to string
83 *
84 * @param err error code to resolve to a string
85 * @return point to a static string containing the error code
86 */
87const char *
88GNUNET_NAT_AUTO_status2string (enum GNUNET_NAT_StatusCode err);
89
90
91/**
92 * Function called with the result from the autoconfiguration.
93 *
94 * @param cls closure
95 * @param diff minimal suggested changes to the original configuration
96 * to make it work (as best as we can)
97 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
98 * @param type what the situation of the NAT
99 */
100typedef void
101(*GNUNET_NAT_AUTO_AutoResultCallback)(void *cls,
102 const struct GNUNET_CONFIGURATION_Handle *diff,
103 enum GNUNET_NAT_StatusCode result,
104 enum GNUNET_NAT_Type type);
105
106
107/**
108 * Start auto-configuration routine. The transport adapters should
109 * be stopped while this function is called.
110 *
111 * @param cfg initial configuration
112 * @param cb function to call with autoconfiguration result
113 * @param cb_cls closure for @a cb
114 * @return handle to cancel operation
115 */
116struct GNUNET_NAT_AUTO_AutoHandle *
117GNUNET_NAT_AUTO_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
118 GNUNET_NAT_AUTO_AutoResultCallback cb,
119 void *cb_cls);
120
121
122/**
123 * Abort autoconfiguration.
124 *
125 * @param ah handle for operation to abort
126 */
127void
128GNUNET_NAT_AUTO_autoconfig_cancel (struct GNUNET_NAT_AUTO_AutoHandle *ah);
129
130
131#endif
132
133/** @} */ /* end of group */
134
135/* end of gnunet_nat_auto_service.h */
diff --git a/src/include/gnunet_nat_lib.h b/src/include/gnunet_nat_lib.h
deleted file mode 100644
index 853a86c2d..000000000
--- a/src/include/gnunet_nat_lib.h
+++ /dev/null
@@ -1,591 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2007-2014 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @author Christian Grothoff
23 * @author Milan Bouchet-Valat
24 *
25 * @file
26 * Library handling UPnP and NAT-PMP port forwarding
27 * and external IP address retrieval
28 *
29 * @defgroup nat NAT library
30 * Library handling UPnP and NAT-PMP port forwarding
31 * and external IP address retrieval
32 *
33 * @{
34 */
35
36#ifndef GNUNET_NAT_LIB_H
37#define GNUNET_NAT_LIB_H
38
39#include "gnunet_util_lib.h"
40
41
42/**
43 * Signature of the callback passed to #GNUNET_NAT_register() for
44 * a function to call whenever our set of 'valid' addresses changes.
45 *
46 * @param cls closure
47 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
48 * the previous (now invalid) one
49 * @param addr either the previous or the new public IP address
50 * @param addrlen actual length of the @a addr
51 */
52typedef void
53(*GNUNET_NAT_AddressCallback) (void *cls,
54 int add_remove,
55 const struct sockaddr *addr,
56 socklen_t addrlen);
57
58
59/**
60 * Signature of the callback passed to #GNUNET_NAT_register().
61 * for a function to call whenever someone asks us to do connection
62 * reversal.
63 *
64 * @param cls closure
65 * @param addr public IP address of the other peer
66 * @param addrlen actual lenght of the @a addr
67 */
68typedef void
69(*GNUNET_NAT_ReversalCallback) (void *cls,
70 const struct sockaddr *addr,
71 socklen_t addrlen);
72
73
74/**
75 * Handle for active NAT registrations.
76 */
77struct GNUNET_NAT_Handle;
78
79
80
81/**
82 * What the situation of the NAT connectivity
83 */
84enum GNUNET_NAT_Type
85{
86 /**
87 * We have a direct connection
88 */
89 GNUNET_NAT_TYPE_NO_NAT = GNUNET_OK,
90
91 /**
92 * We are under a NAT but cannot traverse it
93 */
94 GNUNET_NAT_TYPE_UNREACHABLE_NAT,
95
96 /**
97 * We can traverse using STUN
98 */
99 GNUNET_NAT_TYPE_STUN_PUNCHED_NAT,
100
101 /**
102 * WE can traverse using UPNP
103 */
104 GNUNET_NAT_TYPE_UPNP_NAT
105
106};
107
108/**
109 * Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
110 */
111enum GNUNET_NAT_StatusCode
112{
113 /**
114 * Just the default
115 */
116 GNUNET_NAT_ERROR_SUCCESS = GNUNET_OK,
117
118 /**
119 * IPC Failure
120 */
121 GNUNET_NAT_ERROR_IPC_FAILURE,
122
123 /**
124 * Failure in network subsystem, check permissions
125 */
126 GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR,
127
128 /**
129 * test timed out
130 */
131 GNUNET_NAT_ERROR_TIMEOUT,
132
133 /**
134 * detected that we are offline
135 */
136 GNUNET_NAT_ERROR_NOT_ONLINE,
137
138 /**
139 * `upnpc` command not found
140 */
141 GNUNET_NAT_ERROR_UPNPC_NOT_FOUND,
142
143 /**
144 * Failed to run `upnpc` command
145 */
146 GNUNET_NAT_ERROR_UPNPC_FAILED,
147
148 /**
149 * `upnpc' command took too long, process killed
150 */
151 GNUNET_NAT_ERROR_UPNPC_TIMEOUT,
152
153 /**
154 * `upnpc' command failed to establish port mapping
155 */
156 GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED,
157
158 /**
159 * `external-ip' command not found
160 */
161 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND,
162
163 /**
164 * Failed to run `external-ip` command
165 */
166 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED,
167
168 /**
169 * `external-ip' command output invalid
170 */
171 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID,
172
173 /**
174 * "no valid address was returned by `external-ip'"
175 */
176 GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID,
177
178 /**
179 * Could not determine interface with internal/local network address
180 */
181 GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO,
182
183 /**
184 * No working gnunet-helper-nat-server found
185 */
186 GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND,
187
188 /**
189 * NAT test could not be initialized
190 */
191 GNUNET_NAT_ERROR_NAT_TEST_START_FAILED,
192
193 /**
194 * NAT test timeout
195 */
196 GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT,
197
198 /**
199 * NAT test failed to initiate
200 */
201 GNUNET_NAT_ERROR_NAT_REGISTER_FAILED,
202
203 /**
204 *
205 */
206 GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND,
207
208 /**
209 *
210 */
211 GNUNET_NAT_ERROR_
212};
213
214
215/**
216 * Converts `enum GNUNET_NAT_StatusCode` to string
217 *
218 * @param err error code to resolve to a string
219 * @return point to a static string containing the error code
220 */
221const char *
222GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err);
223
224
225/**
226 * Attempt to enable port redirection and detect public IP address
227 * contacting UPnP or NAT-PMP routers on the local network. Use addr
228 * to specify to which of the local host's addresses should the
229 * external port be mapped. The port is taken from the corresponding
230 * sockaddr_in[6] field. The NAT module should call the given
231 * callback for any 'plausible' external address.
232 *
233 * @param cfg configuration to use
234 * @param is_tcp #GNUNET_YES for TCP, #GNUNET_NO for UDP
235 * @param adv_port advertised port (port we are either bound to or that our OS
236 * locally performs redirection from to our bound port).
237 * @param num_addrs number of addresses in @a addrs
238 * @param addrs list of local addresses packets should be redirected to
239 * @param addrlens actual lengths of the addresses in @a addrs
240 * @param address_callback function to call everytime the public IP address changes
241 * @param reversal_callback function to call if someone wants connection reversal from us,
242 * NULL if connection reversal is not supported
243 * @param callback_cls closure for callbacks
244 * @return NULL on error, otherwise handle that can be used to unregister
245 */
246struct GNUNET_NAT_Handle *
247GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
248 int is_tcp,
249 uint16_t adv_port,
250 unsigned int num_addrs,
251 const struct sockaddr **addrs,
252 const socklen_t *addrlens,
253 GNUNET_NAT_AddressCallback address_callback,
254 GNUNET_NAT_ReversalCallback reversal_callback,
255 void *callback_cls,
256 struct GNUNET_NETWORK_Handle* sock);
257
258
259/**
260 * Test if the given address is (currently) a plausible IP address for
261 * this peer.
262 *
263 * @param h the handle returned by register
264 * @param addr IP address to test (IPv4 or IPv6)
265 * @param addrlen number of bytes in @a addr
266 * @return #GNUNET_YES if the address is plausible,
267 * #GNUNET_NO if the address is not plausible,
268 * #GNUNET_SYSERR if the address is malformed
269 */
270int
271GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
272 const void *addr,
273 socklen_t addrlen);
274
275
276/**
277 * We learned about a peer (possibly behind NAT) so run the
278 * gnunet-nat-client to send dummy ICMP responses to cause
279 * that peer to connect to us (connection reversal).
280 *
281 * @param h handle (used for configuration)
282 * @param sa the address of the peer (IPv4-only)
283 * @return #GNUNET_SYSERR on error, #GNUNET_NO if nat client is disabled,
284 * #GNUNET_OK otherwise
285 */
286int
287GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h,
288 const struct sockaddr_in *sa);
289
290
291/**
292 * Stop port redirection and public IP address detection for the given
293 * handle. This frees the handle, after having sent the needed
294 * commands to close open ports.
295 *
296 * @param h the handle to stop
297 */
298void
299GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h);
300
301
302/**
303 * Handle to a NAT test.
304 */
305struct GNUNET_NAT_Test;
306
307
308/**
309 * Function called to report success or failure for
310 * NAT configuration test.
311 *
312 * @param cls closure
313 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
314 */
315typedef void (*GNUNET_NAT_TestCallback) (void *cls,
316 enum GNUNET_NAT_StatusCode result);
317
318
319/**
320 * Start testing if NAT traversal works using the
321 * given configuration (IPv4-only).
322 *
323 * @param cfg configuration for the NAT traversal
324 * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
325 * @param bnd_port port to bind to, 0 for connection reversal
326 * @param adv_port externally advertised port to use
327 * @param timeout delay after which the test should be aborted
328 * @param report function to call with the result of the test;
329 * you still must call #GNUNET_NAT_test_stop().
330 * @param report_cls closure for @a report
331 * @return handle to cancel NAT test
332 */
333struct GNUNET_NAT_Test *
334GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
335 int is_tcp,
336 uint16_t bnd_port,
337 uint16_t adv_port,
338 struct GNUNET_TIME_Relative timeout,
339 GNUNET_NAT_TestCallback report,
340 void *report_cls);
341
342
343/**
344 * Stop an active NAT test.
345 *
346 * @param tst test to stop.
347 */
348void
349GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst);
350
351
352/**
353 * Signature of a callback that is given an IP address.
354 *
355 * @param cls closure
356 * @param addr the address, NULL on errors
357 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
358 */
359typedef void
360(*GNUNET_NAT_IPCallback) (void *cls,
361 const struct in_addr *addr,
362 enum GNUNET_NAT_StatusCode result);
363
364
365/**
366 * Opaque handle to cancel #GNUNET_NAT_mini_get_external_ipv4() operation.
367 */
368struct GNUNET_NAT_ExternalHandle;
369
370
371/**
372 * Try to get the external IPv4 address of this peer.
373 *
374 * @param timeout when to fail
375 * @param cb function to call with result
376 * @param cb_cls closure for @a cb
377 * @return handle for cancellation (can only be used until @a cb is called), NULL on error
378 */
379struct GNUNET_NAT_ExternalHandle *
380GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout,
381 GNUNET_NAT_IPCallback cb,
382 void *cb_cls);
383
384
385/**
386 * Cancel operation.
387 *
388 * @param eh operation to cancel
389 */
390void
391GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh);
392
393
394/**
395 * Handle to a mapping created with upnpc.
396 */
397struct GNUNET_NAT_MiniHandle;
398
399
400/**
401 * Signature of the callback passed to #GNUNET_NAT_register() for
402 * a function to call whenever our set of 'valid' addresses changes.
403 *
404 * @param cls closure
405 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
406 * the previous (now invalid) one, #GNUNET_SYSERR indicates an error
407 * @param addr either the previous or the new public IP address
408 * @param addrlen actual length of the @a addr
409 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
410 */
411typedef void
412(*GNUNET_NAT_MiniAddressCallback) (void *cls,
413 int add_remove,
414 const struct sockaddr *addr,
415 socklen_t addrlen,
416 enum GNUNET_NAT_StatusCode result);
417
418
419/**
420 * Start mapping the given port using (mini)upnpc. This function
421 * should typically not be used directly (it is used within the
422 * general-purpose #GNUNET_NAT_register() code). However, it can be
423 * used if specifically UPnP-based NAT traversal is to be used or
424 * tested.
425 *
426 * @param port port to map
427 * @param is_tcp #GNUNET_YES to map TCP, #GNUNET_NO for UDP
428 * @param ac function to call with mapping result
429 * @param ac_cls closure for @a ac
430 * @return NULL on error
431 */
432struct GNUNET_NAT_MiniHandle *
433GNUNET_NAT_mini_map_start (uint16_t port,
434 int is_tcp,
435 GNUNET_NAT_MiniAddressCallback ac,
436 void *ac_cls);
437
438
439/**
440 * Remove a mapping created with (mini)upnpc. Calling
441 * this function will give 'upnpc' 1s to remove the mapping,
442 * so while this function is non-blocking, a task will be
443 * left with the scheduler for up to 1s past this call.
444 *
445 * @param mini the handle
446 */
447void
448GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini);
449
450
451/**
452 * Handle to auto-configuration in progress.
453 */
454struct GNUNET_NAT_AutoHandle;
455
456
457/**
458 * Function called with the result from the autoconfiguration.
459 *
460 * @param cls closure
461 * @param diff minimal suggested changes to the original configuration
462 * to make it work (as best as we can)
463 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
464 * @param type what the situation of the NAT
465 */
466typedef void
467(*GNUNET_NAT_AutoResultCallback)(void *cls,
468 const struct GNUNET_CONFIGURATION_Handle *diff,
469 enum GNUNET_NAT_StatusCode result,
470 enum GNUNET_NAT_Type type);
471
472
473/**
474 * Start auto-configuration routine. The resolver service should
475 * be available when this function is called.
476 *
477 * @param cfg initial configuration
478 * @param cb function to call with autoconfiguration result
479 * @param cb_cls closure for @a cb
480 * @return handle to cancel operation
481 */
482struct GNUNET_NAT_AutoHandle *
483GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
484 GNUNET_NAT_AutoResultCallback cb,
485 void *cb_cls);
486
487
488/**
489 * Abort autoconfiguration.
490 *
491 * @param ah handle for operation to abort
492 */
493void
494GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah);
495
496/**
497 * Handle for active STUN Requests.
498 */
499struct GNUNET_NAT_STUN_Handle;
500
501
502/**
503 * Function called with the result if an error happened during STUN request.
504 *
505 * @param cls closure
506 * @param result the specific error code
507 */
508typedef void
509(*GNUNET_NAT_STUN_ErrorCallback)(void *cls,
510 enum GNUNET_NAT_StatusCode error);
511
512
513/**
514 * Handle to a request given to the resolver. Can be used to cancel
515 * the request prior to the timeout or successful execution. Also
516 * used to track our internal state for the request.
517 */
518struct GNUNET_NAT_STUN_Handle;
519
520
521/**
522 * Make generic STUN request. Sends a generic stun request to the
523 * server specified using the specified socket. The caller must
524 * wait for a reply on the @a sock and call
525 * #GNUNET_NAT_stun_handle_packet() if a reply is received.
526 *
527 * @param server the address of the stun server
528 * @param port port of the stun server
529 * @param sock the socket used to send the request
530 * @param cb callback in case of error (or completion)
531 * @param cb_cls closure for @a cb
532 * @return NULL on error
533 */
534struct GNUNET_NAT_STUN_Handle *
535GNUNET_NAT_stun_make_request (const char *server,
536 uint16_t port,
537 struct GNUNET_NETWORK_Handle *sock,
538 GNUNET_NAT_STUN_ErrorCallback cb,
539 void *cb_cls);
540
541
542/**
543 * Cancel active STUN request. Frees associated resources
544 * and ensures that the callback is no longer invoked.
545 *
546 * @param rh request to cancel
547 */
548void
549GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh);
550
551
552/**
553 * Handle an incoming STUN message. Do some basic sanity checks on
554 * packet size and content, try to extract a bit of information, and
555 * possibly reply. At the moment this only processes BIND requests,
556 * and returns the externally visible address of the request. If a
557 * callback is specified, invoke it with the attribute.
558 *
559 * @param data the packet
560 * @param len the length of the packet
561 * @param arg sockaddr_in where we will set our discovered packet
562 * @return #GNUNET_OK on OK,
563 * #GNUNET_NO if the packet is not a stun packet
564 */
565int
566GNUNET_NAT_stun_handle_packet (const void *data,
567 size_t len,
568 struct sockaddr_in *arg);
569
570
571/**
572 * CHECK if is a valid STUN packet sending to #GNUNET_NAT_stun_handle_packet().
573 * It also check if it can handle the packet based on the NAT handler.
574 * You don't need to call anything else to check if the packet is valid,
575 *
576 * @param cls the NAT handle
577 * @param data packet
578 * @param len length of @a data
579 * @return #GNUNET_NO if it can't decode, #GNUNET_YES if is a packet
580 */
581int
582GNUNET_NAT_is_valid_stun_packet (void *cls,
583 const void *data,
584 size_t len);
585
586
587#endif
588
589/** @} */ /* end of group */
590
591/* end of gnunet_nat_lib.h */
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h
index 1620c9433..e75845207 100644
--- a/src/include/gnunet_nat_service.h
+++ b/src/include/gnunet_nat_service.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2007-2016 GNUnet e.V. 3 Copyright (C) 2007-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -123,6 +123,12 @@ enum GNUNET_NAT_AddressClass
123 GNUNET_NAT_AC_EXTERN = 128, 123 GNUNET_NAT_AC_EXTERN = 128,
124 124
125 /** 125 /**
126 * Addresses that were manually configured by the user.
127 * Used as a bit in combination with #GNUNET_NAT_AC_GLOBAL.
128 */
129 GNUNET_NAT_AC_MANUAL = 256,
130
131 /**
126 * Bitmask for "any" address. 132 * Bitmask for "any" address.
127 */ 133 */
128 GNUNET_NAT_AC_ANY = 65535 134 GNUNET_NAT_AC_ANY = 65535
@@ -131,6 +137,144 @@ enum GNUNET_NAT_AddressClass
131 137
132 138
133/** 139/**
140 * Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
141 */
142enum GNUNET_NAT_StatusCode
143{
144 /**
145 * Just the default
146 */
147 GNUNET_NAT_ERROR_SUCCESS = GNUNET_OK,
148
149 /**
150 * IPC Failure
151 */
152 GNUNET_NAT_ERROR_IPC_FAILURE,
153
154 /**
155 * Failure in network subsystem, check permissions
156 */
157 GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR,
158
159 /**
160 * test timed out
161 */
162 GNUNET_NAT_ERROR_TIMEOUT,
163
164 /**
165 * detected that we are offline
166 */
167 GNUNET_NAT_ERROR_NOT_ONLINE,
168
169 /**
170 * `upnpc` command not found
171 */
172 GNUNET_NAT_ERROR_UPNPC_NOT_FOUND,
173
174 /**
175 * Failed to run `upnpc` command
176 */
177 GNUNET_NAT_ERROR_UPNPC_FAILED,
178
179 /**
180 * `upnpc' command took too long, process killed
181 */
182 GNUNET_NAT_ERROR_UPNPC_TIMEOUT,
183
184 /**
185 * `upnpc' command failed to establish port mapping
186 */
187 GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED,
188
189 /**
190 * `external-ip' command not found
191 */
192 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND,
193
194 /**
195 * Failed to run `external-ip` command
196 */
197 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED,
198
199 /**
200 * `external-ip' command output invalid
201 */
202 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID,
203
204 /**
205 * "no valid address was returned by `external-ip'"
206 */
207 GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID,
208
209 /**
210 * Could not determine interface with internal/local network address
211 */
212 GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO,
213
214 /**
215 * No working gnunet-helper-nat-server found
216 */
217 GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND,
218
219 /**
220 * NAT test could not be initialized
221 */
222 GNUNET_NAT_ERROR_NAT_TEST_START_FAILED,
223
224 /**
225 * NAT test timeout
226 */
227 GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT,
228
229 /**
230 * NAT test failed to initiate
231 */
232 GNUNET_NAT_ERROR_NAT_REGISTER_FAILED,
233
234 /**
235 *
236 */
237 GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND
238
239};
240
241
242
243/**
244 * What the situation of the NAT connectivity
245 */
246enum GNUNET_NAT_Type
247{
248 /**
249 * We have a direct connection
250 */
251 GNUNET_NAT_TYPE_NO_NAT = GNUNET_OK,
252
253 /**
254 * We are under a NAT but cannot traverse it
255 */
256 GNUNET_NAT_TYPE_UNREACHABLE_NAT,
257
258 /**
259 * We can traverse using STUN
260 */
261 GNUNET_NAT_TYPE_STUN_PUNCHED_NAT,
262
263 /**
264 * We can traverse using UPNP
265 */
266 GNUNET_NAT_TYPE_UPNP_NAT,
267
268 /**
269 * We know nothing about the NAT.
270 */
271 GNUNET_NAT_TYPE_UNKNOWN
272
273};
274
275
276
277/**
134 * Signature of the callback passed to #GNUNET_NAT_register() for 278 * Signature of the callback passed to #GNUNET_NAT_register() for
135 * a function to call whenever our set of 'valid' addresses changes. 279 * a function to call whenever our set of 'valid' addresses changes.
136 * 280 *
@@ -179,8 +323,8 @@ struct GNUNET_NAT_Handle;
179 * address_callback for any 'plausible' external address. 323 * address_callback for any 'plausible' external address.
180 * 324 *
181 * @param cfg configuration to use 325 * @param cfg configuration to use
326 * @param config_section name of the configuration section for options
182 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP 327 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
183 * @param hole_external hostname and port of manually punched hole in NAT, otherwise NULL (or empty string)
184 * @param num_addrs number of addresses in @a addrs 328 * @param num_addrs number of addresses in @a addrs
185 * @param addrs list of local addresses packets should be redirected to 329 * @param addrs list of local addresses packets should be redirected to
186 * @param addrlens actual lengths of the addresses in @a addrs 330 * @param addrlens actual lengths of the addresses in @a addrs
@@ -192,8 +336,8 @@ struct GNUNET_NAT_Handle;
192 */ 336 */
193struct GNUNET_NAT_Handle * 337struct GNUNET_NAT_Handle *
194GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, 338GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
339 const char *config_section,
195 uint8_t proto, 340 uint8_t proto,
196 const char *hole_external,
197 unsigned int num_addrs, 341 unsigned int num_addrs,
198 const struct sockaddr **addrs, 342 const struct sockaddr **addrs,
199 const socklen_t *addrlens, 343 const socklen_t *addrlens,
@@ -251,127 +395,6 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh);
251 395
252 396
253/** 397/**
254 * Handle to a NAT test.
255 */
256struct GNUNET_NAT_Test;
257
258
259/**
260 * Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
261 */
262enum GNUNET_NAT_StatusCode
263{
264 /**
265 * Just the default
266 */
267 GNUNET_NAT_ERROR_SUCCESS = GNUNET_OK,
268
269 /**
270 * IPC Failure
271 */
272 GNUNET_NAT_ERROR_IPC_FAILURE,
273
274 /**
275 * Failure in network subsystem, check permissions
276 */
277 GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR,
278
279 /**
280 * test timed out
281 */
282 GNUNET_NAT_ERROR_TIMEOUT,
283
284 /**
285 * detected that we are offline
286 */
287 GNUNET_NAT_ERROR_NOT_ONLINE,
288
289 /**
290 * `upnpc` command not found
291 */
292 GNUNET_NAT_ERROR_UPNPC_NOT_FOUND,
293
294 /**
295 * Failed to run `upnpc` command
296 */
297 GNUNET_NAT_ERROR_UPNPC_FAILED,
298
299 /**
300 * `upnpc' command took too long, process killed
301 */
302 GNUNET_NAT_ERROR_UPNPC_TIMEOUT,
303
304 /**
305 * `upnpc' command failed to establish port mapping
306 */
307 GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED,
308
309 /**
310 * `external-ip' command not found
311 */
312 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND,
313
314 /**
315 * Failed to run `external-ip` command
316 */
317 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED,
318
319 /**
320 * `external-ip' command output invalid
321 */
322 GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID,
323
324 /**
325 * "no valid address was returned by `external-ip'"
326 */
327 GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID,
328
329 /**
330 * Could not determine interface with internal/local network address
331 */
332 GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO,
333
334 /**
335 * No working gnunet-helper-nat-server found
336 */
337 GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND,
338
339 /**
340 * NAT test could not be initialized
341 */
342 GNUNET_NAT_ERROR_NAT_TEST_START_FAILED,
343
344 /**
345 * NAT test timeout
346 */
347 GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT,
348
349 /**
350 * NAT test failed to initiate
351 */
352 GNUNET_NAT_ERROR_NAT_REGISTER_FAILED,
353
354 /**
355 *
356 */
357 GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND
358
359};
360
361
362/**
363 * Function called to report success or failure for
364 * NAT configuration test.
365 *
366 * @param cls closure
367 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
368 */
369typedef void
370(*GNUNET_NAT_TestCallback) (void *cls,
371 enum GNUNET_NAT_StatusCode result);
372
373
374/**
375 * Handle an incoming STUN message. This function is useful as 398 * Handle an incoming STUN message. This function is useful as
376 * some GNUnet service may be listening on a UDP port and might 399 * some GNUnet service may be listening on a UDP port and might
377 * thus receive STUN messages while trying to receive other data. 400 * thus receive STUN messages while trying to receive other data.
@@ -411,6 +434,18 @@ struct GNUNET_NAT_STUN_Handle;
411 434
412 435
413/** 436/**
437 * Function called to report success or failure for
438 * NAT configuration test.
439 *
440 * @param cls closure
441 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
442 */
443typedef void
444(*GNUNET_NAT_TestCallback) (void *cls,
445 enum GNUNET_NAT_StatusCode result);
446
447
448/**
414 * Make Generic STUN request. Sends a generic stun request to the 449 * Make Generic STUN request. Sends a generic stun request to the
415 * server specified using the specified socket. If we do this, 450 * server specified using the specified socket. If we do this,
416 * we need to watch for possible responses and call 451 * we need to watch for possible responses and call
@@ -442,130 +477,6 @@ void
442GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh); 477GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh);
443 478
444 479
445/**
446 * Start testing if NAT traversal works using the given configuration
447 * (IPv4-only). The transport adapters should be down while using
448 * this function.
449 *
450 * @param cfg configuration for the NAT traversal
451 * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
452 * @param bind_ip IPv4 address to bind to
453 * @param bnd_port port to bind to, 0 to test connection reversal
454 * @param extern_ip IPv4 address to externally advertise
455 * @param extern_port externally advertised port to use
456 * @param report function to call with the result of the test
457 * @param report_cls closure for @a report
458 * @return handle to cancel NAT test
459 */
460struct GNUNET_NAT_Test *
461GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
462 uint8_t proto,
463 struct in_addr bind_ip,
464 uint16_t bnd_port,
465 struct in_addr extern_ip,
466 uint16_t extern_port,
467 GNUNET_NAT_TestCallback report,
468 void *report_cls);
469
470
471/**
472 * Stop an active NAT test.
473 *
474 * @param tst test to stop.
475 */
476void
477GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst);
478
479
480/**
481 * Handle to auto-configuration in progress.
482 */
483struct GNUNET_NAT_AutoHandle;
484
485
486/**
487 * What the situation of the NAT connectivity
488 */
489enum GNUNET_NAT_Type
490{
491 /**
492 * We have a direct connection
493 */
494 GNUNET_NAT_TYPE_NO_NAT = GNUNET_OK,
495
496 /**
497 * We are under a NAT but cannot traverse it
498 */
499 GNUNET_NAT_TYPE_UNREACHABLE_NAT,
500
501 /**
502 * We can traverse using STUN
503 */
504 GNUNET_NAT_TYPE_STUN_PUNCHED_NAT,
505
506 /**
507 * We can traverse using UPNP
508 */
509 GNUNET_NAT_TYPE_UPNP_NAT,
510
511 /**
512 * We know nothing about the NAT.
513 */
514 GNUNET_NAT_TYPE_UNKNOWN
515
516};
517
518
519/**
520 * Converts `enum GNUNET_NAT_StatusCode` to string
521 *
522 * @param err error code to resolve to a string
523 * @return point to a static string containing the error code
524 */
525const char *
526GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err);
527
528
529/**
530 * Function called with the result from the autoconfiguration.
531 *
532 * @param cls closure
533 * @param diff minimal suggested changes to the original configuration
534 * to make it work (as best as we can)
535 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
536 * @param type what the situation of the NAT
537 */
538typedef void
539(*GNUNET_NAT_AutoResultCallback)(void *cls,
540 const struct GNUNET_CONFIGURATION_Handle *diff,
541 enum GNUNET_NAT_StatusCode result,
542 enum GNUNET_NAT_Type type);
543
544
545/**
546 * Start auto-configuration routine. The transport adapters should
547 * be stopped while this function is called.
548 *
549 * @param cfg initial configuration
550 * @param cb function to call with autoconfiguration result
551 * @param cb_cls closure for @a cb
552 * @return handle to cancel operation
553 */
554struct GNUNET_NAT_AutoHandle *
555GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
556 GNUNET_NAT_AutoResultCallback cb,
557 void *cb_cls);
558
559
560/**
561 * Abort autoconfiguration.
562 *
563 * @param ah handle for operation to abort
564 */
565void
566GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah);
567
568
569#endif 480#endif
570 481
571/** @} */ /* end of group */ 482/** @} */ /* end of group */
diff --git a/src/include/gnunet_peerinfo_service.h b/src/include/gnunet_peerinfo_service.h
index 44df483a0..b5c2153ac 100644
--- a/src/include/gnunet_peerinfo_service.h
+++ b/src/include/gnunet_peerinfo_service.h
@@ -101,7 +101,7 @@ GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h);
101struct GNUNET_MQ_Envelope * 101struct GNUNET_MQ_Envelope *
102GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h, 102GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h,
103 const struct GNUNET_HELLO_Message *hello, 103 const struct GNUNET_HELLO_Message *hello,
104 GNUNET_MQ_NotifyCallback cont, 104 GNUNET_SCHEDULER_TaskCallback cont,
105 void *cont_cls); 105 void *cont_cls);
106 106
107 107
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index cf26f1727..e31b1f33c 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2645,7 +2645,7 @@ extern "C"
2645/** 2645/**
2646 * Send origin an ACK that the connection is complete 2646 * Send origin an ACK that the connection is complete
2647 */ 2647 */
2648#define GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK 1001 2648#define GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK 1001
2649 2649
2650/** 2650/**
2651 * Notify that a connection is no longer valid 2651 * Notify that a connection is no longer valid
@@ -2660,49 +2660,53 @@ extern "C"
2660/** 2660/**
2661 * At some point, the route will spontaneously change TODO 2661 * At some point, the route will spontaneously change TODO
2662 */ 2662 */
2663#define GNUNET_MESSAGE_TYPE_CADET_PATH_CHANGED 1004 2663#define GNUNET_MESSAGE_TYPE_CADET_CONNECTION_PATH_CHANGED_UNIMPLEMENTED 1004
2664 2664
2665/** 2665/**
2666 * Hop-by-hop, connection dependent ACK. 2666 * Hop-by-hop, connection dependent ACK.
2667 */ 2667 */
2668#define GNUNET_MESSAGE_TYPE_CADET_ACK 1005 2668#define GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK 1005
2669 2669
2670/** 2670/**
2671 * Poll for a hop-by-hop ACK. 2671 * Axolotl key exchange.
2672 */ 2672 */
2673#define GNUNET_MESSAGE_TYPE_CADET_POLL 1006 2673#define GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX 1007
2674 2674
2675/** 2675/**
2676 * Key exchange encapsulation. 2676 * Axolotl encrypted data.
2677 */ 2677 */
2678#define GNUNET_MESSAGE_TYPE_CADET_KX 1007 2678#define GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED 1008
2679 2679
2680/** 2680/**
2681 * Axolotl encrypted data. 2681 * We do not bother with ACKs for
2682 * #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED messages, but we instead
2683 * poll for one if we got nothing for a while and start to be worried.
2682 */ 2684 */
2683#define GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED 1008 2685#define GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL 1006
2686
2687
2684 2688
2685/********************************** Channel *********************************/ 2689/********************************** Channel *********************************/
2686 2690
2687/** 2691/**
2688 * Payload data (inside an encrypted tunnel). 2692 * Payload data (inside an encrypted tunnel).
2689 */ 2693 */
2690#define GNUNET_MESSAGE_TYPE_CADET_DATA 1010 2694#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA 1010
2691 2695
2692/** 2696/**
2693 * Confirm payload data end-to-end. 2697 * Confirm payload data end-to-end.
2694 */ 2698 */
2695#define GNUNET_MESSAGE_TYPE_CADET_DATA_ACK 1011 2699#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK 1011
2696 2700
2697/** 2701/**
2698 * Announce connection is still alive (direction sensitive). 2702 * Announce connection is still alive (direction sensitive).
2699 */ 2703 */
2700#define GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE 1012 2704#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE 1012
2701 2705
2702/** 2706/**
2703 * Ask the cadet service to create a new channel. 2707 * Ask the cadet service to create a new channel.
2704 */ 2708 */
2705#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE 1013 2709#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN 1013
2706 2710
2707/** 2711/**
2708 * Ask the cadet service to destroy a channel. 2712 * Ask the cadet service to destroy a channel.
@@ -2712,12 +2716,12 @@ extern "C"
2712/** 2716/**
2713 * Confirm the creation of a channel 2717 * Confirm the creation of a channel
2714 */ 2718 */
2715#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK 1015 2719#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK 1015
2716 2720
2717/** 2721/**
2718 * Reject the creation of a channel 2722 * Reject the creation of a channel
2719 */ 2723 */
2720#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK 1016 2724#define GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED 1016
2721 2725
2722/*********************************** Local **********************************/ 2726/*********************************** Local **********************************/
2723 2727
@@ -2789,6 +2793,11 @@ extern "C"
2789 */ 2793 */
2790#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP 1038 2794#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP 1038
2791 2795
2796/**
2797 * End of local information about all peers known to the service.
2798 */
2799#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END 1039
2800
2792/******************************** Application *******************************/ 2801/******************************** Application *******************************/
2793 2802
2794/** 2803/**
@@ -2833,7 +2842,7 @@ extern "C"
2833/** 2842/**
2834 * Message to ask NAT service to request autoconfiguration. 2843 * Message to ask NAT service to request autoconfiguration.
2835 */ 2844 */
2836#define GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG 1067 2845#define GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG 1067
2837 2846
2838/** 2847/**
2839 * Message from NAT service with the autoconfiguration result. 2848 * Message from NAT service with the autoconfiguration result.
@@ -2841,8 +2850,31 @@ extern "C"
2841#define GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT 1068 2850#define GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT 1068
2842 2851
2843 2852
2853/* 1080-1109 reserved for TMCG (Heiko Stamer, see gnunet-developers, January 2017) */
2854
2855
2856/******************************************************************************/
2857/*********************************** AUCTION ********************************/
2858/******************************************************************************/
2859
2860/**
2861 * Client wants to create a new auction.
2862 */
2863#define GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_CREATE 1110
2864
2865/**
2866 * Client wants to join an existing auction.
2867 */
2868#define GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_JOIN 1111
2869
2870/**
2871 * Service reports the auction outcome to the client.
2872 */
2873#define GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_OUTCOME 1112
2874
2875
2844/** 2876/**
2845 * Next available: 1080 2877 * Next available: 1130
2846 */ 2878 */
2847 2879
2848 2880
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index 353287cbf..03bc4575e 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -151,11 +151,6 @@ extern "C"
151#define GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING 20 151#define GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING 20
152 152
153/** 153/**
154 * Key exchange in CADET
155 */
156#define GNUNET_SIGNATURE_PURPOSE_CADET_KX 21
157
158/**
159 * Signature for the first round of distributed key generation. 154 * Signature for the first round of distributed key generation.
160 */ 155 */
161#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1 22 156#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1 22
diff --git a/src/json/.gitignore b/src/json/.gitignore
new file mode 100644
index 000000000..6709c749d
--- /dev/null
+++ b/src/json/.gitignore
@@ -0,0 +1 @@
test_json
diff --git a/src/jsonapi/.gitignore b/src/jsonapi/.gitignore
new file mode 100644
index 000000000..077606988
--- /dev/null
+++ b/src/jsonapi/.gitignore
@@ -0,0 +1 @@
test_jsonapi
diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c
index e84fdb20f..de65e0ab7 100644
--- a/src/multicast/gnunet-service-multicast.c
+++ b/src/multicast/gnunet-service-multicast.c
@@ -710,15 +710,19 @@ cadet_notify_transmit_ready (void *cls, size_t buf_size, void *buf)
710static void 710static void
711cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg) 711cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
712{ 712{
713 uint16_t msg_size = ntohs (msg->size);
714 struct GNUNET_MessageHeader *msg_copy = GNUNET_malloc (msg_size);
715 GNUNET_memcpy (msg_copy, msg, msg_size);
716
713 struct CadetTransmitClosure *tcls = GNUNET_malloc (sizeof (*tcls)); 717 struct CadetTransmitClosure *tcls = GNUNET_malloc (sizeof (*tcls));
714 tcls->chn = chn; 718 tcls->chn = chn;
715 tcls->msg = msg; 719 tcls->msg = msg_copy;
716 720
717 chn->msgs_pending++; 721 chn->msgs_pending++;
718 chn->tmit_handle 722 chn->tmit_handle
719 = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO, 723 = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO,
720 GNUNET_TIME_UNIT_FOREVER_REL, 724 GNUNET_TIME_UNIT_FOREVER_REL,
721 ntohs (msg->size), 725 msg_size,
722 &cadet_notify_transmit_ready, 726 &cadet_notify_transmit_ready,
723 tcls); 727 tcls);
724 GNUNET_assert (NULL != chn->tmit_handle); 728 GNUNET_assert (NULL != chn->tmit_handle);
@@ -783,9 +787,21 @@ cadet_send_join_decision_cb (void *cls,
783 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls; 787 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
784 struct Channel *chn = channel; 788 struct Channel *chn = channel;
785 789
790 const struct MulticastJoinDecisionMessage *dcsn =
791 (struct MulticastJoinDecisionMessage *) &hdcsn[1];
792
786 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key)) 793 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
787 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer))) 794 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
788 { 795 {
796 if (GNUNET_YES == ntohl (dcsn->is_admitted))
797 {
798 chn->join_status = JOIN_ADMITTED;
799 }
800 else
801 {
802 chn->join_status = JOIN_REFUSED;
803 }
804
789 cadet_send_channel (chn, &hdcsn->header); 805 cadet_send_channel (chn, &hdcsn->header);
790 return GNUNET_NO; 806 return GNUNET_NO;
791 } 807 }
@@ -1019,6 +1035,7 @@ handle_client_member_join (void *cls,
1019 if (NULL == mem) 1035 if (NULL == mem)
1020 { 1036 {
1021 mem = GNUNET_new (struct Member); 1037 mem = GNUNET_new (struct Member);
1038 mem->origin = msg->origin;
1022 mem->priv_key = msg->member_key; 1039 mem->priv_key = msg->member_key;
1023 mem->pub_key = mem_pub_key; 1040 mem->pub_key = mem_pub_key;
1024 mem->pub_key_hash = mem_pub_key_hash; 1041 mem->pub_key_hash = mem_pub_key_hash;
@@ -1083,9 +1100,10 @@ handle_client_member_join (void *cls,
1083 join_msg_size = ntohs (join_msg->size); 1100 join_msg_size = ntohs (join_msg->size);
1084 } 1101 }
1085 1102
1103 uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
1086 struct MulticastJoinRequestMessage * 1104 struct MulticastJoinRequestMessage *
1087 req = GNUNET_malloc (sizeof (*req) + join_msg_size); 1105 req = GNUNET_malloc (req_msg_size);
1088 req->header.size = htons (sizeof (*req) + join_msg_size); 1106 req->header.size = htons (req_msg_size);
1089 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST); 1107 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1090 req->group_pub_key = grp->pub_key; 1108 req->group_pub_key = grp->pub_key;
1091 req->peer = this_peer; 1109 req->peer = this_peer;
@@ -1094,7 +1112,7 @@ handle_client_member_join (void *cls,
1094 GNUNET_memcpy (&req[1], join_msg, join_msg_size); 1112 GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1095 1113
1096 req->member_pub_key = mem->pub_key; 1114 req->member_pub_key = mem->pub_key;
1097 req->purpose.size = htonl (msg_size 1115 req->purpose.size = htonl (req_msg_size
1098 - sizeof (req->header) 1116 - sizeof (req->header)
1099 - sizeof (req->reserved) 1117 - sizeof (req->reserved)
1100 - sizeof (req->signature)); 1118 - sizeof (req->signature));
@@ -1534,6 +1552,7 @@ cadet_recv_join_request (void *cls,
1534 void **ctx, 1552 void **ctx,
1535 const struct GNUNET_MessageHeader *m) 1553 const struct GNUNET_MessageHeader *m)
1536{ 1554{
1555 GNUNET_CADET_receive_done(channel);
1537 const struct MulticastJoinRequestMessage * 1556 const struct MulticastJoinRequestMessage *
1538 req = (const struct MulticastJoinRequestMessage *) m; 1557 req = (const struct MulticastJoinRequestMessage *) m;
1539 uint16_t size = ntohs (m->size); 1558 uint16_t size = ntohs (m->size);
@@ -1576,6 +1595,7 @@ cadet_recv_join_request (void *cls,
1576 chn->join_status = JOIN_WAITING; 1595 chn->join_status = JOIN_WAITING;
1577 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_pub_hash, chn, 1596 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_pub_hash, chn,
1578 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1597 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1598 *ctx = chn;
1579 1599
1580 client_send_all (&group_pub_hash, m); 1600 client_send_all (&group_pub_hash, m);
1581 return GNUNET_OK; 1601 return GNUNET_OK;
@@ -1591,10 +1611,14 @@ cadet_recv_join_decision (void *cls,
1591 void **ctx, 1611 void **ctx,
1592 const struct GNUNET_MessageHeader *m) 1612 const struct GNUNET_MessageHeader *m)
1593{ 1613{
1614 GNUNET_CADET_receive_done (channel);
1615 const struct MulticastJoinDecisionMessageHeader *
1616 hdcsn = (const struct MulticastJoinDecisionMessageHeader *) m;
1594 const struct MulticastJoinDecisionMessage * 1617 const struct MulticastJoinDecisionMessage *
1595 dcsn = (const struct MulticastJoinDecisionMessage *) m; 1618 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1596 uint16_t size = ntohs (m->size); 1619 uint16_t size = ntohs (m->size);
1597 if (size < sizeof (*dcsn)) 1620 if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
1621 sizeof (struct MulticastJoinDecisionMessage))
1598 { 1622 {
1599 GNUNET_break_op (0); 1623 GNUNET_break_op (0);
1600 return GNUNET_SYSERR; 1624 return GNUNET_SYSERR;
@@ -1623,15 +1647,10 @@ cadet_recv_join_decision (void *cls,
1623 break; 1647 break;
1624 } 1648 }
1625 1649
1626 struct MulticastJoinDecisionMessageHeader * 1650 // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
1627 hdcsn = GNUNET_malloc (sizeof (*hdcsn) + size);
1628 hdcsn->peer = chn->peer;
1629 GNUNET_memcpy (&hdcsn[1], dcsn, sizeof (*hdcsn) + size);
1630
1631 struct Member *mem = (struct Member *) chn->group; 1651 struct Member *mem = (struct Member *) chn->group;
1632 client_send_join_decision (mem, hdcsn); 1652 client_send_join_decision (mem, hdcsn);
1633 GNUNET_free (hdcsn); 1653 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1634 if (GNUNET_YES == ntohs (dcsn->is_admitted))
1635 { 1654 {
1636 chn->join_status = JOIN_ADMITTED; 1655 chn->join_status = JOIN_ADMITTED;
1637 return GNUNET_OK; 1656 return GNUNET_OK;
@@ -1652,6 +1671,7 @@ cadet_recv_message (void *cls,
1652 void **ctx, 1671 void **ctx,
1653 const struct GNUNET_MessageHeader *m) 1672 const struct GNUNET_MessageHeader *m)
1654{ 1673{
1674 GNUNET_CADET_receive_done(channel);
1655 const struct GNUNET_MULTICAST_MessageHeader * 1675 const struct GNUNET_MULTICAST_MessageHeader *
1656 msg = (const struct GNUNET_MULTICAST_MessageHeader *) m; 1676 msg = (const struct GNUNET_MULTICAST_MessageHeader *) m;
1657 uint16_t size = ntohs (m->size); 1677 uint16_t size = ntohs (m->size);
@@ -1697,6 +1717,7 @@ cadet_recv_request (void *cls,
1697 void **ctx, 1717 void **ctx,
1698 const struct GNUNET_MessageHeader *m) 1718 const struct GNUNET_MessageHeader *m)
1699{ 1719{
1720 GNUNET_CADET_receive_done(channel);
1700 const struct GNUNET_MULTICAST_RequestHeader * 1721 const struct GNUNET_MULTICAST_RequestHeader *
1701 req = (const struct GNUNET_MULTICAST_RequestHeader *) m; 1722 req = (const struct GNUNET_MULTICAST_RequestHeader *) m;
1702 uint16_t size = ntohs (m->size); 1723 uint16_t size = ntohs (m->size);
@@ -1742,6 +1763,7 @@ cadet_recv_replay_request (void *cls,
1742 void **ctx, 1763 void **ctx,
1743 const struct GNUNET_MessageHeader *m) 1764 const struct GNUNET_MessageHeader *m)
1744{ 1765{
1766 GNUNET_CADET_receive_done(channel);
1745 struct MulticastReplayRequestMessage rep; 1767 struct MulticastReplayRequestMessage rep;
1746 uint16_t size = ntohs (m->size); 1768 uint16_t size = ntohs (m->size);
1747 if (size < sizeof (rep)) 1769 if (size < sizeof (rep))
@@ -1784,6 +1806,7 @@ cadet_recv_replay_response (void *cls,
1784 void **ctx, 1806 void **ctx,
1785 const struct GNUNET_MessageHeader *m) 1807 const struct GNUNET_MessageHeader *m)
1786{ 1808{
1809 GNUNET_CADET_receive_done(channel);
1787 //struct Channel *chn = *ctx; 1810 //struct Channel *chn = *ctx;
1788 1811
1789 /* @todo FIXME: got replay error response, send request to other members */ 1812 /* @todo FIXME: got replay error response, send request to other members */
@@ -1882,6 +1905,9 @@ static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1882 { cadet_recv_join_request, 1905 { cadet_recv_join_request,
1883 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 }, 1906 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 },
1884 1907
1908 { cadet_recv_join_decision,
1909 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
1910
1885 { cadet_recv_message, 1911 { cadet_recv_message,
1886 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 }, 1912 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1887 1913
diff --git a/src/multicast/multicast_api.c b/src/multicast/multicast_api.c
index 7cfe70835..a8b1dee40 100644
--- a/src/multicast/multicast_api.c
+++ b/src/multicast/multicast_api.c
@@ -556,7 +556,7 @@ group_disconnect (struct GNUNET_MULTICAST_Group *grp,
556 if (NULL != last) 556 if (NULL != last)
557 { 557 {
558 GNUNET_MQ_notify_sent (last, 558 GNUNET_MQ_notify_sent (last,
559 (GNUNET_MQ_NotifyCallback) group_cleanup, grp); 559 (GNUNET_SCHEDULER_TaskCallback) group_cleanup, grp);
560 } 560 }
561 else 561 else
562 { 562 {
@@ -786,7 +786,7 @@ origin_connect (struct GNUNET_MULTICAST_Origin *orig)
786 GNUNET_MQ_handler_end () 786 GNUNET_MQ_handler_end ()
787 }; 787 };
788 788
789 grp->mq = GNUNET_CLIENT_connecT (grp->cfg, "multicast", 789 grp->mq = GNUNET_CLIENT_connect (grp->cfg, "multicast",
790 handlers, origin_disconnected, orig); 790 handlers, origin_disconnected, orig);
791 GNUNET_assert (NULL != grp->mq); 791 GNUNET_assert (NULL != grp->mq);
792 GNUNET_MQ_send_copy (grp->mq, grp->connect_env); 792 GNUNET_MQ_send_copy (grp->mq, grp->connect_env);
@@ -1076,7 +1076,7 @@ member_connect (struct GNUNET_MULTICAST_Member *mem)
1076 GNUNET_MQ_handler_end () 1076 GNUNET_MQ_handler_end ()
1077 }; 1077 };
1078 1078
1079 grp->mq = GNUNET_CLIENT_connecT (grp->cfg, "multicast", 1079 grp->mq = GNUNET_CLIENT_connect (grp->cfg, "multicast",
1080 handlers, member_disconnected, mem); 1080 handlers, member_disconnected, mem);
1081 GNUNET_assert (NULL != grp->mq); 1081 GNUNET_assert (NULL != grp->mq);
1082 GNUNET_MQ_send_copy (grp->mq, grp->connect_env); 1082 GNUNET_MQ_send_copy (grp->mq, grp->connect_env);
diff --git a/src/my/.gitignore b/src/my/.gitignore
new file mode 100644
index 000000000..3338ba2ea
--- /dev/null
+++ b/src/my/.gitignore
@@ -0,0 +1 @@
test_my
diff --git a/src/namecache/.gitignore b/src/namecache/.gitignore
index 7f6924c27..6d2d8488a 100644
--- a/src/namecache/.gitignore
+++ b/src/namecache/.gitignore
@@ -1,2 +1,6 @@
1gnunet-service-namecache 1gnunet-service-namecache
2gnunet-namecache 2gnunet-namecache
3test_namecache_api_cache_block
4test_plugin_namecache_postgres
5test_plugin_namecache_sqlite
6zonefiles
diff --git a/src/namecache/namecache_api.c b/src/namecache/namecache_api.c
index 9ccb91bc8..c12dacd4c 100644
--- a/src/namecache/namecache_api.c
+++ b/src/namecache/namecache_api.c
@@ -336,7 +336,7 @@ reconnect (struct GNUNET_NAMECACHE_Handle *h)
336 GNUNET_MQ_handler_end () 336 GNUNET_MQ_handler_end ()
337 }; 337 };
338 GNUNET_assert (NULL == h->mq); 338 GNUNET_assert (NULL == h->mq);
339 h->mq = GNUNET_CLIENT_connecT (h->cfg, 339 h->mq = GNUNET_CLIENT_connect (h->cfg,
340 "namecache", 340 "namecache",
341 handlers, 341 handlers,
342 &mq_error_handler, 342 &mq_error_handler,
diff --git a/src/namestore/.gitignore b/src/namestore/.gitignore
index 15482dd69..a1153c6f9 100644
--- a/src/namestore/.gitignore
+++ b/src/namestore/.gitignore
@@ -1,3 +1,20 @@
1gnunet-service-namestore 1gnunet-service-namestore
2gnunet-namestore 2gnunet-namestore
3gnunet-namestore-fcfsd 3gnunet-namestore-fcfsd
4test_namestore_api_lookup_nick
5test_namestore_api_lookup_private
6test_namestore_api_lookup_public
7test_namestore_api_lookup_shadow
8test_namestore_api_lookup_shadow_filter
9test_namestore_api_monitoring
10test_namestore_api_monitoring_existing
11test_namestore_api_remove
12test_namestore_api_remove_not_existing_record
13test_namestore_api_store
14test_namestore_api_store_update
15test_namestore_api_zone_iteration
16test_namestore_api_zone_iteration_nick
17test_namestore_api_zone_iteration_specific_zone
18test_namestore_api_zone_iteration_stop
19test_plugin_namestore_postgres
20test_plugin_namestore_sqlite
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index fd232de81..933ba7b95 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -806,7 +806,7 @@ reconnect (struct GNUNET_NAMESTORE_Handle *h)
806 struct GNUNET_NAMESTORE_QueueEntry *qe; 806 struct GNUNET_NAMESTORE_QueueEntry *qe;
807 807
808 GNUNET_assert (NULL == h->mq); 808 GNUNET_assert (NULL == h->mq);
809 h->mq = GNUNET_CLIENT_connecT (h->cfg, 809 h->mq = GNUNET_CLIENT_connect (h->cfg,
810 "namestore", 810 "namestore",
811 handlers, 811 handlers,
812 &mq_error_handler, 812 &mq_error_handler,
diff --git a/src/namestore/namestore_api_monitor.c b/src/namestore/namestore_api_monitor.c
index 00f0887d4..cd7c7dadb 100644
--- a/src/namestore/namestore_api_monitor.c
+++ b/src/namestore/namestore_api_monitor.c
@@ -262,7 +262,7 @@ reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm)
262 GNUNET_MQ_destroy (zm->mq); 262 GNUNET_MQ_destroy (zm->mq);
263 zm->error_cb (zm->error_cb_cls); 263 zm->error_cb (zm->error_cb_cls);
264 } 264 }
265 zm->mq = GNUNET_CLIENT_connecT (zm->cfg, 265 zm->mq = GNUNET_CLIENT_connect (zm->cfg,
266 "namestore", 266 "namestore",
267 handlers, 267 handlers,
268 &mq_error_handler, 268 &mq_error_handler,
diff --git a/src/nat-auto/.gitignore b/src/nat-auto/.gitignore
new file mode 100644
index 000000000..6ba53d72f
--- /dev/null
+++ b/src/nat-auto/.gitignore
@@ -0,0 +1,3 @@
1gnunet-service-nat-auto
2gnunet-nat-auto
3gnunet-nat-server
diff --git a/src/nat-auto/Makefile.am b/src/nat-auto/Makefile.am
new file mode 100644
index 000000000..19695fabd
--- /dev/null
+++ b/src/nat-auto/Makefile.am
@@ -0,0 +1,58 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4libexecdir= $(pkglibdir)/libexec/
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8pkgcfg_DATA = \
9 nat-auto.conf
10
11bin_PROGRAMS = \
12 gnunet-nat-auto \
13 gnunet-nat-server
14
15libexec_PROGRAMS = \
16 gnunet-service-nat-auto
17
18gnunet_nat_server_SOURCES = \
19 gnunet-nat-server.c nat-auto.h
20gnunet_nat_server_LDADD = \
21 $(top_builddir)/src/nat/libgnunetnatnew.la \
22 $(top_builddir)/src/util/libgnunetutil.la
23
24gnunet_nat_auto_SOURCES = \
25 gnunet-nat-auto.c nat-auto.h
26gnunet_nat_auto_LDADD = \
27 libgnunetnatauto.la \
28 $(top_builddir)/src/util/libgnunetutil.la
29
30
31if USE_COVERAGE
32 AM_CFLAGS = -fprofile-arcs -ftest-coverage
33endif
34
35lib_LTLIBRARIES = \
36 libgnunetnatauto.la
37
38libgnunetnatauto_la_SOURCES = \
39 nat_auto_api.c \
40 nat_auto_api_test.c
41libgnunetnatauto_la_LIBADD = \
42 $(top_builddir)/src/nat/libgnunetnatnew.la \
43 $(top_builddir)/src/util/libgnunetutil.la \
44 $(GN_LIBINTL) @EXT_LIBS@
45libgnunetnatauto_la_LDFLAGS = \
46 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
47 -version-info 0:0:0
48
49gnunet_service_nat_auto_SOURCES = \
50 gnunet-service-nat-auto.c
51gnunet_service_nat_auto_LDADD = \
52 $(top_builddir)/src/util/libgnunetutil.la \
53 $(top_builddir)/src/statistics/libgnunetstatistics.la \
54 $(top_builddir)/src/nat/libgnunetnatnew.la \
55 $(LIBGCRYPT_LIBS) \
56 -lgcrypt \
57 $(GN_LIBINTL)
58
diff --git a/src/nat-auto/gnunet-nat-auto.c b/src/nat-auto/gnunet-nat-auto.c
new file mode 100644
index 000000000..9ba81eb5f
--- /dev/null
+++ b/src/nat-auto/gnunet-nat-auto.c
@@ -0,0 +1,381 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2015, 2016, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file src/nat/gnunet-nat-auto.c
23 * @brief Command-line tool for testing and autoconfiguration of NAT traversal
24 * @author Christian Grothoff
25 * @author Bruno Cabral
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_nat_service.h"
30#include "gnunet_nat_auto_service.h"
31
32/**
33 * Value to return from #main().
34 */
35static int global_ret;
36
37/**
38 * Handle to ongoing autoconfiguration.
39 */
40static struct GNUNET_NAT_AUTO_AutoHandle *ah;
41
42/**
43 * If we do auto-configuration, should we write the result
44 * to a file?
45 */
46static int write_cfg;
47
48/**
49 * Configuration filename.
50 */
51static const char *cfg_file;
52
53/**
54 * Original configuration.
55 */
56static const struct GNUNET_CONFIGURATION_Handle *cfg;
57
58/**
59 * Adapter we are supposed to test.
60 */
61static char *section_name;
62
63/**
64 * Should we run autoconfiguration?
65 */
66static unsigned int do_auto;
67
68/**
69 * Handle to a NAT test operation.
70 */
71static struct GNUNET_NAT_AUTO_Test *nt;
72
73/**
74 * Flag set to 1 if we use IPPROTO_UDP.
75 */
76static int use_udp;
77
78/**
79 * Flag set to 1 if we use IPPROTO_TCP.
80 */
81static int use_tcp;
82
83/**
84 * Protocol to use.
85 */
86static uint8_t proto;
87
88/**
89 * Test if all activities have finished, and if so,
90 * terminate.
91 */
92static void
93test_finished ()
94{
95 if (NULL != ah)
96 return;
97 if (NULL != nt)
98 return;
99 GNUNET_SCHEDULER_shutdown ();
100}
101
102
103/**
104 * Function to iterate over sugested changes options
105 *
106 * @param cls closure
107 * @param section name of the section
108 * @param option name of the option
109 * @param value value of the option
110 */
111static void
112auto_conf_iter (void *cls,
113 const char *section,
114 const char *option,
115 const char *value)
116{
117 struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
118
119 PRINTF ("%s: %s\n",
120 option,
121 value);
122 if (NULL != new_cfg)
123 GNUNET_CONFIGURATION_set_value_string (new_cfg,
124 section,
125 option,
126 value);
127}
128
129
130/**
131 * Function called with the result from the autoconfiguration.
132 *
133 * @param cls closure
134 * @param diff minimal suggested changes to the original configuration
135 * to make it work (as best as we can)
136 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
137 * @param type what the situation of the NAT
138 */
139static void
140auto_config_cb (void *cls,
141 const struct GNUNET_CONFIGURATION_Handle *diff,
142 enum GNUNET_NAT_StatusCode result,
143 enum GNUNET_NAT_Type type)
144{
145 const char *nat_type;
146 char unknown_type[64];
147 struct GNUNET_CONFIGURATION_Handle *new_cfg;
148
149 ah = NULL;
150 switch (type)
151 {
152 case GNUNET_NAT_TYPE_NO_NAT:
153 nat_type = "NO NAT";
154 break;
155 case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
156 nat_type = "NAT but we can traverse";
157 break;
158 case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
159 nat_type = "NAT but STUN is able to identify the correct information";
160 break;
161 case GNUNET_NAT_TYPE_UPNP_NAT:
162 nat_type = "NAT but UPNP opened the ports";
163 break;
164 default:
165 SPRINTF (unknown_type,
166 "NAT unknown, type %u",
167 type);
168 nat_type = unknown_type;
169 break;
170 }
171
172 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
173 "NAT status: %s/%s\n",
174 GNUNET_NAT_AUTO_status2string (result),
175 nat_type);
176
177 /* Shortcut: if there are no changes suggested, bail out early. */
178 if (GNUNET_NO ==
179 GNUNET_CONFIGURATION_is_dirty (diff))
180 {
181 test_finished ();
182 return;
183 }
184
185 /* Apply diff to original configuration and show changes
186 to the user */
187 new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
188
189 if (NULL != diff)
190 {
191 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
192 _("Suggested configuration changes:\n"));
193 GNUNET_CONFIGURATION_iterate_section_values (diff,
194 "nat",
195 &auto_conf_iter,
196 new_cfg);
197 }
198
199 /* If desired, write configuration to file; we write only the
200 changes to the defaults to keep things compact. */
201 if ( (write_cfg) &&
202 (NULL != diff) )
203 {
204 struct GNUNET_CONFIGURATION_Handle *def_cfg;
205
206 GNUNET_CONFIGURATION_set_value_string (new_cfg,
207 "ARM",
208 "CONFIG",
209 NULL);
210 def_cfg = GNUNET_CONFIGURATION_create ();
211 GNUNET_break (GNUNET_OK ==
212 GNUNET_CONFIGURATION_load (def_cfg,
213 NULL));
214 if (GNUNET_OK !=
215 GNUNET_CONFIGURATION_write_diffs (def_cfg,
216 new_cfg,
217 cfg_file))
218 {
219 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
220 _("Failed to write configuration to `%s'\n"),
221 cfg_file);
222 global_ret = 1;
223 }
224 else
225 {
226 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
227 _("Wrote updated configuration to `%s'\n"),
228 cfg_file);
229 }
230 GNUNET_CONFIGURATION_destroy (def_cfg);
231 }
232
233 if (NULL != new_cfg)
234 GNUNET_CONFIGURATION_destroy (new_cfg);
235 test_finished ();
236}
237
238
239/**
240 * Function called to report success or failure for
241 * NAT configuration test.
242 *
243 * @param cls closure
244 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
245 */
246static void
247test_report_cb (void *cls,
248 enum GNUNET_NAT_StatusCode result)
249{
250 nt = NULL;
251 PRINTF ("NAT test result: %s\n",
252 GNUNET_NAT_AUTO_status2string (result));
253 test_finished ();
254}
255
256
257/**
258 * Task run on shutdown.
259 *
260 * @param cls NULL
261 */
262static void
263do_shutdown (void *cls)
264{
265 if (NULL != ah)
266 {
267 GNUNET_NAT_AUTO_autoconfig_cancel (ah);
268 ah = NULL;
269 }
270 if (NULL != nt)
271 {
272 GNUNET_NAT_AUTO_test_stop (nt);
273 nt = NULL;
274 }
275}
276
277
278/**
279 * Main function that will be run.
280 *
281 * @param cls closure
282 * @param args remaining command-line arguments
283 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
284 * @param c configuration
285 */
286static void
287run (void *cls,
288 char *const *args,
289 const char *cfgfile,
290 const struct GNUNET_CONFIGURATION_Handle *c)
291{
292 cfg_file = cfgfile;
293 cfg = c;
294
295 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
296 NULL);
297
298 if (do_auto)
299 {
300 ah = GNUNET_NAT_AUTO_autoconfig_start (c,
301 &auto_config_cb,
302 NULL);
303 }
304
305 if (use_tcp && use_udp)
306 {
307 if (do_auto)
308 return;
309 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
310 "Cannot use TCP and UDP\n");
311 global_ret = 1;
312 return;
313 }
314 proto = 0;
315 if (use_tcp)
316 proto = IPPROTO_TCP;
317 if (use_udp)
318 proto = IPPROTO_UDP;
319
320 if (NULL != section_name)
321 {
322 nt = GNUNET_NAT_AUTO_test_start (c,
323 proto,
324 section_name,
325 &test_report_cb,
326 NULL);
327 }
328 test_finished ();
329}
330
331
332/**
333 * Main function of gnunet-nat-auto
334 *
335 * @param argc number of command-line arguments
336 * @param argv command line
337 * @return 0 on success, -1 on error
338 */
339int
340main (int argc,
341 char *const argv[])
342{
343 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
344 {'a', "auto", NULL,
345 gettext_noop ("run autoconfiguration"),
346 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
347 {'S', "section", "NAME",
348 gettext_noop ("section name providing the configuration for the adapter"),
349 GNUNET_YES, &GNUNET_GETOPT_set_string, &section_name },
350 {'t', "tcp", NULL,
351 gettext_noop ("use TCP"),
352 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_tcp },
353 {'u', "udp", NULL,
354 gettext_noop ("use UDP"),
355 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
356 {'w', "write", NULL,
357 gettext_noop ("write configuration file (for autoconfiguration)"),
358 GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
359 GNUNET_GETOPT_OPTION_END
360 };
361
362 if (GNUNET_OK !=
363 GNUNET_STRINGS_get_utf8_args (argc, argv,
364 &argc, &argv))
365 return 2;
366 if (GNUNET_OK !=
367 GNUNET_PROGRAM_run (argc, argv,
368 "gnunet-nat-auto [options]",
369 _("GNUnet NAT traversal autoconfiguration"),
370 options,
371 &run,
372 NULL))
373 {
374 global_ret = 1;
375 }
376 GNUNET_free ((void*) argv);
377 return global_ret;
378}
379
380
381/* end of gnunet-nat-auto.c */
diff --git a/src/nat/nat_test.c b/src/nat-auto/gnunet-nat-auto_legacy.c
index 803ff23e3..32f40c037 100644
--- a/src/nat/nat_test.c
+++ b/src/nat-auto/gnunet-nat-auto_legacy.c
@@ -391,7 +391,7 @@ addr_cb (void *cls,
391 391
392 ca = GNUNET_new (struct ClientActivity); 392 ca = GNUNET_new (struct ClientActivity);
393 ca->h = h; 393 ca->h = h;
394 ca->mq = GNUNET_CLIENT_connecT (h->cfg, 394 ca->mq = GNUNET_CLIENT_connect (h->cfg,
395 "gnunet-nat-server", 395 "gnunet-nat-server",
396 NULL, 396 NULL,
397 &mq_error_handler, 397 &mq_error_handler,
diff --git a/src/nat/gnunet-nat-server.c b/src/nat-auto/gnunet-nat-server.c
index 1692a8ef1..dd08f8d36 100644
--- a/src/nat/gnunet-nat-server.c
+++ b/src/nat-auto/gnunet-nat-server.c
@@ -25,9 +25,9 @@
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_nat_lib.h" 28#include "gnunet_nat_service.h"
29#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "nat.h" 30#include "nat-auto.h"
31 31
32 32
33/** 33/**
@@ -54,24 +54,39 @@ try_anat (uint32_t dst_ipv4,
54 int is_tcp) 54 int is_tcp)
55{ 55{
56 struct GNUNET_NAT_Handle *h; 56 struct GNUNET_NAT_Handle *h;
57 struct sockaddr_in sa; 57 struct sockaddr_in lsa;
58 struct sockaddr_in rsa;
59 socklen_t sa_len;
58 60
59 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 61 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
60 "Asking for connection reversal with %x and code %u\n", 62 "Asking for connection reversal with %x and code %u\n",
61 (unsigned int) dst_ipv4, 63 (unsigned int) dst_ipv4,
62 (unsigned int) dport); 64 (unsigned int) dport);
63 h = GNUNET_NAT_register (cfg, 65 memset (&lsa, 0, sizeof (lsa));
64 is_tcp, 66 lsa.sin_family = AF_INET;
65 dport,
66 0,
67 NULL, NULL, NULL, NULL, NULL, NULL);
68 memset (&sa, 0, sizeof (sa));
69 sa.sin_family = AF_INET;
70#if HAVE_SOCKADDR_IN_SIN_LEN 67#if HAVE_SOCKADDR_IN_SIN_LEN
71 sa.sin_len = sizeof (sa); 68 lsa.sin_len = sizeof (sa);
72#endif 69#endif
73 sa.sin_addr.s_addr = dst_ipv4; 70 lsa.sin_addr.s_addr = 0;
74 GNUNET_NAT_run_client (h, &sa); 71 lsa.sin_port = htons (dport);
72 memset (&rsa, 0, sizeof (rsa));
73 rsa.sin_family = AF_INET;
74#if HAVE_SOCKADDR_IN_SIN_LEN
75 rsa.sin_len = sizeof (sa);
76#endif
77 rsa.sin_addr.s_addr = dst_ipv4;
78 rsa.sin_port = htons (dport);
79 sa_len = sizeof (lsa);
80 h = GNUNET_NAT_register (cfg,
81 "none",
82 is_tcp ? IPPROTO_TCP : IPPROTO_UDP,
83 1,
84 (const struct sockaddr **) &lsa,
85 &sa_len,
86 NULL, NULL, NULL);
87 GNUNET_NAT_request_reversal (h,
88 &lsa,
89 &rsa);
75 GNUNET_NAT_unregister (h); 90 GNUNET_NAT_unregister (h);
76} 91}
77 92
@@ -240,12 +255,12 @@ test (void *cls,
240 struct GNUNET_SERVER_Client *client, 255 struct GNUNET_SERVER_Client *client,
241 const struct GNUNET_MessageHeader *msg) 256 const struct GNUNET_MessageHeader *msg)
242{ 257{
243 const struct GNUNET_NAT_TestMessage *tm; 258 const struct GNUNET_NAT_AUTO_TestMessage *tm;
244 uint16_t dport; 259 uint16_t dport;
245 260
246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
247 "Received test request\n"); 262 "Received test request\n");
248 tm = (const struct GNUNET_NAT_TestMessage *) msg; 263 tm = (const struct GNUNET_NAT_AUTO_TestMessage *) msg;
249 dport = ntohs (tm->dport); 264 dport = ntohs (tm->dport);
250 if (0 == dport) 265 if (0 == dport)
251 try_anat (tm->dst_ipv4, 266 try_anat (tm->dst_ipv4,
@@ -293,7 +308,7 @@ run (void *cls,
293{ 308{
294 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 309 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
295 {&test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST, 310 {&test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST,
296 sizeof (struct GNUNET_NAT_TestMessage)}, 311 sizeof (struct GNUNET_NAT_AUTO_TestMessage)},
297 {NULL, NULL, 0, 0} 312 {NULL, NULL, 0, 0}
298 }; 313 };
299 unsigned int port; 314 unsigned int port;
diff --git a/src/nat-auto/gnunet-service-nat-auto.c b/src/nat-auto/gnunet-service-nat-auto.c
new file mode 100644
index 000000000..ae570c351
--- /dev/null
+++ b/src/nat-auto/gnunet-service-nat-auto.c
@@ -0,0 +1,482 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21/**
22 * @file nat-auto/gnunet-service-nat-auto.c
23 * @brief NAT autoconfiguration service
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - merge client handle and autoconfig context
28 * - implement "more" autoconfig:
29 * + re-work gnunet-nat-server & integrate!
30 * + integrate "legacy" code
31 * + test manually punched NAT (how?)
32 */
33#include "platform.h"
34#include <math.h>
35#include "gnunet_util_lib.h"
36#include "gnunet_protocols.h"
37#include "gnunet_signatures.h"
38#include "gnunet_nat_service.h"
39#include "gnunet_statistics_service.h"
40#include "gnunet_resolver_service.h"
41#include "nat-auto.h"
42#include <gcrypt.h>
43
44
45/**
46 * How long do we wait until we forcefully terminate autoconfiguration?
47 */
48#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
49
50
51/**
52 * Internal data structure we track for each of our clients.
53 */
54struct ClientHandle
55{
56
57 /**
58 * Kept in a DLL.
59 */
60 struct ClientHandle *next;
61
62 /**
63 * Kept in a DLL.
64 */
65 struct ClientHandle *prev;
66
67 /**
68 * Underlying handle for this client with the service.
69 */
70 struct GNUNET_SERVICE_Client *client;
71
72 /**
73 * Message queue for communicating with the client.
74 */
75 struct GNUNET_MQ_Handle *mq;
76};
77
78
79/**
80 * Context for autoconfiguration operations.
81 */
82struct AutoconfigContext
83{
84 /**
85 * Kept in a DLL.
86 */
87 struct AutoconfigContext *prev;
88
89 /**
90 * Kept in a DLL.
91 */
92 struct AutoconfigContext *next;
93
94 /**
95 * Which client asked the question.
96 */
97 struct ClientHandle *ch;
98
99 /**
100 * Configuration we are creating.
101 */
102 struct GNUNET_CONFIGURATION_Handle *c;
103
104 /**
105 * Original configuration (for diffing).
106 */
107 struct GNUNET_CONFIGURATION_Handle *orig;
108
109 /**
110 * Timeout task to force termination.
111 */
112 struct GNUNET_SCHEDULER_Task *timeout_task;
113
114 /**
115 * #GNUNET_YES if upnpc should be used,
116 * #GNUNET_NO if upnpc should not be used,
117 * #GNUNET_SYSERR if we should simply not change the option.
118 */
119 int enable_upnpc;
120
121 /**
122 * Status code to return to the client.
123 */
124 enum GNUNET_NAT_StatusCode status_code;
125
126 /**
127 * NAT type to return to the client.
128 */
129 enum GNUNET_NAT_Type type;
130};
131
132
133/**
134 * Head of client DLL.
135 */
136static struct ClientHandle *ch_head;
137
138/**
139 * Tail of client DLL.
140 */
141static struct ClientHandle *ch_tail;
142
143/**
144 * DLL of our autoconfiguration operations.
145 */
146static struct AutoconfigContext *ac_head;
147
148/**
149 * DLL of our autoconfiguration operations.
150 */
151static struct AutoconfigContext *ac_tail;
152
153/**
154 * Handle to our current configuration.
155 */
156static const struct GNUNET_CONFIGURATION_Handle *cfg;
157
158/**
159 * Handle to the statistics service.
160 */
161static struct GNUNET_STATISTICS_Handle *stats;
162
163
164/**
165 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
166 * from client.
167 *
168 * @param cls client who sent the message
169 * @param message the message received
170 * @return #GNUNET_OK if message is well-formed
171 */
172static int
173check_autoconfig_request (void *cls,
174 const struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *message)
175{
176 return GNUNET_OK; /* checked later */
177}
178
179
180/**
181 * Stop all pending activities with respect to the @a ac
182 *
183 * @param ac autoconfiguration to terminate activities for
184 */
185static void
186terminate_ac_activities (struct AutoconfigContext *ac)
187{
188 if (NULL != ac->timeout_task)
189 {
190 GNUNET_SCHEDULER_cancel (ac->timeout_task);
191 ac->timeout_task = NULL;
192 }
193}
194
195
196/**
197 * Finish handling the autoconfiguration request and send
198 * the response to the client.
199 *
200 * @param cls the `struct AutoconfigContext` to conclude
201 */
202static void
203conclude_autoconfig_request (void *cls)
204{
205 struct AutoconfigContext *ac = cls;
206 struct ClientHandle *ch = ac->ch;
207 struct GNUNET_NAT_AUTO_AutoconfigResultMessage *arm;
208 struct GNUNET_MQ_Envelope *env;
209 size_t c_size;
210 char *buf;
211 struct GNUNET_CONFIGURATION_Handle *diff;
212
213 ac->timeout_task = NULL;
214 terminate_ac_activities (ac);
215
216 /* Send back response */
217 diff = GNUNET_CONFIGURATION_get_diff (ac->orig,
218 ac->c);
219 buf = GNUNET_CONFIGURATION_serialize (diff,
220 &c_size);
221 GNUNET_CONFIGURATION_destroy (diff);
222 env = GNUNET_MQ_msg_extra (arm,
223 c_size,
224 GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT);
225 arm->status_code = htonl ((uint32_t) ac->status_code);
226 arm->type = htonl ((uint32_t) ac->type);
227 GNUNET_memcpy (&arm[1],
228 buf,
229 c_size);
230 GNUNET_free (buf);
231 GNUNET_MQ_send (ch->mq,
232 env);
233
234 /* clean up */
235 GNUNET_CONFIGURATION_destroy (ac->orig);
236 GNUNET_CONFIGURATION_destroy (ac->c);
237 GNUNET_CONTAINER_DLL_remove (ac_head,
238 ac_tail,
239 ac);
240 GNUNET_free (ac);
241 GNUNET_SERVICE_client_continue (ch->client);
242}
243
244
245/**
246 * Check if all autoconfiguration operations have concluded,
247 * and if they have, send the result back to the client.
248 *
249 * @param ac autoconfiguation context to check
250 */
251static void
252check_autoconfig_finished (struct AutoconfigContext *ac)
253{
254 GNUNET_SCHEDULER_cancel (ac->timeout_task);
255 ac->timeout_task
256 = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request,
257 ac);
258}
259
260
261/**
262 * Update ENABLE_UPNPC configuration option.
263 *
264 * @param ac autoconfiguration to update
265 */
266static void
267update_enable_upnpc_option (struct AutoconfigContext *ac)
268{
269 switch (ac->enable_upnpc)
270 {
271 case GNUNET_YES:
272 GNUNET_CONFIGURATION_set_value_string (ac->c,
273 "NAT",
274 "ENABLE_UPNP",
275 "YES");
276 break;
277 case GNUNET_NO:
278 GNUNET_CONFIGURATION_set_value_string (ac->c,
279 "NAT",
280 "ENABLE_UPNP",
281 "NO");
282 break;
283 case GNUNET_SYSERR:
284 /* We are unsure, do not change option */
285 break;
286 }
287}
288
289
290/**
291 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
292 * client.
293 *
294 * @param cls client who sent the message
295 * @param message the message received
296 */
297static void
298handle_autoconfig_request (void *cls,
299 const struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *message)
300{
301 struct ClientHandle *ch = cls;
302 size_t left = ntohs (message->header.size) - sizeof (*message);
303 struct AutoconfigContext *ac;
304
305 ac = GNUNET_new (struct AutoconfigContext);
306 ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
307 ac->ch = ch;
308 ac->c = GNUNET_CONFIGURATION_create ();
309 if (GNUNET_OK !=
310 GNUNET_CONFIGURATION_deserialize (ac->c,
311 (const char *) &message[1],
312 left,
313 GNUNET_NO))
314 {
315 GNUNET_break (0);
316 GNUNET_SERVICE_client_drop (ch->client);
317 GNUNET_CONFIGURATION_destroy (ac->c);
318 GNUNET_free (ac);
319 return;
320 }
321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
322 "Received REQUEST_AUTO_CONFIG message from client\n");
323
324 GNUNET_CONTAINER_DLL_insert (ac_head,
325 ac_tail,
326 ac);
327 ac->orig
328 = GNUNET_CONFIGURATION_dup (ac->c);
329 ac->timeout_task
330 = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT,
331 &conclude_autoconfig_request,
332 ac);
333 ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
334
335 /* Probe for upnpc */
336 if (GNUNET_SYSERR ==
337 GNUNET_OS_check_helper_binary ("upnpc",
338 GNUNET_NO,
339 NULL))
340 {
341 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
342 _("UPnP client `upnpc` command not found, disabling UPnP\n"));
343 ac->enable_upnpc = GNUNET_NO;
344 }
345 else
346 {
347 /* We might at some point be behind NAT, try upnpc */
348 ac->enable_upnpc = GNUNET_YES;
349 }
350 update_enable_upnpc_option (ac);
351
352 /* Finally, check if we are already done */
353 check_autoconfig_finished (ac);
354}
355
356
357/**
358 * Task run during shutdown.
359 *
360 * @param cls unused
361 */
362static void
363shutdown_task (void *cls)
364{
365 struct AutoconfigContext *ac;
366
367 while (NULL != (ac = ac_head))
368 {
369 GNUNET_CONTAINER_DLL_remove (ac_head,
370 ac_tail,
371 ac);
372 terminate_ac_activities (ac);
373 GNUNET_free (ac);
374 }
375 if (NULL != stats)
376 {
377 GNUNET_STATISTICS_destroy (stats,
378 GNUNET_NO);
379 stats = NULL;
380 }
381}
382
383
384/**
385 * Setup NAT service.
386 *
387 * @param cls closure
388 * @param c configuration to use
389 * @param service the initialized service
390 */
391static void
392run (void *cls,
393 const struct GNUNET_CONFIGURATION_Handle *c,
394 struct GNUNET_SERVICE_Handle *service)
395{
396 cfg = c;
397 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
398 NULL);
399 stats = GNUNET_STATISTICS_create ("nat-auto",
400 cfg);
401}
402
403
404/**
405 * Callback called when a client connects to the service.
406 *
407 * @param cls closure for the service
408 * @param c the new client that connected to the service
409 * @param mq the message queue used to send messages to the client
410 * @return a `struct ClientHandle`
411 */
412static void *
413client_connect_cb (void *cls,
414 struct GNUNET_SERVICE_Client *c,
415 struct GNUNET_MQ_Handle *mq)
416{
417 struct ClientHandle *ch;
418
419 ch = GNUNET_new (struct ClientHandle);
420 ch->mq = mq;
421 ch->client = c;
422 GNUNET_CONTAINER_DLL_insert (ch_head,
423 ch_tail,
424 ch);
425 return ch;
426}
427
428
429/**
430 * Callback called when a client disconnected from the service
431 *
432 * @param cls closure for the service
433 * @param c the client that disconnected
434 * @param internal_cls a `struct ClientHandle *`
435 */
436static void
437client_disconnect_cb (void *cls,
438 struct GNUNET_SERVICE_Client *c,
439 void *internal_cls)
440{
441 struct ClientHandle *ch = internal_cls;
442
443 GNUNET_CONTAINER_DLL_remove (ch_head,
444 ch_tail,
445 ch);
446 GNUNET_free (ch);
447}
448
449
450/**
451 * Define "main" method using service macro.
452 */
453GNUNET_SERVICE_MAIN
454("nat-auto",
455 GNUNET_SERVICE_OPTION_NONE,
456 &run,
457 &client_connect_cb,
458 &client_disconnect_cb,
459 NULL,
460 GNUNET_MQ_hd_var_size (autoconfig_request,
461 GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG,
462 struct GNUNET_NAT_AUTO_AutoconfigRequestMessage,
463 NULL),
464 GNUNET_MQ_handler_end ());
465
466
467#if defined(LINUX) && defined(__GLIBC__)
468#include <malloc.h>
469
470/**
471 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
472 */
473void __attribute__ ((constructor))
474GNUNET_ARM_memory_init ()
475{
476 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
477 mallopt (M_TOP_PAD, 1 * 1024);
478 malloc_trim (0);
479}
480#endif
481
482/* end of gnunet-service-nat.c */
diff --git a/src/nat/nat_auto.c b/src/nat-auto/gnunet-service-nat-auto_legacy.c
index 061d0cbe6..bcfa4b92b 100644
--- a/src/nat/nat_auto.c
+++ b/src/nat-auto/gnunet-service-nat-auto_legacy.c
@@ -670,7 +670,7 @@ test_nat_punched (struct GNUNET_NAT_AutoHandle *ah)
670 LOG (GNUNET_ERROR_TYPE_INFO, 670 LOG (GNUNET_ERROR_TYPE_INFO,
671 "Asking gnunet-nat-server to connect to `%s'\n", 671 "Asking gnunet-nat-server to connect to `%s'\n",
672 ah->stun_ip); 672 ah->stun_ip);
673 ah->mq = GNUNET_CLIENT_connecT (ah->cfg, 673 ah->mq = GNUNET_CLIENT_connect (ah->cfg,
674 "gnunet-nat-server", 674 "gnunet-nat-server",
675 NULL, 675 NULL,
676 &mq_error_handler, 676 &mq_error_handler,
diff --git a/src/nat-auto/nat-auto.conf.in b/src/nat-auto/nat-auto.conf.in
new file mode 100644
index 000000000..9461ffcc8
--- /dev/null
+++ b/src/nat-auto/nat-auto.conf.in
@@ -0,0 +1,15 @@
1[nat-auto]
2AUTOSTART = @AUTOSTART@
3@UNIXONLY@ PORT = 2124
4HOSTNAME = localhost
5BINARY = gnunet-service-nat-auto
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nat-auto.sock
9UNIX_MATCH_UID = YES
10UNIX_MATCH_GID = YES
11
12[gnunet-nat-server]
13HOSTNAME = gnunet.org
14PORT = 5724
15NOARMBIND = YES
diff --git a/src/nat-auto/nat-auto.h b/src/nat-auto/nat-auto.h
new file mode 100644
index 000000000..07b5a5b91
--- /dev/null
+++ b/src/nat-auto/nat-auto.h
@@ -0,0 +1,110 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2016, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file src/nat-auto/nat-auto.h
23 * @brief Messages for interaction with gnunet-nat-auto-service
24 * @author Christian Grothoff
25 *
26 */
27#ifndef NAT_AUTO_H
28#define NAT_AUTO_H
29#include "gnunet_util_lib.h"
30
31
32
33GNUNET_NETWORK_STRUCT_BEGIN
34
35/**
36 * Request to test NAT traversal, sent to the gnunet-nat-server
37 * (not the service!).
38 */
39struct GNUNET_NAT_AUTO_TestMessage
40{
41 /**
42 * Header with type #GNUNET_MESSAGE_TYPE_NAT_TEST
43 */
44 struct GNUNET_MessageHeader header;
45
46 /**
47 * IPv4 target IP address
48 */
49 uint32_t dst_ipv4;
50
51 /**
52 * Port to use, 0 to send dummy ICMP response.
53 */
54 uint16_t dport;
55
56 /**
57 * Data to send OR advertised-port (in NBO) to use for dummy ICMP.
58 */
59 uint16_t data;
60
61 /**
62 * #GNUNET_YES for TCP, #GNUNET_NO for UDP.
63 */
64 int32_t is_tcp;
65
66};
67
68
69/**
70 * Client requesting automatic configuration.
71 */
72struct GNUNET_NAT_AUTO_AutoconfigRequestMessage
73{
74 /**
75 * Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG
76 */
77 struct GNUNET_MessageHeader header;
78
79 /* Followed by configuration (diff, serialized, compressed) */
80
81};
82
83
84/**
85 * Service responding with proposed configuration.
86 */
87struct GNUNET_NAT_AUTO_AutoconfigResultMessage
88{
89 /**
90 * Header with type #GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
91 */
92 struct GNUNET_MessageHeader header;
93
94 /**
95 * An `enum GNUNET_NAT_StatusCode` in NBO.
96 */
97 int32_t status_code GNUNET_PACKED;
98
99 /**
100 * An `enum GNUNET_NAT_Type` in NBO.
101 */
102 int32_t type GNUNET_PACKED;
103
104 /* Followed by configuration (diff, serialized, compressed) */
105};
106
107
108GNUNET_NETWORK_STRUCT_END
109
110#endif
diff --git a/src/nat-auto/nat_auto_api.c b/src/nat-auto/nat_auto_api.c
new file mode 100644
index 000000000..a5b41ac49
--- /dev/null
+++ b/src/nat-auto/nat_auto_api.c
@@ -0,0 +1,273 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2007-2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @author Christian Grothoff
23 * @author Milan Bouchet-Valat
24 *
25 * @file nat-auto/nat_auto_api.c
26 * Routines for NAT auto configuration.
27 */
28#include "platform.h"
29#include "gnunet_nat_service.h"
30#include "gnunet_nat_auto_service.h"
31#include "nat-auto.h"
32
33
34
35/**
36 * Handle to auto-configuration in progress.
37 */
38struct GNUNET_NAT_AUTO_AutoHandle
39{
40
41 /**
42 * Configuration we use.
43 */
44 const struct GNUNET_CONFIGURATION_Handle *cfg;
45
46 /**
47 * Message queue for communicating with the NAT service.
48 */
49 struct GNUNET_MQ_Handle *mq;
50
51 /**
52 * Function called with the result from the autoconfiguration.
53 */
54 GNUNET_NAT_AUTO_AutoResultCallback arc;
55
56 /**
57 * Closure for @e arc.
58 */
59 void *arc_cls;
60
61};
62
63
64/**
65 * Converts `enum GNUNET_NAT_StatusCode` to string
66 *
67 * @param err error code to resolve to a string
68 * @return point to a static string containing the error code
69 */
70const char *
71GNUNET_NAT_AUTO_status2string (enum GNUNET_NAT_StatusCode err)
72{
73 switch (err)
74 {
75 case GNUNET_NAT_ERROR_SUCCESS:
76 return _ ("Operation Successful");
77 case GNUNET_NAT_ERROR_IPC_FAILURE:
78 return _ ("IPC failure");
79 case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
80 return _ ("Failure in network subsystem, check permissions.");
81 case GNUNET_NAT_ERROR_TIMEOUT:
82 return _ ("Encountered timeout while performing operation");
83 case GNUNET_NAT_ERROR_NOT_ONLINE:
84 return _ ("detected that we are offline");
85 case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
86 return _ ("`upnpc` command not found");
87 case GNUNET_NAT_ERROR_UPNPC_FAILED:
88 return _ ("Failed to run `upnpc` command");
89 case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
90 return _ ("`upnpc' command took too long, process killed");
91 case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
92 return _ ("`upnpc' command failed to establish port mapping");
93 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
94 return _ ("`external-ip' command not found");
95 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
96 return _ ("Failed to run `external-ip` command");
97 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
98 return _ ("`external-ip' command output invalid");
99 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
100 return _ ("no valid address was returned by `external-ip'");
101 case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
102 return _ ("Could not determine interface with internal/local network address");
103 case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
104 return _ ("No functioning gnunet-helper-nat-server installation found");
105 case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
106 return _ ("NAT test could not be initialized");
107 case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
108 return _ ("NAT test timeout reached");
109 case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
110 return _ ("could not register NAT");
111 case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
112 return _ ("No working gnunet-helper-nat-client installation found");
113 default:
114 return "unknown status code";
115 }
116}
117
118
119/**
120 * Check result from autoconfiguration attempt.
121 *
122 * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle`
123 * @param res the result
124 * @return #GNUNET_OK if @a res is well-formed (always for now)
125 */
126static int
127check_auto_result (void *cls,
128 const struct GNUNET_NAT_AUTO_AutoconfigResultMessage *res)
129{
130 return GNUNET_OK;
131}
132
133
134/**
135 * Handle result from autoconfiguration attempt.
136 *
137 * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle`
138 * @param res the result
139 */
140static void
141handle_auto_result (void *cls,
142 const struct GNUNET_NAT_AUTO_AutoconfigResultMessage *res)
143{
144 struct GNUNET_NAT_AUTO_AutoHandle *ah = cls;
145 size_t left;
146 struct GNUNET_CONFIGURATION_Handle *cfg;
147 enum GNUNET_NAT_Type type
148 = (enum GNUNET_NAT_Type) ntohl (res->type);
149 enum GNUNET_NAT_StatusCode status
150 = (enum GNUNET_NAT_StatusCode) ntohl (res->status_code);
151
152 left = ntohs (res->header.size) - sizeof (*res);
153 cfg = GNUNET_CONFIGURATION_create ();
154 if (GNUNET_OK !=
155 GNUNET_CONFIGURATION_deserialize (cfg,
156 (const char *) &res[1],
157 left,
158 GNUNET_NO))
159 {
160 GNUNET_break (0);
161 ah->arc (ah->arc_cls,
162 NULL,
163 GNUNET_NAT_ERROR_IPC_FAILURE,
164 type);
165 }
166 else
167 {
168 ah->arc (ah->arc_cls,
169 cfg,
170 status,
171 type);
172 }
173 GNUNET_CONFIGURATION_destroy (cfg);
174 GNUNET_NAT_AUTO_autoconfig_cancel (ah);
175}
176
177
178/**
179 * Handle queue errors by reporting autoconfiguration failure.
180 *
181 * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle *`
182 * @param error details about the error
183 */
184static void
185ah_error_handler (void *cls,
186 enum GNUNET_MQ_Error error)
187{
188 struct GNUNET_NAT_AUTO_AutoHandle *ah = cls;
189
190 ah->arc (ah->arc_cls,
191 NULL,
192 GNUNET_NAT_ERROR_IPC_FAILURE,
193 GNUNET_NAT_TYPE_UNKNOWN);
194 GNUNET_NAT_AUTO_autoconfig_cancel (ah);
195}
196
197
198/**
199 * Start auto-configuration routine. The transport adapters should
200 * be stopped while this function is called.
201 *
202 * @param cfg initial configuration
203 * @param cb function to call with autoconfiguration result
204 * @param cb_cls closure for @a cb
205 * @return handle to cancel operation
206 */
207struct GNUNET_NAT_AUTO_AutoHandle *
208GNUNET_NAT_AUTO_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
209 GNUNET_NAT_AUTO_AutoResultCallback cb,
210 void *cb_cls)
211{
212 struct GNUNET_NAT_AUTO_AutoHandle *ah = GNUNET_new (struct GNUNET_NAT_AUTO_AutoHandle);
213 struct GNUNET_MQ_MessageHandler handlers[] = {
214 GNUNET_MQ_hd_var_size (auto_result,
215 GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT,
216 struct GNUNET_NAT_AUTO_AutoconfigResultMessage,
217 ah),
218 GNUNET_MQ_handler_end ()
219 };
220 struct GNUNET_MQ_Envelope *env;
221 struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *req;
222 char *buf;
223 size_t size;
224
225 buf = GNUNET_CONFIGURATION_serialize (cfg,
226 &size);
227 if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*req))
228 {
229 GNUNET_break (0);
230 GNUNET_free (buf);
231 GNUNET_free (ah);
232 return NULL;
233 }
234 ah->arc = cb;
235 ah->arc_cls = cb_cls;
236 ah->mq = GNUNET_CLIENT_connect (cfg,
237 "nat",
238 handlers,
239 &ah_error_handler,
240 ah);
241 if (NULL == ah->mq)
242 {
243 GNUNET_break (0);
244 GNUNET_free (buf);
245 GNUNET_free (ah);
246 return NULL;
247 }
248 env = GNUNET_MQ_msg_extra (req,
249 size,
250 GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG);
251 GNUNET_memcpy (&req[1],
252 buf,
253 size);
254 GNUNET_free (buf);
255 GNUNET_MQ_send (ah->mq,
256 env);
257 return ah;
258}
259
260
261/**
262 * Abort autoconfiguration.
263 *
264 * @param ah handle for operation to abort
265 */
266void
267GNUNET_NAT_AUTO_autoconfig_cancel (struct GNUNET_NAT_AUTO_AutoHandle *ah)
268{
269 GNUNET_MQ_destroy (ah->mq);
270 GNUNET_free (ah);
271}
272
273/* end of nat_api_auto.c */
diff --git a/src/nat/nat_api_test.c b/src/nat-auto/nat_auto_api_test.c
index d47c14094..fb2bcd679 100644
--- a/src/nat/nat_api_test.c
+++ b/src/nat-auto/nat_auto_api_test.c
@@ -18,14 +18,15 @@
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20/** 20/**
21 * @file nat/nat_api_test.c 21 * @file nat/nat_auto_api_test.c
22 * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server) 22 * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server)
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 */ 24 */
25#include "platform.h" 25#include "platform.h"
26#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
27#include "gnunet_nat_lib.h" 27#include "gnunet_nat_service.h"
28#include "nat.h" 28#include "gnunet_nat_auto_service.h"
29#include "nat-auto.h"
29 30
30#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) 31#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
31 32
@@ -54,7 +55,7 @@ struct NatActivity
54 /** 55 /**
55 * Handle of the master context. 56 * Handle of the master context.
56 */ 57 */
57 struct GNUNET_NAT_Test *h; 58 struct GNUNET_NAT_AUTO_Test *h;
58 59
59 /** 60 /**
60 * Task reading from the incoming connection. 61 * Task reading from the incoming connection.
@@ -86,7 +87,7 @@ struct ClientActivity
86 /** 87 /**
87 * Handle to overall NAT test. 88 * Handle to overall NAT test.
88 */ 89 */
89 struct GNUNET_NAT_Test *h; 90 struct GNUNET_NAT_AUTO_Test *h;
90 91
91}; 92};
92 93
@@ -94,7 +95,7 @@ struct ClientActivity
94/** 95/**
95 * Handle to a NAT test. 96 * Handle to a NAT test.
96 */ 97 */
97struct GNUNET_NAT_Test 98struct GNUNET_NAT_AUTO_Test
98{ 99{
99 100
100 /** 101 /**
@@ -153,19 +154,19 @@ struct GNUNET_NAT_Test
153 struct GNUNET_SCHEDULER_Task *ttask; 154 struct GNUNET_SCHEDULER_Task *ttask;
154 155
155 /** 156 /**
156 * #GNUNET_YES if we're testing TCP 157 * Section name of plugin to test.
157 */ 158 */
158 int is_tcp; 159 char *section_name;
159 160
160 /** 161 /**
161 * Data that should be transmitted or source-port. 162 * IPPROTO_TCP or IPPROTO_UDP.
162 */ 163 */
163 uint16_t data; 164 int proto;
164 165
165 /** 166 /**
166 * Advertised port to the other peer. 167 * Data that should be transmitted or source-port.
167 */ 168 */
168 uint16_t adv_port; 169 uint16_t data;
169 170
170 /** 171 /**
171 * Status code to be reported to the timeout/status call 172 * Status code to be reported to the timeout/status call
@@ -187,7 +188,7 @@ reversal_cb (void *cls,
187 const struct sockaddr *addr, 188 const struct sockaddr *addr,
188 socklen_t addrlen) 189 socklen_t addrlen)
189{ 190{
190 struct GNUNET_NAT_Test *h = cls; 191 struct GNUNET_NAT_AUTO_Test *h = cls;
191 const struct sockaddr_in *sa; 192 const struct sockaddr_in *sa;
192 193
193 if (sizeof (struct sockaddr_in) != addrlen) 194 if (sizeof (struct sockaddr_in) != addrlen)
@@ -209,12 +210,12 @@ reversal_cb (void *cls,
209 * Activity on our incoming socket. Read data from the 210 * Activity on our incoming socket. Read data from the
210 * incoming connection. 211 * incoming connection.
211 * 212 *
212 * @param cls the `struct GNUNET_NAT_Test` 213 * @param cls the `struct GNUNET_NAT_AUTO_Test`
213 */ 214 */
214static void 215static void
215do_udp_read (void *cls) 216do_udp_read (void *cls)
216{ 217{
217 struct GNUNET_NAT_Test *tst = cls; 218 struct GNUNET_NAT_AUTO_Test *tst = cls;
218 uint16_t data; 219 uint16_t data;
219 const struct GNUNET_SCHEDULER_TaskContext *tc; 220 const struct GNUNET_SCHEDULER_TaskContext *tc;
220 221
@@ -255,7 +256,7 @@ static void
255do_read (void *cls) 256do_read (void *cls)
256{ 257{
257 struct NatActivity *na = cls; 258 struct NatActivity *na = cls;
258 struct GNUNET_NAT_Test *tst; 259 struct GNUNET_NAT_AUTO_Test *tst;
259 uint16_t data; 260 uint16_t data;
260 const struct GNUNET_SCHEDULER_TaskContext *tc; 261 const struct GNUNET_SCHEDULER_TaskContext *tc;
261 262
@@ -292,12 +293,12 @@ do_read (void *cls)
292 * Activity on our listen socket. Accept the 293 * Activity on our listen socket. Accept the
293 * incoming connection. 294 * incoming connection.
294 * 295 *
295 * @param cls the `struct GNUNET_NAT_Test` 296 * @param cls the `struct GNUNET_NAT_AUTO_Test`
296 */ 297 */
297static void 298static void
298do_accept (void *cls) 299do_accept (void *cls)
299{ 300{
300 struct GNUNET_NAT_Test *tst = cls; 301 struct GNUNET_NAT_AUTO_Test *tst = cls;
301 struct GNUNET_NETWORK_Handle *s; 302 struct GNUNET_NETWORK_Handle *s;
302 struct NatActivity *wl; 303 struct NatActivity *wl;
303 304
@@ -342,7 +343,7 @@ mq_error_handler (void *cls,
342 enum GNUNET_MQ_Error error) 343 enum GNUNET_MQ_Error error)
343{ 344{
344 struct ClientActivity *ca = cls; 345 struct ClientActivity *ca = cls;
345 struct GNUNET_NAT_Test *tst = ca->h; 346 struct GNUNET_NAT_AUTO_Test *tst = ca->h;
346 347
347 GNUNET_CONTAINER_DLL_remove (tst->ca_head, 348 GNUNET_CONTAINER_DLL_remove (tst->ca_head,
348 tst->ca_tail, 349 tst->ca_tail,
@@ -358,19 +359,21 @@ mq_error_handler (void *cls,
358 * @param cls closure 359 * @param cls closure
359 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean 360 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
360 * the previous (now invalid) one 361 * the previous (now invalid) one
362 * @param ac address class the address belongs to
361 * @param addr either the previous or the new public IP address 363 * @param addr either the previous or the new public IP address
362 * @param addrlen actual length of the @a addr 364 * @param addrlen actual length of the @a addr
363 */ 365 */
364static void 366static void
365addr_cb (void *cls, 367addr_cb (void *cls,
366 int add_remove, 368 int add_remove,
369 enum GNUNET_NAT_AddressClass ac,
367 const struct sockaddr *addr, 370 const struct sockaddr *addr,
368 socklen_t addrlen) 371 socklen_t addrlen)
369{ 372{
370 struct GNUNET_NAT_Test *h = cls; 373 struct GNUNET_NAT_AUTO_Test *h = cls;
371 struct ClientActivity *ca; 374 struct ClientActivity *ca;
372 struct GNUNET_MQ_Envelope *env; 375 struct GNUNET_MQ_Envelope *env;
373 struct GNUNET_NAT_TestMessage *msg; 376 struct GNUNET_NAT_AUTO_TestMessage *msg;
374 const struct sockaddr_in *sa; 377 const struct sockaddr_in *sa;
375 378
376 if (GNUNET_YES != add_remove) 379 if (GNUNET_YES != add_remove)
@@ -390,7 +393,7 @@ addr_cb (void *cls,
390 393
391 ca = GNUNET_new (struct ClientActivity); 394 ca = GNUNET_new (struct ClientActivity);
392 ca->h = h; 395 ca->h = h;
393 ca->mq = GNUNET_CLIENT_connecT (h->cfg, 396 ca->mq = GNUNET_CLIENT_connect (h->cfg,
394 "gnunet-nat-server", 397 "gnunet-nat-server",
395 NULL, 398 NULL,
396 &mq_error_handler, 399 &mq_error_handler,
@@ -411,58 +414,50 @@ addr_cb (void *cls,
411 msg->dst_ipv4 = sa->sin_addr.s_addr; 414 msg->dst_ipv4 = sa->sin_addr.s_addr;
412 msg->dport = sa->sin_port; 415 msg->dport = sa->sin_port;
413 msg->data = h->data; 416 msg->data = h->data;
414 msg->is_tcp = htonl ((uint32_t) h->is_tcp); 417 msg->is_tcp = htonl ((uint32_t) (h->proto == IPPROTO_TCP));
415 GNUNET_MQ_send (ca->mq, 418 GNUNET_MQ_send (ca->mq,
416 env); 419 env);
417} 420}
418 421
419 422
420/** 423/**
421 * Timeout task for a nat test. 424 * Calls the report-callback reporting failure.
422 * Calls the report-callback with a timeout return value
423 * 425 *
424 * Destroys the nat handle after the callback has been processed. 426 * Destroys the nat handle after the callback has been processed.
425 * 427 *
426 * @param cls handle to the timed out NAT test 428 * @param cls handle to the timed out NAT test
427 */ 429 */
428static void 430static void
429do_timeout (void *cls) 431do_fail (void *cls)
430{ 432{
431 struct GNUNET_NAT_Test *nh = cls; 433 struct GNUNET_NAT_AUTO_Test *nh = cls;
432 434
433 nh->ttask = NULL; 435 nh->ttask = NULL;
434 nh->report (nh->report_cls, 436 nh->report (nh->report_cls,
435 (GNUNET_NAT_ERROR_SUCCESS == nh->status) 437 nh->status);
436 ? GNUNET_NAT_ERROR_TIMEOUT
437 : nh->status);
438} 438}
439 439
440 440
441/** 441/**
442 * Start testing if NAT traversal works using the 442 * Start testing if NAT traversal works using the given configuration.
443 * given configuration (IPv4-only). 443 * The transport adapters should be down while using this function.
444 *
445 * ALL failures are reported directly to the report callback
446 * 444 *
447 * @param cfg configuration for the NAT traversal 445 * @param cfg configuration for the NAT traversal
448 * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP 446 * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
449 * @param bnd_port port to bind to, 0 for connection reversal 447 * @param section_name configuration section to use for configuration
450 * @param adv_port externally advertised port to use
451 * @param timeout delay after which the test should be aborted
452 * @param report function to call with the result of the test 448 * @param report function to call with the result of the test
453 * @param report_cls closure for @a report 449 * @param report_cls closure for @a report
454 * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback 450 * @return handle to cancel NAT test
455 */ 451 */
456struct GNUNET_NAT_Test * 452struct GNUNET_NAT_AUTO_Test *
457GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg, 453GNUNET_NAT_AUTO_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
458 int is_tcp, 454 uint8_t proto,
459 uint16_t bnd_port, 455 const char *section_name,
460 uint16_t adv_port, 456 GNUNET_NAT_TestCallback report,
461 struct GNUNET_TIME_Relative timeout, 457 void *report_cls)
462 GNUNET_NAT_TestCallback report,
463 void *report_cls)
464{ 458{
465 struct GNUNET_NAT_Test *nh; 459 struct GNUNET_NAT_AUTO_Test *nh;
460 unsigned long long bnd_port;
466 struct sockaddr_in sa; 461 struct sockaddr_in sa;
467 const struct sockaddr *addrs[] = { 462 const struct sockaddr *addrs[] = {
468 (const struct sockaddr *) &sa 463 (const struct sockaddr *) &sa
@@ -471,18 +466,30 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
471 sizeof (sa) 466 sizeof (sa)
472 }; 467 };
473 468
469 if ( (GNUNET_OK !=
470 GNUNET_CONFIGURATION_get_value_number (cfg,
471 section_name,
472 "PORT",
473 &bnd_port)) ||
474 (bnd_port > 65535) )
475 {
476 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
477 _("Failed to find valid PORT in section `%s'\n"),
478 section_name);
479 return NULL;
480 }
481
474 memset (&sa, 0, sizeof (sa)); 482 memset (&sa, 0, sizeof (sa));
475 sa.sin_family = AF_INET; 483 sa.sin_family = AF_INET;
476 sa.sin_port = htons (bnd_port); 484 sa.sin_port = htons ((uint16_t) bnd_port);
477#if HAVE_SOCKADDR_IN_SIN_LEN 485#if HAVE_SOCKADDR_IN_SIN_LEN
478 sa.sin_len = sizeof (sa); 486 sa.sin_len = sizeof (sa);
479#endif 487#endif
480 488
481 nh = GNUNET_new (struct GNUNET_NAT_Test); 489 nh = GNUNET_new (struct GNUNET_NAT_AUTO_Test);
482 nh->cfg = cfg; 490 nh->cfg = cfg;
483 nh->is_tcp = is_tcp; 491 nh->proto = proto;
484 nh->data = bnd_port; 492 nh->section_name = GNUNET_strdup (section_name);
485 nh->adv_port = adv_port;
486 nh->report = report; 493 nh->report = report;
487 nh->report_cls = report_cls; 494 nh->report_cls = report_cls;
488 nh->status = GNUNET_NAT_ERROR_SUCCESS; 495 nh->status = GNUNET_NAT_ERROR_SUCCESS;
@@ -490,28 +497,24 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
490 { 497 {
491 nh->nat 498 nh->nat
492 = GNUNET_NAT_register (cfg, 499 = GNUNET_NAT_register (cfg,
493 is_tcp, 500 section_name,
494 0, 501 proto,
495 0, 502 0, NULL, NULL,
496 NULL,
497 NULL,
498 &addr_cb, 503 &addr_cb,
499 &reversal_cb, 504 &reversal_cb,
500 nh, 505 nh);
501 NULL);
502 } 506 }
503 else 507 else
504 { 508 {
505 nh->lsock = 509 nh->lsock
506 GNUNET_NETWORK_socket_create (AF_INET, 510 = GNUNET_NETWORK_socket_create (AF_INET,
507 (is_tcp == 511 proto,
508 GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM,
509 0); 512 0);
510 if ((nh->lsock == NULL) || 513 if ( (NULL == nh->lsock) ||
511 (GNUNET_OK != 514 (GNUNET_OK !=
512 GNUNET_NETWORK_socket_bind (nh->lsock, 515 GNUNET_NETWORK_socket_bind (nh->lsock,
513 (const struct sockaddr *) &sa, 516 (const struct sockaddr *) &sa,
514 sizeof (sa)))) 517 sizeof (sa))))
515 { 518 {
516 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 519 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
517 _("Failed to create listen socket bound to `%s' for NAT test: %s\n"), 520 _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
@@ -524,11 +527,11 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
524 nh->lsock = NULL; 527 nh->lsock = NULL;
525 } 528 }
526 nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR; 529 nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
527 nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, 530 nh->ttask = GNUNET_SCHEDULER_add_now (&do_fail,
528 nh); 531 nh);
529 return nh; 532 return nh;
530 } 533 }
531 if (GNUNET_YES == is_tcp) 534 if (IPPROTO_TCP == proto)
532 { 535 {
533 GNUNET_break (GNUNET_OK == 536 GNUNET_break (GNUNET_OK ==
534 GNUNET_NETWORK_socket_listen (nh->lsock, 537 GNUNET_NETWORK_socket_listen (nh->lsock,
@@ -550,17 +553,16 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
550 LOG (GNUNET_ERROR_TYPE_INFO, 553 LOG (GNUNET_ERROR_TYPE_INFO,
551 "NAT test listens on port %u (%s)\n", 554 "NAT test listens on port %u (%s)\n",
552 bnd_port, 555 bnd_port,
553 (GNUNET_YES == is_tcp) ? "tcp" : "udp"); 556 (IPPROTO_TCP == proto) ? "tcp" : "udp");
554 nh->nat = GNUNET_NAT_register (cfg, 557 nh->nat = GNUNET_NAT_register (cfg,
555 is_tcp, 558 section_name,
556 adv_port, 559 proto,
557 1, 560 1,
558 addrs, 561 addrs,
559 addrlens, 562 addrlens,
560 &addr_cb, 563 &addr_cb,
561 NULL, 564 NULL,
562 nh, 565 nh);
563 NULL);
564 if (NULL == nh->nat) 566 if (NULL == nh->nat)
565 { 567 {
566 LOG (GNUNET_ERROR_TYPE_INFO, 568 LOG (GNUNET_ERROR_TYPE_INFO,
@@ -576,14 +578,11 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
576 nh->lsock = NULL; 578 nh->lsock = NULL;
577 } 579 }
578 nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED; 580 nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
579 nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, 581 nh->ttask = GNUNET_SCHEDULER_add_now (&do_fail,
580 nh); 582 nh);
581 return nh; 583 return nh;
582 } 584 }
583 } 585 }
584 nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout,
585 &do_timeout,
586 nh);
587 return nh; 586 return nh;
588} 587}
589 588
@@ -594,7 +593,7 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
594 * @param tst test to stop. 593 * @param tst test to stop.
595 */ 594 */
596void 595void
597GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) 596GNUNET_NAT_AUTO_test_stop (struct GNUNET_NAT_AUTO_Test *tst)
598{ 597{
599 struct NatActivity *pos; 598 struct NatActivity *pos;
600 struct ClientActivity *cpos; 599 struct ClientActivity *cpos;
@@ -638,7 +637,8 @@ GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst)
638 GNUNET_NAT_unregister (tst->nat); 637 GNUNET_NAT_unregister (tst->nat);
639 tst->nat = NULL; 638 tst->nat = NULL;
640 } 639 }
640 GNUNET_free (tst->section_name);
641 GNUNET_free (tst); 641 GNUNET_free (tst);
642} 642}
643 643
644/* end of nat_test.c */ 644/* end of nat_auto_api_test.c */
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index 1dd8e44b9..3dc001dd7 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -34,7 +34,6 @@ install-exec-hook:
34endif 34endif
35 35
36bin_PROGRAMS = \ 36bin_PROGRAMS = \
37 gnunet-nat-server \
38 gnunet-nat 37 gnunet-nat
39 38
40libexec_PROGRAMS = \ 39libexec_PROGRAMS = \
@@ -42,12 +41,6 @@ libexec_PROGRAMS = \
42 gnunet-service-nat 41 gnunet-service-nat
43 42
44 43
45gnunet_nat_server_SOURCES = \
46 gnunet-nat-server.c nat.h
47gnunet_nat_server_LDADD = \
48 libgnunetnat.la \
49 $(top_builddir)/src/util/libgnunetutil.la
50
51gnunet_helper_nat_server_SOURCES = \ 44gnunet_helper_nat_server_SOURCES = \
52 $(NATSERVER) 45 $(NATSERVER)
53 46
@@ -67,26 +60,11 @@ if USE_COVERAGE
67endif 60endif
68 61
69lib_LTLIBRARIES = \ 62lib_LTLIBRARIES = \
70 libgnunetnat.la \
71 libgnunetnatnew.la 63 libgnunetnatnew.la
72 64
73libgnunetnat_la_SOURCES = \
74 nat.c nat.h \
75 nat_auto.c \
76 nat_test.c \
77 nat_mini.c \
78 nat_stun.c
79libgnunetnat_la_LIBADD = \
80 $(top_builddir)/src/util/libgnunetutil.la \
81 $(GN_LIBINTL) @EXT_LIBS@
82libgnunetnat_la_LDFLAGS = \
83 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
84 -version-info 1:1:1
85
86libgnunetnatnew_la_SOURCES = \ 65libgnunetnatnew_la_SOURCES = \
87 nat_api.c \ 66 nat_api.c \
88 nat_api_stun.c nat_stun.h \ 67 nat_api_stun.c nat_stun.h \
89 nat_api_test.c \
90 nat.h 68 nat.h
91libgnunetnatnew_la_LIBADD = \ 69libgnunetnatnew_la_LIBADD = \
92 $(top_builddir)/src/util/libgnunetutil.la \ 70 $(top_builddir)/src/util/libgnunetutil.la \
@@ -96,7 +74,8 @@ libgnunetnatnew_la_LDFLAGS = \
96 -version-info 2:0:0 74 -version-info 2:0:0
97 75
98gnunet_service_nat_SOURCES = \ 76gnunet_service_nat_SOURCES = \
99 gnunet-service-nat.c \ 77 gnunet-service-nat.c gnunet-service-nat.h \
78 gnunet-service-nat_externalip.c gnunet-service-nat_externalip.h \
100 gnunet-service-nat_stun.c gnunet-service-nat_stun.h \ 79 gnunet-service-nat_stun.c gnunet-service-nat_stun.h \
101 gnunet-service-nat_mini.c gnunet-service-nat_mini.h \ 80 gnunet-service-nat_mini.c gnunet-service-nat_mini.h \
102 gnunet-service-nat_helper.c gnunet-service-nat_helper.h 81 gnunet-service-nat_helper.c gnunet-service-nat_helper.h
@@ -107,40 +86,40 @@ gnunet_service_nat_LDADD = \
107 -lgcrypt \ 86 -lgcrypt \
108 $(GN_LIBINTL) 87 $(GN_LIBINTL)
109 88
110check_PROGRAMS = \ 89#check_PROGRAMS = \
111 test_nat \ 90# test_nat \
112 test_nat_mini \ 91# test_nat_mini \
113 test_nat_test \ 92# test_nat_test \
114 test_stun 93# test_stun
115 94
116if ENABLE_TEST_RUN 95if ENABLE_TEST_RUN
117 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; 96 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
118 TESTS = $(check_PROGRAMS) 97 TESTS = $(check_PROGRAMS)
119endif 98endif
120 99
121test_nat_SOURCES = \ 100#test_nat_SOURCES = \
122 test_nat.c 101# test_nat.c
123test_nat_LDADD = \ 102#test_nat_LDADD = \
124 libgnunetnat.la \ 103# libgnunetnat.la \
125 $(top_builddir)/src/util/libgnunetutil.la 104# $(top_builddir)/src/util/libgnunetutil.la
126 105
127test_nat_mini_SOURCES = \ 106#test_nat_mini_SOURCES = \
128 test_nat_mini.c 107# test_nat_mini.c
129test_nat_mini_LDADD = \ 108#test_nat_mini_LDADD = \
130 libgnunetnat.la \ 109# libgnunetnat.la \
131 $(top_builddir)/src/util/libgnunetutil.la 110# $(top_builddir)/src/util/libgnunetutil.la
132 111
133test_nat_test_SOURCES = \ 112#test_nat_test_SOURCES = \
134 test_nat_test.c 113# test_nat_test.c
135test_nat_test_LDADD = \ 114#test_nat_test_LDADD = \
136 libgnunetnat.la \ 115# libgnunetnat.la \
137 $(top_builddir)/src/util/libgnunetutil.la 116# $(top_builddir)/src/util/libgnunetutil.la
138 117
139test_stun_SOURCES = \ 118#test_stun_SOURCES = \
140 test_stun.c 119# test_stun.c
141test_stun_LDADD = \ 120#test_stun_LDADD = \
142 libgnunetnat.la \ 121# libgnunetnat.la \
143 $(top_builddir)/src/util/libgnunetutil.la 122# $(top_builddir)/src/util/libgnunetutil.la
144 123
145EXTRA_DIST = \ 124EXTRA_DIST = \
146 test_nat_data.conf \ 125 test_nat_data.conf \
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c
index 81e4549b5..f198adc0a 100644
--- a/src/nat/gnunet-nat.c
+++ b/src/nat/gnunet-nat.c
@@ -34,15 +34,10 @@
34static int global_ret; 34static int global_ret;
35 35
36/** 36/**
37 * Handle to ongoing autoconfiguration. 37 * Name of section in configuration file to use for
38 */ 38 * additional options.
39static struct GNUNET_NAT_AutoHandle *ah;
40
41/**
42 * External hostname and port, if user manually punched
43 * the NAT.
44 */ 39 */
45static char *hole_external; 40static char *section_name;
46 41
47/** 42/**
48 * Flag set to 1 if we use IPPROTO_UDP. 43 * Flag set to 1 if we use IPPROTO_UDP.
@@ -60,39 +55,11 @@ static int listen_reversal;
60static int use_tcp; 55static int use_tcp;
61 56
62/** 57/**
63 * If we do auto-configuration, should we write the result
64 * to a file?
65 */
66static int write_cfg;
67
68/**
69 * Configuration filename.
70 */
71static const char *cfg_file;
72
73/**
74 * Original configuration.
75 */
76static const struct GNUNET_CONFIGURATION_Handle *cfg;
77
78/**
79 * Protocol to use. 58 * Protocol to use.
80 */ 59 */
81static uint8_t proto; 60static uint8_t proto;
82 61
83/** 62/**
84 * Address we are bound to (in test), or should bind to
85 * (if #do_stun is set).
86 */
87static char *bind_addr;
88
89/**
90 * External IP address and port to use for the test.
91 * If not set, use #bind_addr.
92 */
93static char *extern_addr;
94
95/**
96 * Local address to use for connection reversal request. 63 * Local address to use for connection reversal request.
97 */ 64 */
98static char *local_addr; 65static char *local_addr;
@@ -108,16 +75,6 @@ static char *remote_addr;
108static unsigned int do_stun; 75static unsigned int do_stun;
109 76
110/** 77/**
111 * Should we run autoconfiguration?
112 */
113static unsigned int do_auto;
114
115/**
116 * Handle to a NAT test operation.
117 */
118static struct GNUNET_NAT_Test *nt;
119
120/**
121 * Handle to NAT operation. 78 * Handle to NAT operation.
122 */ 79 */
123static struct GNUNET_NAT_Handle *nh; 80static struct GNUNET_NAT_Handle *nh;
@@ -140,10 +97,6 @@ static struct GNUNET_SCHEDULER_Task *rtask;
140static void 97static void
141test_finished () 98test_finished ()
142{ 99{
143 if (NULL != ah)
144 return;
145 if (NULL != nt)
146 return;
147 if (NULL != nh) 100 if (NULL != nh)
148 return; 101 return;
149 if (NULL != rtask) 102 if (NULL != rtask)
@@ -153,160 +106,6 @@ test_finished ()
153 106
154 107
155/** 108/**
156 * Function to iterate over sugested changes options
157 *
158 * @param cls closure
159 * @param section name of the section
160 * @param option name of the option
161 * @param value value of the option
162 */
163static void
164auto_conf_iter (void *cls,
165 const char *section,
166 const char *option,
167 const char *value)
168{
169 struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
170
171 PRINTF ("%s: %s\n",
172 option,
173 value);
174 if (NULL != new_cfg)
175 GNUNET_CONFIGURATION_set_value_string (new_cfg,
176 section,
177 option,
178 value);
179}
180
181
182/**
183 * Function called with the result from the autoconfiguration.
184 *
185 * @param cls closure
186 * @param diff minimal suggested changes to the original configuration
187 * to make it work (as best as we can)
188 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
189 * @param type what the situation of the NAT
190 */
191static void
192auto_config_cb (void *cls,
193 const struct GNUNET_CONFIGURATION_Handle *diff,
194 enum GNUNET_NAT_StatusCode result,
195 enum GNUNET_NAT_Type type)
196{
197 const char *nat_type;
198 char unknown_type[64];
199 struct GNUNET_CONFIGURATION_Handle *new_cfg;
200
201 ah = NULL;
202 switch (type)
203 {
204 case GNUNET_NAT_TYPE_NO_NAT:
205 nat_type = "NO NAT";
206 break;
207 case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
208 nat_type = "NAT but we can traverse";
209 break;
210 case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
211 nat_type = "NAT but STUN is able to identify the correct information";
212 break;
213 case GNUNET_NAT_TYPE_UPNP_NAT:
214 nat_type = "NAT but UPNP opened the ports";
215 break;
216 default:
217 SPRINTF (unknown_type,
218 "NAT unknown, type %u",
219 type);
220 nat_type = unknown_type;
221 break;
222 }
223
224 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
225 "NAT status: %s/%s\n",
226 GNUNET_NAT_status2string (result),
227 nat_type);
228
229 /* Shortcut: if there are no changes suggested, bail out early. */
230 if (GNUNET_NO ==
231 GNUNET_CONFIGURATION_is_dirty (diff))
232 {
233 test_finished ();
234 return;
235 }
236
237 /* Apply diff to original configuration and show changes
238 to the user */
239 new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
240
241 if (NULL != diff)
242 {
243 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
244 _("Suggested configuration changes:\n"));
245 GNUNET_CONFIGURATION_iterate_section_values (diff,
246 "nat",
247 &auto_conf_iter,
248 new_cfg);
249 }
250
251 /* If desired, write configuration to file; we write only the
252 changes to the defaults to keep things compact. */
253 if ( (write_cfg) &&
254 (NULL != diff) )
255 {
256 struct GNUNET_CONFIGURATION_Handle *def_cfg;
257
258 GNUNET_CONFIGURATION_set_value_string (new_cfg,
259 "ARM",
260 "CONFIG",
261 NULL);
262 def_cfg = GNUNET_CONFIGURATION_create ();
263 GNUNET_break (GNUNET_OK ==
264 GNUNET_CONFIGURATION_load (def_cfg,
265 NULL));
266 if (GNUNET_OK !=
267 GNUNET_CONFIGURATION_write_diffs (def_cfg,
268 new_cfg,
269 cfg_file))
270 {
271 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
272 _("Failed to write configuration to `%s'\n"),
273 cfg_file);
274 global_ret = 1;
275 }
276 else
277 {
278 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
279 _("Wrote updated configuration to `%s'\n"),
280 cfg_file);
281 }
282 GNUNET_CONFIGURATION_destroy (def_cfg);
283 }
284
285 if (NULL != new_cfg)
286 GNUNET_CONFIGURATION_destroy (new_cfg);
287 test_finished ();
288}
289
290
291/**
292 * Function called to report success or failure for
293 * NAT configuration test.
294 *
295 * @param cls closure
296 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
297 */
298static void
299test_report_cb (void *cls,
300 enum GNUNET_NAT_StatusCode result)
301{
302 nt = NULL;
303 PRINTF ("NAT test result: %s\n",
304 GNUNET_NAT_status2string (result));
305 test_finished ();
306}
307
308
309/**
310 * Signature of the callback passed to #GNUNET_NAT_register() for 109 * Signature of the callback passed to #GNUNET_NAT_register() for
311 * a function to call whenever our set of 'valid' addresses changes. 110 * a function to call whenever our set of 'valid' addresses changes.
312 * 111 *
@@ -362,16 +161,6 @@ reversal_cb (void *cls,
362static void 161static void
363do_shutdown (void *cls) 162do_shutdown (void *cls)
364{ 163{
365 if (NULL != ah)
366 {
367 GNUNET_NAT_autoconfig_cancel (ah);
368 ah = NULL;
369 }
370 if (NULL != nt)
371 {
372 GNUNET_NAT_test_stop (nt);
373 nt = NULL;
374 }
375 if (NULL != nh) 164 if (NULL != nh)
376 { 165 {
377 GNUNET_NAT_unregister (nh); 166 GNUNET_NAT_unregister (nh);
@@ -452,16 +241,11 @@ run (void *cls,
452 const struct GNUNET_CONFIGURATION_Handle *c) 241 const struct GNUNET_CONFIGURATION_Handle *c)
453{ 242{
454 uint8_t af; 243 uint8_t af;
455 struct sockaddr_in bind_sa;
456 struct sockaddr_in extern_sa;
457 struct sockaddr *local_sa; 244 struct sockaddr *local_sa;
458 struct sockaddr *remote_sa; 245 struct sockaddr *remote_sa;
459 socklen_t local_len; 246 socklen_t local_len;
460 size_t remote_len; 247 size_t remote_len;
461 248
462 cfg_file = cfgfile;
463 cfg = c;
464
465 if (use_tcp && use_udp) 249 if (use_tcp && use_udp)
466 { 250 {
467 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 251 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
@@ -478,50 +262,13 @@ run (void *cls,
478 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, 262 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
479 NULL); 263 NULL);
480 264
481 if (do_auto)
482 {
483 ah = GNUNET_NAT_autoconfig_start (c,
484 &auto_config_cb,
485 NULL);
486 }
487
488 if (0 == proto) 265 if (0 == proto)
489 { 266 {
490 if (do_auto)
491 return; /* all good, we just run auto config */
492 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 267 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
493 "Must specify either TCP or UDP\n"); 268 "Must specify either TCP or UDP\n");
494 global_ret = 1; 269 global_ret = 1;
495 return; 270 return;
496 } 271 }
497 if (NULL != bind_addr)
498 {
499 if (GNUNET_OK !=
500 GNUNET_STRINGS_to_address_ipv4 (bind_addr,
501 strlen (bind_addr),
502 &bind_sa))
503 {
504 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
505 "Invalid socket address `%s'\n",
506 bind_addr);
507 global_ret = 1;
508 return;
509 }
510 }
511 if (NULL != extern_addr)
512 {
513 if (GNUNET_OK !=
514 GNUNET_STRINGS_to_address_ipv4 (extern_addr,
515 strlen (extern_addr),
516 &extern_sa))
517 {
518 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
519 "Invalid socket address `%s'\n",
520 extern_addr);
521 global_ret = 1;
522 return;
523 }
524 }
525 if (NULL != local_addr) 272 if (NULL != local_addr)
526 { 273 {
527 local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr, 274 local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
@@ -551,25 +298,13 @@ run (void *cls,
551 } 298 }
552 } 299 }
553 300
554 if (NULL != bind_addr)
555 {
556 if (NULL == extern_addr)
557 extern_sa = bind_sa;
558 nt = GNUNET_NAT_test_start (c,
559 proto,
560 bind_sa.sin_addr,
561 ntohs (bind_sa.sin_port),
562 extern_sa.sin_addr,
563 ntohs (extern_sa.sin_port),
564 &test_report_cb,
565 NULL);
566 }
567
568 if (NULL != local_addr) 301 if (NULL != local_addr)
569 { 302 {
303 if (NULL == section_name)
304 section_name = GNUNET_strdup ("undefined");
570 nh = GNUNET_NAT_register (c, 305 nh = GNUNET_NAT_register (c,
306 section_name,
571 proto, 307 proto,
572 hole_external,
573 1, 308 1,
574 (const struct sockaddr **) &local_sa, 309 (const struct sockaddr **) &local_sa,
575 &local_len, 310 &local_len,
@@ -607,9 +342,11 @@ run (void *cls,
607 GNUNET_SCHEDULER_shutdown (); 342 GNUNET_SCHEDULER_shutdown ();
608 return; 343 return;
609 } 344 }
345 GNUNET_assert (AF_INET == local_sa->sa_family);
346 GNUNET_assert (AF_INET == remote_sa->sa_family);
610 ret = GNUNET_NAT_request_reversal (nh, 347 ret = GNUNET_NAT_request_reversal (nh,
611 (const struct sockaddr_in *) &local_sa, 348 (const struct sockaddr_in *) local_sa,
612 (const struct sockaddr_in *) &remote_sa); 349 (const struct sockaddr_in *) remote_sa);
613 switch (ret) 350 switch (ret)
614 { 351 {
615 case GNUNET_SYSERR: 352 case GNUNET_SYSERR:
@@ -683,24 +420,15 @@ main (int argc,
683 char *const argv[]) 420 char *const argv[])
684{ 421{
685 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 422 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
686 {'a', "auto", NULL,
687 gettext_noop ("run autoconfiguration"),
688 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
689 {'b', "bind", "ADDRESS",
690 gettext_noop ("which IP and port are we bound to"),
691 GNUNET_YES, &GNUNET_GETOPT_set_string, &bind_addr },
692 {'e', "external", "ADDRESS",
693 gettext_noop ("which external IP and port should be used to test"),
694 GNUNET_YES, &GNUNET_GETOPT_set_string, &extern_addr },
695 {'i', "in", "ADDRESS", 423 {'i', "in", "ADDRESS",
696 gettext_noop ("which IP and port are we locally using to bind/listen to"), 424 gettext_noop ("which IP and port are we locally using to bind/listen to"),
697 GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr }, 425 GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr },
698 {'r', "remote", "ADDRESS", 426 {'r', "remote", "ADDRESS",
699 gettext_noop ("which remote IP and port should be asked for connection reversal"), 427 gettext_noop ("which remote IP and port should be asked for connection reversal"),
700 GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr }, 428 GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr },
701 {'p', "punched", NULL, 429 {'S', "section", NULL,
702 gettext_noop ("external hostname and port of NAT, if punched manually; use AUTO for hostname for automatic determination of the external IP"), 430 gettext_noop ("name of configuration section to find additional options, such as manual host punching data"),
703 GNUNET_YES, &GNUNET_GETOPT_set_string, &hole_external }, 431 GNUNET_YES, &GNUNET_GETOPT_set_string, &section_name },
704 {'s', "stun", NULL, 432 {'s', "stun", NULL,
705 gettext_noop ("enable STUN processing"), 433 gettext_noop ("enable STUN processing"),
706 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_stun }, 434 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_stun },
@@ -710,9 +438,6 @@ main (int argc,
710 {'u', "udp", NULL, 438 {'u', "udp", NULL,
711 gettext_noop ("use UDP"), 439 gettext_noop ("use UDP"),
712 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp }, 440 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
713 {'w', "write", NULL,
714 gettext_noop ("write configuration file (for autoconfiguration)"),
715 GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
716 {'W', "watch", NULL, 441 {'W', "watch", NULL,
717 gettext_noop ("watch for connection reversal requests"), 442 gettext_noop ("watch for connection reversal requests"),
718 GNUNET_NO, &GNUNET_GETOPT_set_one, &listen_reversal }, 443 GNUNET_NO, &GNUNET_GETOPT_set_one, &listen_reversal },
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index e29f37108..98d87262e 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -23,20 +23,16 @@
23 * @brief network address translation traversal service 23 * @brief network address translation traversal service
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * 25 *
26 * The purpose of this service is to enable transports to 26 * The purpose of this service is to enable transports to
27 * traverse NAT routers, by providing traversal options and 27 * traverse NAT routers, by providing traversal options and
28 * knowledge about the local network topology. 28 * knowledge about the local network topology.
29 * 29 *
30 * TODO: 30 * TODO:
31 * - test and document (!) ICMP based NAT traversal 31 * - migrate test cases to new NAT service
32 * - implement manual hole punching support (incl. DNS 32 * - add new traceroute-based logic for external IP detection
33 * lookup for DynDNS setups!) 33 *
34 * - implement "more" autoconfig:
35 * re-work gnunet-nat-server & integrate!
36 * + test manually punched NAT (how?)
37 * - implement & test STUN processing to classify NAT; 34 * - implement & test STUN processing to classify NAT;
38 * basically, open port & try different methods. 35 * basically, open port & try different methods.
39 * - implement NEW logic for external IP detection
40 */ 36 */
41#include "platform.h" 37#include "platform.h"
42#include <math.h> 38#include <math.h>
@@ -44,7 +40,10 @@
44#include "gnunet_protocols.h" 40#include "gnunet_protocols.h"
45#include "gnunet_signatures.h" 41#include "gnunet_signatures.h"
46#include "gnunet_statistics_service.h" 42#include "gnunet_statistics_service.h"
43#include "gnunet_resolver_service.h"
47#include "gnunet_nat_service.h" 44#include "gnunet_nat_service.h"
45#include "gnunet-service-nat.h"
46#include "gnunet-service-nat_externalip.h"
48#include "gnunet-service-nat_stun.h" 47#include "gnunet-service-nat_stun.h"
49#include "gnunet-service-nat_mini.h" 48#include "gnunet-service-nat_mini.h"
50#include "gnunet-service-nat_helper.h" 49#include "gnunet-service-nat_helper.h"
@@ -64,26 +63,13 @@
64#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 63#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
65 64
66/** 65/**
67 * How long do we wait until we re-try running `external-ip` if the 66 * How often do we scan for changes in how our external (dyndns) hostname resolves?
68 * command failed to terminate nicely?
69 */ 67 */
70#define EXTERN_IP_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) 68#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7)
71 69
72/**
73 * How long do we wait until we re-try running `external-ip` if the
74 * command failed (but terminated)?
75 */
76#define EXTERN_IP_RETRY_FAILURE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
77 70
78/** 71/**
79 * How long do we wait until we re-try running `external-ip` if the 72 * Information we track per client address.
80 * command succeeded?
81 */
82#define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
83
84
85/**
86 * Information we track per client address.
87 */ 73 */
88struct ClientAddress 74struct ClientAddress
89{ 75{
@@ -98,7 +84,54 @@ struct ClientAddress
98 * pending. 84 * pending.
99 */ 85 */
100 struct GNUNET_NAT_MiniHandle *mh; 86 struct GNUNET_NAT_MiniHandle *mh;
101 87
88};
89
90
91/**
92 * List of local addresses this system has.
93 */
94struct LocalAddressList
95{
96 /**
97 * This is a linked list.
98 */
99 struct LocalAddressList *next;
100
101 /**
102 * Previous entry.
103 */
104 struct LocalAddressList *prev;
105
106 /**
107 * Context for a gnunet-helper-nat-server used to listen
108 * for ICMP messages to this client for connection reversal.
109 */
110 struct HelperContext *hc;
111
112 /**
113 * The address itself (i.e. `struct sockaddr_in` or `struct
114 * sockaddr_in6`, in the respective byte order).
115 */
116 struct sockaddr_storage addr;
117
118 /**
119 * Address family. (FIXME: redundant, addr.ss_family! Remove!?)
120 */
121 int af;
122
123 /**
124 * #GNUNET_YES if we saw this one in the previous iteration,
125 * but not in the current iteration and thus might need to
126 * remove it at the end.
127 */
128 int old;
129
130 /**
131 * What type of address is this?
132 */
133 enum GNUNET_NAT_AddressClass ac;
134
102}; 135};
103 136
104 137
@@ -112,7 +145,7 @@ struct ClientHandle
112 * Kept in a DLL. 145 * Kept in a DLL.
113 */ 146 */
114 struct ClientHandle *next; 147 struct ClientHandle *next;
115 148
116 /** 149 /**
117 * Kept in a DLL. 150 * Kept in a DLL.
118 */ 151 */
@@ -120,7 +153,7 @@ struct ClientHandle
120 153
121 /** 154 /**
122 * Underlying handle for this client with the service. 155 * Underlying handle for this client with the service.
123 */ 156 */
124 struct GNUNET_SERVICE_Client *client; 157 struct GNUNET_SERVICE_Client *client;
125 158
126 /** 159 /**
@@ -136,74 +169,70 @@ struct ClientHandle
136 /** 169 /**
137 * External DNS name and port given by user due to manual 170 * External DNS name and port given by user due to manual
138 * hole punching. Special DNS name 'AUTO' is used to indicate 171 * hole punching. Special DNS name 'AUTO' is used to indicate
139 * desire for automatic determination of the external IP 172 * desire for automatic determination of the external IP
140 * (instead of DNS or manual configuration, i.e. to be used 173 * (instead of DNS or manual configuration, i.e. to be used
141 * if the IP keeps changing and we have no DynDNS, but we do 174 * if the IP keeps changing and we have no DynDNS, but we do
142 * have a hole punched). 175 * have a hole punched).
143 */ 176 */
144 char *hole_external; 177 char *hole_external;
145 178
146 /** 179 /**
147 * What does this client care about? 180 * Name of the configuration section this client cares about.
148 */ 181 */
149 enum GNUNET_NAT_RegisterFlags flags; 182 char *section_name;
150 183
151 /** 184 /**
152 * Is any of the @e caddrs in a reserved subnet for NAT? 185 * Task for periodically re-running the @e ext_dns DNS lookup.
153 */ 186 */
154 int natted_address; 187 struct GNUNET_SCHEDULER_Task *ext_dns_task;
155 188
156 /** 189 /**
157 * Number of addresses that this service is bound to. 190 * Handle for (DYN)DNS lookup of our external IP as given in
158 * Length of the @e caddrs array. 191 * @e hole_external.
159 */ 192 */
160 uint16_t num_caddrs; 193 struct GNUNET_RESOLVER_RequestHandle *ext_dns;
161 194
162 /** 195 /**
163 * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP. 196 * Handle for monitoring external IP changes.
164 */ 197 */
165 uint8_t proto; 198 struct GN_ExternalIPMonitor *external_monitor;
166
167};
168 199
200 /**
201 * DLL of external IP addresses as given in @e hole_external.
202 */
203 struct LocalAddressList *ext_addr_head;
169 204
170/**
171 * List of local addresses this system has.
172 */
173struct LocalAddressList
174{
175 /** 205 /**
176 * This is a linked list. 206 * DLL of external IP addresses as given in @e hole_external.
177 */ 207 */
178 struct LocalAddressList *next; 208 struct LocalAddressList *ext_addr_tail;
179 209
180 /** 210 /**
181 * Previous entry. 211 * Port number we found in @e hole_external.
182 */ 212 */
183 struct LocalAddressList *prev; 213 uint16_t ext_dns_port;
184 214
185 /** 215 /**
186 * Context for a gnunet-helper-nat-server used to listen 216 * What does this client care about?
187 * for ICMP messages to this client for connection reversal.
188 */ 217 */
189 struct HelperContext *hc; 218 enum GNUNET_NAT_RegisterFlags flags;
190 219
191 /** 220 /**
192 * The address itself (i.e. `struct sockaddr_in` or `struct 221 * Is any of the @e caddrs in a reserved subnet for NAT?
193 * sockaddr_in6`, in the respective byte order).
194 */ 222 */
195 struct sockaddr_storage addr; 223 int natted_address;
196 224
197 /** 225 /**
198 * Address family. 226 * Number of addresses that this service is bound to.
227 * Length of the @e caddrs array.
199 */ 228 */
200 int af; 229 uint16_t num_caddrs;
201 230
202 /** 231 /**
203 * What type of address is this? 232 * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
204 */ 233 */
205 enum GNUNET_NAT_AddressClass ac; 234 uint8_t proto;
206 235
207}; 236};
208 237
209 238
@@ -214,12 +243,12 @@ struct StunExternalIP
214{ 243{
215 /** 244 /**
216 * Kept in a DLL. 245 * Kept in a DLL.
217 */ 246 */
218 struct StunExternalIP *next; 247 struct StunExternalIP *next;
219 248
220 /** 249 /**
221 * Kept in a DLL. 250 * Kept in a DLL.
222 */ 251 */
223 struct StunExternalIP *prev; 252 struct StunExternalIP *prev;
224 253
225 /** 254 /**
@@ -228,13 +257,13 @@ struct StunExternalIP
228 struct GNUNET_SCHEDULER_Task *timeout_task; 257 struct GNUNET_SCHEDULER_Task *timeout_task;
229 258
230 /** 259 /**
231 * Our external IP address as reported by the 260 * Our external IP address as reported by the
232 * STUN server. 261 * STUN server.
233 */ 262 */
234 struct sockaddr_in external_addr; 263 struct sockaddr_in external_addr;
235 264
236 /** 265 /**
237 * Address of the reporting STUN server. Used to 266 * Address of the reporting STUN server. Used to
238 * detect when a STUN server changes its opinion 267 * detect when a STUN server changes its opinion
239 * to more quickly remove stale results. 268 * to more quickly remove stale results.
240 */ 269 */
@@ -248,83 +277,14 @@ struct StunExternalIP
248 277
249 278
250/** 279/**
251 * Context for autoconfiguration operations. 280 * Timeout to use when STUN data is considered stale.
252 */
253struct AutoconfigContext
254{
255 /**
256 * Kept in a DLL.
257 */
258 struct AutoconfigContext *prev;
259
260 /**
261 * Kept in a DLL.
262 */
263 struct AutoconfigContext *next;
264
265 /**
266 * Which client asked the question.
267 */
268 struct ClientHandle *ch;
269
270 /**
271 * Configuration we are creating.
272 */
273 struct GNUNET_CONFIGURATION_Handle *c;
274
275 /**
276 * Original configuration (for diffing).
277 */
278 struct GNUNET_CONFIGURATION_Handle *orig;
279
280 /**
281 * Timeout task to force termination.
282 */
283 struct GNUNET_SCHEDULER_Task *timeout_task;
284
285 /**
286 * What type of system are we on?
287 */
288 char *system_type;
289
290 /**
291 * Handle to activity to probe for our external IP.
292 */
293 struct GNUNET_NAT_ExternalHandle *probe_external;
294
295 /**
296 * #GNUNET_YES if upnpc should be used,
297 * #GNUNET_NO if upnpc should not be used,
298 * #GNUNET_SYSERR if we should simply not change the option.
299 */
300 int enable_upnpc;
301
302 /**
303 * Status code to return to the client.
304 */
305 enum GNUNET_NAT_StatusCode status_code;
306
307 /**
308 * NAT type to return to the client.
309 */
310 enum GNUNET_NAT_Type type;
311};
312
313
314/**
315 * DLL of our autoconfiguration operations.
316 */
317static struct AutoconfigContext *ac_head;
318
319/**
320 * DLL of our autoconfiguration operations.
321 */ 281 */
322static struct AutoconfigContext *ac_tail; 282static struct GNUNET_TIME_Relative stun_stale_timeout;
323 283
324/** 284/**
325 * Timeout to use when STUN data is considered stale. 285 * How often do we scan for changes in how our external (dyndns) hostname resolves?
326 */ 286 */
327static struct GNUNET_TIME_Relative stun_stale_timeout; 287static struct GNUNET_TIME_Relative dyndns_frequency;
328 288
329/** 289/**
330 * Handle to our current configuration. 290 * Handle to our current configuration.
@@ -345,7 +305,7 @@ static struct GNUNET_SCHEDULER_Task *scan_task;
345 * Head of client DLL. 305 * Head of client DLL.
346 */ 306 */
347static struct ClientHandle *ch_head; 307static struct ClientHandle *ch_head;
348 308
349/** 309/**
350 * Tail of client DLL. 310 * Tail of client DLL.
351 */ 311 */
@@ -363,36 +323,19 @@ static struct LocalAddressList *lal_tail;
363 323
364/** 324/**
365 * Kept in a DLL. 325 * Kept in a DLL.
366 */ 326 */
367static struct StunExternalIP *se_head; 327static struct StunExternalIP *se_head;
368 328
369/** 329/**
370 * Kept in a DLL. 330 * Kept in a DLL.
371 */ 331 */
372static struct StunExternalIP *se_tail; 332static struct StunExternalIP *se_tail;
373 333
374/** 334/**
375 * Is UPnP enabled? #GNUNET_YES if enabled, #GNUNET_NO if disabled, 335 * Is UPnP enabled? #GNUNET_YES if enabled, #GNUNET_NO if disabled,
376 * #GNUNET_SYSERR if configuration enabled but binary is unavailable. 336 * #GNUNET_SYSERR if configuration enabled but binary is unavailable.
377 */ 337 */
378static int enable_upnp; 338int enable_upnp;
379
380/**
381 * Task run to obtain our external IP (if #enable_upnp is set
382 * and if we find we have a NATed IP address).
383 */
384static struct GNUNET_SCHEDULER_Task *probe_external_ip_task;
385
386/**
387 * Handle to our operation to run `external-ip`.
388 */
389static struct GNUNET_NAT_ExternalHandle *probe_external_ip_op;
390
391/**
392 * What is our external IP address as claimed by `external-ip`?
393 * 0 for unknown.
394 */
395static struct in_addr mini_external_ipv4;
396 339
397 340
398/** 341/**
@@ -422,7 +365,7 @@ free_lal (struct LocalAddressList *lal)
422 365
423/** 366/**
424 * Free the DLL starting at #lal_head. 367 * Free the DLL starting at #lal_head.
425 */ 368 */
426static void 369static void
427destroy_lal () 370destroy_lal ()
428{ 371{
@@ -474,22 +417,22 @@ check_register (void *cls,
474#endif 417#endif
475 default: 418 default:
476 GNUNET_break (0); 419 GNUNET_break (0);
477 return GNUNET_SYSERR; 420 return GNUNET_SYSERR;
478 } 421 }
479 if (alen > left) 422 if (alen > left)
480 { 423 {
481 GNUNET_break (0); 424 GNUNET_break (0);
482 return GNUNET_SYSERR; 425 return GNUNET_SYSERR;
483 } 426 }
484 off += alen; 427 off += alen;
485 left -= alen; 428 left -= alen;
486 } 429 }
487 if (left != ntohs (message->hole_external_len)) 430 if (left != ntohs (message->str_len))
488 { 431 {
489 GNUNET_break (0); 432 GNUNET_break (0);
490 return GNUNET_SYSERR; 433 return GNUNET_SYSERR;
491 } 434 }
492 return GNUNET_OK; 435 return GNUNET_OK;
493} 436}
494 437
495 438
@@ -535,7 +478,7 @@ match_ipv6 (const char *network,
535 struct in6_addr net; 478 struct in6_addr net;
536 struct in6_addr mask; 479 struct in6_addr mask;
537 unsigned int off; 480 unsigned int off;
538 481
539 if (0 == bits) 482 if (0 == bits)
540 return GNUNET_YES; 483 return GNUNET_YES;
541 GNUNET_assert (1 == inet_pton (AF_INET6, 484 GNUNET_assert (1 == inet_pton (AF_INET6,
@@ -607,7 +550,7 @@ is_nat_v6 (const struct in6_addr *ip)
607struct IfcProcContext 550struct IfcProcContext
608{ 551{
609 552
610 /** 553 /**
611 * Head of DLL of local addresses. 554 * Head of DLL of local addresses.
612 */ 555 */
613 struct LocalAddressList *lal_head; 556 struct LocalAddressList *lal_head;
@@ -718,7 +661,7 @@ notify_client (enum GNUNET_NAT_AddressClass ac,
718{ 661{
719 struct GNUNET_MQ_Envelope *env; 662 struct GNUNET_MQ_Envelope *env;
720 struct GNUNET_NAT_AddressChangeNotificationMessage *msg; 663 struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
721 664
722 env = GNUNET_MQ_msg_extra (msg, 665 env = GNUNET_MQ_msg_extra (msg,
723 addr_len, 666 addr_len,
724 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); 667 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
@@ -729,7 +672,7 @@ notify_client (enum GNUNET_NAT_AddressClass ac,
729 addr_len); 672 addr_len);
730 GNUNET_MQ_send (ch->mq, 673 GNUNET_MQ_send (ch->mq,
731 env); 674 env);
732} 675}
733 676
734 677
735/** 678/**
@@ -748,7 +691,7 @@ check_notify_client (struct LocalAddressList *delta,
748 size_t alen; 691 size_t alen;
749 struct sockaddr_in v4; 692 struct sockaddr_in v4;
750 struct sockaddr_in6 v6; 693 struct sockaddr_in6 v6;
751 694
752 if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES)) 695 if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
753 return; 696 return;
754 switch (delta->af) 697 switch (delta->af)
@@ -758,14 +701,14 @@ check_notify_client (struct LocalAddressList *delta,
758 GNUNET_memcpy (&v4, 701 GNUNET_memcpy (&v4,
759 &delta->addr, 702 &delta->addr,
760 alen); 703 alen);
761 704
762 /* Check for client notifications */ 705 /* Check for client notifications */
763 for (unsigned int i=0;i<ch->num_caddrs;i++) 706 for (unsigned int i=0;i<ch->num_caddrs;i++)
764 { 707 {
765 const struct sockaddr_in *c4; 708 const struct sockaddr_in *c4;
766 709
767 if (AF_INET != ch->caddrs[i].ss.ss_family) 710 if (AF_INET != ch->caddrs[i].ss.ss_family)
768 return; /* IPv4 not relevant */ 711 continue; /* IPv4 not relevant */
769 c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss; 712 c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
770 if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) && 713 if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) &&
771 (0 != c4->sin_addr.s_addr) && 714 (0 != c4->sin_addr.s_addr) &&
@@ -806,9 +749,9 @@ check_notify_client (struct LocalAddressList *delta,
806 for (unsigned int i=0;i<ch->num_caddrs;i++) 749 for (unsigned int i=0;i<ch->num_caddrs;i++)
807 { 750 {
808 const struct sockaddr_in6 *c6; 751 const struct sockaddr_in6 *c6;
809 752
810 if (AF_INET6 != ch->caddrs[i].ss.ss_family) 753 if (AF_INET6 != ch->caddrs[i].ss.ss_family)
811 return; /* IPv4 not relevant */ 754 continue; /* IPv4 not relevant */
812 c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss; 755 c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
813 if ( match_ipv6 ("::1", &c6->sin6_addr, 128) && 756 if ( match_ipv6 ("::1", &c6->sin6_addr, 128) &&
814 (0 != memcmp (&c6->sin6_addr, 757 (0 != memcmp (&c6->sin6_addr,
@@ -888,19 +831,40 @@ notify_clients (struct LocalAddressList *delta,
888/** 831/**
889 * Tell relevant client about a change in our external 832 * Tell relevant client about a change in our external
890 * IPv4 address. 833 * IPv4 address.
891 * 834 *
835 * @param cls client to check if it cares and possibly notify
892 * @param v4 the external address that changed 836 * @param v4 the external address that changed
893 * @param ch client to check if it cares and possibly notify
894 * @param add #GNUNET_YES to add, #GNUNET_NO to remove 837 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
895 */ 838 */
896static void 839static void
897check_notify_client_external_ipv4_change (const struct in_addr *v4, 840notify_client_external_ipv4_change (void *cls,
898 struct ClientHandle *ch, 841 const struct in_addr *v4,
899 int add) 842 int add)
900{ 843{
844 struct ClientHandle *ch = cls;
901 struct sockaddr_in sa; 845 struct sockaddr_in sa;
902 int have_v4; 846 int have_v4;
903 847
848 /* (0) check if this impacts 'hole_external' */
849 if ( (NULL != ch->hole_external) &&
850 (0 == strcasecmp (ch->hole_external,
851 "AUTO")) )
852 {
853 struct LocalAddressList lal;
854 struct sockaddr_in *s4;
855
856 memset (&lal, 0, sizeof (lal));
857 s4 = (struct sockaddr_in *) &lal.addr;
858 s4->sin_family = AF_INET;
859 s4->sin_port = htons (ch->ext_dns_port);
860 s4->sin_addr = *v4;
861 lal.af = AF_INET;
862 lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
863 check_notify_client (&lal,
864 ch,
865 add);
866 }
867
904 /* (1) check if client cares. */ 868 /* (1) check if client cares. */
905 if (! ch->natted_address) 869 if (! ch->natted_address)
906 return; 870 return;
@@ -919,17 +883,17 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4,
919 if (GNUNET_NO == have_v4) 883 if (GNUNET_NO == have_v4)
920 return; /* IPv6-only */ 884 return; /* IPv6-only */
921 885
922 /* build address info */ 886 /* (2) build address info */
923 memset (&sa, 887 memset (&sa,
924 0, 888 0,
925 sizeof (sa)); 889 sizeof (sa));
926 sa.sin_family = AF_INET; 890 sa.sin_family = AF_INET;
927 sa.sin_addr = *v4; 891 sa.sin_addr = *v4;
928 sa.sin_port = htons (0); 892 sa.sin_port = htons (0);
929 893
930 /* (3) notify client of change */ 894 /* (3) notify client of change */
931 notify_client (is_nat_v4 (v4) 895 notify_client (is_nat_v4 (v4)
932 ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN 896 ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN
933 : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL, 897 : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL,
934 ch, 898 ch,
935 add, 899 add,
@@ -939,117 +903,11 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4,
939 903
940 904
941/** 905/**
942 * Tell relevant clients about a change in our external
943 * IPv4 address.
944 *
945 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
946 * @param v4 the external address that changed
947 */
948static void
949notify_clients_external_ipv4_change (int add,
950 const struct in_addr *v4)
951{
952 for (struct ClientHandle *ch = ch_head;
953 NULL != ch;
954 ch = ch->next)
955 check_notify_client_external_ipv4_change (v4,
956 ch,
957 add);
958}
959
960
961/**
962 * Task used to run `external-ip` to get our external IPv4
963 * address and pass it to NATed clients if possible.
964 *
965 * @param cls NULL
966 */
967static void
968run_external_ip (void *cls);
969
970
971/**
972 * We learn our current external IP address. If it changed,
973 * notify all of our applicable clients. Also re-schedule
974 * #run_external_ip with an appropriate timeout.
975 *
976 * @param cls NULL
977 * @param addr the address, NULL on errors
978 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
979 */
980static void
981handle_external_ip (void *cls,
982 const struct in_addr *addr,
983 enum GNUNET_NAT_StatusCode result)
984{
985 char buf[INET_ADDRSTRLEN];
986
987 probe_external_ip_op = NULL;
988 GNUNET_SCHEDULER_cancel (probe_external_ip_task);
989 probe_external_ip_task
990 = GNUNET_SCHEDULER_add_delayed ((NULL == addr)
991 ? EXTERN_IP_RETRY_FAILURE
992 : EXTERN_IP_RETRY_SUCCESS,
993 &run_external_ip,
994 NULL);
995 switch (result)
996 {
997 case GNUNET_NAT_ERROR_SUCCESS:
998 if (addr->s_addr == mini_external_ipv4.s_addr)
999 return; /* not change */
1000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1001 "Our external IP is now %s\n",
1002 inet_ntop (AF_INET,
1003 addr,
1004 buf,
1005 sizeof (buf)));
1006 if (0 != mini_external_ipv4.s_addr)
1007 notify_clients_external_ipv4_change (GNUNET_NO,
1008 &mini_external_ipv4);
1009 mini_external_ipv4 = *addr;
1010 notify_clients_external_ipv4_change (GNUNET_YES,
1011 &mini_external_ipv4);
1012 break;
1013 default:
1014 if (0 != mini_external_ipv4.s_addr)
1015 notify_clients_external_ipv4_change (GNUNET_NO,
1016 &mini_external_ipv4);
1017 mini_external_ipv4.s_addr = 0;
1018 break;
1019 }
1020}
1021
1022
1023/**
1024 * Task used to run `external-ip` to get our external IPv4
1025 * address and pass it to NATed clients if possible.
1026 *
1027 * @param cls NULL
1028 */
1029static void
1030run_external_ip (void *cls)
1031{
1032 probe_external_ip_task
1033 = GNUNET_SCHEDULER_add_delayed (EXTERN_IP_RETRY_TIMEOUT,
1034 &run_external_ip,
1035 NULL);
1036 if (NULL != probe_external_ip_op)
1037 {
1038 GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
1039 probe_external_ip_op = NULL;
1040 }
1041 probe_external_ip_op
1042 = GNUNET_NAT_mini_get_external_ipv4_ (&handle_external_ip,
1043 NULL);
1044}
1045
1046
1047/**
1048 * We got a connection reversal request from another peer. 906 * We got a connection reversal request from another peer.
1049 * Notify applicable clients. 907 * Notify applicable clients.
1050 * 908 *
1051 * @param cls closure with the `struct LocalAddressList` 909 * @param cls closure with the `struct LocalAddressList`
1052 * @param ra IP address of the peer who wants us to connect to it 910 * @param ra IP address of the peer who wants us to connect to it
1053 */ 911 */
1054static void 912static void
1055reversal_callback (void *cls, 913reversal_callback (void *cls,
@@ -1063,7 +921,7 @@ reversal_callback (void *cls,
1063 for (struct ClientHandle *ch = ch_head; 921 for (struct ClientHandle *ch = ch_head;
1064 NULL != ch; 922 NULL != ch;
1065 ch = ch->next) 923 ch = ch->next)
1066 { 924 {
1067 struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm; 925 struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm;
1068 struct GNUNET_MQ_Envelope *env; 926 struct GNUNET_MQ_Envelope *env;
1069 int match; 927 int match;
@@ -1077,7 +935,7 @@ reversal_callback (void *cls,
1077 { 935 {
1078 struct ClientAddress *ca = &ch->caddrs[i]; 936 struct ClientAddress *ca = &ch->caddrs[i];
1079 const struct sockaddr_in *c4; 937 const struct sockaddr_in *c4;
1080 938
1081 if (AF_INET != ca->ss.ss_family) 939 if (AF_INET != ca->ss.ss_family)
1082 continue; 940 continue;
1083 c4 = (const struct sockaddr_in *) &ca->ss; 941 c4 = (const struct sockaddr_in *) &ca->ss;
@@ -1107,7 +965,7 @@ reversal_callback (void *cls,
1107 * Task we run periodically to scan for network interfaces. 965 * Task we run periodically to scan for network interfaces.
1108 * 966 *
1109 * @param cls NULL 967 * @param cls NULL
1110 */ 968 */
1111static void 969static void
1112run_scan (void *cls) 970run_scan (void *cls)
1113{ 971{
@@ -1115,7 +973,7 @@ run_scan (void *cls)
1115 int found; 973 int found;
1116 int have_nat; 974 int have_nat;
1117 struct LocalAddressList *lnext; 975 struct LocalAddressList *lnext;
1118 976
1119 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ, 977 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
1120 &run_scan, 978 &run_scan,
1121 NULL); 979 NULL);
@@ -1194,8 +1052,8 @@ run_scan (void *cls)
1194 { 1052 {
1195 const struct sockaddr_in *s4 1053 const struct sockaddr_in *s4
1196 = (const struct sockaddr_in *) &pos->addr; 1054 = (const struct sockaddr_in *) &pos->addr;
1197 1055
1198 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1199 "Found NATed local address %s, starting NAT server\n", 1057 "Found NATed local address %s, starting NAT server\n",
1200 GNUNET_a2s ((void *) &pos->addr, sizeof (*s4))); 1058 GNUNET_a2s ((void *) &pos->addr, sizeof (*s4)));
1201 pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr, 1059 pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr,
@@ -1204,29 +1062,7 @@ run_scan (void *cls)
1204 } 1062 }
1205 } 1063 }
1206 } 1064 }
1207 if ( (GNUNET_YES == have_nat) && 1065 GN_nat_status_changed (have_nat);
1208 (GNUNET_YES == enable_upnp) &&
1209 (NULL == probe_external_ip_task) &&
1210 (NULL == probe_external_ip_op) )
1211 {
1212 probe_external_ip_task
1213 = GNUNET_SCHEDULER_add_now (&run_external_ip,
1214 NULL);
1215 }
1216 if ( (GNUNET_NO == have_nat) &&
1217 (GNUNET_YES == enable_upnp) )
1218 {
1219 if (NULL != probe_external_ip_task)
1220 {
1221 GNUNET_SCHEDULER_cancel (probe_external_ip_task);
1222 probe_external_ip_task = NULL;
1223 }
1224 if (NULL != probe_external_ip_op)
1225 {
1226 GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
1227 probe_external_ip_op = NULL;
1228 }
1229 }
1230} 1066}
1231 1067
1232 1068
@@ -1267,6 +1103,10 @@ upnp_addr_change_cb (void *cls,
1267 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1103 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1268 "external-ip binary not found\n"); 1104 "external-ip binary not found\n");
1269 return; 1105 return;
1106 case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
1107 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1108 "upnpc binary not found\n");
1109 return;
1270 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED: 1110 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
1271 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1111 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1272 "external-ip binary could not be run\n"); 1112 "external-ip binary could not be run\n");
@@ -1317,6 +1157,250 @@ upnp_addr_change_cb (void *cls,
1317 1157
1318 1158
1319/** 1159/**
1160 * Resolve the `hole_external` name to figure out our
1161 * external address from a manually punched hole. The
1162 * port number has already been parsed, this task is
1163 * responsible for periodically doing a DNS lookup.
1164 *
1165 * @param ch client handle to act upon
1166 */
1167static void
1168dyndns_lookup (void *cls);
1169
1170
1171/**
1172 * Our (external) hostname was resolved. Update lists of
1173 * current external IPs (note that DNS may return multiple
1174 * addresses!) and notify client accordingly.
1175 *
1176 * @param cls the `struct ClientHandle`
1177 * @param addr NULL on error, otherwise result of DNS lookup
1178 * @param addrlen number of bytes in @a addr
1179 */
1180static void
1181process_external_ip (void *cls,
1182 const struct sockaddr *addr,
1183 socklen_t addrlen)
1184{
1185 struct ClientHandle *ch = cls;
1186 struct LocalAddressList *lal;
1187 struct sockaddr_storage ss;
1188 struct sockaddr_in *v4;
1189 struct sockaddr_in6 *v6;
1190
1191 if (NULL == addr)
1192 {
1193 struct LocalAddressList *laln;
1194
1195 ch->ext_dns = NULL;
1196 ch->ext_dns_task
1197 = GNUNET_SCHEDULER_add_delayed (dyndns_frequency,
1198 &dyndns_lookup,
1199 ch);
1200 /* Current iteration is over, remove 'old' IPs now */
1201 for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
1202 {
1203 laln = lal->next;
1204 if (GNUNET_YES == lal->old)
1205 {
1206 GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
1207 ch->ext_addr_tail,
1208 lal);
1209 check_notify_client (lal,
1210 ch,
1211 GNUNET_NO);
1212 GNUNET_free (lal);
1213 }
1214 }
1215 return;
1216 }
1217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1218 "Got IP `%s' for external address `%s'\n",
1219 GNUNET_a2s (addr,
1220 addrlen),
1221 ch->hole_external);
1222
1223 /* build sockaddr storage with port number */
1224 memset (&ss, 0, sizeof (ss));
1225 memcpy (&ss, addr, addrlen);
1226 switch (addr->sa_family)
1227 {
1228 case AF_INET:
1229 v4 = (struct sockaddr_in *) &ss;
1230 v4->sin_port = htons (ch->ext_dns_port);
1231 break;
1232 case AF_INET6:
1233 v6 = (struct sockaddr_in6 *) &ss;
1234 v6->sin6_port = htons (ch->ext_dns_port);
1235 break;
1236 default:
1237 GNUNET_break (0);
1238 return;
1239 }
1240 /* See if 'ss' matches any of our known addresses */
1241 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1242 {
1243 if (GNUNET_NO == lal->old)
1244 continue; /* already processed, skip */
1245 if ( (addr->sa_family == lal->addr.ss_family) &&
1246 (0 == memcmp (&ss,
1247 &lal->addr,
1248 addrlen)) )
1249 {
1250 /* Address unchanged, remember so we do not remove */
1251 lal->old = GNUNET_NO;
1252 return; /* done here */
1253 }
1254 }
1255 /* notify client, and remember IP for later removal! */
1256 lal = GNUNET_new (struct LocalAddressList);
1257 lal->addr = ss;
1258 lal->af = ss.ss_family;
1259 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1260 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1261 ch->ext_addr_tail,
1262 lal);
1263 check_notify_client (lal,
1264 ch,
1265 GNUNET_YES);
1266}
1267
1268
1269/**
1270 * Resolve the `hole_external` name to figure out our
1271 * external address from a manually punched hole. The
1272 * port number has already been parsed, this task is
1273 * responsible for periodically doing a DNS lookup.
1274 *
1275 * @param ch client handle to act upon
1276 */
1277static void
1278dyndns_lookup (void *cls)
1279{
1280 struct ClientHandle *ch = cls;
1281 struct LocalAddressList *lal;
1282
1283 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1284 lal->old = GNUNET_YES;
1285 ch->ext_dns_task = NULL;
1286 ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external,
1287 AF_UNSPEC,
1288 GNUNET_TIME_UNIT_MINUTES,
1289 &process_external_ip,
1290 ch);
1291}
1292
1293
1294/**
1295 * Resolve the `hole_external` name to figure out our
1296 * external address from a manually punched hole. The
1297 * given name may be "AUTO" in which case we should use
1298 * the IP address(es) we have from upnpc or other methods.
1299 * The name can also be an IP address, in which case we
1300 * do not need to do DNS resolution. Finally, we also
1301 * need to parse the port number.
1302 *
1303 * @param ch client handle to act upon
1304 */
1305static void
1306lookup_hole_external (struct ClientHandle *ch)
1307{
1308 char *port;
1309 unsigned int pnum;
1310 struct sockaddr_in *s4;
1311 struct LocalAddressList *lal;
1312
1313 port = strrchr (ch->hole_external, ':');
1314 if (NULL == port)
1315 {
1316 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1317 _("Malformed punched hole specification `%s' (lacks port)\n"),
1318 ch->hole_external);
1319 return;
1320 }
1321 if ( (1 != sscanf (port + 1,
1322 "%u",
1323 &pnum)) ||
1324 (pnum > 65535) )
1325 {
1326 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1327 _("Invalid port number in punched hole specification `%s' (lacks port)\n"),
1328 port + 1);
1329 return;
1330 }
1331 ch->ext_dns_port = (uint16_t) pnum;
1332 *port = '\0';
1333
1334 lal = GNUNET_new (struct LocalAddressList);
1335 if ('[' == *ch->hole_external)
1336 {
1337 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr;
1338
1339 s6->sin6_family = AF_INET6;
1340 if (']' != (ch->hole_external[strlen(ch->hole_external)-1]))
1341 {
1342 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1343 _("Malformed punched hole specification `%s' (lacks `]')\n"),
1344 ch->hole_external);
1345 GNUNET_free (lal);
1346 return;
1347 }
1348 ch->hole_external[strlen(ch->hole_external)-1] = '\0';
1349 if (1 != inet_pton (AF_INET6,
1350 ch->hole_external + 1,
1351 &s6->sin6_addr))
1352 {
1353 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1354 _("Malformed punched hole specification `%s' (IPv6 address invalid)"),
1355 ch->hole_external + 1);
1356 GNUNET_free (lal);
1357 return;
1358 }
1359 s6->sin6_port = htons (ch->ext_dns_port);
1360 lal->af = AF_INET6;
1361 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1362 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1363 ch->ext_addr_tail,
1364 lal);
1365 check_notify_client (lal,
1366 ch,
1367 GNUNET_YES);
1368 return;
1369 }
1370
1371 s4 = (struct sockaddr_in *) &lal->addr;
1372 s4->sin_family = AF_INET;
1373 if (1 == inet_pton (AF_INET,
1374 ch->hole_external,
1375 &s4->sin_addr))
1376 {
1377 s4->sin_port = htons (ch->ext_dns_port);
1378 lal->af = AF_INET;
1379 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1380 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1381 ch->ext_addr_tail,
1382 lal);
1383 check_notify_client (lal,
1384 ch,
1385 GNUNET_YES);
1386 return;
1387 }
1388 if (0 == strcasecmp (ch->hole_external,
1389 "AUTO"))
1390 {
1391 /* handled in #notify_client_external_ipv4_change() */
1392 GNUNET_free (lal);
1393 return;
1394 }
1395 /* got a DNS name, trigger lookup! */
1396 GNUNET_free (lal);
1397 ch->ext_dns_task
1398 = GNUNET_SCHEDULER_add_now (&dyndns_lookup,
1399 ch);
1400}
1401
1402
1403/**
1320 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client. 1404 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
1321 * We remember the client for updates upon future NAT events. 1405 * We remember the client for updates upon future NAT events.
1322 * 1406 *
@@ -1367,7 +1451,7 @@ handle_register (void *cls,
1367 case AF_INET: 1451 case AF_INET:
1368 { 1452 {
1369 const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa; 1453 const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa;
1370 1454
1371 alen = sizeof (struct sockaddr_in); 1455 alen = sizeof (struct sockaddr_in);
1372 if (is_nat_v4 (&s4->sin_addr)) 1456 if (is_nat_v4 (&s4->sin_addr))
1373 is_nat = GNUNET_YES; 1457 is_nat = GNUNET_YES;
@@ -1377,7 +1461,7 @@ handle_register (void *cls,
1377 case AF_INET6: 1461 case AF_INET6:
1378 { 1462 {
1379 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa; 1463 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa;
1380 1464
1381 alen = sizeof (struct sockaddr_in6); 1465 alen = sizeof (struct sockaddr_in6);
1382 if (is_nat_v6 (&s6->sin6_addr)) 1466 if (is_nat_v6 (&s6->sin6_addr))
1383 is_nat = GNUNET_YES; 1467 is_nat = GNUNET_YES;
@@ -1393,14 +1477,14 @@ handle_register (void *cls,
1393 default: 1477 default:
1394 GNUNET_break (0); 1478 GNUNET_break (0);
1395 GNUNET_SERVICE_client_drop (ch->client); 1479 GNUNET_SERVICE_client_drop (ch->client);
1396 return; 1480 return;
1397 } 1481 }
1398 /* store address */ 1482 /* store address */
1399 GNUNET_assert (alen <= left); 1483 GNUNET_assert (alen <= left);
1400 GNUNET_assert (alen <= sizeof (struct sockaddr_storage)); 1484 GNUNET_assert (alen <= sizeof (struct sockaddr_storage));
1401 GNUNET_memcpy (&ch->caddrs[i].ss, 1485 GNUNET_memcpy (&ch->caddrs[i].ss,
1402 sa, 1486 sa,
1403 alen); 1487 alen);
1404 1488
1405 /* If applicable, try UPNPC NAT punching */ 1489 /* If applicable, try UPNPC NAT punching */
1406 if ( (is_nat) && 1490 if ( (is_nat) &&
@@ -1419,10 +1503,16 @@ handle_register (void *cls,
1419 off += alen; 1503 off += alen;
1420 } 1504 }
1421 1505
1422 ch->hole_external 1506 ch->section_name
1423 = GNUNET_strndup (off, 1507 = GNUNET_strndup (off,
1424 ntohs (message->hole_external_len)); 1508 ntohs (message->str_len));
1425 1509 if (GNUNET_OK ==
1510 GNUNET_CONFIGURATION_get_value_string (cfg,
1511 ch->section_name,
1512 "HOLE_EXTERNAL",
1513 &ch->hole_external))
1514 lookup_hole_external (ch);
1515
1426 /* Actually send IP address list to client */ 1516 /* Actually send IP address list to client */
1427 for (struct LocalAddressList *lal = lal_head; 1517 for (struct LocalAddressList *lal = lal_head;
1428 NULL != lal; 1518 NULL != lal;
@@ -1433,12 +1523,9 @@ handle_register (void *cls,
1433 GNUNET_YES); 1523 GNUNET_YES);
1434 } 1524 }
1435 /* Also consider IPv4 determined by `external-ip` */ 1525 /* Also consider IPv4 determined by `external-ip` */
1436 if (0 != mini_external_ipv4.s_addr) 1526 ch->external_monitor
1437 { 1527 = GN_external_ipv4_monitor_start (&notify_client_external_ipv4_change,
1438 check_notify_client_external_ipv4_change (&mini_external_ipv4, 1528 ch);
1439 ch,
1440 GNUNET_YES);
1441 }
1442 GNUNET_SERVICE_client_continue (ch->client); 1529 GNUNET_SERVICE_client_continue (ch->client);
1443} 1530}
1444 1531
@@ -1457,7 +1544,7 @@ check_stun (void *cls,
1457{ 1544{
1458 size_t sa_len = ntohs (message->sender_addr_size); 1545 size_t sa_len = ntohs (message->sender_addr_size);
1459 size_t expect = sa_len + ntohs (message->payload_size); 1546 size_t expect = sa_len + ntohs (message->payload_size);
1460 1547
1461 if (ntohs (message->header.size) - sizeof (*message) != expect) 1548 if (ntohs (message->header.size) - sizeof (*message) != expect)
1462 { 1549 {
1463 GNUNET_break (0); 1550 GNUNET_break (0);
@@ -1490,7 +1577,7 @@ notify_clients_stun_change (const struct sockaddr_in *ip,
1490 struct sockaddr_in v4; 1577 struct sockaddr_in v4;
1491 struct GNUNET_NAT_AddressChangeNotificationMessage *msg; 1578 struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
1492 struct GNUNET_MQ_Envelope *env; 1579 struct GNUNET_MQ_Envelope *env;
1493 1580
1494 if (! ch->natted_address) 1581 if (! ch->natted_address)
1495 continue; 1582 continue;
1496 v4 = *ip; 1583 v4 = *ip;
@@ -1580,9 +1667,9 @@ handle_stun (void *cls,
1580 GNUNET_NAT_stun_handle_packet_ (payload, 1667 GNUNET_NAT_stun_handle_packet_ (payload,
1581 payload_size, 1668 payload_size,
1582 &external_addr)) 1669 &external_addr))
1583 { 1670 {
1584 /* We now know that a server at "sa" claims that 1671 /* We now know that a server at "sa" claims that
1585 we are visible at IP "external_addr". 1672 we are visible at IP "external_addr".
1586 1673
1587 We should (for some fixed period of time) tell 1674 We should (for some fixed period of time) tell
1588 all of our clients that listen to a NAT'ed address 1675 all of our clients that listen to a NAT'ed address
@@ -1685,347 +1772,44 @@ handle_request_connection_reversal (void *cls,
1685 const char *buf = (const char *) &message[1]; 1772 const char *buf = (const char *) &message[1];
1686 size_t local_sa_len = ntohs (message->local_addr_size); 1773 size_t local_sa_len = ntohs (message->local_addr_size);
1687 size_t remote_sa_len = ntohs (message->remote_addr_size); 1774 size_t remote_sa_len = ntohs (message->remote_addr_size);
1688 const struct sockaddr *local_sa = (const struct sockaddr *) &buf[0]; 1775 struct sockaddr_in l4;
1689 const struct sockaddr *remote_sa = (const struct sockaddr *) &buf[local_sa_len]; 1776 struct sockaddr_in r4;
1690 const struct sockaddr_in *l4 = NULL;
1691 const struct sockaddr_in *r4;
1692 int ret; 1777 int ret;
1693 1778
1694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1779 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695 "Received REQUEST CONNECTION REVERSAL message from client\n"); 1780 "Received REQUEST CONNECTION REVERSAL message from client\n");
1696 switch (local_sa->sa_family) 1781 if (local_sa_len != sizeof (struct sockaddr_in))
1697 { 1782 {
1698 case AF_INET: 1783 GNUNET_break_op (0);
1699 if (local_sa_len != sizeof (struct sockaddr_in))
1700 {
1701 GNUNET_break (0);
1702 GNUNET_SERVICE_client_drop (ch->client);
1703 return;
1704 }
1705 l4 = (const struct sockaddr_in *) local_sa;
1706 break;
1707 case AF_INET6:
1708 if (local_sa_len != sizeof (struct sockaddr_in6))
1709 {
1710 GNUNET_break (0);
1711 GNUNET_SERVICE_client_drop (ch->client);
1712 return;
1713 }
1714 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1715 _("Connection reversal for IPv6 not supported yet\n"));
1716 ret = GNUNET_SYSERR;
1717 break;
1718 default:
1719 GNUNET_break (0);
1720 GNUNET_SERVICE_client_drop (ch->client); 1784 GNUNET_SERVICE_client_drop (ch->client);
1721 return; 1785 return;
1722 } 1786 }
1723 switch (remote_sa->sa_family) 1787 if (remote_sa_len != sizeof (struct sockaddr_in))
1724 { 1788 {
1725 case AF_INET: 1789 GNUNET_break_op (0);
1726 if (remote_sa_len != sizeof (struct sockaddr_in))
1727 {
1728 GNUNET_break (0);
1729 GNUNET_SERVICE_client_drop (ch->client);
1730 return;
1731 }
1732 r4 = (const struct sockaddr_in *) remote_sa;
1733 ret = GN_request_connection_reversal (&l4->sin_addr,
1734 ntohs (l4->sin_port),
1735 &r4->sin_addr);
1736 break;
1737 case AF_INET6:
1738 if (remote_sa_len != sizeof (struct sockaddr_in6))
1739 {
1740 GNUNET_break (0);
1741 GNUNET_SERVICE_client_drop (ch->client);
1742 return;
1743 }
1744 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1745 _("Connection reversal for IPv6 not supported yet\n"));
1746 ret = GNUNET_SYSERR;
1747 break;
1748 default:
1749 GNUNET_break (0);
1750 GNUNET_SERVICE_client_drop (ch->client); 1790 GNUNET_SERVICE_client_drop (ch->client);
1751 return; 1791 return;
1752 } 1792 }
1793 GNUNET_memcpy (&l4,
1794 buf,
1795 sizeof (struct sockaddr_in));
1796 GNUNET_break_op (AF_INET == l4.sin_family);
1797 buf += sizeof (struct sockaddr_in);
1798 GNUNET_memcpy (&r4,
1799 buf,
1800 sizeof (struct sockaddr_in));
1801 GNUNET_break_op (AF_INET == r4.sin_family);
1802 ret = GN_request_connection_reversal (&l4.sin_addr,
1803 ntohs (l4.sin_port),
1804 &r4.sin_addr);
1753 if (GNUNET_OK != ret) 1805 if (GNUNET_OK != ret)
1754 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1806 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1755 _("Connection reversal request failed\n")); 1807 _("Connection reversal request failed\n"));
1756 GNUNET_SERVICE_client_continue (ch->client); 1808 GNUNET_SERVICE_client_continue (ch->client);
1757} 1809}
1758 1810
1759 1811
1760/** 1812/**
1761 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
1762 * from client.
1763 *
1764 * @param cls client who sent the message
1765 * @param message the message received
1766 * @return #GNUNET_OK if message is well-formed
1767 */
1768static int
1769check_autoconfig_request (void *cls,
1770 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
1771{
1772 return GNUNET_OK; /* checked later */
1773}
1774
1775
1776/**
1777 * Stop all pending activities with respect to the @a ac
1778 *
1779 * @param ac autoconfiguration to terminate activities for
1780 */
1781static void
1782terminate_ac_activities (struct AutoconfigContext *ac)
1783{
1784 if (NULL != ac->probe_external)
1785 {
1786 GNUNET_NAT_mini_get_external_ipv4_cancel_ (ac->probe_external);
1787 ac->probe_external = NULL;
1788 }
1789 if (NULL != ac->timeout_task)
1790 {
1791 GNUNET_SCHEDULER_cancel (ac->timeout_task);
1792 ac->timeout_task = NULL;
1793 }
1794}
1795
1796
1797/**
1798 * Finish handling the autoconfiguration request and send
1799 * the response to the client.
1800 *
1801 * @param cls the `struct AutoconfigContext` to conclude
1802 */
1803static void
1804conclude_autoconfig_request (void *cls)
1805{
1806 struct AutoconfigContext *ac = cls;
1807 struct ClientHandle *ch = ac->ch;
1808 struct GNUNET_NAT_AutoconfigResultMessage *arm;
1809 struct GNUNET_MQ_Envelope *env;
1810 size_t c_size;
1811 char *buf;
1812 struct GNUNET_CONFIGURATION_Handle *diff;
1813
1814 ac->timeout_task = NULL;
1815 terminate_ac_activities (ac);
1816
1817 /* Send back response */
1818 diff = GNUNET_CONFIGURATION_get_diff (ac->orig,
1819 ac->c);
1820 buf = GNUNET_CONFIGURATION_serialize (diff,
1821 &c_size);
1822 GNUNET_CONFIGURATION_destroy (diff);
1823 env = GNUNET_MQ_msg_extra (arm,
1824 c_size,
1825 GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT);
1826 arm->status_code = htonl ((uint32_t) ac->status_code);
1827 arm->type = htonl ((uint32_t) ac->type);
1828 GNUNET_memcpy (&arm[1],
1829 buf,
1830 c_size);
1831 GNUNET_free (buf);
1832 GNUNET_MQ_send (ch->mq,
1833 env);
1834
1835 /* clean up */
1836 GNUNET_free (ac->system_type);
1837 GNUNET_CONFIGURATION_destroy (ac->orig);
1838 GNUNET_CONFIGURATION_destroy (ac->c);
1839 GNUNET_CONTAINER_DLL_remove (ac_head,
1840 ac_tail,
1841 ac);
1842 GNUNET_free (ac);
1843 GNUNET_SERVICE_client_continue (ch->client);
1844}
1845
1846
1847/**
1848 * Check if all autoconfiguration operations have concluded,
1849 * and if they have, send the result back to the client.
1850 *
1851 * @param ac autoconfiguation context to check
1852 */
1853static void
1854check_autoconfig_finished (struct AutoconfigContext *ac)
1855{
1856 if (NULL != ac->probe_external)
1857 return;
1858 GNUNET_SCHEDULER_cancel (ac->timeout_task);
1859 ac->timeout_task
1860 = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request,
1861 ac);
1862}
1863
1864
1865/**
1866 * Update ENABLE_UPNPC configuration option.
1867 *
1868 * @param ac autoconfiguration to update
1869 */
1870static void
1871update_enable_upnpc_option (struct AutoconfigContext *ac)
1872{
1873 switch (ac->enable_upnpc)
1874 {
1875 case GNUNET_YES:
1876 GNUNET_CONFIGURATION_set_value_string (ac->c,
1877 "NAT",
1878 "ENABLE_UPNP",
1879 "YES");
1880 break;
1881 case GNUNET_NO:
1882 GNUNET_CONFIGURATION_set_value_string (ac->c,
1883 "NAT",
1884 "ENABLE_UPNP",
1885 "NO");
1886 break;
1887 case GNUNET_SYSERR:
1888 /* We are unsure, do not change option */
1889 break;
1890 }
1891}
1892
1893
1894/**
1895 * Handle result from external IP address probe during
1896 * autoconfiguration.
1897 *
1898 * @param cls our `struct AutoconfigContext`
1899 * @param addr the address, NULL on errors
1900 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
1901 */
1902static void
1903auto_external_result_cb (void *cls,
1904 const struct in_addr *addr,
1905 enum GNUNET_NAT_StatusCode result)
1906{
1907 struct AutoconfigContext *ac = cls;
1908
1909 ac->probe_external = NULL;
1910 switch (result)
1911 {
1912 case GNUNET_NAT_ERROR_SUCCESS:
1913 ac->enable_upnpc = GNUNET_YES;
1914 break;
1915 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
1916 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
1917 case GNUNET_NAT_ERROR_IPC_FAILURE:
1918 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1919 "Disabling UPNPC: %d\n",
1920 (int) result);
1921 ac->enable_upnpc = GNUNET_NO; /* did not work */
1922 break;
1923 default:
1924 GNUNET_break (0); /* unexpected */
1925 ac->enable_upnpc = GNUNET_SYSERR;
1926 break;
1927 }
1928 update_enable_upnpc_option (ac);
1929 check_autoconfig_finished (ac);
1930}
1931
1932
1933/**
1934 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
1935 * client.
1936 *
1937 * @param cls client who sent the message
1938 * @param message the message received
1939 */
1940static void
1941handle_autoconfig_request (void *cls,
1942 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
1943{
1944 struct ClientHandle *ch = cls;
1945 size_t left = ntohs (message->header.size) - sizeof (*message);
1946 struct LocalAddressList *lal;
1947 struct AutoconfigContext *ac;
1948
1949 ac = GNUNET_new (struct AutoconfigContext);
1950 ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
1951 ac->ch = ch;
1952 ac->c = GNUNET_CONFIGURATION_create ();
1953 if (GNUNET_OK !=
1954 GNUNET_CONFIGURATION_deserialize (ac->c,
1955 (const char *) &message[1],
1956 left,
1957 GNUNET_NO))
1958 {
1959 GNUNET_break (0);
1960 GNUNET_SERVICE_client_drop (ch->client);
1961 GNUNET_CONFIGURATION_destroy (ac->c);
1962 GNUNET_free (ac);
1963 return;
1964 }
1965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1966 "Received REQUEST_AUTO_CONFIG message from client\n");
1967
1968 if (GNUNET_OK !=
1969 GNUNET_CONFIGURATION_get_value_string (ac->c,
1970 "PEER",
1971 "SYSTEM_TYPE",
1972 &ac->system_type))
1973 ac->system_type = GNUNET_strdup ("UNKNOWN");
1974
1975 GNUNET_CONTAINER_DLL_insert (ac_head,
1976 ac_tail,
1977 ac);
1978 ac->orig
1979 = GNUNET_CONFIGURATION_dup (ac->c);
1980 ac->timeout_task
1981 = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT,
1982 &conclude_autoconfig_request,
1983 ac);
1984 ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
1985
1986 /* Probe for upnpc */
1987 if (GNUNET_SYSERR ==
1988 GNUNET_OS_check_helper_binary ("upnpc",
1989 GNUNET_NO,
1990 NULL))
1991 {
1992 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1993 _("UPnP client `upnpc` command not found, disabling UPnP\n"));
1994 ac->enable_upnpc = GNUNET_NO;
1995 }
1996 else
1997 {
1998 for (lal = lal_head; NULL != lal; lal = lal->next)
1999 if (GNUNET_NAT_AC_LAN == (lal->ac & GNUNET_NAT_AC_LAN))
2000 /* we are behind NAT, useful to try upnpc */
2001 ac->enable_upnpc = GNUNET_YES;
2002 }
2003 if (GNUNET_YES == ac->enable_upnpc)
2004 {
2005 /* If we are a mobile device, always leave it on as the network
2006 may change to one that supports UPnP anytime. If we are
2007 stationary, check if our network actually supports UPnP, and if
2008 not, disable it. */
2009 if ( (0 == strcasecmp (ac->system_type,
2010 "INFRASTRUCTURE")) ||
2011 (0 == strcasecmp (ac->system_type,
2012 "DESKTOP")) )
2013 {
2014 /* Check if upnpc gives us an external IP */
2015 ac->probe_external
2016 = GNUNET_NAT_mini_get_external_ipv4_ (&auto_external_result_cb,
2017 ac);
2018 }
2019 }
2020 if (NULL == ac->probe_external)
2021 update_enable_upnpc_option (ac);
2022
2023 /* Finally, check if we are already done */
2024 check_autoconfig_finished (ac);
2025}
2026
2027
2028/**
2029 * Task run during shutdown. 1813 * Task run during shutdown.
2030 * 1814 *
2031 * @param cls unused 1815 * @param cls unused
@@ -2034,16 +1818,7 @@ static void
2034shutdown_task (void *cls) 1818shutdown_task (void *cls)
2035{ 1819{
2036 struct StunExternalIP *se; 1820 struct StunExternalIP *se;
2037 struct AutoconfigContext *ac;
2038 1821
2039 while (NULL != (ac = ac_head))
2040 {
2041 GNUNET_CONTAINER_DLL_remove (ac_head,
2042 ac_tail,
2043 ac);
2044 terminate_ac_activities (ac);
2045 GNUNET_free (ac);
2046 }
2047 while (NULL != (se = se_head)) 1822 while (NULL != (se = se_head))
2048 { 1823 {
2049 GNUNET_CONTAINER_DLL_remove (se_head, 1824 GNUNET_CONTAINER_DLL_remove (se_head,
@@ -2052,16 +1827,7 @@ shutdown_task (void *cls)
2052 GNUNET_SCHEDULER_cancel (se->timeout_task); 1827 GNUNET_SCHEDULER_cancel (se->timeout_task);
2053 GNUNET_free (se); 1828 GNUNET_free (se);
2054 } 1829 }
2055 if (NULL != probe_external_ip_task) 1830 GN_nat_status_changed (GNUNET_NO);
2056 {
2057 GNUNET_SCHEDULER_cancel (probe_external_ip_task);
2058 probe_external_ip_task = NULL;
2059 }
2060 if (NULL != probe_external_ip_op)
2061 {
2062 GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
2063 probe_external_ip_op = NULL;
2064 }
2065 if (NULL != scan_task) 1831 if (NULL != scan_task)
2066 { 1832 {
2067 GNUNET_SCHEDULER_cancel (scan_task); 1833 GNUNET_SCHEDULER_cancel (scan_task);
@@ -2098,7 +1864,7 @@ run (void *cls,
2098 stun_stale_timeout = GNUNET_TIME_UNIT_HOURS; 1864 stun_stale_timeout = GNUNET_TIME_UNIT_HOURS;
2099 1865
2100 /* Check for UPnP */ 1866 /* Check for UPnP */
2101 enable_upnp 1867 enable_upnp
2102 = GNUNET_CONFIGURATION_get_value_yesno (cfg, 1868 = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2103 "NAT", 1869 "NAT",
2104 "ENABLE_UPNP"); 1870 "ENABLE_UPNP");
@@ -2115,7 +1881,13 @@ run (void *cls,
2115 enable_upnp = GNUNET_SYSERR; 1881 enable_upnp = GNUNET_SYSERR;
2116 } 1882 }
2117 } 1883 }
2118 1884 if (GNUNET_OK !=
1885 GNUNET_CONFIGURATION_get_value_time (cfg,
1886 "nat",
1887 "DYNDNS_FREQUENCY",
1888 &dyndns_frequency))
1889 dyndns_frequency = DYNDNS_FREQUENCY;
1890
2119 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 1891 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
2120 NULL); 1892 NULL);
2121 stats = GNUNET_STATISTICS_create ("nat", 1893 stats = GNUNET_STATISTICS_create ("nat",
@@ -2163,6 +1935,7 @@ client_disconnect_cb (void *cls,
2163 void *internal_cls) 1935 void *internal_cls)
2164{ 1936{
2165 struct ClientHandle *ch = internal_cls; 1937 struct ClientHandle *ch = internal_cls;
1938 struct LocalAddressList *lal;
2166 1939
2167 GNUNET_CONTAINER_DLL_remove (ch_head, 1940 GNUNET_CONTAINER_DLL_remove (ch_head,
2168 ch_tail, 1941 ch_tail,
@@ -2176,7 +1949,30 @@ client_disconnect_cb (void *cls,
2176 } 1949 }
2177 } 1950 }
2178 GNUNET_free_non_null (ch->caddrs); 1951 GNUNET_free_non_null (ch->caddrs);
2179 GNUNET_free (ch->hole_external); 1952 while (NULL != (lal = ch->ext_addr_head))
1953 {
1954 GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
1955 ch->ext_addr_tail,
1956 lal);
1957 GNUNET_free (lal);
1958 }
1959 if (NULL != ch->ext_dns_task)
1960 {
1961 GNUNET_SCHEDULER_cancel (ch->ext_dns_task);
1962 ch->ext_dns_task = NULL;
1963 }
1964 if (NULL != ch->external_monitor)
1965 {
1966 GN_external_ipv4_monitor_stop (ch->external_monitor);
1967 ch->external_monitor = NULL;
1968 }
1969 if (NULL != ch->ext_dns)
1970 {
1971 GNUNET_RESOLVER_request_cancel (ch->ext_dns);
1972 ch->ext_dns = NULL;
1973 }
1974 GNUNET_free_non_null (ch->hole_external);
1975 GNUNET_free_non_null (ch->section_name);
2180 GNUNET_free (ch); 1976 GNUNET_free (ch);
2181} 1977}
2182 1978
@@ -2203,10 +1999,6 @@ GNUNET_SERVICE_MAIN
2203 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, 1999 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
2204 struct GNUNET_NAT_RequestConnectionReversalMessage, 2000 struct GNUNET_NAT_RequestConnectionReversalMessage,
2205 NULL), 2001 NULL),
2206 GNUNET_MQ_hd_var_size (autoconfig_request,
2207 GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG,
2208 struct GNUNET_NAT_AutoconfigRequestMessage,
2209 NULL),
2210 GNUNET_MQ_handler_end ()); 2002 GNUNET_MQ_handler_end ());
2211 2003
2212 2004
diff --git a/src/nat/gnunet-service-nat.h b/src/nat/gnunet-service-nat.h
new file mode 100644
index 000000000..96eb9f78b
--- /dev/null
+++ b/src/nat/gnunet-service-nat.h
@@ -0,0 +1,35 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21/**
22 * @file nat/gnunet-service-nat.h
23 * @brief network address translation traversal service
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_NAT_H
27#define GNUNET_SERVICE_NAT_H
28
29/**
30 * Is UPnP enabled? #GNUNET_YES if enabled, #GNUNET_NO if disabled,
31 * #GNUNET_SYSERR if configuration enabled but binary is unavailable.
32 */
33extern int enable_upnp;
34
35#endif
diff --git a/src/nat/gnunet-service-nat_externalip.c b/src/nat/gnunet-service-nat_externalip.c
new file mode 100644
index 000000000..979d2f0f5
--- /dev/null
+++ b/src/nat/gnunet-service-nat_externalip.c
@@ -0,0 +1,314 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2015, 2016, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * Code to figure out what our external IPv4 address(es) might
22 * be (external IPv4s are what is seen on the rest of the Internet).
23 *
24 * This can be implemented using different methods, and we allow
25 * the main service to be notified about changes to what we believe
26 * is our external IPv4 address.
27 *
28 * Note that this is explicitly only about NATed systems; if one
29 * of our network interfaces has a global IP address this does
30 * not count as "external".
31 *
32 * TODO:
33 * - implement NEW logic for external IP detection based on traceroute!
34 *
35 * @file nat/gnunet-service-nat_externalip.c
36 * @brief Functions for monitoring external IPv4 addresses
37 * @author Christian Grothoff
38 */
39#include "platform.h"
40#include <math.h>
41#include "gnunet_util_lib.h"
42#include "gnunet_protocols.h"
43#include "gnunet_signatures.h"
44#include "gnunet_statistics_service.h"
45#include "gnunet_resolver_service.h"
46#include "gnunet_nat_service.h"
47#include "gnunet-service-nat.h"
48#include "gnunet-service-nat_externalip.h"
49#include "gnunet-service-nat_stun.h"
50#include "gnunet-service-nat_mini.h"
51#include "gnunet-service-nat_helper.h"
52#include "nat.h"
53#include <gcrypt.h>
54
55
56/**
57 * How long do we wait until we re-try running `external-ip` if the
58 * command failed to terminate nicely?
59 */
60#define EXTERN_IP_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
61
62/**
63 * How long do we wait until we re-try running `external-ip` if the
64 * command failed (but terminated)?
65 */
66#define EXTERN_IP_RETRY_FAILURE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
67
68/**
69 * How long do we wait until we re-try running `external-ip` if the
70 * command succeeded?
71 */
72#define EXTERN_IP_RETRY_SUCCESS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
73
74
75/**
76 * Handle to monitor for external IP changes.
77 */
78struct GN_ExternalIPMonitor
79{
80 /**
81 * Kept in DLL.
82 */
83 struct GN_ExternalIPMonitor *next;
84
85 /**
86 * Kept in DLL.
87 */
88 struct GN_ExternalIPMonitor *prev;
89
90 /**
91 * Function to call when we believe our external IPv4 address changed.
92 */
93 GN_NotifyExternalIPv4Change cb;
94
95 /**
96 * Closure for @e cb.
97 */
98 void *cb_cls;
99
100};
101
102
103/**
104 * List of monitors, kept in DLL.
105 */
106static struct GN_ExternalIPMonitor *mon_head;
107
108/**
109 * List of monitors, kept in DLL.
110 */
111static struct GN_ExternalIPMonitor *mon_tail;
112
113/**
114 * Task run to obtain our external IP (if #enable_upnp is set
115 * and if we find we have a NATed IP address).
116 */
117static struct GNUNET_SCHEDULER_Task *probe_external_ip_task;
118
119/**
120 * Handle to our operation to run `external-ip`.
121 */
122static struct GNUNET_NAT_ExternalHandle *probe_external_ip_op;
123
124/**
125 * What is our external IP address as claimed by `external-ip`?
126 * 0 for unknown.
127 */
128static struct in_addr mini_external_ipv4;
129
130
131/**
132 * Tell relevant clients about a change in our external
133 * IPv4 address.
134 *
135 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
136 * @param v4 the external address that changed
137 */
138static void
139notify_monitors_external_ipv4_change (int add,
140 const struct in_addr *v4)
141{
142 for (struct GN_ExternalIPMonitor *mon = mon_head;
143 NULL != mon;
144 mon = mon->next)
145 mon->cb (mon->cb_cls,
146 v4,
147 add);
148}
149
150
151/**
152 * Task used to run `external-ip` to get our external IPv4
153 * address and pass it to NATed clients if possible.
154 *
155 * @param cls NULL
156 */
157static void
158run_external_ip (void *cls);
159
160
161/**
162 * We learn our current external IP address. If it changed,
163 * notify all of our applicable clients. Also re-schedule
164 * #run_external_ip with an appropriate timeout.
165 *
166 * @param cls NULL
167 * @param addr the address, NULL on errors
168 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
169 */
170static void
171handle_external_ip (void *cls,
172 const struct in_addr *addr,
173 enum GNUNET_NAT_StatusCode result)
174{
175 char buf[INET_ADDRSTRLEN];
176
177 probe_external_ip_op = NULL;
178 GNUNET_SCHEDULER_cancel (probe_external_ip_task);
179 probe_external_ip_task
180 = GNUNET_SCHEDULER_add_delayed ((NULL == addr)
181 ? EXTERN_IP_RETRY_FAILURE
182 : EXTERN_IP_RETRY_SUCCESS,
183 &run_external_ip,
184 NULL);
185 switch (result)
186 {
187 case GNUNET_NAT_ERROR_SUCCESS:
188 if (addr->s_addr == mini_external_ipv4.s_addr)
189 return; /* not change */
190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191 "Our external IP is now %s\n",
192 inet_ntop (AF_INET,
193 addr,
194 buf,
195 sizeof (buf)));
196 if (0 != mini_external_ipv4.s_addr)
197 notify_monitors_external_ipv4_change (GNUNET_NO,
198 &mini_external_ipv4);
199 mini_external_ipv4 = *addr;
200 notify_monitors_external_ipv4_change (GNUNET_YES,
201 &mini_external_ipv4);
202 break;
203 default:
204 if (0 != mini_external_ipv4.s_addr)
205 notify_monitors_external_ipv4_change (GNUNET_NO,
206 &mini_external_ipv4);
207 mini_external_ipv4.s_addr = 0;
208 break;
209 }
210}
211
212
213/**
214 * Task used to run `external-ip` to get our external IPv4
215 * address and pass it to NATed clients if possible.
216 *
217 * @param cls NULL
218 */
219static void
220run_external_ip (void *cls)
221{
222 probe_external_ip_task
223 = GNUNET_SCHEDULER_add_delayed (EXTERN_IP_RETRY_TIMEOUT,
224 &run_external_ip,
225 NULL);
226 if (NULL != probe_external_ip_op)
227 {
228 GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
229 probe_external_ip_op = NULL;
230 }
231 probe_external_ip_op
232 = GNUNET_NAT_mini_get_external_ipv4_ (&handle_external_ip,
233 NULL);
234}
235
236
237/**
238 * We have changed our opinion about being NATed in the first
239 * place. Adapt our probing.
240 *
241 * @param have_nat #GNUNET_YES if we believe we are behind NAT
242 */
243void
244GN_nat_status_changed (int have_nat)
245{
246 if (GNUNET_YES != enable_upnp)
247 return;
248 if ( (GNUNET_YES == have_nat) &&
249 (NULL == probe_external_ip_task) &&
250 (NULL == probe_external_ip_op) )
251 {
252 probe_external_ip_task
253 = GNUNET_SCHEDULER_add_now (&run_external_ip,
254 NULL);
255 return;
256 }
257 if (GNUNET_NO == have_nat)
258 {
259 if (NULL != probe_external_ip_task)
260 {
261 GNUNET_SCHEDULER_cancel (probe_external_ip_task);
262 probe_external_ip_task = NULL;
263 }
264 if (NULL != probe_external_ip_op)
265 {
266 GNUNET_NAT_mini_get_external_ipv4_cancel_ (probe_external_ip_op);
267 probe_external_ip_op = NULL;
268 }
269 }
270}
271
272
273/**
274 * Start monitoring external IPv4 addresses.
275 *
276 * @param cb function to call on changes
277 * @param cb_cls closure for @a cb
278 * @return handle to cancel
279 */
280struct GN_ExternalIPMonitor *
281GN_external_ipv4_monitor_start (GN_NotifyExternalIPv4Change cb,
282 void *cb_cls)
283{
284 struct GN_ExternalIPMonitor *mon;
285
286 mon = GNUNET_new (struct GN_ExternalIPMonitor);
287 mon->cb = cb;
288 mon->cb_cls = cb_cls;
289 GNUNET_CONTAINER_DLL_insert (mon_head,
290 mon_tail,
291 mon);
292 if (0 != mini_external_ipv4.s_addr)
293 cb (cb_cls,
294 &mini_external_ipv4,
295 GNUNET_YES);
296 return mon;
297}
298
299
300/**
301 * Stop calling monitor.
302 *
303 * @param mon monitor to call
304 */
305void
306GN_external_ipv4_monitor_stop (struct GN_ExternalIPMonitor *mon)
307{
308 GNUNET_CONTAINER_DLL_remove (mon_head,
309 mon_tail,
310 mon);
311 GNUNET_free (mon);
312}
313
314/* end of gnunet-service-nat_externalip.c */
diff --git a/src/nat/gnunet-service-nat_externalip.h b/src/nat/gnunet-service-nat_externalip.h
new file mode 100644
index 000000000..31910555d
--- /dev/null
+++ b/src/nat/gnunet-service-nat_externalip.h
@@ -0,0 +1,92 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2015, 2016, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * Code to figure out what our external IPv4 address(es) might
22 * be (external IPv4s are what is seen on the rest of the Internet).
23 *
24 * This can be implemented using different methods, and we allow
25 * the main service to be notified about changes to what we believe
26 * is our external IPv4 address.
27 *
28 * Note that this is explicitly only about NATed systems; if one
29 * of our network interfaces has a global IP address this does
30 * not count as "external".
31 *
32 * @file nat/gnunet-service-nat_externalip.h
33 * @brief Functions for monitoring external IPv4 addresses
34 * @author Christian Grothoff
35 */
36#ifndef GNUNET_SERVICE_NAT_EXTERNALIP_H
37#define GNUNET_SERVICE_NAT_EXTERNALIP_H
38
39#include "platform.h"
40
41
42/**
43 * We have changed our opinion about being NATed in the first
44 * place. Adapt our probing.
45 *
46 * @param have_nat #GNUNET_YES if we believe we are behind NAT
47 */
48void
49GN_nat_status_changed (int have_nat);
50
51
52/**
53 * Function we call when we believe our external IPv4 address changed.
54 *
55 * @param cls closure
56 * @param ip address to add/remove
57 * @param add_remove #GNUNET_YES to add, #GNUNET_NO to remove
58 */
59typedef void
60(*GN_NotifyExternalIPv4Change)(void *cls,
61 const struct in_addr *ip,
62 int add_remove);
63
64
65/**
66 * Handle to monitor for external IP changes.
67 */
68struct GN_ExternalIPMonitor;
69
70
71/**
72 * Start monitoring external IPv4 addresses.
73 *
74 * @param cb function to call on changes
75 * @param cb_cls closure for @a cb
76 * @return handle to cancel
77 */
78struct GN_ExternalIPMonitor *
79GN_external_ipv4_monitor_start (GN_NotifyExternalIPv4Change cb,
80 void *cb_cls);
81
82
83/**
84 * Stop calling monitor.
85 *
86 * @param mon monitor to call
87 */
88void
89GN_external_ipv4_monitor_stop (struct GN_ExternalIPMonitor *mon);
90
91
92#endif
diff --git a/src/nat/gnunet-service-nat_helper.c b/src/nat/gnunet-service-nat_helper.c
index 7e5051d65..e91f63beb 100644
--- a/src/nat/gnunet-service-nat_helper.c
+++ b/src/nat/gnunet-service-nat_helper.c
@@ -49,7 +49,7 @@ struct HelperContext
49 * Closure for @e cb. 49 * Closure for @e cb.
50 */ 50 */
51 void *cb_cls; 51 void *cb_cls;
52 52
53 /** 53 /**
54 * How long do we wait for restarting a crashed gnunet-helper-nat-server? 54 * How long do we wait for restarting a crashed gnunet-helper-nat-server?
55 */ 55 */
@@ -126,7 +126,7 @@ nat_server_read (void *cls)
126 memset (mybuf, 126 memset (mybuf,
127 0, 127 0,
128 sizeof (mybuf)); 128 sizeof (mybuf));
129 bytes 129 bytes
130 = GNUNET_DISK_file_read (h->server_stdout_handle, 130 = GNUNET_DISK_file_read (h->server_stdout_handle,
131 mybuf, 131 mybuf,
132 sizeof (mybuf)); 132 sizeof (mybuf));
@@ -134,7 +134,7 @@ nat_server_read (void *cls)
134 { 134 {
135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
136 "Finished reading from server stdout with code: %d\n", 136 "Finished reading from server stdout with code: %d\n",
137 bytes); 137 (int) bytes);
138 if (0 != GNUNET_OS_process_kill (h->server_proc, 138 if (0 != GNUNET_OS_process_kill (h->server_proc,
139 GNUNET_TERM_SIG)) 139 GNUNET_TERM_SIG))
140 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, 140 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
@@ -185,7 +185,7 @@ nat_server_read (void *cls)
185 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 185 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
186 _("gnunet-helper-nat-server generated malformed address `%s'\n"), 186 _("gnunet-helper-nat-server generated malformed address `%s'\n"),
187 mybuf); 187 mybuf);
188 h->server_read_task 188 h->server_read_task
189 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 189 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
190 h->server_stdout_handle, 190 h->server_stdout_handle,
191 &nat_server_read, 191 &nat_server_read,
@@ -199,7 +199,7 @@ nat_server_read (void *cls)
199 port); 199 port);
200 h->cb (h->cb_cls, 200 h->cb (h->cb_cls,
201 &sin_addr); 201 &sin_addr);
202 h->server_read_task 202 h->server_read_task
203 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 203 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
204 h->server_stdout_handle, 204 h->server_stdout_handle,
205 &nat_server_read, 205 &nat_server_read,
@@ -219,9 +219,9 @@ restart_nat_server (void *cls)
219 struct HelperContext *h = cls; 219 struct HelperContext *h = cls;
220 char *binary; 220 char *binary;
221 char ia[INET_ADDRSTRLEN]; 221 char ia[INET_ADDRSTRLEN];
222 222
223 h->server_read_task = NULL; 223 h->server_read_task = NULL;
224 h->server_stdout 224 h->server_stdout
225 = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, 225 = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES,
226 GNUNET_NO, GNUNET_YES); 226 GNUNET_NO, GNUNET_YES);
227 if (NULL == h->server_stdout) 227 if (NULL == h->server_stdout)
@@ -243,7 +243,7 @@ restart_nat_server (void *cls)
243 /* Start the server process */ 243 /* Start the server process */
244 binary 244 binary
245 = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); 245 = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
246 h->server_proc 246 h->server_proc
247 = GNUNET_OS_start_process (GNUNET_NO, 247 = GNUNET_OS_start_process (GNUNET_NO,
248 0, 248 0,
249 NULL, 249 NULL,
@@ -267,10 +267,10 @@ restart_nat_server (void *cls)
267 /* Close the write end of the read pipe */ 267 /* Close the write end of the read pipe */
268 GNUNET_DISK_pipe_close_end (h->server_stdout, 268 GNUNET_DISK_pipe_close_end (h->server_stdout,
269 GNUNET_DISK_PIPE_END_WRITE); 269 GNUNET_DISK_PIPE_END_WRITE);
270 h->server_stdout_handle 270 h->server_stdout_handle
271 = GNUNET_DISK_pipe_handle (h->server_stdout, 271 = GNUNET_DISK_pipe_handle (h->server_stdout,
272 GNUNET_DISK_PIPE_END_READ); 272 GNUNET_DISK_PIPE_END_READ);
273 h->server_read_task 273 h->server_read_task
274 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 274 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
275 h->server_stdout_handle, 275 h->server_stdout_handle,
276 &nat_server_read, 276 &nat_server_read,
@@ -316,7 +316,7 @@ GN_start_gnunet_nat_server_ (const struct in_addr *internal_address,
316 */ 316 */
317void 317void
318GN_stop_gnunet_nat_server_ (struct HelperContext *h) 318GN_stop_gnunet_nat_server_ (struct HelperContext *h)
319{ 319{
320 if (NULL != h->server_read_task) 320 if (NULL != h->server_read_task)
321 { 321 {
322 GNUNET_SCHEDULER_cancel (h->server_read_task); 322 GNUNET_SCHEDULER_cancel (h->server_read_task);
@@ -384,13 +384,13 @@ GN_request_connection_reversal (const struct in_addr *internal_address,
384 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 384 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
385 "inet_ntop"); 385 "inet_ntop");
386 return GNUNET_SYSERR; 386 return GNUNET_SYSERR;
387 } 387 }
388 GNUNET_snprintf (port_as_string, 388 GNUNET_snprintf (port_as_string,
389 sizeof (port_as_string), 389 sizeof (port_as_string),
390 "%d", 390 "%d",
391 internal_port); 391 internal_port);
392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
393 _("Running gnunet-helper-nat-client %s %s %u\n"), 393 "Running gnunet-helper-nat-client %s %s %u\n",
394 intv4, 394 intv4,
395 remv4, 395 remv4,
396 internal_port); 396 internal_port);
diff --git a/src/nat/gnunet-service-nat_mini.h b/src/nat/gnunet-service-nat_mini.h
index 2c0dd3445..8a7af9bf1 100644
--- a/src/nat/gnunet-service-nat_mini.h
+++ b/src/nat/gnunet-service-nat_mini.h
@@ -55,7 +55,7 @@ struct GNUNET_NAT_ExternalHandle;
55 */ 55 */
56struct GNUNET_NAT_ExternalHandle * 56struct GNUNET_NAT_ExternalHandle *
57GNUNET_NAT_mini_get_external_ipv4_ (GNUNET_NAT_IPCallback cb, 57GNUNET_NAT_mini_get_external_ipv4_ (GNUNET_NAT_IPCallback cb,
58 void *cb_cls); 58 void *cb_cls);
59 59
60 60
61/** 61/**
diff --git a/src/nat/nat.c b/src/nat/nat.c
deleted file mode 100644
index 08dd5dd1e..000000000
--- a/src/nat/nat.c
+++ /dev/null
@@ -1,2054 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file nat/nat.c
23 * @brief Library handling UPnP and NAT-PMP port forwarding and
24 * external IP address retrieval
25 * @author Milan Bouchet-Valat
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_resolver_service.h"
31#include "gnunet_nat_lib.h"
32#include "nat.h"
33
34#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
35
36/**
37 * How often do we scan for changes in our IP address from our local
38 * interfaces?
39 */
40#define IFC_SCAN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
41
42/**
43 * How often do we scan for changes in how our hostname resolves?
44 */
45#define HOSTNAME_DNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 20)
46
47
48/**
49 * How often do we scan for changes in how our external (dyndns) hostname resolves?
50 */
51#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7)
52
53/**
54 * How long until we give up trying to resolve our own hostname?
55 */
56#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
57
58
59/**
60 * How often do we check a STUN server ?
61 */
62#define STUN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
63
64
65/**
66 * Where did the given local address originate from?
67 * To be used for debugging as well as in the future
68 * to remove all addresses from a certain source when
69 * we reevaluate the source.
70 */
71enum LocalAddressSource
72{
73 /**
74 * Address was obtained by DNS resolution of the external hostname
75 * given in the configuration (i.e. hole-punched DynDNS setup).
76 */
77 LAL_EXTERNAL_IP,
78
79 /**
80 * Address was obtained by an external STUN server
81 */
82 LAL_EXTERNAL_STUN_IP,
83
84 /**
85 * Address was obtained by DNS resolution of the external hostname
86 * given in the configuration (i.e. hole-punched DynDNS setup)
87 * during the previous iteration (see #3213).
88 */
89 LAL_EXTERNAL_IP_OLD,
90
91 /**
92 * Address was obtained by looking up our own hostname in DNS.
93 */
94 LAL_HOSTNAME_DNS,
95
96 /**
97 * Address was obtained by scanning our hosts's network interfaces
98 * and taking their address (no DNS involved).
99 */
100 LAL_INTERFACE_ADDRESS,
101
102 /**
103 * Addresses we were explicitly bound to.
104 */
105 LAL_BINDTO_ADDRESS,
106
107 /**
108 * Addresses from UPnP or PMP
109 */
110 LAL_UPNP,
111
112 /**
113 * End of the list.
114 */
115 LAL_END
116};
117
118
119/**
120 * List of local addresses that we currently deem valid. Actual
121 * struct is followed by the 'struct sockaddr'. Note that the code
122 * intentionally makes no attempt to ensure that a particular address
123 * is only listed once (especially since it may come from different
124 * sources, and the source is an "internal" construct).
125 */
126struct LocalAddressList
127{
128 /**
129 * This is a linked list.
130 */
131 struct LocalAddressList *next;
132
133 /**
134 * Previous entry.
135 */
136 struct LocalAddressList *prev;
137
138 /**
139 * Number of bytes of address that follow.
140 */
141 socklen_t addrlen;
142
143 /**
144 * Origin of the local address.
145 */
146 enum LocalAddressSource source;
147};
148
149
150/**
151 * Handle for miniupnp-based NAT traversal actions.
152 */
153struct MiniList
154{
155
156 /**
157 * Doubly-linked list.
158 */
159 struct MiniList *next;
160
161 /**
162 * Doubly-linked list.
163 */
164 struct MiniList *prev;
165
166 /**
167 * Handle to mini-action.
168 */
169 struct GNUNET_NAT_MiniHandle *mini;
170
171 /**
172 * Local port number that was mapped.
173 */
174 uint16_t port;
175
176};
177
178
179/**
180 * List of STUN servers
181 */
182struct StunServerList
183{
184
185 /**
186 * Doubly-linked list.
187 */
188 struct StunServerList *next;
189
190 /**
191 * Doubly-linked list.
192 */
193 struct StunServerList *prev;
194
195 /**
196 * Address
197 */
198 char * address;
199
200 /**
201 * Server Port
202 */
203 uint16_t port;
204
205};
206
207
208/**
209 * Handle for active NAT registrations.
210 */
211struct GNUNET_NAT_Handle
212{
213
214 /**
215 * Configuration to use.
216 */
217 const struct GNUNET_CONFIGURATION_Handle *cfg;
218
219 /**
220 * Function to call when we learn about a new address.
221 */
222 GNUNET_NAT_AddressCallback address_callback;
223
224 /**
225 * Function to call when we notice another peer asking for
226 * connection reversal.
227 */
228 GNUNET_NAT_ReversalCallback reversal_callback;
229
230 /**
231 * Closure for callbacks (@e address_callback and @e reversal_callback)
232 */
233 void *callback_cls;
234
235 /**
236 * Handle for (DYN)DNS lookup of our external IP.
237 */
238 struct GNUNET_RESOLVER_RequestHandle *ext_dns;
239
240 /**
241 * Handle for request of hostname resolution, non-NULL if pending.
242 */
243 struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
244
245 /**
246 * stdout pipe handle for the gnunet-helper-nat-server process
247 */
248 struct GNUNET_DISK_PipeHandle *server_stdout;
249
250 /**
251 * stdout file handle (for reading) for the gnunet-helper-nat-server process
252 */
253 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
254
255 /**
256 * Linked list of currently valid addresses (head).
257 */
258 struct LocalAddressList *lal_head;
259
260 /**
261 * Linked list of currently valid addresses (tail).
262 */
263 struct LocalAddressList *lal_tail;
264
265 /**
266 * How long do we wait for restarting a crashed gnunet-helper-nat-server?
267 */
268 struct GNUNET_TIME_Relative server_retry_delay;
269
270 /**
271 * ID of select gnunet-helper-nat-server stdout read task
272 */
273 struct GNUNET_SCHEDULER_Task *server_read_task;
274
275 /**
276 * ID of interface IP-scan task
277 */
278 struct GNUNET_SCHEDULER_Task *ifc_task;
279
280 /**
281 * ID of hostname DNS lookup task
282 */
283 struct GNUNET_SCHEDULER_Task *hostname_task;
284
285 /**
286 * ID of DynDNS lookup task
287 */
288 struct GNUNET_SCHEDULER_Task *dns_task;
289
290 /**
291 * Active STUN request, if any.
292 */
293 struct GNUNET_NAT_STUN_Handle *stun_request;
294
295 /**
296 * How often do we scan for changes in our IP address from our local
297 * interfaces?
298 */
299 struct GNUNET_TIME_Relative ifc_scan_frequency;
300
301 /**
302 * How often do we scan for changes in how our hostname resolves?
303 */
304 struct GNUNET_TIME_Relative hostname_dns_frequency;
305
306 /**
307 * How often do we scan for changes in how our external (dyndns) hostname resolves?
308 */
309 struct GNUNET_TIME_Relative dyndns_frequency;
310
311 /**
312 * The process id of the server process (if behind NAT)
313 */
314 struct GNUNET_OS_Process *server_proc;
315
316 /**
317 * LAN address as passed by the caller (array).
318 */
319 struct sockaddr **local_addrs;
320
321 /**
322 * Length of the @e local_addrs.
323 */
324 socklen_t *local_addrlens;
325
326 /**
327 * List of handles for UPnP-traversal, one per local port (if
328 * not IPv6-only).
329 */
330 struct MiniList *mini_head;
331
332 /**
333 * List of handles for UPnP-traversal, one per local port (if
334 * not IPv6-only).
335 */
336 struct MiniList *mini_tail;
337
338 /**
339 * Number of entries in 'local_addrs' array.
340 */
341 unsigned int num_local_addrs;
342
343 /**
344 * Our external address (according to config, UPnP may disagree...),
345 * in dotted decimal notation, IPv4-only. Or NULL if not known.
346 */
347 char *external_address;
348
349 /**
350 * Presumably our internal address (according to config)
351 */
352 char *internal_address;
353
354 /**
355 * Is this transport configured to be behind a NAT?
356 */
357 int behind_nat;
358
359 /**
360 * Has the NAT been punched? (according to config)
361 */
362 int nat_punched;
363
364 /**
365 * Is this transport configured to allow connections to NAT'd peers?
366 */
367 int enable_nat_client;
368
369 /**
370 * Should we run the gnunet-helper-nat-server?
371 */
372 int enable_nat_server;
373
374 /**
375 * Are we allowed to try UPnP/PMP for NAT traversal?
376 */
377 int enable_upnp;
378
379 /**
380 * Should we use local addresses (loopback)? (according to config)
381 */
382 int use_localaddresses;
383
384 /**
385 * Should we return local addresses to clients
386 */
387 int return_localaddress;
388
389 /**
390 * Should we do a DNS lookup of our hostname to find out our own IP?
391 */
392 int use_hostname;
393
394 /**
395 * Is using IPv6 disabled?
396 */
397 int disable_ipv6;
398
399 /**
400 * Is this TCP or UDP?
401 */
402 int is_tcp;
403
404 /**
405 * Port we advertise to the outside.
406 */
407 uint16_t adv_port;
408
409 /**
410 * Should we use STUN ?
411 */
412 int use_stun;
413
414 /**
415 * How often should we check STUN ?
416 */
417 struct GNUNET_TIME_Relative stun_frequency;
418
419 /**
420 * STUN socket
421 */
422 struct GNUNET_NETWORK_Handle* socket;
423
424 /*
425 * Am I waiting for a STUN response ?
426 */
427 int waiting_stun;
428
429 /**
430 * STUN request task
431 */
432 struct GNUNET_SCHEDULER_Task *stun_task;
433
434 /**
435 * Head of List of STUN servers
436 */
437 struct StunServerList *stun_servers_head;
438
439 /**
440 * Tail of List of STUN servers
441 */
442 struct StunServerList *stun_servers_tail;
443
444 /**
445 * Actual STUN Server
446 */
447 struct StunServerList *actual_stun_server;
448
449};
450
451
452/**
453 * Try to start the gnunet-helper-nat-server (if it is not
454 * already running).
455 *
456 * @param h handle to NAT
457 */
458static void
459start_gnunet_nat_server (struct GNUNET_NAT_Handle *h);
460
461
462/**
463 * Remove all addresses from the list of 'local' addresses
464 * that originated from the given source.
465 *
466 * @param h handle to NAT
467 * @param src source that identifies addresses to remove
468 */
469static void
470remove_from_address_list_by_source (struct GNUNET_NAT_Handle *h,
471 enum LocalAddressSource src)
472{
473 struct LocalAddressList *pos;
474 struct LocalAddressList *next;
475
476 next = h->lal_head;
477 while (NULL != (pos = next))
478 {
479 next = pos->next;
480 if (pos->source != src)
481 continue;
482 GNUNET_CONTAINER_DLL_remove (h->lal_head,
483 h->lal_tail,
484 pos);
485 if (NULL != h->address_callback)
486 h->address_callback (h->callback_cls,
487 GNUNET_NO,
488 (const struct sockaddr *) &pos[1],
489 pos->addrlen);
490 GNUNET_free (pos);
491 }
492}
493
494
495/**
496 * Add the given address to the list of 'local' addresses, thereby
497 * making it a 'legal' address for this peer to have.
498 *
499 * @param h handle to NAT
500 * @param src where did the local address originate from?
501 * @param arg the address, some `struct sockaddr`
502 * @param arg_size number of bytes in @a arg
503 */
504static void
505add_to_address_list_as_is (struct GNUNET_NAT_Handle *h,
506 enum LocalAddressSource src,
507 const struct sockaddr *arg,
508 socklen_t arg_size)
509{
510 struct LocalAddressList *lal;
511
512 lal = GNUNET_malloc (sizeof (struct LocalAddressList) + arg_size);
513 GNUNET_memcpy (&lal[1], arg, arg_size);
514 lal->addrlen = arg_size;
515 lal->source = src;
516 GNUNET_CONTAINER_DLL_insert (h->lal_head,
517 h->lal_tail,
518 lal);
519 LOG (GNUNET_ERROR_TYPE_DEBUG,
520 "Adding address `%s' from source %d\n",
521 GNUNET_a2s (arg, arg_size),
522 src);
523 if (NULL != h->address_callback)
524 h->address_callback (h->callback_cls,
525 GNUNET_YES,
526 arg,
527 arg_size);
528}
529
530
531/**
532 * Add the given address to the list of 'local' addresses, thereby
533 * making it a 'legal' address for this peer to have. Set the
534 * port number in the process to the advertised port and possibly
535 * also to zero (if we have the gnunet-helper-nat-server).
536 *
537 * @param h handle to NAT
538 * @param src where did the local address originate from?
539 * @param arg the address, some `struct sockaddr`
540 * @param arg_size number of bytes in @a arg
541 */
542static void
543add_to_address_list (struct GNUNET_NAT_Handle *h,
544 enum LocalAddressSource src,
545 const struct sockaddr *arg,
546 socklen_t arg_size)
547{
548 struct sockaddr_in s4;
549 const struct sockaddr_in *in4;
550 struct sockaddr_in6 s6;
551 const struct sockaddr_in6 *in6;
552
553 if (arg_size == sizeof (struct sockaddr_in))
554 {
555 in4 = (const struct sockaddr_in *) arg;
556 s4 = *in4;
557 s4.sin_port = htons (h->adv_port);
558 add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4,
559 sizeof (struct sockaddr_in));
560 if (GNUNET_YES == h->enable_nat_server)
561 {
562 /* also add with PORT = 0 to indicate NAT server is enabled */
563 s4.sin_port = htons (0);
564 add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4,
565 sizeof (struct sockaddr_in));
566 }
567 }
568 else if (arg_size == sizeof (struct sockaddr_in6))
569 {
570 if (GNUNET_YES != h->disable_ipv6)
571 {
572 in6 = (const struct sockaddr_in6 *) arg;
573 s6 = *in6;
574 s6.sin6_port = htons (h->adv_port);
575 add_to_address_list_as_is (h, src, (const struct sockaddr *) &s6,
576 sizeof (struct sockaddr_in6));
577 }
578 }
579 else
580 {
581 GNUNET_assert (0);
582 }
583}
584
585
586/**
587 * Add the given IP address to the list of 'local' addresses, thereby
588 * making it a 'legal' address for this peer to have.
589 *
590 * @param h handle to NAT
591 * @param src where did the local address originate from?
592 * @param addr the address, some `struct in_addr` or `struct in6_addr`
593 * @param addrlen number of bytes in addr
594 */
595static void
596add_ip_to_address_list (struct GNUNET_NAT_Handle *h,
597 enum LocalAddressSource src,
598 const void *addr,
599 socklen_t addrlen)
600{
601 struct sockaddr_in s4;
602 const struct in_addr *in4;
603 struct sockaddr_in6 s6;
604 const struct in6_addr *in6;
605
606 if (addrlen == sizeof (struct in_addr))
607 {
608 in4 = (const struct in_addr *) addr;
609 memset (&s4, 0, sizeof (s4));
610 s4.sin_family = AF_INET;
611 s4.sin_port = 0;
612#if HAVE_SOCKADDR_IN_SIN_LEN
613 s4.sin_len = (u_char) sizeof (struct sockaddr_in);
614#endif
615 s4.sin_addr = *in4;
616 add_to_address_list (h, src, (const struct sockaddr *) &s4,
617 sizeof (struct sockaddr_in));
618 if (GNUNET_YES == h->enable_nat_server)
619 {
620 /* also add with PORT = 0 to indicate NAT server is enabled */
621 s4.sin_port = htons (0);
622 add_to_address_list (h, src, (const struct sockaddr *) &s4,
623 sizeof (struct sockaddr_in));
624
625 }
626 }
627 else if (addrlen == sizeof (struct in6_addr))
628 {
629 if (GNUNET_YES != h->disable_ipv6)
630 {
631 in6 = (const struct in6_addr *) addr;
632 memset (&s6, 0, sizeof (s6));
633 s6.sin6_family = AF_INET6;
634 s6.sin6_port = htons (h->adv_port);
635#if HAVE_SOCKADDR_IN_SIN_LEN
636 s6.sin6_len = (u_char) sizeof (struct sockaddr_in6);
637#endif
638 s6.sin6_addr = *in6;
639 add_to_address_list (h, src, (const struct sockaddr *) &s6,
640 sizeof (struct sockaddr_in6));
641 }
642 }
643 else
644 {
645 GNUNET_assert (0);
646 }
647}
648
649
650/**
651 * Task to do DNS lookup on our external hostname to
652 * get DynDNS-IP addresses.
653 *
654 * @param cls the NAT handle
655 */
656static void
657resolve_dns (void *cls);
658
659
660/**
661 * Our (external) hostname was resolved and the configuration says that
662 * the NAT was hole-punched.
663 *
664 * @param cls the `struct GNUNET_NAT_Handle`
665 * @param addr NULL on error, otherwise result of DNS lookup
666 * @param addrlen number of bytes in @a addr
667 */
668static void
669process_external_ip (void *cls,
670 const struct sockaddr *addr,
671 socklen_t addrlen)
672{
673 struct GNUNET_NAT_Handle *h = cls;
674 struct in_addr dummy;
675
676 if (NULL == addr)
677 {
678 h->ext_dns = NULL;
679 /* Current iteration is over, remove 'old' IPs now */
680 LOG (GNUNET_ERROR_TYPE_DEBUG,
681 "Purging old IPs for external address\n");
682 remove_from_address_list_by_source (h,
683 LAL_EXTERNAL_IP_OLD);
684 if (1 == inet_pton (AF_INET,
685 h->external_address,
686 &dummy))
687 {
688 LOG (GNUNET_ERROR_TYPE_DEBUG,
689 "Got numeric IP for external address, not repeating lookup\n");
690 return; /* repated lookup pointless: was numeric! */
691 }
692 h->dns_task =
693 GNUNET_SCHEDULER_add_delayed (h->dyndns_frequency,
694 &resolve_dns, h);
695 return;
696 }
697 LOG (GNUNET_ERROR_TYPE_DEBUG,
698 "Got IP `%s' for external address `%s'\n",
699 GNUNET_a2s (addr,
700 addrlen),
701 h->external_address);
702 add_to_address_list (h,
703 LAL_EXTERNAL_IP,
704 addr,
705 addrlen);
706}
707
708
709/**
710 * Task to do a lookup on our hostname for IP addresses.
711 *
712 * @param cls the NAT handle
713 */
714static void
715resolve_hostname (void *cls);
716
717
718/**
719 * Function called by the resolver for each address obtained from DNS
720 * for our own hostname. Add the addresses to the list of our IP
721 * addresses.
722 *
723 * @param cls closure
724 * @param addr one of the addresses of the host, NULL for the last address
725 * @param addrlen length of the @a addr
726 */
727static void
728process_hostname_ip (void *cls,
729 const struct sockaddr *addr,
730 socklen_t addrlen)
731{
732 struct GNUNET_NAT_Handle *h = cls;
733
734 if (NULL == addr)
735 {
736 h->hostname_dns = NULL;
737 h->hostname_task =
738 GNUNET_SCHEDULER_add_delayed (h->hostname_dns_frequency,
739 &resolve_hostname,
740 h);
741 return;
742 }
743 add_to_address_list (h,
744 LAL_HOSTNAME_DNS,
745 addr,
746 addrlen);
747}
748
749
750/**
751 * Length of the interface names returned from os_network.c.
752 * (in that file, hardcoded at 11).
753 */
754#define IF_NAME_LEN 11
755
756
757/**
758 * Add the IP of our network interface to the list of
759 * our IP addresses.
760 *
761 * @param cls the `struct GNUNET_NAT_Handle`
762 * @param name name of the interface
763 * @param isDefault do we think this may be our default interface
764 * @param addr address of the interface
765 * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
766 * @param netmask the network mask (can be NULL for unknown or unassigned))
767 * @param addrlen number of bytes in @a addr and @a broadcast_addr
768 * @return #GNUNET_OK to continue iterating
769 */
770static int
771process_interfaces (void *cls,
772 const char *name,
773 int isDefault,
774 const struct sockaddr *addr,
775 const struct sockaddr *broadcast_addr,
776 const struct sockaddr *netmask,
777 socklen_t addrlen)
778{
779 const static struct in6_addr any6 = IN6ADDR_ANY_INIT;
780 struct GNUNET_NAT_Handle *h = cls;
781 const struct sockaddr_in *s4;
782 const struct sockaddr_in6 *s6;
783 const void *ip;
784 char buf[INET6_ADDRSTRLEN];
785 unsigned int i;
786 int have_any;
787 char *tun_if;
788
789 /* skip virtual interfaces created by GNUnet-vpn */
790 if (GNUNET_OK ==
791 GNUNET_CONFIGURATION_get_value_string (h->cfg,
792 "vpn",
793 "IFNAME",
794 &tun_if))
795 {
796 if (0 == strncasecmp (name,
797 tun_if,
798 IF_NAME_LEN))
799 {
800 GNUNET_free (tun_if);
801 return GNUNET_OK;
802 }
803 GNUNET_free (tun_if);
804 }
805 /* skip virtual interfaces created by GNUnet-dns */
806 if (GNUNET_OK ==
807 GNUNET_CONFIGURATION_get_value_string (h->cfg,
808 "dns",
809 "IFNAME",
810 &tun_if))
811 {
812 if (0 == strncasecmp (name,
813 tun_if,
814 IF_NAME_LEN))
815 {
816 GNUNET_free (tun_if);
817 return GNUNET_OK;
818 }
819 GNUNET_free (tun_if);
820 }
821 /* skip virtual interfaces created by GNUnet-exit */
822 if (GNUNET_OK ==
823 GNUNET_CONFIGURATION_get_value_string (h->cfg,
824 "exit",
825 "TUN_IFNAME",
826 &tun_if))
827 {
828 if (0 == strncasecmp (name,
829 tun_if,
830 IF_NAME_LEN))
831 {
832 GNUNET_free (tun_if);
833 return GNUNET_OK;
834 }
835 GNUNET_free (tun_if);
836 }
837
838 switch (addr->sa_family)
839 {
840 case AF_INET:
841 /* check if we're bound to the "ANY" IP address */
842 have_any = GNUNET_NO;
843 for (i=0;i<h->num_local_addrs;i++)
844 {
845 if (h->local_addrs[i]->sa_family != AF_INET)
846 continue;
847#ifndef INADDR_ANY
848#define INADDR_ANY 0
849#endif
850 if (INADDR_ANY == ((struct sockaddr_in*) h->local_addrs[i])->sin_addr.s_addr)
851 {
852 have_any = GNUNET_YES;
853 break;
854 }
855 }
856 if (GNUNET_NO == have_any)
857 return GNUNET_OK; /* not bound to IP 0.0.0.0 but to specific IP addresses,
858 do not use those from interfaces */
859 s4 = (struct sockaddr_in *) addr;
860 ip = &s4->sin_addr;
861
862 /* Check if address is in 127.0.0.0/8 */
863 uint32_t address = ntohl ((uint32_t) (s4->sin_addr.s_addr));
864 uint32_t value = (address & 0xFF000000) ^ 0x7F000000;
865
866 if ((h->return_localaddress == GNUNET_NO) && (value == 0))
867 {
868 return GNUNET_OK;
869 }
870 if ((GNUNET_YES == h->use_localaddresses) || (value != 0))
871 {
872 add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s4->sin_addr,
873 sizeof (struct in_addr));
874 }
875 break;
876 case AF_INET6:
877 /* check if we're bound to the "ANY" IP address */
878 have_any = GNUNET_NO;
879 for (i=0;i<h->num_local_addrs;i++)
880 {
881 if (h->local_addrs[i]->sa_family != AF_INET6)
882 continue;
883 if (0 == memcmp (&any6,
884 &((struct sockaddr_in6*) h->local_addrs[i])->sin6_addr,
885 sizeof (struct in6_addr)))
886 {
887 have_any = GNUNET_YES;
888 break;
889 }
890 }
891 if (GNUNET_NO == have_any)
892 return GNUNET_OK; /* not bound to "ANY" IP (::0) but to specific IP addresses,
893 do not use those from interfaces */
894
895 s6 = (struct sockaddr_in6 *) addr;
896 if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
897 {
898 /* skip link local addresses */
899 return GNUNET_OK;
900 }
901 if ((h->return_localaddress == GNUNET_NO) &&
902 (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr)))
903 {
904 return GNUNET_OK;
905 }
906 ip = &s6->sin6_addr;
907 if (GNUNET_YES == h->use_localaddresses)
908 {
909 add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s6->sin6_addr,
910 sizeof (struct in6_addr));
911 }
912 break;
913 default:
914 GNUNET_break (0);
915 return GNUNET_OK;
916 }
917 if ( (h->internal_address == NULL) &&
918 (h->server_proc == NULL) &&
919 (h->server_read_task == NULL) &&
920 (GNUNET_YES == isDefault) &&
921 ( (addr->sa_family == AF_INET) ||
922 (addr->sa_family == AF_INET6) ) )
923 {
924 /* no internal address configured, but we found a "default"
925 * interface, try using that as our 'internal' address */
926 h->internal_address =
927 GNUNET_strdup (inet_ntop (addr->sa_family, ip, buf, sizeof (buf)));
928 start_gnunet_nat_server (h);
929 }
930 return GNUNET_OK;
931}
932
933
934/**
935 * Task that restarts the gnunet-helper-nat-server process after a crash
936 * after a certain delay.
937 *
938 * @param cls the `struct GNUNET_NAT_Handle`
939 */
940static void
941restart_nat_server (void *cls)
942{
943 struct GNUNET_NAT_Handle *h = cls;
944
945 h->server_read_task = NULL;
946 start_gnunet_nat_server (h);
947}
948
949
950/**
951 * We have been notified that gnunet-helper-nat-server has written
952 * something to stdout. Handle the output, then reschedule this
953 * function to be called again once more is available.
954 *
955 * @param cls the NAT handle
956 */
957static void
958nat_server_read (void *cls)
959{
960 struct GNUNET_NAT_Handle *h = cls;
961 char mybuf[40];
962 ssize_t bytes;
963 size_t i;
964 int port;
965 const char *port_start;
966 struct sockaddr_in sin_addr;
967
968 h->server_read_task = NULL;
969 memset (mybuf, 0, sizeof (mybuf));
970 bytes =
971 GNUNET_DISK_file_read (h->server_stdout_handle, mybuf, sizeof (mybuf));
972 if (bytes < 1)
973 {
974 LOG (GNUNET_ERROR_TYPE_DEBUG,
975 "Finished reading from server stdout with code: %d\n",
976 bytes);
977 if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG))
978 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill");
979 GNUNET_OS_process_wait (h->server_proc);
980 GNUNET_OS_process_destroy (h->server_proc);
981 h->server_proc = NULL;
982 GNUNET_DISK_pipe_close (h->server_stdout);
983 h->server_stdout = NULL;
984 h->server_stdout_handle = NULL;
985 /* now try to restart it */
986 h->server_retry_delay = GNUNET_TIME_STD_BACKOFF (h->server_retry_delay);
987 h->server_read_task =
988 GNUNET_SCHEDULER_add_delayed (h->server_retry_delay,
989 &restart_nat_server, h);
990 return;
991 }
992
993 port_start = NULL;
994 for (i = 0; i < sizeof (mybuf); i++)
995 {
996 if (mybuf[i] == '\n')
997 {
998 mybuf[i] = '\0';
999 break;
1000 }
1001 if ((mybuf[i] == ':') && (i + 1 < sizeof (mybuf)))
1002 {
1003 mybuf[i] = '\0';
1004 port_start = &mybuf[i + 1];
1005 }
1006 }
1007
1008 /* construct socket address of sender */
1009 memset (&sin_addr, 0, sizeof (sin_addr));
1010 sin_addr.sin_family = AF_INET;
1011#if HAVE_SOCKADDR_IN_SIN_LEN
1012 sin_addr.sin_len = sizeof (sin_addr);
1013#endif
1014 if ((NULL == port_start) || (1 != SSCANF (port_start, "%d", &port)) ||
1015 (-1 == inet_pton (AF_INET, mybuf, &sin_addr.sin_addr)))
1016 {
1017 /* should we restart gnunet-helper-nat-server? */
1018 LOG (GNUNET_ERROR_TYPE_WARNING, "nat",
1019 _("gnunet-helper-nat-server generated malformed address `%s'\n"),
1020 mybuf);
1021 h->server_read_task =
1022 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1023 h->server_stdout_handle,
1024 &nat_server_read, h);
1025 return;
1026 }
1027 sin_addr.sin_port = htons ((uint16_t) port);
1028 LOG (GNUNET_ERROR_TYPE_DEBUG, "gnunet-helper-nat-server read: %s:%d\n", mybuf,
1029 port);
1030 h->reversal_callback (h->callback_cls, (const struct sockaddr *) &sin_addr,
1031 sizeof (sin_addr));
1032 h->server_read_task =
1033 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1034 h->server_stdout_handle,
1035 &nat_server_read,
1036 h);
1037}
1038
1039
1040/**
1041 * Try to start the gnunet-helper-nat-server (if it is not
1042 * already running).
1043 *
1044 * @param h handle to NAT
1045 */
1046static void
1047start_gnunet_nat_server (struct GNUNET_NAT_Handle *h)
1048{
1049 char *binary;
1050
1051 if ((h->behind_nat == GNUNET_YES) && (h->enable_nat_server == GNUNET_YES) &&
1052 (h->internal_address != NULL) &&
1053 (NULL !=
1054 (h->server_stdout =
1055 GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES))))
1056 {
1057 LOG (GNUNET_ERROR_TYPE_DEBUG,
1058 "Starting `%s' at `%s'\n",
1059 "gnunet-helper-nat-server", h->internal_address);
1060 /* Start the server process */
1061 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
1062 h->server_proc =
1063 GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout, NULL,
1064 binary,
1065 "gnunet-helper-nat-server",
1066 h->internal_address, NULL);
1067 GNUNET_free (binary);
1068 if (h->server_proc == NULL)
1069 {
1070 LOG (GNUNET_ERROR_TYPE_WARNING, "nat", _("Failed to start %s\n"),
1071 "gnunet-helper-nat-server");
1072 GNUNET_DISK_pipe_close (h->server_stdout);
1073 h->server_stdout = NULL;
1074 }
1075 else
1076 {
1077 /* Close the write end of the read pipe */
1078 GNUNET_DISK_pipe_close_end (h->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1079 h->server_stdout_handle =
1080 GNUNET_DISK_pipe_handle (h->server_stdout, GNUNET_DISK_PIPE_END_READ);
1081 h->server_read_task =
1082 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1083 h->server_stdout_handle,
1084 &nat_server_read, h);
1085 }
1086 }
1087}
1088
1089
1090/**
1091 * Task to scan the local network interfaces for IP addresses.
1092 *
1093 * @param cls the NAT handle
1094 */
1095static void
1096list_interfaces (void *cls)
1097{
1098 struct GNUNET_NAT_Handle *h = cls;
1099
1100 h->ifc_task = NULL;
1101 remove_from_address_list_by_source (h, LAL_INTERFACE_ADDRESS);
1102 GNUNET_OS_network_interfaces_list (&process_interfaces, h);
1103 h->ifc_task =
1104 GNUNET_SCHEDULER_add_delayed (h->ifc_scan_frequency,
1105 &list_interfaces, h);
1106}
1107
1108
1109/**
1110 * Callback with the result from the STUN request.
1111 *
1112 * @param cls the NAT handle
1113 * @param result the status
1114 */
1115static void
1116stun_request_callback (void *cls,
1117 enum GNUNET_NAT_StatusCode result)
1118{
1119 struct GNUNET_NAT_Handle *h = cls;
1120
1121 h->stun_request = NULL;
1122 switch (result)
1123 {
1124 case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
1125 LOG (GNUNET_ERROR_TYPE_WARNING,
1126 "Failed to transmit STUN request\n");
1127 break;
1128 case GNUNET_NAT_ERROR_NOT_ONLINE:
1129 LOG (GNUNET_ERROR_TYPE_WARNING,
1130 "Failed to resolve STUN server (are we online?)\n");
1131 break;
1132 case GNUNET_NAT_ERROR_SUCCESS:
1133 /* all good, STUN request active */
1134 h->waiting_stun = GNUNET_YES;
1135 break;
1136 default:
1137 /* unexpected error code for STUN */
1138 GNUNET_break (0);
1139 }
1140}
1141
1142
1143/**
1144 * CHECK if is a valid STUN packet sending to GNUNET_NAT_stun_handle_packet().
1145 * It also check if it can handle the packet based on the NAT handler.
1146 * You don't need to call anything else to check if the packet is valid,
1147 *
1148 * @param cls the NAT handle
1149 * @param data packet
1150 * @param len packet length
1151 * @return #GNUNET_NO if it can't decode, #GNUNET_YES if is a packet
1152 */
1153int
1154GNUNET_NAT_is_valid_stun_packet (void *cls,
1155 const void *data,
1156 size_t len)
1157{
1158 struct GNUNET_NAT_Handle *h = cls;
1159 struct sockaddr_in answer;
1160
1161 /* We are not expecting a STUN message */
1162 if (GNUNET_YES != h->waiting_stun)
1163 return GNUNET_NO;
1164
1165 /* We dont have STUN installed */
1166 if (! h->use_stun)
1167 return GNUNET_NO;
1168
1169 /* Empty the answer structure */
1170 memset (&answer,
1171 0,
1172 sizeof(struct sockaddr_in));
1173
1174 /* Lets handle the packet*/
1175 if (GNUNET_NO ==
1176 GNUNET_NAT_stun_handle_packet (data,
1177 len,
1178 &answer))
1179 return GNUNET_NO;
1180
1181 LOG (GNUNET_ERROR_TYPE_INFO,
1182 "STUN server returned %s:%d\n",
1183 inet_ntoa (answer.sin_addr),
1184 ntohs (answer.sin_port));
1185 /* Remove old IPs from previous STUN calls */
1186 remove_from_address_list_by_source (h,
1187 LAL_EXTERNAL_STUN_IP);
1188 /* Add new IP from STUN packet */
1189 add_to_address_list (h,
1190 LAL_EXTERNAL_STUN_IP,
1191 (const struct sockaddr *) &answer,
1192 sizeof (struct sockaddr_in));
1193 h->waiting_stun = GNUNET_NO;
1194 return GNUNET_YES;
1195}
1196
1197
1198/**
1199 * Task to do a STUN request
1200 *
1201 * @param cls the NAT handle
1202 */
1203static void
1204process_stun (void *cls)
1205{
1206 struct GNUNET_NAT_Handle *h = cls;
1207 struct StunServerList *elem = h->actual_stun_server;
1208
1209 h->stun_task = NULL;
1210 /* Make the request */
1211 LOG (GNUNET_ERROR_TYPE_INFO,
1212 "I will request the stun server %s:%i\n",
1213 elem->address,
1214 elem->port);
1215 if (NULL != h->stun_request)
1216 {
1217 GNUNET_NAT_stun_make_request_cancel (h->stun_request);
1218 h->stun_request = NULL;
1219 }
1220 h->waiting_stun = GNUNET_NO;
1221 h->stun_request
1222 = GNUNET_NAT_stun_make_request (elem->address,
1223 elem->port,
1224 h->socket,
1225 &stun_request_callback,
1226 h);
1227 if (NULL == h->stun_request)
1228 {
1229 LOG (GNUNET_ERROR_TYPE_ERROR,
1230 "STUN request to %s:%i failed\n",
1231 elem->address,
1232 elem->port);
1233 }
1234 h->stun_task =
1235 GNUNET_SCHEDULER_add_delayed (h->stun_frequency,
1236 &process_stun,
1237 h);
1238
1239 /* Set actual Server*/
1240 if (NULL != elem->next)
1241 {
1242 h->actual_stun_server = elem->next;
1243 }
1244 else
1245 {
1246 h->actual_stun_server = h->stun_servers_head;
1247 }
1248}
1249
1250
1251/**
1252 * Task to do a lookup on our hostname for IP addresses.
1253 *
1254 * @param cls the NAT handle
1255 */
1256static void
1257resolve_hostname (void *cls)
1258{
1259 struct GNUNET_NAT_Handle *h = cls;
1260
1261 h->hostname_task = NULL;
1262 remove_from_address_list_by_source (h, LAL_HOSTNAME_DNS);
1263 GNUNET_assert (NULL == h->hostname_dns);
1264 h->hostname_dns =
1265 GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC,
1266 HOSTNAME_RESOLVE_TIMEOUT,
1267 &process_hostname_ip,
1268 h);
1269}
1270
1271
1272/**
1273 * Task to do DNS lookup on our external hostname to
1274 * get DynDNS-IP addresses.
1275 *
1276 * @param cls the NAT handle
1277 */
1278static void
1279resolve_dns (void *cls)
1280{
1281 struct GNUNET_NAT_Handle *h = cls;
1282 struct LocalAddressList *pos;
1283
1284 h->dns_task = NULL;
1285 for (pos = h->lal_head; NULL != pos; pos = pos->next)
1286 if (pos->source == LAL_EXTERNAL_IP)
1287 pos->source = LAL_EXTERNAL_IP_OLD;
1288 LOG (GNUNET_ERROR_TYPE_DEBUG,
1289 "Resolving external address `%s'\n",
1290 h->external_address);
1291 GNUNET_assert (NULL == h->ext_dns);
1292 h->ext_dns =
1293 GNUNET_RESOLVER_ip_get (h->external_address,
1294 AF_INET,
1295 GNUNET_TIME_UNIT_MINUTES,
1296 &process_external_ip,
1297 h);
1298}
1299
1300
1301/**
1302 * Add or remove UPnP-mapped addresses.
1303 *
1304 * @param cls the `struct GNUNET_NAT_Handle`
1305 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
1306 * the previous (now invalid) one
1307 * @param addr either the previous or the new public IP address
1308 * @param addrlen actual lenght of @a addr
1309 * @param ret GNUNET_NAT_ERROR_SUCCESS on success, otherwise an error code
1310 */
1311static void
1312upnp_add (void *cls,
1313 int add_remove,
1314 const struct sockaddr *addr,
1315 socklen_t addrlen,
1316 enum GNUNET_NAT_StatusCode ret)
1317{
1318 struct GNUNET_NAT_Handle *h = cls;
1319 struct LocalAddressList *pos;
1320 struct LocalAddressList *next;
1321
1322
1323 if (GNUNET_NAT_ERROR_SUCCESS != ret)
1324 {
1325 /* Error while running upnp client */
1326 LOG (GNUNET_ERROR_TYPE_ERROR,
1327 _("Error while running upnp client:\n"));
1328 //FIXME: convert error code to string
1329 return;
1330 }
1331
1332 if (GNUNET_YES == add_remove)
1333 {
1334 add_to_address_list (h,
1335 LAL_UPNP,
1336 addr,
1337 addrlen);
1338 return;
1339 }
1340 else if (GNUNET_NO == add_remove)
1341 {
1342 /* remove address */
1343 next = h->lal_head;
1344 while (NULL != (pos = next))
1345 {
1346 next = pos->next;
1347 if ((pos->source != LAL_UPNP) || (pos->addrlen != addrlen) ||
1348 (0 != memcmp (&pos[1], addr, addrlen)))
1349 continue;
1350 GNUNET_CONTAINER_DLL_remove (h->lal_head,
1351 h->lal_tail,
1352 pos);
1353 if (NULL != h->address_callback)
1354 h->address_callback (h->callback_cls,
1355 GNUNET_NO,
1356 (const struct sockaddr *) &pos[1],
1357 pos->addrlen);
1358 GNUNET_free (pos);
1359 return; /* only remove once */
1360 }
1361 /* asked to remove address that does not exist */
1362 LOG (GNUNET_ERROR_TYPE_ERROR,
1363 "Asked to remove unkown address `%s'\n",
1364 GNUNET_a2s(addr, addrlen));
1365 GNUNET_break (0);
1366 }
1367 else
1368 {
1369
1370 GNUNET_break (0);
1371 }
1372}
1373
1374
1375/**
1376 * Try to add a port mapping using UPnP.
1377 *
1378 * @param h overall NAT handle
1379 * @param port port to map with UPnP
1380 */
1381static void
1382add_minis (struct GNUNET_NAT_Handle *h,
1383 uint16_t port)
1384{
1385 struct MiniList *ml;
1386
1387 ml = h->mini_head;
1388 while (NULL != ml)
1389 {
1390 if (port == ml->port)
1391 return; /* already got this port */
1392 ml = ml->next;
1393 }
1394
1395 ml = GNUNET_new (struct MiniList);
1396 ml->port = port;
1397 ml->mini = GNUNET_NAT_mini_map_start (port, h->is_tcp, &upnp_add, h);
1398
1399 if (NULL == ml->mini)
1400 {
1401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1402 _("Failed to run upnp client for port %u\n"), ml->port);
1403 GNUNET_free (ml);
1404 return;
1405 }
1406
1407 GNUNET_CONTAINER_DLL_insert (h->mini_head,
1408 h->mini_tail,
1409 ml);
1410}
1411
1412
1413/**
1414 * Task to add addresses from original bind to set of valid addrs.
1415 *
1416 * @param h the NAT handle
1417 */
1418static void
1419add_from_bind (struct GNUNET_NAT_Handle *h)
1420{
1421 static struct in6_addr any = IN6ADDR_ANY_INIT;
1422
1423 unsigned int i;
1424 struct sockaddr *sa;
1425 const struct sockaddr_in *v4;
1426
1427 for (i = 0; i < h->num_local_addrs; i++)
1428 {
1429 sa = h->local_addrs[i];
1430 switch (sa->sa_family)
1431 {
1432 case AF_INET:
1433 if (sizeof (struct sockaddr_in) != h->local_addrlens[i])
1434 {
1435 GNUNET_break (0);
1436 break;
1437 }
1438 v4 = (const struct sockaddr_in *) sa;
1439 if (0 != v4->sin_addr.s_addr)
1440 add_to_address_list (h,
1441 LAL_BINDTO_ADDRESS, sa,
1442 sizeof (struct sockaddr_in));
1443 if (h->enable_upnp)
1444 {
1445 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1446 "Running upnp client for address `%s'\n",
1447 GNUNET_a2s (sa,sizeof (struct sockaddr_in)));
1448 add_minis (h, ntohs (v4->sin_port));
1449 }
1450 break;
1451 case AF_INET6:
1452 if (sizeof (struct sockaddr_in6) != h->local_addrlens[i])
1453 {
1454 GNUNET_break (0);
1455 break;
1456 }
1457 if (0 !=
1458 memcmp (&((const struct sockaddr_in6 *) sa)->sin6_addr,
1459 &any,
1460 sizeof (struct in6_addr)))
1461 add_to_address_list (h,
1462 LAL_BINDTO_ADDRESS,
1463 sa,
1464 sizeof (struct sockaddr_in6));
1465 break;
1466 default:
1467 break;
1468 }
1469 }
1470}
1471
1472
1473/**
1474 * Attempt to enable port redirection and detect public IP address contacting
1475 * UPnP or NAT-PMP routers on the local network. Use addr to specify to which
1476 * of the local host's addresses should the external port be mapped. The port
1477 * is taken from the corresponding sockaddr_in[6] field.
1478 *
1479 * @param cfg configuration to use
1480 * @param is_tcp #GNUNET_YES for TCP, #GNUNET_NO for UDP
1481 * @param adv_port advertised port (port we are either bound to or that our OS
1482 * locally performs redirection from to our bound port).
1483 * @param num_addrs number of addresses in @a addrs
1484 * @param addrs the local addresses packets should be redirected to
1485 * @param addrlens actual lengths of the addresses
1486 * @param address_callback function to call everytime the public IP address changes
1487 * @param reversal_callback function to call if someone wants connection reversal from us
1488 * @param callback_cls closure for callbacks
1489 * @param sock used socket
1490 * @return NULL on error, otherwise handle that can be used to unregister
1491 */
1492struct GNUNET_NAT_Handle *
1493GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
1494 int is_tcp,
1495 uint16_t adv_port,
1496 unsigned int num_addrs,
1497 const struct sockaddr **addrs,
1498 const socklen_t *addrlens,
1499 GNUNET_NAT_AddressCallback address_callback,
1500 GNUNET_NAT_ReversalCallback reversal_callback,
1501 void *callback_cls,
1502 struct GNUNET_NETWORK_Handle *sock)
1503{
1504 struct GNUNET_NAT_Handle *h;
1505 struct in_addr in_addr;
1506 unsigned int i;
1507 char *binary;
1508
1509 LOG (GNUNET_ERROR_TYPE_DEBUG,
1510 "Registered with NAT service at port %u with %u IP bound local addresses\n",
1511 (unsigned int) adv_port, num_addrs);
1512 h = GNUNET_new (struct GNUNET_NAT_Handle);
1513 h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS;
1514 h->cfg = cfg;
1515 h->is_tcp = is_tcp;
1516 h->address_callback = address_callback;
1517 h->reversal_callback = reversal_callback;
1518 h->callback_cls = callback_cls;
1519 h->num_local_addrs = num_addrs;
1520 h->adv_port = adv_port;
1521 if (0 != num_addrs)
1522 {
1523 h->local_addrs = GNUNET_malloc (num_addrs * sizeof (struct sockaddr *));
1524 h->local_addrlens = GNUNET_malloc (num_addrs * sizeof (socklen_t));
1525 for (i = 0; i < num_addrs; i++)
1526 {
1527 GNUNET_assert (addrlens[i] > 0);
1528 GNUNET_assert (addrs[i] != NULL);
1529 h->local_addrlens[i] = addrlens[i];
1530 h->local_addrs[i] = GNUNET_malloc (addrlens[i]);
1531 GNUNET_memcpy (h->local_addrs[i], addrs[i], addrlens[i]);
1532 }
1533 }
1534 if (GNUNET_OK ==
1535 GNUNET_CONFIGURATION_have_value (cfg, "nat", "INTERNAL_ADDRESS"))
1536 {
1537 (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat",
1538 "INTERNAL_ADDRESS",
1539 &h->internal_address);
1540 }
1541 if ((h->internal_address != NULL) &&
1542 (inet_pton (AF_INET, h->internal_address, &in_addr) != 1))
1543 {
1544 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1545 "nat", "INTERNAL_ADDRESS",
1546 _("malformed"));
1547 GNUNET_free (h->internal_address);
1548 h->internal_address = NULL;
1549 }
1550
1551 if (GNUNET_OK ==
1552 GNUNET_CONFIGURATION_have_value (cfg, "nat", "EXTERNAL_ADDRESS"))
1553 {
1554 (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat",
1555 "EXTERNAL_ADDRESS",
1556 &h->external_address);
1557 }
1558 h->behind_nat =
1559 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "BEHIND_NAT");
1560 h->nat_punched =
1561 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "PUNCHED_NAT");
1562 h->enable_nat_client =
1563 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_CLIENT");
1564 h->enable_nat_server =
1565 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_SERVER");
1566 h->enable_upnp =
1567 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_UPNP");
1568 h->use_localaddresses =
1569 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_LOCALADDR");
1570 h->return_localaddress =
1571 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat",
1572 "RETURN_LOCAL_ADDRESSES");
1573
1574 h->use_hostname =
1575 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_HOSTNAME");
1576 h->disable_ipv6 =
1577 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "DISABLEV6");
1578 if (GNUNET_OK !=
1579 GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "DYNDNS_FREQUENCY",
1580 &h->dyndns_frequency))
1581 h->dyndns_frequency = DYNDNS_FREQUENCY;
1582 if (GNUNET_OK !=
1583 GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "IFC_SCAN_FREQUENCY",
1584 &h->ifc_scan_frequency))
1585 h->ifc_scan_frequency = IFC_SCAN_FREQUENCY;
1586 if (GNUNET_OK !=
1587 GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "HOSTNAME_DNS_FREQUENCY",
1588 &h->hostname_dns_frequency))
1589 h->hostname_dns_frequency = HOSTNAME_DNS_FREQUENCY;
1590
1591 if (NULL == reversal_callback)
1592 h->enable_nat_server = GNUNET_NO;
1593
1594 /* Check for UPnP client, disable immediately if not available */
1595 if ( (GNUNET_YES == h->enable_upnp) &&
1596 (GNUNET_SYSERR ==
1597 GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)) )
1598 {
1599 LOG (GNUNET_ERROR_TYPE_ERROR,
1600 _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP \n"));
1601 h->enable_upnp = GNUNET_NO;
1602 }
1603
1604 /* STUN */
1605 h->use_stun =
1606 GNUNET_CONFIGURATION_get_value_yesno (cfg,
1607 "nat",
1608 "USE_STUN");
1609
1610 if (GNUNET_OK !=
1611 GNUNET_CONFIGURATION_get_value_time (cfg,
1612 "nat",
1613 "STUN_FREQUENCY",
1614 &h->stun_frequency))
1615 h->stun_frequency = STUN_FREQUENCY;
1616
1617
1618 /* Check if NAT was hole-punched */
1619 if ((NULL != h->address_callback) &&
1620 (NULL != h->external_address) &&
1621 (GNUNET_YES == h->nat_punched))
1622 {
1623 h->dns_task = GNUNET_SCHEDULER_add_now (&resolve_dns, h);
1624 h->enable_nat_server = GNUNET_NO;
1625 h->enable_upnp = GNUNET_NO;
1626 h->use_stun = GNUNET_NO;
1627 }
1628 else
1629 {
1630 LOG (GNUNET_ERROR_TYPE_DEBUG,
1631 "No external IP address given to add to our list of addresses\n");
1632 }
1633
1634 /* ENABLE STUN ONLY ON UDP */
1635 if( (! is_tcp) &&
1636 (NULL != sock) &&
1637 h->use_stun)
1638 {
1639 char *stun_servers;
1640 size_t urls;
1641 ssize_t pos;
1642 size_t pos_port;
1643
1644 h->socket = sock;
1645 stun_servers = NULL;
1646 /* Lets process the servers*/
1647 (void) GNUNET_CONFIGURATION_get_value_string (cfg,
1648 "nat",
1649 "STUN_SERVERS",
1650 &stun_servers);
1651 urls = 0;
1652 if ( (NULL != stun_servers) &&
1653 (strlen (stun_servers) > 0) )
1654 {
1655 pos_port = 0;
1656 for (pos = strlen (stun_servers) - 1;
1657 pos >= 0;
1658 pos--)
1659 {
1660 if (stun_servers[pos] == ':')
1661 {
1662 pos_port = pos + 1;
1663 stun_servers[pos] = '\0';
1664 continue;
1665 }
1666 if ((stun_servers[pos] == ' ') || (0 == pos))
1667 {
1668 struct StunServerList *ml;
1669
1670 /* Check if we do have a port */
1671 if ((0 == pos_port) || (pos_port <= pos))
1672 {
1673 LOG (GNUNET_ERROR_TYPE_WARNING,
1674 "STUN server format mistake\n");
1675 break;
1676 }
1677 urls++;
1678 ml = GNUNET_new (struct StunServerList);
1679 ml->port = atoi (&stun_servers[pos_port]);
1680
1681 /* Remove trailing space */
1682 if (stun_servers[pos] == ' ')
1683 ml->address = GNUNET_strdup (&stun_servers[pos + 1]);
1684 else
1685 ml->address = GNUNET_strdup (&stun_servers[pos]);
1686 LOG (GNUNET_ERROR_TYPE_DEBUG,
1687 "Found STUN server %s:%i\n",
1688 ml->address,
1689 ml->port);
1690 GNUNET_CONTAINER_DLL_insert (h->stun_servers_head,
1691 h->stun_servers_tail,
1692 ml);
1693 stun_servers[pos] = '\0';
1694 }
1695 }
1696 }
1697 if (0 == urls)
1698 {
1699 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
1700 "nat",
1701 "STUN_SERVERS");
1702 }
1703 else
1704 {
1705 /* Set the actual STUN server*/
1706 h->actual_stun_server = h->stun_servers_head;
1707 }
1708 h->stun_task = GNUNET_SCHEDULER_add_now (&process_stun,
1709 h);
1710 GNUNET_free_non_null (stun_servers);
1711 }
1712
1713
1714 /* Test for SUID binaries */
1715 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
1716 if ( (GNUNET_YES == h->behind_nat) &&
1717 (GNUNET_YES == h->enable_nat_server) &&
1718 (GNUNET_YES !=
1719 GNUNET_OS_check_helper_binary (binary,
1720 GNUNET_YES,
1721 "-d 127.0.0.1" )))
1722 {
1723 // use localhost as source for that one udp-port, ok for testing
1724 h->enable_nat_server = GNUNET_NO;
1725 LOG (GNUNET_ERROR_TYPE_WARNING,
1726 _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"),
1727 "gnunet-helper-nat-server");
1728 }
1729 GNUNET_free (binary);
1730 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
1731 if ((GNUNET_YES == h->enable_nat_client) &&
1732 (GNUNET_YES !=
1733 GNUNET_OS_check_helper_binary (binary,
1734 GNUNET_YES,
1735 "-d 127.0.0.1 127.0.0.2 42"))) /* none of these parameters are actually used in privilege testing mode */
1736 {
1737 h->enable_nat_client = GNUNET_NO;
1738 LOG (GNUNET_ERROR_TYPE_WARNING,
1739 _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"),
1740 "gnunet-helper-nat-client");
1741 }
1742 GNUNET_free (binary);
1743 start_gnunet_nat_server (h);
1744
1745 /* FIXME: add support for UPnP, etc */
1746
1747 if (NULL != h->address_callback)
1748 {
1749 h->ifc_task = GNUNET_SCHEDULER_add_now (&list_interfaces,
1750 h);
1751 if (GNUNET_YES == h->use_hostname)
1752 h->hostname_task = GNUNET_SCHEDULER_add_now (&resolve_hostname,
1753 h);
1754 }
1755 add_from_bind (h);
1756
1757 return h;
1758}
1759
1760
1761/**
1762 * Stop port redirection and public IP address detection for the given handle.
1763 * This frees the handle, after having sent the needed commands to close open ports.
1764 *
1765 * @param h the handle to stop
1766 */
1767void
1768GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h)
1769{
1770 unsigned int i;
1771 struct LocalAddressList *lal;
1772 struct MiniList *ml;
1773 struct StunServerList *ssl;
1774
1775 LOG (GNUNET_ERROR_TYPE_DEBUG,
1776 "NAT unregister called\n");
1777 while (NULL != (ssl = h->stun_servers_head))
1778 {
1779 GNUNET_CONTAINER_DLL_remove (h->stun_servers_head,
1780 h->stun_servers_tail,
1781 ssl);
1782 GNUNET_free (ssl->address);
1783 GNUNET_free (ssl);
1784 }
1785 while (NULL != (lal = h->lal_head))
1786 {
1787 GNUNET_CONTAINER_DLL_remove (h->lal_head,
1788 h->lal_tail,
1789 lal);
1790 if (NULL != h->address_callback)
1791 h->address_callback (h->callback_cls,
1792 GNUNET_NO,
1793 (const struct sockaddr *) &lal[1],
1794 lal->addrlen);
1795 GNUNET_free (lal);
1796 }
1797 while (NULL != (ml = h->mini_head))
1798 {
1799 GNUNET_CONTAINER_DLL_remove (h->mini_head,
1800 h->mini_tail,
1801 ml);
1802 if (NULL != ml->mini)
1803 GNUNET_NAT_mini_map_stop (ml->mini);
1804 GNUNET_free (ml);
1805 }
1806 if (NULL != h->ext_dns)
1807 {
1808 GNUNET_RESOLVER_request_cancel (h->ext_dns);
1809 h->ext_dns = NULL;
1810 }
1811 if (NULL != h->hostname_dns)
1812 {
1813 GNUNET_RESOLVER_request_cancel (h->hostname_dns);
1814 h->hostname_dns = NULL;
1815 }
1816 if (NULL != h->server_read_task)
1817 {
1818 GNUNET_SCHEDULER_cancel (h->server_read_task);
1819 h->server_read_task = NULL;
1820 }
1821 if (NULL != h->ifc_task)
1822 {
1823 GNUNET_SCHEDULER_cancel (h->ifc_task);
1824 h->ifc_task = NULL;
1825 }
1826 if (NULL != h->hostname_task)
1827 {
1828 GNUNET_SCHEDULER_cancel (h->hostname_task);
1829 h->hostname_task = NULL;
1830 }
1831 if (NULL != h->dns_task)
1832 {
1833 GNUNET_SCHEDULER_cancel (h->dns_task);
1834 h->dns_task = NULL;
1835 }
1836 if (NULL != h->stun_task)
1837 {
1838 GNUNET_SCHEDULER_cancel (h->stun_task);
1839 h->stun_task = NULL;
1840 }
1841 if (NULL != h->stun_request)
1842 {
1843 GNUNET_NAT_stun_make_request_cancel (h->stun_request);
1844 h->stun_request = NULL;
1845 }
1846 if (NULL != h->server_proc)
1847 {
1848 if (0 != GNUNET_OS_process_kill (h->server_proc,
1849 GNUNET_TERM_SIG))
1850 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
1851 "nat",
1852 "kill");
1853 GNUNET_OS_process_wait (h->server_proc);
1854 GNUNET_OS_process_destroy (h->server_proc);
1855 h->server_proc = NULL;
1856 GNUNET_DISK_pipe_close (h->server_stdout);
1857 h->server_stdout = NULL;
1858 h->server_stdout_handle = NULL;
1859 }
1860 if (NULL != h->server_stdout)
1861 {
1862 GNUNET_DISK_pipe_close (h->server_stdout);
1863 h->server_stdout = NULL;
1864 h->server_stdout_handle = NULL;
1865 }
1866 for (i = 0; i < h->num_local_addrs; i++)
1867 GNUNET_free (h->local_addrs[i]);
1868 GNUNET_free_non_null (h->local_addrs);
1869 GNUNET_free_non_null (h->local_addrlens);
1870 GNUNET_free_non_null (h->external_address);
1871 GNUNET_free_non_null (h->internal_address);
1872 GNUNET_free (h);
1873}
1874
1875
1876/**
1877 * We learned about a peer (possibly behind NAT) so run the
1878 * gnunet-helper-nat-client to send dummy ICMP responses to cause
1879 * that peer to connect to us (connection reversal).
1880 *
1881 * @param h handle (used for configuration)
1882 * @param sa the address of the peer (IPv4-only)
1883 * @return #GNUNET_SYSERR on error, #GNUNET_NO if nat client is disabled,
1884 * #GNUNET_OK otherwise
1885 */
1886int
1887GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h,
1888 const struct sockaddr_in *sa)
1889
1890
1891{
1892 char inet4[INET_ADDRSTRLEN];
1893 char port_as_string[6];
1894 struct GNUNET_OS_Process *proc;
1895 char *binary;
1896
1897 if (GNUNET_YES != h->enable_nat_client)
1898 return GNUNET_NO; /* not permitted / possible */
1899
1900 if (h->internal_address == NULL)
1901 {
1902 LOG (GNUNET_ERROR_TYPE_WARNING, "nat",
1903 _("Internal IP address not known, cannot use ICMP NAT traversal method\n"));
1904 return GNUNET_SYSERR;
1905 }
1906 GNUNET_assert (sa->sin_family == AF_INET);
1907 if (NULL == inet_ntop (AF_INET, &sa->sin_addr, inet4, INET_ADDRSTRLEN))
1908 {
1909 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
1910 "nat",
1911 "inet_ntop");
1912 return GNUNET_SYSERR;
1913 }
1914 GNUNET_snprintf (port_as_string,
1915 sizeof (port_as_string),
1916 "%d",
1917 h->adv_port);
1918 LOG (GNUNET_ERROR_TYPE_DEBUG,
1919 _("Running gnunet-helper-nat-client %s %s %u\n"),
1920 h->internal_address,
1921 inet4,
1922 (unsigned int) h->adv_port);
1923 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
1924 proc =
1925 GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL,
1926 binary,
1927 "gnunet-helper-nat-client",
1928 h->internal_address,
1929 inet4, port_as_string, NULL);
1930 GNUNET_free (binary);
1931 if (NULL == proc)
1932 return GNUNET_SYSERR;
1933 /* we know that the gnunet-helper-nat-client will terminate virtually
1934 * instantly */
1935 GNUNET_OS_process_wait (proc);
1936 GNUNET_OS_process_destroy (proc);
1937 return GNUNET_OK;
1938}
1939
1940
1941/**
1942 * Test if the given address is (currently) a plausible IP address for this peer.
1943 *
1944 * @param h the handle returned by register
1945 * @param addr IP address to test (IPv4 or IPv6)
1946 * @param addrlen number of bytes in @a addr
1947 * @return #GNUNET_YES if the address is plausible,
1948 * #GNUNET_NO if the address is not plausible,
1949 * #GNUNET_SYSERR if the address is malformed
1950 */
1951int
1952GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
1953 const void *addr,
1954 socklen_t addrlen)
1955{
1956 struct LocalAddressList *pos;
1957 const struct sockaddr_in *in4;
1958 const struct sockaddr_in6 *in6;
1959 char pbuf[INET6_ADDRSTRLEN+1];
1960
1961 if ((addrlen != sizeof (struct in_addr)) &&
1962 (addrlen != sizeof (struct in6_addr)))
1963 {
1964 GNUNET_break (0);
1965 return GNUNET_SYSERR;
1966 }
1967 for (pos = h->lal_head; NULL != pos; pos = pos->next)
1968 {
1969 if (pos->addrlen == sizeof (struct sockaddr_in))
1970 {
1971 in4 = (struct sockaddr_in *) &pos[1];
1972 if ((addrlen == sizeof (struct in_addr)) &&
1973 (0 == memcmp (&in4->sin_addr, addr, sizeof (struct in_addr))))
1974 return GNUNET_YES;
1975 }
1976 else if (pos->addrlen == sizeof (struct sockaddr_in6))
1977 {
1978 in6 = (struct sockaddr_in6 *) &pos[1];
1979 if ((addrlen == sizeof (struct in6_addr)) &&
1980 (0 == memcmp (&in6->sin6_addr, addr, sizeof (struct in6_addr))))
1981 return GNUNET_YES;
1982 }
1983 else
1984 {
1985 GNUNET_assert (0);
1986 }
1987 }
1988 LOG (GNUNET_ERROR_TYPE_WARNING,
1989 "Asked to validate one of my addresses (%s) and validation failed!\n",
1990 inet_ntop ((addrlen == sizeof(struct in_addr))
1991 ? AF_INET
1992 : AF_INET6,
1993 addr,
1994 pbuf, sizeof (pbuf)));
1995 return GNUNET_NO;
1996}
1997
1998/**
1999 * Converts enum GNUNET_NAT_StatusCode to a string
2000 *
2001 * @param err error code to resolve to a string
2002 * @return pointer to a static string containing the error code
2003 */
2004const char *
2005GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err)
2006{
2007 switch (err)
2008 {
2009 case GNUNET_NAT_ERROR_SUCCESS:
2010 return _ ("Operation Successful");
2011 case GNUNET_NAT_ERROR_IPC_FAILURE:
2012 return _ ("Internal Failure (IPC, ...)");
2013 case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
2014 return _ ("Failure in network subsystem, check permissions.");
2015 case GNUNET_NAT_ERROR_TIMEOUT:
2016 return _ ("Encountered timeout while performing operation");
2017 case GNUNET_NAT_ERROR_NOT_ONLINE:
2018 return _ ("detected that we are offline");
2019 case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
2020 return _ ("`upnpc` command not found");
2021 case GNUNET_NAT_ERROR_UPNPC_FAILED:
2022 return _ ("Failed to run `upnpc` command");
2023 case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
2024 return _ ("`upnpc' command took too long, process killed");
2025 case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
2026 return _ ("`upnpc' command failed to establish port mapping");
2027 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
2028 return _ ("`external-ip' command not found");
2029 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
2030 return _ ("Failed to run `external-ip` command");
2031 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
2032 return _ ("`external-ip' command output invalid");
2033 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
2034 return _ ("no valid address was returned by `external-ip'");
2035 case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
2036 return _ ("Could not determine interface with internal/local network address");
2037 case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
2038 return _ ("No functioning gnunet-helper-nat-server installation found");
2039 case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
2040 return _ ("NAT test could not be initialized");
2041 case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
2042 return _ ("NAT test timeout reached");
2043 case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
2044 return _ ("could not register NAT");
2045 case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
2046 return _ ("No working gnunet-helper-nat-client installation found");
2047/* case:
2048 return _ ("");*/
2049 default:
2050 return "unknown status code";
2051 }
2052}
2053
2054/* end of nat.c */
diff --git a/src/nat/nat.conf.in b/src/nat/nat.conf.in
index 304db3c15..87fe29d9c 100644
--- a/src/nat/nat.conf.in
+++ b/src/nat/nat.conf.in
@@ -9,42 +9,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nat.sock
9UNIX_MATCH_UID = YES 9UNIX_MATCH_UID = YES
10UNIX_MATCH_GID = YES 10UNIX_MATCH_GID = YES
11 11
12# Are we behind NAT?
13BEHIND_NAT = NO
14
15# Is the NAT hole-punched?
16PUNCHED_NAT = NO
17
18# Enable UPNP by default? 12# Enable UPNP by default?
19ENABLE_UPNP = NO 13ENABLE_UPNP = YES
20
21# Use addresses from the local network interfaces (inluding loopback, but also others)
22USE_LOCALADDR = YES
23
24# Use address obtained from a DNS lookup of our hostname
25USE_HOSTNAME = NO
26
27# External IP address of the NAT box (if known); IPv4 dotted-decimal ONLY at this time (should allow DynDNS!)
28# normal interface IP address for non-NATed peers;
29# possibly auto-detected (using UPnP) if possible if not specified
30# EXTERNAL_ADDRESS =
31
32# Should we use ICMP-based NAT traversal to try connect to NATed peers
33# or, if we are behind NAT, to allow connections to us?
34ENABLE_ICMP_CLIENT = NO
35ENABLE_ICMP_SERVER = NO
36
37# IP address of the interface connected to the NAT box; IPv4 dotted-decimal ONLY;
38# normal interface IP address for non-NATed peers;
39# likely auto-detected (via interface list) if not specified (!)
40# INTERNAL_ADDRESS =
41 14
42# Disable IPv6 support 15# Disable IPv6 support
16# FIXME: move entirely to transport plugins!
43DISABLEV6 = NO 17DISABLEV6 = NO
44 18
45# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
46RETURN_LOCAL_ADDRESSES = NO
47
48# How often do we query the DNS resolver 19# How often do we query the DNS resolver
49# for our hostname (to get our own IP) 20# for our hostname (to get our own IP)
50HOSTNAME_DNS_FREQUENCY = 20 min 21HOSTNAME_DNS_FREQUENCY = 20 min
@@ -67,8 +38,3 @@ STUN_SERVERS = stun.gnunet.org stun.services.mozilla.com:3478 stun.ekiga.net:347
67# After how long do we consider STUN data stale? 38# After how long do we consider STUN data stale?
68STUN_STALE = 60 min 39STUN_STALE = 60 min
69 40
70
71[gnunet-nat-server]
72HOSTNAME = gnunet.org
73PORT = 5724
74NOARMBIND = YES
diff --git a/src/nat/nat.h b/src/nat/nat.h
index af418c7c2..d34900bd1 100644
--- a/src/nat/nat.h
+++ b/src/nat/nat.h
@@ -29,6 +29,7 @@
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30 30
31 31
32
32GNUNET_NETWORK_STRUCT_BEGIN 33GNUNET_NETWORK_STRUCT_BEGIN
33 34
34/** 35/**
@@ -111,10 +112,9 @@ struct GNUNET_NAT_RegisterMessage
111 112
112 /** 113 /**
113 * Number of bytes in the string that follow which 114 * Number of bytes in the string that follow which
114 * specify the hostname and port of a manually punched 115 * specifies a section name in the configuration.
115 * hole for this client.
116 */ 116 */
117 uint16_t hole_external_len GNUNET_PACKED; 117 uint16_t str_len GNUNET_PACKED;
118 118
119 /** 119 /**
120 * Number of addresses that this service is bound to that follow. 120 * Number of addresses that this service is bound to that follow.
@@ -126,8 +126,7 @@ struct GNUNET_NAT_RegisterMessage
126 /* Followed by @e num_addrs addresses of type 'struct 126 /* Followed by @e num_addrs addresses of type 'struct
127 sockaddr' */ 127 sockaddr' */
128 128
129 /* Followed by @e hole_external_len bytes giving a hostname 129 /* Followed by @e str_len section name to use for options */
130 and port */
131 130
132}; 131};
133 132
@@ -225,45 +224,6 @@ struct GNUNET_NAT_AddressChangeNotificationMessage
225}; 224};
226 225
227 226
228/**
229 * Client requesting automatic configuration.
230 */
231struct GNUNET_NAT_AutoconfigRequestMessage
232{
233 /**
234 * Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG
235 */
236 struct GNUNET_MessageHeader header;
237
238 /* Followed by configuration (diff, serialized, compressed) */
239
240};
241
242
243/**
244 * Service responding with proposed configuration.
245 */
246struct GNUNET_NAT_AutoconfigResultMessage
247{
248 /**
249 * Header with type #GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
250 */
251 struct GNUNET_MessageHeader header;
252
253 /**
254 * An `enum GNUNET_NAT_StatusCode` in NBO.
255 */
256 int32_t status_code GNUNET_PACKED;
257
258 /**
259 * An `enum GNUNET_NAT_Type` in NBO.
260 */
261 int32_t type GNUNET_PACKED;
262
263 /* Followed by configuration (diff, serialized, compressed) */
264};
265
266
267GNUNET_NETWORK_STRUCT_END 227GNUNET_NETWORK_STRUCT_END
268 228
269#endif 229#endif
diff --git a/src/nat/nat_api.c b/src/nat/nat_api.c
index e4dfc1629..eec5d3968 100644
--- a/src/nat/nat_api.c
+++ b/src/nat/nat_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2007-2016 GNUnet e.V. 3 Copyright (C) 2007-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -343,7 +343,7 @@ do_connect (void *cls)
343 struct GNUNET_MQ_Envelope *env; 343 struct GNUNET_MQ_Envelope *env;
344 344
345 nh->reconnect_task = NULL; 345 nh->reconnect_task = NULL;
346 nh->mq = GNUNET_CLIENT_connecT (nh->cfg, 346 nh->mq = GNUNET_CLIENT_connect (nh->cfg,
347 "nat", 347 "nat",
348 handlers, 348 handlers,
349 &mq_error_handler, 349 &mq_error_handler,
@@ -368,8 +368,8 @@ do_connect (void *cls)
368 * address_callback for any 'plausible' external address. 368 * address_callback for any 'plausible' external address.
369 * 369 *
370 * @param cfg configuration to use 370 * @param cfg configuration to use
371 * @param config_section name of the configuration section for optionsx
371 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP 372 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
372 * @param hole_external hostname and port of manually punched hole in NAT, otherwise NULL (or empty string)
373 * @param num_addrs number of addresses in @a addrs 373 * @param num_addrs number of addresses in @a addrs
374 * @param addrs list of local addresses packets should be redirected to 374 * @param addrs list of local addresses packets should be redirected to
375 * @param addrlens actual lengths of the addresses in @a addrs 375 * @param addrlens actual lengths of the addresses in @a addrs
@@ -381,8 +381,8 @@ do_connect (void *cls)
381 */ 381 */
382struct GNUNET_NAT_Handle * 382struct GNUNET_NAT_Handle *
383GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, 383GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
384 const char *config_section,
384 uint8_t proto, 385 uint8_t proto,
385 const char *hole_external,
386 unsigned int num_addrs, 386 unsigned int num_addrs,
387 const struct sockaddr **addrs, 387 const struct sockaddr **addrs,
388 const socklen_t *addrlens, 388 const socklen_t *addrlens,
@@ -393,17 +393,14 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
393 struct GNUNET_NAT_Handle *nh; 393 struct GNUNET_NAT_Handle *nh;
394 struct GNUNET_NAT_RegisterMessage *rm; 394 struct GNUNET_NAT_RegisterMessage *rm;
395 size_t len; 395 size_t len;
396 size_t hole_external_len; 396 size_t str_len;
397 char *off; 397 char *off;
398 398
399 len = 0; 399 len = 0;
400 for (unsigned int i=0;i<num_addrs;i++) 400 for (unsigned int i=0;i<num_addrs;i++)
401 len += addrlens[i]; 401 len += addrlens[i];
402 hole_external_len 402 str_len = strlen (config_section) + 1;
403 = (NULL == hole_external) 403 len += str_len;
404 ? 0
405 : strlen (hole_external);
406 len += hole_external_len;
407 if ( (len > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*rm)) || 404 if ( (len > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*rm)) ||
408 (num_addrs > UINT16_MAX) ) 405 (num_addrs > UINT16_MAX) )
409 { 406 {
@@ -419,7 +416,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
419 if (NULL != reversal_callback) 416 if (NULL != reversal_callback)
420 rm->flags |= GNUNET_NAT_RF_REVERSAL; 417 rm->flags |= GNUNET_NAT_RF_REVERSAL;
421 rm->proto = proto; 418 rm->proto = proto;
422 rm->hole_external_len = htons (hole_external_len); 419 rm->str_len = htons (str_len);
423 rm->num_addrs = htons ((uint16_t) num_addrs); 420 rm->num_addrs = htons ((uint16_t) num_addrs);
424 off = (char *) &rm[1]; 421 off = (char *) &rm[1];
425 for (unsigned int i=0;i<num_addrs;i++) 422 for (unsigned int i=0;i<num_addrs;i++)
@@ -459,8 +456,8 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
459 off += addrlens[i]; 456 off += addrlens[i];
460 } 457 }
461 GNUNET_memcpy (off, 458 GNUNET_memcpy (off,
462 hole_external, 459 config_section,
463 hole_external_len); 460 str_len);
464 461
465 nh = GNUNET_new (struct GNUNET_NAT_Handle); 462 nh = GNUNET_new (struct GNUNET_NAT_Handle);
466 nh->reg = &rm->header; 463 nh->reg = &rm->header;
@@ -681,6 +678,8 @@ GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
681 678
682 if (NULL == nh->mq) 679 if (NULL == nh->mq)
683 return GNUNET_SYSERR; 680 return GNUNET_SYSERR;
681 GNUNET_break (AF_INET == local_sa->sin_family);
682 GNUNET_break (AF_INET == remote_sa->sin_family);
684 env = GNUNET_MQ_msg_extra (req, 683 env = GNUNET_MQ_msg_extra (req,
685 2 * sizeof (struct sockaddr_in), 684 2 * sizeof (struct sockaddr_in),
686 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL); 685 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL);
@@ -710,249 +709,19 @@ GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
710void 709void
711GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh) 710GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh)
712{ 711{
713 GNUNET_MQ_destroy (nh->mq); 712 if (NULL != nh->mq)
714 GNUNET_free (nh->reg);
715 GNUNET_free (nh);
716}
717
718
719
720/**
721 * Handle to auto-configuration in progress.
722 */
723struct GNUNET_NAT_AutoHandle
724{
725
726 /**
727 * Configuration we use.
728 */
729 const struct GNUNET_CONFIGURATION_Handle *cfg;
730
731 /**
732 * Message queue for communicating with the NAT service.
733 */
734 struct GNUNET_MQ_Handle *mq;
735
736 /**
737 * Function called with the result from the autoconfiguration.
738 */
739 GNUNET_NAT_AutoResultCallback arc;
740
741 /**
742 * Closure for @e arc.
743 */
744 void *arc_cls;
745
746};
747
748
749/**
750 * Converts `enum GNUNET_NAT_StatusCode` to string
751 *
752 * @param err error code to resolve to a string
753 * @return point to a static string containing the error code
754 */
755const char *
756GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err)
757{
758 switch (err)
759 {
760 case GNUNET_NAT_ERROR_SUCCESS:
761 return _ ("Operation Successful");
762 case GNUNET_NAT_ERROR_IPC_FAILURE:
763 return _ ("IPC failure");
764 case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
765 return _ ("Failure in network subsystem, check permissions.");
766 case GNUNET_NAT_ERROR_TIMEOUT:
767 return _ ("Encountered timeout while performing operation");
768 case GNUNET_NAT_ERROR_NOT_ONLINE:
769 return _ ("detected that we are offline");
770 case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
771 return _ ("`upnpc` command not found");
772 case GNUNET_NAT_ERROR_UPNPC_FAILED:
773 return _ ("Failed to run `upnpc` command");
774 case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
775 return _ ("`upnpc' command took too long, process killed");
776 case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
777 return _ ("`upnpc' command failed to establish port mapping");
778 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
779 return _ ("`external-ip' command not found");
780 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
781 return _ ("Failed to run `external-ip` command");
782 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
783 return _ ("`external-ip' command output invalid");
784 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
785 return _ ("no valid address was returned by `external-ip'");
786 case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
787 return _ ("Could not determine interface with internal/local network address");
788 case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
789 return _ ("No functioning gnunet-helper-nat-server installation found");
790 case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
791 return _ ("NAT test could not be initialized");
792 case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
793 return _ ("NAT test timeout reached");
794 case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
795 return _ ("could not register NAT");
796 case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
797 return _ ("No working gnunet-helper-nat-client installation found");
798 default:
799 return "unknown status code";
800 }
801}
802
803
804/**
805 * Check result from autoconfiguration attempt.
806 *
807 * @param cls the `struct GNUNET_NAT_AutoHandle`
808 * @param res the result
809 * @return #GNUNET_OK if @a res is well-formed (always for now)
810 */
811static int
812check_auto_result (void *cls,
813 const struct GNUNET_NAT_AutoconfigResultMessage *res)
814{
815 return GNUNET_OK;
816}
817
818
819/**
820 * Handle result from autoconfiguration attempt.
821 *
822 * @param cls the `struct GNUNET_NAT_AutoHandle`
823 * @param res the result
824 */
825static void
826handle_auto_result (void *cls,
827 const struct GNUNET_NAT_AutoconfigResultMessage *res)
828{
829 struct GNUNET_NAT_AutoHandle *ah = cls;
830 size_t left;
831 struct GNUNET_CONFIGURATION_Handle *cfg;
832 enum GNUNET_NAT_Type type
833 = (enum GNUNET_NAT_Type) ntohl (res->type);
834 enum GNUNET_NAT_StatusCode status
835 = (enum GNUNET_NAT_StatusCode) ntohl (res->status_code);
836
837 left = ntohs (res->header.size) - sizeof (*res);
838 cfg = GNUNET_CONFIGURATION_create ();
839 if (GNUNET_OK !=
840 GNUNET_CONFIGURATION_deserialize (cfg,
841 (const char *) &res[1],
842 left,
843 GNUNET_NO))
844 {
845 GNUNET_break (0);
846 ah->arc (ah->arc_cls,
847 NULL,
848 GNUNET_NAT_ERROR_IPC_FAILURE,
849 type);
850 }
851 else
852 {
853 ah->arc (ah->arc_cls,
854 cfg,
855 status,
856 type);
857 }
858 GNUNET_CONFIGURATION_destroy (cfg);
859 GNUNET_NAT_autoconfig_cancel (ah);
860}
861
862
863/**
864 * Handle queue errors by reporting autoconfiguration failure.
865 *
866 * @param cls the `struct GNUNET_NAT_AutoHandle *`
867 * @param error details about the error
868 */
869static void
870ah_error_handler (void *cls,
871 enum GNUNET_MQ_Error error)
872{
873 struct GNUNET_NAT_AutoHandle *ah = cls;
874
875 ah->arc (ah->arc_cls,
876 NULL,
877 GNUNET_NAT_ERROR_IPC_FAILURE,
878 GNUNET_NAT_TYPE_UNKNOWN);
879 GNUNET_NAT_autoconfig_cancel (ah);
880}
881
882
883/**
884 * Start auto-configuration routine. The transport adapters should
885 * be stopped while this function is called.
886 *
887 * @param cfg initial configuration
888 * @param cb function to call with autoconfiguration result
889 * @param cb_cls closure for @a cb
890 * @return handle to cancel operation
891 */
892struct GNUNET_NAT_AutoHandle *
893GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
894 GNUNET_NAT_AutoResultCallback cb,
895 void *cb_cls)
896{
897 struct GNUNET_NAT_AutoHandle *ah = GNUNET_new (struct GNUNET_NAT_AutoHandle);
898 struct GNUNET_MQ_MessageHandler handlers[] = {
899 GNUNET_MQ_hd_var_size (auto_result,
900 GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT,
901 struct GNUNET_NAT_AutoconfigResultMessage,
902 ah),
903 GNUNET_MQ_handler_end ()
904 };
905 struct GNUNET_MQ_Envelope *env;
906 struct GNUNET_NAT_AutoconfigRequestMessage *req;
907 char *buf;
908 size_t size;
909
910 buf = GNUNET_CONFIGURATION_serialize (cfg,
911 &size);
912 if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*req))
913 { 713 {
914 GNUNET_break (0); 714 GNUNET_MQ_destroy (nh->mq);
915 GNUNET_free (buf); 715 nh->mq = NULL;
916 GNUNET_free (ah);
917 return NULL;
918 } 716 }
919 ah->arc = cb; 717 if (NULL != nh->reconnect_task)
920 ah->arc_cls = cb_cls;
921 ah->mq = GNUNET_CLIENT_connecT (cfg,
922 "nat",
923 handlers,
924 &ah_error_handler,
925 ah);
926 if (NULL == ah->mq)
927 { 718 {
928 GNUNET_break (0); 719 GNUNET_SCHEDULER_cancel (nh->reconnect_task);
929 GNUNET_free (buf); 720 nh->reconnect_task = NULL;
930 GNUNET_free (ah);
931 return NULL;
932 } 721 }
933 env = GNUNET_MQ_msg_extra (req, 722 GNUNET_free (nh->reg);
934 size, 723 GNUNET_free (nh);
935 GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG);
936 GNUNET_memcpy (&req[1],
937 buf,
938 size);
939 GNUNET_free (buf);
940 GNUNET_MQ_send (ah->mq,
941 env);
942 return ah;
943} 724}
944 725
945 726
946/**
947 * Abort autoconfiguration.
948 *
949 * @param ah handle for operation to abort
950 */
951void
952GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah)
953{
954 GNUNET_MQ_destroy (ah->mq);
955 GNUNET_free (ah);
956}
957
958/* end of nat_api.c */ 727/* end of nat_api.c */
diff --git a/src/nat/nat_api_stun.c b/src/nat/nat_api_stun.c
index 7f2ef4eaf..b1309fb53 100644
--- a/src/nat/nat_api_stun.c
+++ b/src/nat/nat_api_stun.c
@@ -38,7 +38,7 @@
38#include "platform.h" 38#include "platform.h"
39#include "gnunet_util_lib.h" 39#include "gnunet_util_lib.h"
40#include "gnunet_resolver_service.h" 40#include "gnunet_resolver_service.h"
41#include "gnunet_nat_lib.h" 41#include "gnunet_nat_service.h"
42 42
43 43
44#include "nat_stun.h" 44#include "nat_stun.h"
@@ -74,7 +74,7 @@ struct GNUNET_NAT_STUN_Handle
74 /** 74 /**
75 * Function to call when a error occours 75 * Function to call when a error occours
76 */ 76 */
77 GNUNET_NAT_STUN_ErrorCallback cb; 77 GNUNET_NAT_TestCallback cb;
78 78
79 /** 79 /**
80 * Closure for @e cb. 80 * Closure for @e cb.
@@ -199,7 +199,7 @@ stun_dns_callback (void *cls,
199 199
200/** 200/**
201 * Make Generic STUN request. Sends a generic stun request to the 201 * Make Generic STUN request. Sends a generic stun request to the
202 * server specified using the specified socket. 202 * server specified using the specified socket.
203 * 203 *
204 * @param server the address of the stun server 204 * @param server the address of the stun server
205 * @param port port of the stun server, in host byte order 205 * @param port port of the stun server, in host byte order
@@ -212,7 +212,7 @@ struct GNUNET_NAT_STUN_Handle *
212GNUNET_NAT_stun_make_request (const char *server, 212GNUNET_NAT_stun_make_request (const char *server,
213 uint16_t port, 213 uint16_t port,
214 struct GNUNET_NETWORK_Handle *sock, 214 struct GNUNET_NETWORK_Handle *sock,
215 GNUNET_NAT_STUN_ErrorCallback cb, 215 GNUNET_NAT_TestCallback cb,
216 void *cb_cls) 216 void *cb_cls)
217{ 217{
218 struct GNUNET_NAT_STUN_Handle *rh; 218 struct GNUNET_NAT_STUN_Handle *rh;
diff --git a/src/nat/nat_mini.c b/src/nat/nat_mini.c
deleted file mode 100644
index 915bcbdb6..000000000
--- a/src/nat/nat_mini.c
+++ /dev/null
@@ -1,712 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2014 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file nat/nat_mini.c
23 * @brief functions for interaction with miniupnp; tested with miniupnpc 1.5
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_nat_lib.h"
29#include "nat.h"
30
31#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
32
33/**
34 * How long do we give upnpc to create a mapping?
35 */
36#define MAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
37
38/**
39 * How long do we give upnpc to remove a mapping?
40 */
41#define UNMAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
42
43/**
44 * How often do we check for changes in the mapping?
45 */
46#define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
47
48
49
50/**
51 * Opaque handle to cancel "GNUNET_NAT_mini_get_external_ipv4" operation.
52 */
53struct GNUNET_NAT_ExternalHandle
54{
55
56 /**
57 * Function to call with the result.
58 */
59 GNUNET_NAT_IPCallback cb;
60
61 /**
62 * Closure for @e cb.
63 */
64 void *cb_cls;
65
66 /**
67 * Read task.
68 */
69 struct GNUNET_SCHEDULER_Task * task;
70
71 /**
72 * Handle to 'external-ip' process.
73 */
74 struct GNUNET_OS_Process *eip;
75
76 /**
77 * Handle to stdout pipe of 'external-ip'.
78 */
79 struct GNUNET_DISK_PipeHandle *opipe;
80
81 /**
82 * Read handle of @e opipe.
83 */
84 const struct GNUNET_DISK_FileHandle *r;
85
86 /**
87 * When should this operation time out?
88 */
89 struct GNUNET_TIME_Absolute timeout;
90
91 /**
92 * Number of bytes in 'buf' that are valid.
93 */
94 size_t off;
95
96 /**
97 * Destination of our read operation (output of 'external-ip').
98 */
99 char buf[17];
100
101 /**
102 * Error code for better debugging and user feedback
103 */
104 enum GNUNET_NAT_StatusCode ret;
105};
106
107
108/**
109 * Read the output of 'external-ip' into buf. When complete, parse the
110 * address and call our callback.
111 *
112 * @param cls the `struct GNUNET_NAT_ExternalHandle`
113 */
114static void
115read_external_ipv4 (void *cls)
116{
117 struct GNUNET_NAT_ExternalHandle *eh = cls;
118 ssize_t ret;
119 struct in_addr addr;
120 const struct GNUNET_SCHEDULER_TaskContext *tc;
121
122 eh->task = NULL;
123 tc = GNUNET_SCHEDULER_get_task_context ();
124 if (GNUNET_YES ==
125 GNUNET_NETWORK_fdset_handle_isset (tc->read_ready, eh->r))
126 {
127 ret =
128 GNUNET_DISK_file_read (eh->r, &eh->buf[eh->off],
129 sizeof (eh->buf) - eh->off);
130 }
131 else
132 {
133 eh->ret = GNUNET_NAT_ERROR_IPC_FAILURE;
134 ret = -1; /* error reading, timeout, etc. */
135 }
136 if (ret > 0)
137 {
138 /* try to read more */
139 eh->off += ret;
140 eh->task =
141 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
142 (eh->timeout), eh->r,
143 &read_external_ipv4, eh);
144 return;
145 }
146 eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID;
147 if ((eh->off > 7) && (eh->buf[eh->off - 1] == '\n'))
148 {
149 eh->buf[eh->off - 1] = '\0';
150 if (1 == inet_pton (AF_INET, eh->buf, &addr))
151 {
152 if (0 != addr.s_addr)
153 eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID; /* got 0.0.0.0 */
154 else
155 eh->ret = GNUNET_NAT_ERROR_SUCCESS;
156 }
157 }
158 eh->cb (eh->cb_cls,
159 (GNUNET_NAT_ERROR_SUCCESS == eh->ret) ? &addr : NULL,
160 eh->ret);
161 GNUNET_NAT_mini_get_external_ipv4_cancel (eh);
162}
163
164
165/**
166 * (Asynchronously) signal error invoking "external-ip" to client.
167 *
168 * @param cls the `struct GNUNET_NAT_ExternalHandle` (freed)
169 */
170static void
171signal_external_ip_error (void *cls)
172{
173 struct GNUNET_NAT_ExternalHandle *eh = cls;
174
175 eh->task = NULL;
176 eh->cb (eh->cb_cls,
177 NULL,
178 eh->ret);
179 GNUNET_free (eh);
180}
181
182
183/**
184 * Try to get the external IPv4 address of this peer.
185 *
186 * @param timeout when to fail
187 * @param cb function to call with result
188 * @param cb_cls closure for @a cb
189 * @return handle for cancellation (can only be used until @a cb is called), never NULL
190 */
191struct GNUNET_NAT_ExternalHandle *
192GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout,
193 GNUNET_NAT_IPCallback cb, void *cb_cls)
194{
195 struct GNUNET_NAT_ExternalHandle *eh;
196
197 eh = GNUNET_new (struct GNUNET_NAT_ExternalHandle);
198 eh->cb = cb;
199 eh->cb_cls = cb_cls;
200 eh->ret = GNUNET_NAT_ERROR_SUCCESS;
201 if (GNUNET_SYSERR ==
202 GNUNET_OS_check_helper_binary ("external-ip", GNUNET_NO, NULL))
203 {
204 LOG (GNUNET_ERROR_TYPE_INFO,
205 _("`external-ip' command not found\n"));
206 eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND;
207 eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
208 eh);
209 return eh;
210 }
211 LOG (GNUNET_ERROR_TYPE_DEBUG,
212 "Running `external-ip' to determine our external IP\n");
213 eh->opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
214 if (NULL == eh->opipe)
215 {
216 eh->ret = GNUNET_NAT_ERROR_IPC_FAILURE;
217 eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
218 eh);
219 return eh;
220 }
221 eh->eip =
222 GNUNET_OS_start_process (GNUNET_NO, 0, NULL, eh->opipe, NULL,
223 "external-ip", "external-ip",
224 NULL);
225 if (NULL == eh->eip)
226 {
227 GNUNET_DISK_pipe_close (eh->opipe);
228 eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED;
229 eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
230 eh);
231 return eh;
232 }
233 GNUNET_DISK_pipe_close_end (eh->opipe, GNUNET_DISK_PIPE_END_WRITE);
234 eh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
235 eh->r = GNUNET_DISK_pipe_handle (eh->opipe, GNUNET_DISK_PIPE_END_READ);
236 eh->task =
237 GNUNET_SCHEDULER_add_read_file (timeout,
238 eh->r,
239 &read_external_ipv4, eh);
240 return eh;
241}
242
243
244/**
245 * Cancel operation.
246 *
247 * @param eh operation to cancel
248 */
249void
250GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh)
251{
252 if (NULL != eh->eip)
253 {
254 (void) GNUNET_OS_process_kill (eh->eip, SIGKILL);
255 GNUNET_OS_process_destroy (eh->eip);
256 }
257 if (NULL != eh->opipe)
258 GNUNET_DISK_pipe_close (eh->opipe);
259 if (NULL != eh->task)
260 GNUNET_SCHEDULER_cancel (eh->task);
261 GNUNET_free (eh);
262}
263
264
265/**
266 * Handle to a mapping created with upnpc.
267 */
268struct GNUNET_NAT_MiniHandle
269{
270
271 /**
272 * Function to call on mapping changes.
273 */
274 GNUNET_NAT_MiniAddressCallback ac;
275
276 /**
277 * Closure for @e ac.
278 */
279 void *ac_cls;
280
281 /**
282 * Command used to install the map.
283 */
284 struct GNUNET_OS_CommandHandle *map_cmd;
285
286 /**
287 * Command used to refresh our map information.
288 */
289 struct GNUNET_OS_CommandHandle *refresh_cmd;
290
291 /**
292 * Command used to remove the mapping.
293 */
294 struct GNUNET_OS_CommandHandle *unmap_cmd;
295
296 /**
297 * Our current external mapping (if we have one).
298 */
299 struct sockaddr_in current_addr;
300
301 /**
302 * We check the mapping periodically to see if it
303 * still works. This task triggers the check.
304 */
305 struct GNUNET_SCHEDULER_Task * refresh_task;
306
307 /**
308 * Are we mapping TCP or UDP?
309 */
310 int is_tcp;
311
312 /**
313 * Did we succeed with creating a mapping?
314 */
315 int did_map;
316
317 /**
318 * Did we find our mapping during refresh scan?
319 */
320 int found;
321
322 /**
323 * Which port are we mapping?
324 */
325 uint16_t port;
326
327};
328
329
330/**
331 * Run "upnpc -l" to find out if our mapping changed.
332 *
333 * @param cls the `struct GNUNET_NAT_MiniHandle`
334 */
335static void
336do_refresh (void *cls);
337
338
339/**
340 * Process the output from the "upnpc -r" command.
341 *
342 * @param cls the `struct GNUNET_NAT_MiniHandle`
343 * @param line line of output, NULL at the end
344 */
345static void
346process_map_output (void *cls, const char *line);
347
348
349/**
350 * Run "upnpc -r" to map our internal port.
351 *
352 * @param mini our handle
353 */
354static void
355run_upnpc_r (struct GNUNET_NAT_MiniHandle *mini)
356{
357 char pstr[6];
358
359 GNUNET_snprintf (pstr,
360 sizeof (pstr),
361 "%u",
362 (unsigned int) mini->port);
363 mini->map_cmd =
364 GNUNET_OS_command_run (&process_map_output, mini, MAP_TIMEOUT,
365 "upnpc", "upnpc", "-r", pstr,
366 mini->is_tcp ? "tcp" : "udp", NULL);
367 if (NULL == mini->map_cmd)
368 {
369 mini->ac (mini->ac_cls,
370 GNUNET_SYSERR,
371 NULL, 0,
372 GNUNET_NAT_ERROR_UPNPC_FAILED);
373 return;
374 }
375}
376
377
378/**
379 * Process the output from "upnpc -l" to see if our
380 * external mapping changed. If so, do the notifications.
381 *
382 * @param cls the `struct GNUNET_NAT_MiniHandle`
383 * @param line line of output, NULL at the end
384 */
385static void
386process_refresh_output (void *cls, const char *line)
387{
388 struct GNUNET_NAT_MiniHandle *mini = cls;
389 char pstr[9];
390 const char *s;
391 unsigned int nport;
392 struct in_addr exip;
393
394 if (NULL == line)
395 {
396 GNUNET_OS_command_stop (mini->refresh_cmd);
397 mini->refresh_cmd = NULL;
398 if (GNUNET_NO == mini->found)
399 {
400 /* mapping disappeared, try to re-create */
401 if (GNUNET_YES == mini->did_map)
402 {
403 mini->ac (mini->ac_cls,
404 GNUNET_NO,
405 (const struct sockaddr *) &mini->current_addr,
406 sizeof (mini->current_addr),
407 GNUNET_NAT_ERROR_SUCCESS);
408 mini->did_map = GNUNET_NO;
409 }
410 run_upnpc_r (mini);
411 }
412 return;
413 }
414 if (!mini->did_map)
415 return; /* never mapped, won't find our mapping anyway */
416
417 /* we're looking for output of the form:
418 * "ExternalIPAddress = 12.134.41.124" */
419
420 s = strstr (line, "ExternalIPAddress = ");
421 if (NULL != s)
422 {
423 s += strlen ("ExternalIPAddress = ");
424 if (1 != inet_pton (AF_INET, s, &exip))
425 return; /* skip */
426 if (exip.s_addr == mini->current_addr.sin_addr.s_addr)
427 return; /* no change */
428 /* update mapping */
429 mini->ac (mini->ac_cls, GNUNET_NO,
430 (const struct sockaddr *) &mini->current_addr,
431 sizeof (mini->current_addr),
432 GNUNET_NAT_ERROR_SUCCESS);
433 mini->current_addr.sin_addr = exip;
434 mini->ac (mini->ac_cls, GNUNET_YES,
435 (const struct sockaddr *) &mini->current_addr,
436 sizeof (mini->current_addr),
437 GNUNET_NAT_ERROR_SUCCESS);
438 return;
439 }
440 /*
441 * we're looking for output of the form:
442 *
443 * "0 TCP 3000->192.168.2.150:3000 'libminiupnpc' ''"
444 * "1 UDP 3001->192.168.2.150:3001 'libminiupnpc' ''"
445 *
446 * the pattern we look for is:
447 *
448 * "%s TCP PORT->STRING:OURPORT *" or
449 * "%s UDP PORT->STRING:OURPORT *"
450 */
451 GNUNET_snprintf (pstr, sizeof (pstr), ":%u ", mini->port);
452 if (NULL == (s = strstr (line, "->")))
453 return; /* skip */
454 if (NULL == strstr (s, pstr))
455 return; /* skip */
456 if (1 !=
457 SSCANF (line,
458 (mini->is_tcp) ? "%*u TCP %u->%*s:%*u %*s" :
459 "%*u UDP %u->%*s:%*u %*s", &nport))
460 return; /* skip */
461 mini->found = GNUNET_YES;
462 if (nport == ntohs (mini->current_addr.sin_port))
463 return; /* no change */
464
465 /* external port changed, update mapping */
466 mini->ac (mini->ac_cls, GNUNET_NO,
467 (const struct sockaddr *) &mini->current_addr,
468 sizeof (mini->current_addr),
469 GNUNET_NAT_ERROR_SUCCESS);
470 mini->current_addr.sin_port = htons ((uint16_t) nport);
471 mini->ac (mini->ac_cls, GNUNET_YES,
472 (const struct sockaddr *) &mini->current_addr,
473 sizeof (mini->current_addr),
474 GNUNET_NAT_ERROR_SUCCESS);
475}
476
477
478/**
479 * Run "upnpc -l" to find out if our mapping changed.
480 *
481 * @param cls the 'struct GNUNET_NAT_MiniHandle'
482 */
483static void
484do_refresh (void *cls)
485{
486 struct GNUNET_NAT_MiniHandle *mini = cls;
487 int ac;
488
489 mini->refresh_task =
490 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
491 &do_refresh, mini);
492 LOG (GNUNET_ERROR_TYPE_DEBUG,
493 "Running `upnpc' to check if our mapping still exists\n");
494 mini->found = GNUNET_NO;
495 ac = GNUNET_NO;
496 if (NULL != mini->map_cmd)
497 {
498 /* took way too long, abort it! */
499 GNUNET_OS_command_stop (mini->map_cmd);
500 mini->map_cmd = NULL;
501 ac = GNUNET_YES;
502 }
503 if (NULL != mini->refresh_cmd)
504 {
505 /* took way too long, abort it! */
506 GNUNET_OS_command_stop (mini->refresh_cmd);
507 mini->refresh_cmd = NULL;
508 ac = GNUNET_YES;
509 }
510 mini->refresh_cmd =
511 GNUNET_OS_command_run (&process_refresh_output, mini, MAP_TIMEOUT,
512 "upnpc", "upnpc", "-l", NULL);
513 if (GNUNET_YES == ac)
514 mini->ac (mini->ac_cls,
515 GNUNET_SYSERR,
516 NULL, 0,
517 GNUNET_NAT_ERROR_UPNPC_TIMEOUT);
518}
519
520
521/**
522 * Process the output from the 'upnpc -r' command.
523 *
524 * @param cls the `struct GNUNET_NAT_MiniHandle`
525 * @param line line of output, NULL at the end
526 */
527static void
528process_map_output (void *cls,
529 const char *line)
530{
531 struct GNUNET_NAT_MiniHandle *mini = cls;
532 const char *ipaddr;
533 char *ipa;
534 const char *pstr;
535 unsigned int port;
536
537 if (NULL == line)
538 {
539 GNUNET_OS_command_stop (mini->map_cmd);
540 mini->map_cmd = NULL;
541 if (GNUNET_YES != mini->did_map)
542 mini->ac (mini->ac_cls,
543 GNUNET_SYSERR,
544 NULL, 0,
545 GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED);
546 if (NULL == mini->refresh_task)
547 mini->refresh_task =
548 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
549 &do_refresh,
550 mini);
551 return;
552 }
553 /*
554 * The upnpc output we're after looks like this:
555 *
556 * "external 87.123.42.204:3000 TCP is redirected to internal 192.168.2.150:3000"
557 */
558 if ((NULL == (ipaddr = strstr (line, " "))) ||
559 (NULL == (pstr = strstr (ipaddr, ":"))) ||
560 (1 != SSCANF (pstr + 1, "%u", &port)))
561 {
562 return; /* skip line */
563 }
564 ipa = GNUNET_strdup (ipaddr + 1);
565 strstr (ipa, ":")[0] = '\0';
566 if (1 != inet_pton (AF_INET, ipa, &mini->current_addr.sin_addr))
567 {
568 GNUNET_free (ipa);
569 return; /* skip line */
570 }
571 GNUNET_free (ipa);
572
573 mini->current_addr.sin_port = htons (port);
574 mini->current_addr.sin_family = AF_INET;
575#if HAVE_SOCKADDR_IN_SIN_LEN
576 mini->current_addr.sin_len = sizeof (struct sockaddr_in);
577#endif
578 mini->did_map = GNUNET_YES;
579 mini->ac (mini->ac_cls, GNUNET_YES,
580 (const struct sockaddr *) &mini->current_addr,
581 sizeof (mini->current_addr),
582 GNUNET_NAT_ERROR_SUCCESS);
583}
584
585
586/**
587 * Start mapping the given port using (mini)upnpc. This function
588 * should typically not be used directly (it is used within the
589 * general-purpose #GNUNET_NAT_register() code). However, it can be
590 * used if specifically UPnP-based NAT traversal is to be used or
591 * tested.
592 *
593 * @param port port to map
594 * @param is_tcp #GNUNET_YES to map TCP, #GNUNET_NO for UDP
595 * @param ac function to call with mapping result
596 * @param ac_cls closure for @a ac
597 * @return NULL on error (no 'upnpc' installed)
598 */
599struct GNUNET_NAT_MiniHandle *
600GNUNET_NAT_mini_map_start (uint16_t port,
601 int is_tcp,
602 GNUNET_NAT_MiniAddressCallback ac,
603 void *ac_cls)
604{
605 struct GNUNET_NAT_MiniHandle *ret;
606
607 if (GNUNET_SYSERR ==
608 GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL))
609 {
610 LOG (GNUNET_ERROR_TYPE_INFO,
611 _("`upnpc' command not found\n"));
612 ac (ac_cls,
613 GNUNET_SYSERR,
614 NULL, 0,
615 GNUNET_NAT_ERROR_UPNPC_NOT_FOUND);
616 return NULL;
617 }
618 LOG (GNUNET_ERROR_TYPE_DEBUG,
619 "Running `upnpc' to install mapping\n");
620 ret = GNUNET_new (struct GNUNET_NAT_MiniHandle);
621 ret->ac = ac;
622 ret->ac_cls = ac_cls;
623 ret->is_tcp = is_tcp;
624 ret->port = port;
625 ret->refresh_task =
626 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
627 &do_refresh,
628 ret);
629 run_upnpc_r (ret);
630 return ret;
631}
632
633
634/**
635 * Process output from our 'unmap' command.
636 *
637 * @param cls the `struct GNUNET_NAT_MiniHandle`
638 * @param line line of output, NULL at the end
639 */
640static void
641process_unmap_output (void *cls, const char *line)
642{
643 struct GNUNET_NAT_MiniHandle *mini = cls;
644
645 if (NULL == line)
646 {
647 LOG (GNUNET_ERROR_TYPE_DEBUG,
648 "UPnP unmap done\n");
649 GNUNET_OS_command_stop (mini->unmap_cmd);
650 mini->unmap_cmd = NULL;
651 GNUNET_free (mini);
652 return;
653 }
654 /* we don't really care about the output... */
655}
656
657
658/**
659 * Remove a mapping created with (mini)upnpc. Calling
660 * this function will give 'upnpc' 1s to remove tha mapping,
661 * so while this function is non-blocking, a task will be
662 * left with the scheduler for up to 1s past this call.
663 *
664 * @param mini the handle
665 */
666void
667GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini)
668{
669 char pstr[6];
670
671 if (NULL != mini->refresh_task)
672 {
673 GNUNET_SCHEDULER_cancel (mini->refresh_task);
674 mini->refresh_task = NULL;
675 }
676 if (NULL != mini->refresh_cmd)
677 {
678 GNUNET_OS_command_stop (mini->refresh_cmd);
679 mini->refresh_cmd = NULL;
680 }
681 if (NULL != mini->map_cmd)
682 {
683 GNUNET_OS_command_stop (mini->map_cmd);
684 mini->map_cmd = NULL;
685 }
686 if (GNUNET_NO == mini->did_map)
687 {
688 GNUNET_free (mini);
689 return;
690 }
691 mini->ac (mini->ac_cls, GNUNET_NO,
692 (const struct sockaddr *) &mini->current_addr,
693 sizeof (mini->current_addr),
694 GNUNET_NAT_ERROR_SUCCESS);
695 /* Note: oddly enough, deletion uses the external port whereas
696 * addition uses the internal port; this rarely matters since they
697 * often are the same, but it might... */
698 GNUNET_snprintf (pstr,
699 sizeof (pstr),
700 "%u",
701 (unsigned int) ntohs (mini->current_addr.sin_port));
702 LOG (GNUNET_ERROR_TYPE_DEBUG,
703 "Unmapping port %u with UPnP\n",
704 ntohs (mini->current_addr.sin_port));
705 mini->unmap_cmd =
706 GNUNET_OS_command_run (&process_unmap_output, mini, UNMAP_TIMEOUT,
707 "upnpc", "upnpc", "-d", pstr,
708 mini->is_tcp ? "tcp" : "udp", NULL);
709}
710
711
712/* end of nat_mini.c */
diff --git a/src/nat/nat_stun.c b/src/nat/nat_stun.c
deleted file mode 100644
index 62916ab84..000000000
--- a/src/nat/nat_stun.c
+++ /dev/null
@@ -1,439 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2015 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * This code provides some support for doing STUN transactions.
22 * We send simplest possible packet ia REQUEST with BIND to a STUN server.
23 *
24 * All STUN packets start with a simple header made of a type,
25 * length (excluding the header) and a 16-byte random transaction id.
26 * Following the header we may have zero or more attributes, each
27 * structured as a type, length and a value (whose format depends
28 * on the type, but often contains addresses).
29 * Of course all fields are in network format.
30 *
31 * This code was based on ministun.c.
32 *
33 * @file nat/nat_stun.c
34 * @brief Functions for STUN functionality
35 * @author Bruno Souza Cabral
36 */
37
38#include "platform.h"
39#include "gnunet_util_lib.h"
40#include "gnunet_resolver_service.h"
41#include "gnunet_nat_lib.h"
42
43
44#include "nat_stun.h"
45
46#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__)
47
48#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
49
50
51/**
52 * Handle to a request given to the resolver. Can be used to cancel
53 * the request prior to the timeout or successful execution. Also
54 * used to track our internal state for the request.
55 */
56struct GNUNET_NAT_STUN_Handle
57{
58
59 /**
60 * Handle to a pending DNS lookup request.
61 */
62 struct GNUNET_RESOLVER_RequestHandle *dns_active;
63
64 /**
65 * Handle to the listen socket
66 */
67 struct GNUNET_NETWORK_Handle *sock;
68
69 /**
70 * Stun server address
71 */
72 char *stun_server;
73
74 /**
75 * Function to call when a error occours
76 */
77 GNUNET_NAT_STUN_ErrorCallback cb;
78
79 /**
80 * Closure for @e cb.
81 */
82 void *cb_cls;
83
84 /**
85 * Do we got a DNS resolution successfully?
86 */
87 int dns_success;
88
89 /**
90 * STUN port
91 */
92 uint16_t stun_port;
93
94};
95
96
97/**
98 * here we store credentials extracted from a message
99*/
100struct StunState
101{
102 uint16_t attr;
103};
104
105
106/**
107 * Encode a class and method to a compatible STUN format
108 *
109 * @param msg_class class to be converted
110 * @param method method to be converted
111 * @return message in a STUN compatible format
112 */
113static int
114encode_message (enum StunClasses msg_class,
115 enum StunMethods method)
116{
117 return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) |
118 (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2);
119}
120
121
122/**
123 * Fill the stun_header with a random request_id
124 *
125 * @param req, stun header to be filled
126 */
127static void
128generate_request_id (struct stun_header *req)
129{
130 unsigned int x;
131
132 req->magic = htonl(STUN_MAGIC_COOKIE);
133 for (x = 0; x < 3; x++)
134 req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
135 UINT32_MAX);
136}
137
138
139/**
140 * Extract the STUN_MAPPED_ADDRESS from the stun response.
141 * This is used as a callback for stun_handle_response
142 * when called from stun_request.
143 *
144 * @param st, pointer where we will set the type
145 * @param attr , received stun attribute
146 * @param arg , pointer to a sockaddr_in where we will set the reported IP and port
147 * @param magic , Magic cookie
148 *
149 * @return 0 on success, other value otherwise
150 */
151static int
152stun_get_mapped (struct StunState *st,
153 struct stun_attr *attr,
154 struct sockaddr_in *arg,
155 unsigned int magic)
156{
157 struct stun_addr *returned_addr = (struct stun_addr *)(attr + 1);
158 struct sockaddr_in *sa = (struct sockaddr_in *)arg;
159 unsigned short type = ntohs(attr->attr);
160
161 switch (type)
162 {
163 case STUN_MAPPED_ADDRESS:
164 if (st->attr == STUN_XOR_MAPPED_ADDRESS ||
165 st->attr == STUN_MS_XOR_MAPPED_ADDRESS)
166 return 1;
167 magic = 0;
168 break;
169 case STUN_MS_XOR_MAPPED_ADDRESS:
170 if (st->attr == STUN_XOR_MAPPED_ADDRESS)
171 return 1;
172 break;
173 case STUN_XOR_MAPPED_ADDRESS:
174 break;
175 default:
176 return 1;
177 }
178 if ( (ntohs(attr->len) < 8) &&
179 (returned_addr->family != 1) )
180 {
181 return 1;
182 }
183 st->attr = type;
184 sa->sin_family = AF_INET;
185 sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16);
186 sa->sin_addr.s_addr = returned_addr->addr ^ magic;
187 return 0;
188}
189
190
191/**
192 * Handle an incoming STUN message, Do some basic sanity checks on packet size and content,
193 * try to extract a bit of information, and possibly reply.
194 * At the moment this only processes BIND requests, and returns
195 * the externally visible address of the request.
196 * If a callback is specified, invoke it with the attribute.
197 *
198 * @param data the packet
199 * @param len the length of the packet in @a data
200 * @param[out] arg sockaddr_in where we will set our discovered address
201 *
202 * @return, #GNUNET_OK on OK, #GNUNET_NO if the packet is invalid (not a stun packet)
203 */
204int
205GNUNET_NAT_stun_handle_packet (const void *data,
206 size_t len,
207 struct sockaddr_in *arg)
208{
209 const struct stun_header *hdr = (const struct stun_header *)data;
210 struct stun_attr *attr;
211 struct StunState st;
212 int ret = GNUNET_OK;
213 uint32_t advertised_message_size;
214 uint32_t message_magic_cookie;
215
216 /* On entry, 'len' is the length of the udp payload. After the
217 * initial checks it becomes the size of unprocessed options,
218 * while 'data' is advanced accordingly.
219 */
220 if (len < sizeof(struct stun_header))
221 {
222 LOG (GNUNET_ERROR_TYPE_INFO,
223 "STUN packet too short (only %d, wanting at least %d)\n",
224 (int) len,
225 (int) sizeof(struct stun_header));
226 GNUNET_break_op (0);
227 return GNUNET_NO;
228 }
229 /* Skip header as it is already in hdr */
230 len -= sizeof(struct stun_header);
231 data += sizeof(struct stun_header);
232
233 /* len as advertised in the message */
234 advertised_message_size = ntohs(hdr->msglen);
235
236 message_magic_cookie = ntohl(hdr->magic);
237 /* Compare if the cookie match */
238 if (STUN_MAGIC_COOKIE != message_magic_cookie)
239 {
240 LOG (GNUNET_ERROR_TYPE_INFO,
241 "Invalid magic cookie \n");
242 return GNUNET_NO;
243 }
244
245 LOG (GNUNET_ERROR_TYPE_INFO,
246 "STUN Packet, msg %s (%04x), length: %d\n",
247 stun_msg2str(ntohs(hdr->msgtype)),
248 ntohs(hdr->msgtype),
249 advertised_message_size);
250 if (advertised_message_size > len)
251 {
252 LOG (GNUNET_ERROR_TYPE_INFO,
253 "Scrambled STUN packet length (got %d, expecting %d)\n",
254 advertised_message_size,
255 (int)len);
256 return GNUNET_NO;
257 }
258 len = advertised_message_size;
259 memset (&st, 0, sizeof(st));
260
261 while (len > 0)
262 {
263 if (len < sizeof(struct stun_attr))
264 {
265 LOG (GNUNET_ERROR_TYPE_INFO,
266 "Attribute too short (got %d, expecting %d)\n",
267 (int)len,
268 (int) sizeof(struct stun_attr));
269 break;
270 }
271 attr = (struct stun_attr *)data;
272
273 /* compute total attribute length */
274 advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr);
275
276 /* Check if we still have space in our buffer */
277 if (advertised_message_size > len )
278 {
279 LOG (GNUNET_ERROR_TYPE_INFO,
280 "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n",
281 advertised_message_size,
282 (int)len);
283 break;
284 }
285 stun_get_mapped (&st,
286 attr,
287 arg,
288 hdr->magic);
289 /* Clear attribute id: in case previous entry was a string,
290 * this will act as the terminator for the string.
291 */
292 attr->attr = 0;
293 data += advertised_message_size;
294 len -= advertised_message_size;
295 ret = GNUNET_OK;
296 }
297 return ret;
298}
299
300
301/**
302 * Cancel active STUN request. Frees associated resources
303 * and ensures that the callback is no longer invoked.
304 *
305 * @param rh request to cancel
306 */
307void
308GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh)
309{
310 if (NULL != rh->dns_active)
311 {
312 GNUNET_RESOLVER_request_cancel (rh->dns_active);
313 rh->dns_active = NULL;
314 }
315 GNUNET_free (rh->stun_server);
316 GNUNET_free (rh);
317}
318
319
320/**
321 * Try to establish a connection given the specified address.
322 *
323 * @param cls our `struct GNUNET_NAT_STUN_Handle *`
324 * @param addr address to try, NULL for "last call"
325 * @param addrlen length of @a addr
326 */
327static void
328stun_dns_callback (void *cls,
329 const struct sockaddr *addr,
330 socklen_t addrlen)
331{
332 struct GNUNET_NAT_STUN_Handle *rh = cls;
333 struct stun_header *req;
334 uint8_t reqdata[1024];
335 int reqlen;
336 struct sockaddr_in server;
337
338 if (NULL == addr)
339 {
340 rh->dns_active = NULL;
341 if (GNUNET_NO == rh->dns_success)
342 {
343 LOG (GNUNET_ERROR_TYPE_INFO,
344 "Error resolving host %s\n",
345 rh->stun_server);
346 rh->cb (rh->cb_cls,
347 GNUNET_NAT_ERROR_NOT_ONLINE);
348 }
349 else if (GNUNET_SYSERR == rh->dns_success)
350 {
351 rh->cb (rh->cb_cls,
352 GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
353 }
354 else
355 {
356 rh->cb (rh->cb_cls,
357 GNUNET_NAT_ERROR_SUCCESS);
358 }
359 GNUNET_NAT_stun_make_request_cancel (rh);
360 return;
361 }
362
363 rh->dns_success = GNUNET_YES;
364 memset (&server,0, sizeof(server));
365 server.sin_family = AF_INET;
366 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr;
367 server.sin_port = htons(rh->stun_port);
368#if HAVE_SOCKADDR_IN_SIN_LEN
369 server.sin_len = (u_char) sizeof (struct sockaddr_in);
370#endif
371
372 /*Craft the simplest possible STUN packet. A request binding*/
373 req = (struct stun_header *)reqdata;
374 generate_request_id (req);
375 reqlen = 0;
376 req->msgtype = 0;
377 req->msglen = 0;
378 req->msglen = htons (reqlen);
379 req->msgtype = htons (encode_message (STUN_REQUEST,
380 STUN_BINDING));
381
382 /* Send the packet */
383 if (-1 ==
384 GNUNET_NETWORK_socket_sendto (rh->sock,
385 req,
386 ntohs(req->msglen) + sizeof(*req),
387 (const struct sockaddr *) &server,
388 sizeof (server)))
389 {
390 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
391 "sendto");
392 rh->dns_success = GNUNET_SYSERR;
393 return;
394 }
395}
396
397
398/**
399 * Make Generic STUN request. Sends a generic stun request to the
400 * server specified using the specified socket, possibly waiting for
401 * a reply and filling the 'reply' field with the externally visible
402 * address.
403 *
404 * @param server the address of the stun server
405 * @param port port of the stun server
406 * @param sock the socket used to send the request
407 * @param cb callback in case of error
408 * @param cb_cls closure for @a cb
409 * @return NULL on error
410 */
411struct GNUNET_NAT_STUN_Handle *
412GNUNET_NAT_stun_make_request (const char *server,
413 uint16_t port,
414 struct GNUNET_NETWORK_Handle *sock,
415 GNUNET_NAT_STUN_ErrorCallback cb,
416 void *cb_cls)
417{
418 struct GNUNET_NAT_STUN_Handle *rh;
419
420 rh = GNUNET_new (struct GNUNET_NAT_STUN_Handle);
421 rh->sock = sock;
422 rh->cb = cb;
423 rh->cb_cls = cb_cls;
424 rh->stun_server = GNUNET_strdup (server);
425 rh->stun_port = port;
426 rh->dns_success = GNUNET_NO;
427 rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server,
428 AF_INET,
429 TIMEOUT,
430 &stun_dns_callback, rh);
431 if (NULL == rh->dns_active)
432 {
433 GNUNET_NAT_stun_make_request_cancel (rh);
434 return NULL;
435 }
436 return rh;
437}
438
439/* end of nat_stun.c */
diff --git a/src/nse/.gitignore b/src/nse/.gitignore
index 4e6257696..a2575673c 100644
--- a/src/nse/.gitignore
+++ b/src/nse/.gitignore
@@ -1,3 +1,5 @@
1gnunet-service-nse 1gnunet-service-nse
2gnunet-nse 2gnunet-nse
3gnunet-nse-profiler 3gnunet-nse-profiler
4test_nse_api
5perf_kdf
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c
index 511f95514..4d54a740b 100644
--- a/src/nse/gnunet-service-nse.c
+++ b/src/nse/gnunet-service-nse.c
@@ -1346,7 +1346,7 @@ shutdown_task (void *cls)
1346 } 1346 }
1347 if (NULL != core_api) 1347 if (NULL != core_api)
1348 { 1348 {
1349 GNUNET_CORE_disconnecT (core_api); 1349 GNUNET_CORE_disconnect (core_api);
1350 core_api = NULL; 1350 core_api = NULL;
1351 } 1351 }
1352 if (NULL != stats) 1352 if (NULL != stats)
@@ -1607,7 +1607,7 @@ run (void *cls,
1607 GNUNET_YES); 1607 GNUNET_YES);
1608 nc = GNUNET_notification_context_create (1); 1608 nc = GNUNET_notification_context_create (1);
1609 /* Connect to core service and register core handlers */ 1609 /* Connect to core service and register core handlers */
1610 core_api = GNUNET_CORE_connecT (cfg, /* Main configuration */ 1610 core_api = GNUNET_CORE_connect (cfg, /* Main configuration */
1611 NULL, /* Closure passed to functions */ 1611 NULL, /* Closure passed to functions */
1612 &core_init, /* Call core_init once connected */ 1612 &core_init, /* Call core_init once connected */
1613 &handle_core_connect, /* Handle connects */ 1613 &handle_core_connect, /* Handle connects */
diff --git a/src/nse/nse_api.c b/src/nse/nse_api.c
index cfe5482eb..d50b0214a 100644
--- a/src/nse/nse_api.c
+++ b/src/nse/nse_api.c
@@ -150,7 +150,7 @@ reconnect (void *cls)
150 LOG (GNUNET_ERROR_TYPE_DEBUG, 150 LOG (GNUNET_ERROR_TYPE_DEBUG,
151 "Connecting to network size estimation service.\n"); 151 "Connecting to network size estimation service.\n");
152 GNUNET_assert (NULL == h->mq); 152 GNUNET_assert (NULL == h->mq);
153 h->mq = GNUNET_CLIENT_connecT (h->cfg, 153 h->mq = GNUNET_CLIENT_connect (h->cfg,
154 "nse", 154 "nse",
155 handlers, 155 handlers,
156 &mq_error_handler, 156 &mq_error_handler,
diff --git a/src/peerinfo-tool/.gitignore b/src/peerinfo-tool/.gitignore
index dc2209862..d4ed4f801 100644
--- a/src/peerinfo-tool/.gitignore
+++ b/src/peerinfo-tool/.gitignore
@@ -1 +1,2 @@
1gnunet-peerinfo 1gnunet-peerinfo
2test_gnunet_peerinfo.py
diff --git a/src/peerinfo-tool/Makefile.am b/src/peerinfo-tool/Makefile.am
index f22380a9e..c79c3ac68 100644
--- a/src/peerinfo-tool/Makefile.am
+++ b/src/peerinfo-tool/Makefile.am
@@ -19,7 +19,6 @@ gnunet_peerinfo_SOURCES = \
19 19
20gnunet_peerinfo_LDADD = \ 20gnunet_peerinfo_LDADD = \
21 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 21 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
22 $(top_builddir)/src/nat/libgnunetnat.la \
23 $(top_builddir)/src/transport/libgnunettransport.la \ 22 $(top_builddir)/src/transport/libgnunettransport.la \
24 $(top_builddir)/src/hello/libgnunethello.la \ 23 $(top_builddir)/src/hello/libgnunethello.la \
25 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 24 $(top_builddir)/src/statistics/libgnunetstatistics.la \
diff --git a/src/peerinfo/.gitignore b/src/peerinfo/.gitignore
index 950ed60a6..e2a79a211 100644
--- a/src/peerinfo/.gitignore
+++ b/src/peerinfo/.gitignore
@@ -1 +1,5 @@
1gnunet-service-peerinfo 1gnunet-service-peerinfo
2test_peerinfo_api
3test_peerinfo_api_friend_only
4test_peerinfo_api_notify_friend_only
5test_peerinfo_shipped_hellos
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c
index 3080fb503..b75d4e291 100644
--- a/src/peerinfo/peerinfo_api.c
+++ b/src/peerinfo/peerinfo_api.c
@@ -462,7 +462,7 @@ reconnect (struct GNUNET_PEERINFO_Handle *h)
462 GNUNET_MQ_destroy (h->mq); 462 GNUNET_MQ_destroy (h->mq);
463 h->mq = NULL; 463 h->mq = NULL;
464 } 464 }
465 h->mq = GNUNET_CLIENT_connecT (h->cfg, 465 h->mq = GNUNET_CLIENT_connect (h->cfg,
466 "peerinfo", 466 "peerinfo",
467 handlers, 467 handlers,
468 &mq_error_handler, 468 &mq_error_handler,
@@ -557,7 +557,7 @@ GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic)
557struct GNUNET_MQ_Envelope * 557struct GNUNET_MQ_Envelope *
558GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h, 558GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h,
559 const struct GNUNET_HELLO_Message *hello, 559 const struct GNUNET_HELLO_Message *hello,
560 GNUNET_MQ_NotifyCallback cont, 560 GNUNET_SCHEDULER_TaskCallback cont,
561 void *cont_cls) 561 void *cont_cls)
562{ 562{
563 struct GNUNET_MQ_Envelope *env; 563 struct GNUNET_MQ_Envelope *env;
diff --git a/src/peerinfo/peerinfo_api_notify.c b/src/peerinfo/peerinfo_api_notify.c
index e707a911e..ce226d96e 100644
--- a/src/peerinfo/peerinfo_api_notify.c
+++ b/src/peerinfo/peerinfo_api_notify.c
@@ -212,7 +212,7 @@ reconnect (void *cls)
212 struct NotifyMessage *nm; 212 struct NotifyMessage *nm;
213 213
214 nc->task = NULL; 214 nc->task = NULL;
215 nc->mq = GNUNET_CLIENT_connecT (nc->cfg, 215 nc->mq = GNUNET_CLIENT_connect (nc->cfg,
216 "peerinfo", 216 "peerinfo",
217 handlers, 217 handlers,
218 &mq_error_handler, 218 &mq_error_handler,
diff --git a/src/peerstore/.gitignore b/src/peerstore/.gitignore
index a07db8a36..33304d90b 100644
--- a/src/peerstore/.gitignore
+++ b/src/peerstore/.gitignore
@@ -1,2 +1,8 @@
1gnunet-service-peerstore 1gnunet-service-peerstore
2gnunet-peerstore 2gnunet-peerstore
3perf_peerstore_store
4test_peerstore_api_iterate
5test_peerstore_api_store
6test_peerstore_api_sync
7test_peerstore_api_watch
8test_plugin_peerstore_sqlite
diff --git a/src/peerstore/peerstore_api.c b/src/peerstore/peerstore_api.c
index 47bf7775e..c9fcd17ab 100644
--- a/src/peerstore/peerstore_api.c
+++ b/src/peerstore/peerstore_api.c
@@ -829,7 +829,7 @@ reconnect (struct GNUNET_PEERSTORE_Handle *h)
829 GNUNET_MQ_destroy (h->mq); 829 GNUNET_MQ_destroy (h->mq);
830 h->mq = NULL; 830 h->mq = NULL;
831 } 831 }
832 h->mq = GNUNET_CLIENT_connecT (h->cfg, 832 h->mq = GNUNET_CLIENT_connect (h->cfg,
833 "peerstore", 833 "peerstore",
834 mq_handlers, 834 mq_handlers,
835 &handle_client_error, 835 &handle_client_error,
diff --git a/src/pq/.gitignore b/src/pq/.gitignore
new file mode 100644
index 000000000..8de68ddc9
--- /dev/null
+++ b/src/pq/.gitignore
@@ -0,0 +1 @@
test_pq
diff --git a/src/psyc/psyc_api.c b/src/psyc/psyc_api.c
index 9769bb853..c6544df3a 100644
--- a/src/psyc/psyc_api.c
+++ b/src/psyc/psyc_api.c
@@ -598,7 +598,7 @@ channel_disconnect (struct GNUNET_PSYC_Channel *chn,
598 struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (chn->mq); 598 struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (chn->mq);
599 if (NULL != env) 599 if (NULL != env)
600 { 600 {
601 GNUNET_MQ_notify_sent (env, (GNUNET_MQ_NotifyCallback) channel_cleanup, chn); 601 GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) channel_cleanup, chn);
602 } 602 }
603 else 603 else
604 { 604 {
@@ -694,7 +694,7 @@ master_connect (struct GNUNET_PSYC_Master *mst)
694 GNUNET_MQ_handler_end () 694 GNUNET_MQ_handler_end ()
695 }; 695 };
696 696
697 chn->mq = GNUNET_CLIENT_connecT (chn->cfg, "psyc", 697 chn->mq = GNUNET_CLIENT_connect (chn->cfg, "psyc",
698 handlers, master_disconnected, mst); 698 handlers, master_disconnected, mst);
699 GNUNET_assert (NULL != chn->mq); 699 GNUNET_assert (NULL != chn->mq);
700 chn->tmit = GNUNET_PSYC_transmit_create (chn->mq); 700 chn->tmit = GNUNET_PSYC_transmit_create (chn->mq);
@@ -993,7 +993,7 @@ slave_connect (struct GNUNET_PSYC_Slave *slv)
993 GNUNET_MQ_handler_end () 993 GNUNET_MQ_handler_end ()
994 }; 994 };
995 995
996 chn->mq = GNUNET_CLIENT_connecT (chn->cfg, "psyc", 996 chn->mq = GNUNET_CLIENT_connect (chn->cfg, "psyc",
997 handlers, slave_disconnected, slv); 997 handlers, slave_disconnected, slv);
998 GNUNET_assert (NULL != chn->mq); 998 GNUNET_assert (NULL != chn->mq);
999 chn->tmit = GNUNET_PSYC_transmit_create (chn->mq); 999 chn->tmit = GNUNET_PSYC_transmit_create (chn->mq);
diff --git a/src/psycstore/gnunet-service-psycstore.c b/src/psycstore/gnunet-service-psycstore.c
index 573a58d5c..10c92a878 100644
--- a/src/psycstore/gnunet-service-psycstore.c
+++ b/src/psycstore/gnunet-service-psycstore.c
@@ -198,8 +198,8 @@ send_fragment (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg,
198 res->psycstore_flags = htonl (flags); 198 res->psycstore_flags = htonl (flags);
199 GNUNET_memcpy (&res[1], msg, msg_size); 199 GNUNET_memcpy (&res[1], msg, msg_size);
200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
201 "Sending fragment %ld to client\n", 201 "Sending fragment %llu to client\n",
202 GNUNET_ntohll (msg->fragment_id)); 202 (unsigned long long) GNUNET_ntohll (msg->fragment_id));
203 GNUNET_free (msg); 203 GNUNET_free (msg);
204 204
205 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (sc->client), env); 205 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (sc->client), env);
diff --git a/src/psycstore/psycstore_api.c b/src/psycstore/psycstore_api.c
index 480d594fc..40322662e 100644
--- a/src/psycstore/psycstore_api.c
+++ b/src/psycstore/psycstore_api.c
@@ -348,7 +348,7 @@ do_connect (struct GNUNET_PSYCSTORE_Handle *h)
348 348
349 h->op = GNUNET_OP_create (); 349 h->op = GNUNET_OP_create ();
350 GNUNET_assert (NULL == h->mq); 350 GNUNET_assert (NULL == h->mq);
351 h->mq = GNUNET_CLIENT_connecT (h->cfg, "psycstore", 351 h->mq = GNUNET_CLIENT_connect (h->cfg, "psycstore",
352 handlers, disconnected, h); 352 handlers, disconnected, h);
353 GNUNET_assert (NULL != h->mq); 353 GNUNET_assert (NULL != h->mq);
354} 354}
diff --git a/src/regex/.gitignore b/src/regex/.gitignore
index 014e54347..39dc89c88 100644
--- a/src/regex/.gitignore
+++ b/src/regex/.gitignore
@@ -3,3 +3,10 @@ gnunet-daemon-regexprofiler
3gnunet-regex-profiler 3gnunet-regex-profiler
4gnunet-regex-simulation-profiler 4gnunet-regex-simulation-profiler
5gnunet-service-regex 5gnunet-service-regex
6test_graph.dot
7test_regex_api
8test_regex_eval_api
9test_regex_graph_api
10test_regex_integration
11test_regex_iterate_api
12test_regex_proofs
diff --git a/src/regex/regex_api_announce.c b/src/regex/regex_api_announce.c
index 8fded96d2..70bf34bc8 100644
--- a/src/regex/regex_api_announce.c
+++ b/src/regex/regex_api_announce.c
@@ -104,7 +104,7 @@ announce_reconnect (struct GNUNET_REGEX_Announcement *a)
104 struct AnnounceMessage *am; 104 struct AnnounceMessage *am;
105 size_t slen; 105 size_t slen;
106 106
107 a->mq = GNUNET_CLIENT_connecT (a->cfg, 107 a->mq = GNUNET_CLIENT_connect (a->cfg,
108 "regex", 108 "regex",
109 NULL, 109 NULL,
110 &announce_mq_error_handler, 110 &announce_mq_error_handler,
diff --git a/src/regex/regex_api_search.c b/src/regex/regex_api_search.c
index ff85f5748..b7a015f87 100644
--- a/src/regex/regex_api_search.c
+++ b/src/regex/regex_api_search.c
@@ -167,7 +167,7 @@ search_reconnect (struct GNUNET_REGEX_Search *s)
167 struct RegexSearchMessage *rsm; 167 struct RegexSearchMessage *rsm;
168 168
169 GNUNET_assert (NULL == s->mq); 169 GNUNET_assert (NULL == s->mq);
170 s->mq = GNUNET_CLIENT_connecT (s->cfg, 170 s->mq = GNUNET_CLIENT_connect (s->cfg,
171 "regex", 171 "regex",
172 handlers, 172 handlers,
173 &mq_error_handler, 173 &mq_error_handler,
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c
index ad3253548..2965808fa 100644
--- a/src/revocation/gnunet-service-revocation.c
+++ b/src/revocation/gnunet-service-revocation.c
@@ -670,7 +670,7 @@ shutdown_task (void *cls)
670 } 670 }
671 if (NULL != core_api) 671 if (NULL != core_api)
672 { 672 {
673 GNUNET_CORE_disconnecT (core_api); 673 GNUNET_CORE_disconnect (core_api);
674 core_api = NULL; 674 core_api = NULL;
675 } 675 }
676 if (NULL != stats) 676 if (NULL != stats)
@@ -894,7 +894,7 @@ run (void *cls,
894 peers = GNUNET_CONTAINER_multipeermap_create (128, 894 peers = GNUNET_CONTAINER_multipeermap_create (128,
895 GNUNET_YES); 895 GNUNET_YES);
896 /* Connect to core service and register core handlers */ 896 /* Connect to core service and register core handlers */
897 core_api = GNUNET_CORE_connecT (cfg, /* Main configuration */ 897 core_api = GNUNET_CORE_connect (cfg, /* Main configuration */
898 NULL, /* Closure passed to functions */ 898 NULL, /* Closure passed to functions */
899 &core_init, /* Call core_init once connected */ 899 &core_init, /* Call core_init once connected */
900 &handle_core_connect, /* Handle connects */ 900 &handle_core_connect, /* Handle connects */
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
index 8c00ac2ae..fde0296a4 100644
--- a/src/revocation/revocation_api.c
+++ b/src/revocation/revocation_api.c
@@ -125,7 +125,7 @@ GNUNET_REVOCATION_query (const struct GNUNET_CONFIGURATION_Handle *cfg,
125 struct QueryMessage *qm; 125 struct QueryMessage *qm;
126 struct GNUNET_MQ_Envelope *env; 126 struct GNUNET_MQ_Envelope *env;
127 127
128 q->mq = GNUNET_CLIENT_connecT (cfg, 128 q->mq = GNUNET_CLIENT_connect (cfg,
129 "revocation", 129 "revocation",
130 handlers, 130 handlers,
131 &query_mq_error_handler, 131 &query_mq_error_handler,
@@ -283,7 +283,7 @@ GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
283 return NULL; 283 return NULL;
284 } 284 }
285 285
286 h->mq = GNUNET_CLIENT_connecT (cfg, 286 h->mq = GNUNET_CLIENT_connect (cfg,
287 "revocation", 287 "revocation",
288 handlers, 288 handlers,
289 &revocation_mq_error_handler, 289 &revocation_mq_error_handler,
diff --git a/src/revocation/test_revocation.c b/src/revocation/test_revocation.c
index ba659d9d8..d3bbb879a 100644
--- a/src/revocation/test_revocation.c
+++ b/src/revocation/test_revocation.c
@@ -337,7 +337,7 @@ core_connect_adapter (void *cls,
337 struct TestPeer *me = cls; 337 struct TestPeer *me = cls;
338 338
339 me->cfg = cfg; 339 me->cfg = cfg;
340 me->ch = GNUNET_CORE_connecT (cfg, 340 me->ch = GNUNET_CORE_connect (cfg,
341 me, 341 me,
342 NULL, 342 NULL,
343 &connect_cb, 343 &connect_cb,
@@ -356,7 +356,7 @@ core_disconnect_adapter (void *cls,
356{ 356{
357 struct TestPeer *me = cls; 357 struct TestPeer *me = cls;
358 358
359 GNUNET_CORE_disconnecT (me->ch); 359 GNUNET_CORE_disconnect (me->ch);
360 me->ch = NULL; 360 me->ch = NULL;
361} 361}
362 362
diff --git a/src/rps/rps_api.c b/src/rps/rps_api.c
index 3d2f37359..504f28b92 100644
--- a/src/rps/rps_api.c
+++ b/src/rps/rps_api.c
@@ -286,7 +286,7 @@ reconnect (struct GNUNET_RPS_Handle *h)
286 286
287 if (NULL != h->mq) 287 if (NULL != h->mq)
288 GNUNET_MQ_destroy (h->mq); 288 GNUNET_MQ_destroy (h->mq);
289 h->mq = GNUNET_CLIENT_connecT (h->cfg, 289 h->mq = GNUNET_CLIENT_connect (h->cfg,
290 "rps", 290 "rps",
291 mq_handlers, 291 mq_handlers,
292 &mq_error_handler, 292 &mq_error_handler,
diff --git a/src/scalarproduct/scalarproduct_api.c b/src/scalarproduct/scalarproduct_api.c
index 9606851c8..df9f8d196 100644
--- a/src/scalarproduct/scalarproduct_api.c
+++ b/src/scalarproduct/scalarproduct_api.c
@@ -256,7 +256,7 @@ GNUNET_SCALARPRODUCT_accept_computation (const struct GNUNET_CONFIGURATION_Handl
256 h->response_proc = &process_status_message; 256 h->response_proc = &process_status_message;
257 h->cfg = cfg; 257 h->cfg = cfg;
258 h->key = *session_key; 258 h->key = *session_key;
259 h->mq = GNUNET_CLIENT_connecT (cfg, 259 h->mq = GNUNET_CLIENT_connect (cfg,
260 "scalarproduct-bob", 260 "scalarproduct-bob",
261 handlers, 261 handlers,
262 &mq_error_handler, 262 &mq_error_handler,
@@ -408,7 +408,7 @@ GNUNET_SCALARPRODUCT_start_computation (const struct GNUNET_CONFIGURATION_Handle
408 if (GNUNET_SYSERR == check_unique (elements, 408 if (GNUNET_SYSERR == check_unique (elements,
409 element_count)) 409 element_count))
410 return NULL; 410 return NULL;
411 h->mq = GNUNET_CLIENT_connecT (cfg, 411 h->mq = GNUNET_CLIENT_connect (cfg,
412 "scalarproduct-alice", 412 "scalarproduct-alice",
413 handlers, 413 handlers,
414 &mq_error_handler, 414 &mq_error_handler,
diff --git a/src/secretsharing/secretsharing_api.c b/src/secretsharing/secretsharing_api.c
index 78167b671..85df66c13 100644
--- a/src/secretsharing/secretsharing_api.c
+++ b/src/secretsharing/secretsharing_api.c
@@ -261,7 +261,7 @@ GNUNET_SECRETSHARING_create_session (const struct GNUNET_CONFIGURATION_Handle *c
261 struct GNUNET_MQ_Envelope *ev; 261 struct GNUNET_MQ_Envelope *ev;
262 struct GNUNET_SECRETSHARING_CreateMessage *msg; 262 struct GNUNET_SECRETSHARING_CreateMessage *msg;
263 263
264 s->mq = GNUNET_CLIENT_connecT (cfg, 264 s->mq = GNUNET_CLIENT_connect (cfg,
265 "secretsharing", 265 "secretsharing",
266 mq_handlers, 266 mq_handlers,
267 &handle_session_client_error, 267 &handle_session_client_error,
@@ -348,7 +348,7 @@ GNUNET_SECRETSHARING_decrypt (const struct GNUNET_CONFIGURATION_Handle *cfg,
348 348
349 s->decrypt_cb = decrypt_cb; 349 s->decrypt_cb = decrypt_cb;
350 s->decrypt_cls = decrypt_cb_cls; 350 s->decrypt_cls = decrypt_cb_cls;
351 s->mq = GNUNET_CLIENT_connecT (cfg, 351 s->mq = GNUNET_CLIENT_connect (cfg,
352 "secretsharing", 352 "secretsharing",
353 mq_handlers, 353 mq_handlers,
354 &handle_decrypt_client_error, 354 &handle_decrypt_client_error,
diff --git a/src/set/Makefile.am b/src/set/Makefile.am
index 0142b1729..4d990479c 100644
--- a/src/set/Makefile.am
+++ b/src/set/Makefile.am
@@ -16,11 +16,13 @@ if USE_COVERAGE
16 AM_CFLAGS = -fprofile-arcs -ftest-coverage 16 AM_CFLAGS = -fprofile-arcs -ftest-coverage
17endif 17endif
18 18
19if HAVE_TESTING
19bin_PROGRAMS = \ 20bin_PROGRAMS = \
20 gnunet-set-profiler 21 gnunet-set-profiler
21 22
22noinst_PROGRAMS = \ 23noinst_PROGRAMS = \
23 gnunet-set-ibf-profiler 24 gnunet-set-ibf-profiler
25endif
24 26
25libexec_PROGRAMS = \ 27libexec_PROGRAMS = \
26 gnunet-service-set 28 gnunet-service-set
diff --git a/src/set/set_api.c b/src/set/set_api.c
index 7a33b86ea..7a7267a33 100644
--- a/src/set/set_api.c
+++ b/src/set/set_api.c
@@ -586,7 +586,7 @@ create_internal (const struct GNUNET_CONFIGURATION_Handle *cfg,
586 struct GNUNET_SET_CopyLazyConnectMessage *copy_msg; 586 struct GNUNET_SET_CopyLazyConnectMessage *copy_msg;
587 587
588 set->cfg = cfg; 588 set->cfg = cfg;
589 set->mq = GNUNET_CLIENT_connecT (cfg, 589 set->mq = GNUNET_CLIENT_connect (cfg,
590 "set", 590 "set",
591 mq_handlers, 591 mq_handlers,
592 &handle_client_set_error, 592 &handle_client_set_error,
@@ -914,7 +914,7 @@ listen_connect (void *cls)
914 914
915 lh->reconnect_task = NULL; 915 lh->reconnect_task = NULL;
916 GNUNET_assert (NULL == lh->mq); 916 GNUNET_assert (NULL == lh->mq);
917 lh->mq = GNUNET_CLIENT_connecT (lh->cfg, 917 lh->mq = GNUNET_CLIENT_connect (lh->cfg,
918 "set", 918 "set",
919 mq_handlers, 919 mq_handlers,
920 &handle_client_listener_error, 920 &handle_client_listener_error,
diff --git a/src/social/gnunet-social.c b/src/social/gnunet-social.c
index afd06028c..6d72ca552 100644
--- a/src/social/gnunet-social.c
+++ b/src/social/gnunet-social.c
@@ -360,7 +360,7 @@ notify_data (void *cls, uint16_t *data_size, void *data)
360 360
361 if (0 == tmit->size) 361 if (0 == tmit->size)
362 { 362 {
363 if (op_host_announce || op_host_assign || op_guest_talk) 363 if ((op_host_announce || op_host_assign || op_guest_talk) && !opt_follow)
364 { 364 {
365 exit_success (); 365 exit_success ();
366 } 366 }
diff --git a/src/social/social_api.c b/src/social/social_api.c
index f78cb9a85..a7fe0916f 100644
--- a/src/social/social_api.c
+++ b/src/social/social_api.c
@@ -893,7 +893,7 @@ handle_guest_enter_decision (void *cls,
893 struct GNUNET_SOCIAL_Guest *gst = cls; 893 struct GNUNET_SOCIAL_Guest *gst = cls;
894 894
895 struct GNUNET_PSYC_Message *pmsg = NULL; 895 struct GNUNET_PSYC_Message *pmsg = NULL;
896 if (ntohs (dcsn->header.size) <= sizeof (*dcsn) + sizeof (*pmsg)) 896 if (ntohs (dcsn->header.size) > sizeof (*dcsn))
897 pmsg = (struct GNUNET_PSYC_Message *) GNUNET_MQ_extract_nested_mh (dcsn); 897 pmsg = (struct GNUNET_PSYC_Message *) GNUNET_MQ_extract_nested_mh (dcsn);
898 898
899 if (NULL != gst->entry_dcsn_cb) 899 if (NULL != gst->entry_dcsn_cb)
@@ -1087,7 +1087,7 @@ place_disconnect (struct GNUNET_SOCIAL_Place *plc,
1087 struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (plc->mq); 1087 struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (plc->mq);
1088 if (NULL != env) 1088 if (NULL != env)
1089 { 1089 {
1090 GNUNET_MQ_notify_sent (env, (GNUNET_MQ_NotifyCallback) place_cleanup, plc); 1090 GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) place_cleanup, plc);
1091 } 1091 }
1092 else 1092 else
1093 { 1093 {
@@ -1195,7 +1195,7 @@ host_connect (struct GNUNET_SOCIAL_Host *hst)
1195 GNUNET_MQ_handler_end () 1195 GNUNET_MQ_handler_end ()
1196 }; 1196 };
1197 1197
1198 plc->mq = GNUNET_CLIENT_connecT (plc->cfg, "social", 1198 plc->mq = GNUNET_CLIENT_connect (plc->cfg, "social",
1199 handlers, host_disconnected, hst); 1199 handlers, host_disconnected, hst);
1200 GNUNET_assert (NULL != plc->mq); 1200 GNUNET_assert (NULL != plc->mq);
1201 plc->tmit = GNUNET_PSYC_transmit_create (plc->mq); 1201 plc->tmit = GNUNET_PSYC_transmit_create (plc->mq);
@@ -1697,7 +1697,7 @@ guest_connect (struct GNUNET_SOCIAL_Guest *gst)
1697 GNUNET_MQ_handler_end () 1697 GNUNET_MQ_handler_end ()
1698 }; 1698 };
1699 1699
1700 plc->mq = GNUNET_CLIENT_connecT (plc->cfg, "social", 1700 plc->mq = GNUNET_CLIENT_connect (plc->cfg, "social",
1701 handlers, guest_disconnected, gst); 1701 handlers, guest_disconnected, gst);
1702 GNUNET_assert (NULL != plc->mq); 1702 GNUNET_assert (NULL != plc->mq);
1703 plc->tmit = GNUNET_PSYC_transmit_create (plc->mq); 1703 plc->tmit = GNUNET_PSYC_transmit_create (plc->mq);
@@ -2597,7 +2597,7 @@ app_connect (struct GNUNET_SOCIAL_App *app)
2597 GNUNET_MQ_handler_end () 2597 GNUNET_MQ_handler_end ()
2598 }; 2598 };
2599 2599
2600 app->mq = GNUNET_CLIENT_connecT (app->cfg, "social", 2600 app->mq = GNUNET_CLIENT_connect (app->cfg, "social",
2601 handlers, app_disconnected, app); 2601 handlers, app_disconnected, app);
2602 GNUNET_assert (NULL != app->mq); 2602 GNUNET_assert (NULL != app->mq);
2603 GNUNET_MQ_send_copy (app->mq, app->connect_env); 2603 GNUNET_MQ_send_copy (app->mq, app->connect_env);
@@ -2701,7 +2701,7 @@ GNUNET_SOCIAL_app_disconnect (struct GNUNET_SOCIAL_App *app,
2701 struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (app->mq); 2701 struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (app->mq);
2702 if (NULL != env) 2702 if (NULL != env)
2703 { 2703 {
2704 GNUNET_MQ_notify_sent (env, (GNUNET_MQ_NotifyCallback) app_cleanup, app); 2704 GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) app_cleanup, app);
2705 } 2705 }
2706 else 2706 else
2707 { 2707 {
diff --git a/src/statistics/.gitignore b/src/statistics/.gitignore
index 55f015bce..f1f567149 100644
--- a/src/statistics/.gitignore
+++ b/src/statistics/.gitignore
@@ -1,2 +1,7 @@
1gnunet-statistics 1gnunet-statistics
2gnunet-service-statistics 2gnunet-service-statistics
3test_gnunet_statistics.py
4test_statistics_api
5test_statistics_api_loop
6test_statistics_api_watch
7test_statistics_api_watch_zero_value
diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c
index bfa2da3b4..ad4453b2a 100644
--- a/src/statistics/statistics_api.c
+++ b/src/statistics/statistics_api.c
@@ -678,7 +678,7 @@ try_connect (struct GNUNET_STATISTICS_Handle *h)
678 return GNUNET_NO; 678 return GNUNET_NO;
679 if (NULL != h->mq) 679 if (NULL != h->mq)
680 return GNUNET_YES; 680 return GNUNET_YES;
681 h->mq = GNUNET_CLIENT_connecT (h->cfg, 681 h->mq = GNUNET_CLIENT_connect (h->cfg,
682 "statistics", 682 "statistics",
683 handlers, 683 handlers,
684 &mq_error_handler, 684 &mq_error_handler,
diff --git a/src/template/.gitignore b/src/template/.gitignore
index 6e6ad861c..8ac4bacb5 100644
--- a/src/template/.gitignore
+++ b/src/template/.gitignore
@@ -1,2 +1,3 @@
1gnunet-template 1gnunet-template
2gnunet-service-template 2gnunet-service-template
3test_template_api
diff --git a/src/testbed-logger/.gitignore b/src/testbed-logger/.gitignore
index eb2ed00b0..de0c2dcfe 100644
--- a/src/testbed-logger/.gitignore
+++ b/src/testbed-logger/.gitignore
@@ -1 +1,2 @@
1gnunet-service-testbed-logger 1gnunet-service-testbed-logger
2test_testbed_logger_api
diff --git a/src/testbed-logger/testbed_logger_api.c b/src/testbed-logger/testbed_logger_api.c
index 19a5d9b50..25494aed0 100644
--- a/src/testbed-logger/testbed_logger_api.c
+++ b/src/testbed-logger/testbed_logger_api.c
@@ -224,7 +224,7 @@ GNUNET_TESTBED_LOGGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
224 struct GNUNET_TESTBED_LOGGER_Handle *h; 224 struct GNUNET_TESTBED_LOGGER_Handle *h;
225 225
226 h = GNUNET_new (struct GNUNET_TESTBED_LOGGER_Handle); 226 h = GNUNET_new (struct GNUNET_TESTBED_LOGGER_Handle);
227 h->mq = GNUNET_CLIENT_connecT (cfg, 227 h->mq = GNUNET_CLIENT_connect (cfg,
228 "testbed-logger", 228 "testbed-logger",
229 NULL, 229 NULL,
230 &mq_error_handler, 230 &mq_error_handler,
diff --git a/src/testbed/.gitignore b/src/testbed/.gitignore
index acffa9b91..f7cfb1e23 100644
--- a/src/testbed/.gitignore
+++ b/src/testbed/.gitignore
@@ -5,3 +5,33 @@ gnunet-daemon-testbed-blacklist
5gnunet-daemon-testbed-underlay 5gnunet-daemon-testbed-underlay
6gnunet-helper-testbed 6gnunet-helper-testbed
7gnunet-service-testbed 7gnunet-service-testbed
8gnunet-service-test-barriers
9test_gnunet_helper_testbed
10test_testbed_api
11test_testbed_api_2peers_1controller
12test_testbed_api_3peers_3controllers
13test_testbed_api_barriers
14test_testbed_api_controllerlink
15test_testbed_api_hosts
16test_testbed_api_operations
17test_testbed_api_peer_reconfiguration
18test_testbed_api_peers_manage_services
19test_testbed_api_sd
20test_testbed_api_statistics
21test_testbed_api_test
22test_testbed_api_test_timeout
23test_testbed_api_testbed_run
24test_testbed_api_testbed_run_topology2dtorus
25test_testbed_api_testbed_run_topologyclique
26test_testbed_api_testbed_run_topologyfromfile
27test_testbed_api_testbed_run_topologyline
28test_testbed_api_testbed_run_topologyrandom
29test_testbed_api_testbed_run_topologyring
30test_testbed_api_testbed_run_topologyscalefree
31test_testbed_api_testbed_run_topologysmallworld
32test_testbed_api_testbed_run_topologysmallworldring
33test_testbed_api_testbed_run_topologystar
34test_testbed_api_testbed_run_waitforever
35test_testbed_api_topology
36test_testbed_api_topology_clique
37test_testbed_underlay
diff --git a/src/testbed/gnunet-service-testbed_connectionpool.c b/src/testbed/gnunet-service-testbed_connectionpool.c
index b0e369c6a..6bc744ba8 100644
--- a/src/testbed/gnunet-service-testbed_connectionpool.c
+++ b/src/testbed/gnunet-service-testbed_connectionpool.c
@@ -623,12 +623,12 @@ core_peer_connect_cb (void *cls,
623 623
624 624
625/** 625/**
626 * Function called after #GNUNET_CORE_connecT() has succeeded (or failed 626 * Function called after #GNUNET_CORE_connect() has succeeded (or failed
627 * for good). Note that the private key of the peer is intentionally 627 * for good). Note that the private key of the peer is intentionally
628 * not exposed here; if you need it, your process should try to read 628 * not exposed here; if you need it, your process should try to read
629 * the private key file directly (which should work if you are 629 * the private key file directly (which should work if you are
630 * authorized...). Implementations of this function must not call 630 * authorized...). Implementations of this function must not call
631 * #GNUNET_CORE_disconnecT() (other than by scheduling a new task to 631 * #GNUNET_CORE_disconnect() (other than by scheduling a new task to
632 * do this later). 632 * do this later).
633 * 633 *
634 * @param cls the #PooledConnection object 634 * @param cls the #PooledConnection object
@@ -675,7 +675,7 @@ opstart_get_handle_core (void *cls)
675 LOG_DEBUG ("Opening a CORE connection to peer %u\n", 675 LOG_DEBUG ("Opening a CORE connection to peer %u\n",
676 entry->index); 676 entry->index);
677 entry->handle_core 677 entry->handle_core
678 = GNUNET_CORE_connecT (entry->cfg, 678 = GNUNET_CORE_connect (entry->cfg,
679 entry, /* closure */ 679 entry, /* closure */
680 &core_startup_cb, /* core startup notify */ 680 &core_startup_cb, /* core startup notify */
681 &core_peer_connect_cb, /* peer connect notify */ 681 &core_peer_connect_cb, /* peer connect notify */
@@ -697,7 +697,7 @@ oprelease_get_handle_core (void *cls)
697 697
698 if (NULL == entry->handle_core) 698 if (NULL == entry->handle_core)
699 return; 699 return;
700 GNUNET_CORE_disconnecT (entry->handle_core); 700 GNUNET_CORE_disconnect (entry->handle_core);
701 entry->handle_core = NULL; 701 entry->handle_core = NULL;
702 GNUNET_free_non_null (entry->peer_identity); 702 GNUNET_free_non_null (entry->peer_identity);
703 entry->peer_identity = NULL; 703 entry->peer_identity = NULL;
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c
index ae40948b3..0e0a5da9c 100644
--- a/src/testbed/testbed_api.c
+++ b/src/testbed/testbed_api.c
@@ -1646,7 +1646,7 @@ GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
1646 controller->cc_cls = cc_cls; 1646 controller->cc_cls = cc_cls;
1647 controller->event_mask = event_mask; 1647 controller->event_mask = event_mask;
1648 controller->cfg = GNUNET_CONFIGURATION_dup (cfg); 1648 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1649 controller->mq = GNUNET_CLIENT_connecT (controller->cfg, 1649 controller->mq = GNUNET_CLIENT_connect (controller->cfg,
1650 "testbed", 1650 "testbed",
1651 handlers, 1651 handlers,
1652 &mq_error_handler, 1652 &mq_error_handler,
diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c
index 1679756a1..93698d4b7 100644
--- a/src/testbed/testbed_api_barriers.c
+++ b/src/testbed/testbed_api_barriers.c
@@ -215,7 +215,7 @@ GNUNET_TESTBED_barrier_wait (const char *name,
215 h->name = GNUNET_strdup (name); 215 h->name = GNUNET_strdup (name);
216 h->cb = cb; 216 h->cb = cb;
217 h->cb_cls = cb_cls; 217 h->cb_cls = cb_cls;
218 h->mq = GNUNET_CLIENT_connecT (h->cfg, 218 h->mq = GNUNET_CLIENT_connect (h->cfg,
219 "testbed-barrier", 219 "testbed-barrier",
220 handlers, 220 handlers,
221 &mq_error_handler, 221 &mq_error_handler,
diff --git a/src/testing/.gitignore b/src/testing/.gitignore
index 212ed2ad3..f350da1f2 100644
--- a/src/testing/.gitignore
+++ b/src/testing/.gitignore
@@ -1,2 +1,7 @@
1list-keys 1list-keys
2gnunet-testing 2gnunet-testing
3test_testing_peerstartup
4test_testing_peerstartup2
5test_testing_portreservation
6test_testing_servicestartup
7test_testing_sharedservices
diff --git a/src/topology/.gitignore b/src/topology/.gitignore
index 9ac8c7c47..cfa95ec7e 100644
--- a/src/topology/.gitignore
+++ b/src/topology/.gitignore
@@ -1 +1,2 @@
1gnunet-daemon-topology 1gnunet-daemon-topology
2test_gnunet_daemon_topology
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index 69f01e043..d48f07e71 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -902,7 +902,7 @@ process_peer (void *cls,
902 902
903 903
904/** 904/**
905 * Function called after #GNUNET_CORE_connecT has succeeded 905 * Function called after #GNUNET_CORE_connect has succeeded
906 * (or failed for good). 906 * (or failed for good).
907 * 907 *
908 * @param cls closure 908 * @param cls closure
@@ -1101,7 +1101,7 @@ cleaning_task (void *cls)
1101 } 1101 }
1102 if (NULL != handle) 1102 if (NULL != handle)
1103 { 1103 {
1104 GNUNET_CORE_disconnecT (handle); 1104 GNUNET_CORE_disconnect (handle);
1105 handle = NULL; 1105 handle = NULL;
1106 } 1106 }
1107 whitelist_peers (); 1107 whitelist_peers ();
@@ -1189,7 +1189,7 @@ run (void *cls,
1189 &blacklist_check, 1189 &blacklist_check,
1190 NULL); 1190 NULL);
1191 ats = GNUNET_ATS_connectivity_init (cfg); 1191 ats = GNUNET_ATS_connectivity_init (cfg);
1192 handle = GNUNET_CORE_connecT (cfg, 1192 handle = GNUNET_CORE_connect (cfg,
1193 NULL, 1193 NULL,
1194 &core_init, 1194 &core_init,
1195 &connect_notify, 1195 &connect_notify,
diff --git a/src/transport/.gitignore b/src/transport/.gitignore
index eab8d3146..d035b4011 100644
--- a/src/transport/.gitignore
+++ b/src/transport/.gitignore
@@ -7,3 +7,79 @@ gnunet-transport
7gnunet-transport-certificate-creation 7gnunet-transport-certificate-creation
8gnunet-transport-profiler 8gnunet-transport-profiler
9gnunet-transport-wlan-receiver 9gnunet-transport-wlan-receiver
10https_cert_qutoa_p2.crt
11https_key_quota_p2.key
12test_http_common
13test_plugin_bluetooth
14test_plugin_http_client
15test_plugin_http_server
16test_plugin_https_client
17test_plugin_https_server
18test_plugin_tcp
19test_plugin_udp
20test_plugin_unix
21test_plugin_wlan
22test_quota_compliance_bluetooth
23test_quota_compliance_bluetooth_asymmetric
24test_quota_compliance_http
25test_quota_compliance_http_asymmetric
26test_quota_compliance_https
27test_quota_compliance_https_asymmetric
28test_quota_compliance_tcp
29test_quota_compliance_tcp_asymmetric
30test_quota_compliance_udp
31test_quota_compliance_unix
32test_quota_compliance_unix_asymmetric
33test_quota_compliance_wlan
34test_quota_compliance_wlan_asymmetric
35test_transport_address_switch_http
36test_transport_address_switch_https
37test_transport_address_switch_tcp
38test_transport_address_switch_udp
39test_transport_api_blacklisting_tcp
40test_transport_api_bluetooth
41test_transport_api_disconnect_tcp
42test_transport_api_http
43test_transport_api_http_reverse
44test_transport_api_https
45test_transport_api_limited_sockets_tcp
46test_transport_api_manipulation_cfg
47test_transport_api_manipulation_recv_tcp
48test_transport_api_manipulation_send_tcp
49test_transport_api_monitor_peers
50test_transport_api_multi
51test_transport_api_reliability_bluetooth
52test_transport_api_reliability_http
53test_transport_api_reliability_http_xhr
54test_transport_api_reliability_https
55test_transport_api_reliability_https_xhr
56test_transport_api_reliability_tcp
57test_transport_api_reliability_tcp_nat
58test_transport_api_reliability_udp
59test_transport_api_reliability_unix
60test_transport_api_reliability_wlan
61test_transport_api_restart_1peer
62test_transport_api_restart_2peers
63test_transport_api_slow_ats
64test_transport_api_tcp
65test_transport_api_tcp_nat
66test_transport_api_timeout_bluetooth
67test_transport_api_timeout_http
68test_transport_api_timeout_https
69test_transport_api_timeout_tcp
70test_transport_api_timeout_udp
71test_transport_api_timeout_unix
72test_transport_api_timeout_wlan
73test_transport_api_udp
74test_transport_api_udp_nat
75test_transport_api_unix
76test_transport_api_unix_abstract
77test_transport_api_wlan
78test_transport_blacklisting_inbound_bl_full
79test_transport_blacklisting_inbound_bl_plugin
80test_transport_blacklisting_multiple_plugins
81test_transport_blacklisting_no_bl
82test_transport_blacklisting_outbound_bl_full
83test_transport_blacklisting_outbound_bl_plugin
84test_transport_testing_restart
85test_transport_testing_startstop
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 9fb451383..0b523eecc 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -235,7 +235,6 @@ gnunet_transport_profiler_SOURCES = \
235 gnunet-transport-profiler.c 235 gnunet-transport-profiler.c
236gnunet_transport_profiler_LDADD = \ 236gnunet_transport_profiler_LDADD = \
237 libgnunettransport.la \ 237 libgnunettransport.la \
238 $(top_builddir)/src/nat/libgnunetnat.la \
239 $(top_builddir)/src/hello/libgnunethello.la \ 238 $(top_builddir)/src/hello/libgnunethello.la \
240 $(top_builddir)/src/ats/libgnunetats.la \ 239 $(top_builddir)/src/ats/libgnunetats.la \
241 $(top_builddir)/src/util/libgnunetutil.la \ 240 $(top_builddir)/src/util/libgnunetutil.la \
@@ -245,7 +244,6 @@ gnunet_transport_SOURCES = \
245 gnunet-transport.c 244 gnunet-transport.c
246gnunet_transport_LDADD = \ 245gnunet_transport_LDADD = \
247 libgnunettransport.la \ 246 libgnunettransport.la \
248 $(top_builddir)/src/nat/libgnunetnat.la \
249 $(top_builddir)/src/hello/libgnunethello.la \ 247 $(top_builddir)/src/hello/libgnunethello.la \
250 $(top_builddir)/src/util/libgnunetutil.la \ 248 $(top_builddir)/src/util/libgnunetutil.la \
251 $(GN_LIBINTL) 249 $(GN_LIBINTL)
@@ -268,7 +266,6 @@ gnunet_service_transport_LDADD = \
268 $(top_builddir)/src/ats/libgnunetats.la \ 266 $(top_builddir)/src/ats/libgnunetats.la \
269 $(top_builddir)/src/hello/libgnunethello.la \ 267 $(top_builddir)/src/hello/libgnunethello.la \
270 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 268 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
271 $(top_builddir)/src/nat/libgnunetnat.la \
272 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 269 $(top_builddir)/src/statistics/libgnunetstatistics.la \
273 $(top_builddir)/src/util/libgnunetutil.la \ 270 $(top_builddir)/src/util/libgnunetutil.la \
274 $(GN_GLPK) \ 271 $(GN_GLPK) \
@@ -299,7 +296,7 @@ libgnunet_plugin_transport_tcp_la_LIBADD = \
299 $(top_builddir)/src/hello/libgnunethello.la \ 296 $(top_builddir)/src/hello/libgnunethello.la \
300 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 297 $(top_builddir)/src/statistics/libgnunetstatistics.la \
301 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 298 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
302 $(top_builddir)/src/nat/libgnunetnat.la \ 299 $(top_builddir)/src/nat/libgnunetnatnew.la \
303 $(top_builddir)/src/util/libgnunetutil.la \ 300 $(top_builddir)/src/util/libgnunetutil.la \
304 $(LTLIBINTL) 301 $(LTLIBINTL)
305libgnunet_plugin_transport_tcp_la_LDFLAGS = \ 302libgnunet_plugin_transport_tcp_la_LDFLAGS = \
@@ -347,7 +344,7 @@ libgnunet_plugin_transport_udp_la_LIBADD = \
347 $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ 344 $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \
348 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 345 $(top_builddir)/src/statistics/libgnunetstatistics.la \
349 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 346 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
350 $(top_builddir)/src/nat/libgnunetnat.la \ 347 $(top_builddir)/src/nat/libgnunetnatnew.la \
351 $(top_builddir)/src/util/libgnunetutil.la \ 348 $(top_builddir)/src/util/libgnunetutil.la \
352 $(LTLIBINTL) 349 $(LTLIBINTL)
353libgnunet_plugin_transport_udp_la_LDFLAGS = \ 350libgnunet_plugin_transport_udp_la_LDFLAGS = \
@@ -372,7 +369,6 @@ libgnunet_plugin_transport_http_client_la_LIBADD = \
372 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 369 $(top_builddir)/src/statistics/libgnunetstatistics.la \
373 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 370 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
374 $(LIB_GNURL) \ 371 $(LIB_GNURL) \
375 $(top_builddir)/src/nat/libgnunetnat.la \
376 $(top_builddir)/src/util/libgnunetutil.la 372 $(top_builddir)/src/util/libgnunetutil.la
377libgnunet_plugin_transport_http_client_la_LDFLAGS = \ 373libgnunet_plugin_transport_http_client_la_LDFLAGS = \
378 $(GN_PLUGIN_LDFLAGS) 374 $(GN_PLUGIN_LDFLAGS)
@@ -388,7 +384,7 @@ libgnunet_plugin_transport_http_server_la_LIBADD = \
388 $(top_builddir)/src/hello/libgnunethello.la \ 384 $(top_builddir)/src/hello/libgnunethello.la \
389 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 385 $(top_builddir)/src/statistics/libgnunetstatistics.la \
390 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 386 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
391 $(top_builddir)/src/nat/libgnunetnat.la \ 387 $(top_builddir)/src/nat/libgnunetnatnew.la \
392 $(top_builddir)/src/util/libgnunetutil.la 388 $(top_builddir)/src/util/libgnunetutil.la
393libgnunet_plugin_transport_http_server_la_LDFLAGS = \ 389libgnunet_plugin_transport_http_server_la_LDFLAGS = \
394 $(GN_LIBMHD) \ 390 $(GN_LIBMHD) \
@@ -403,7 +399,6 @@ libgnunet_plugin_transport_https_client_la_LIBADD = \
403 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 399 $(top_builddir)/src/statistics/libgnunetstatistics.la \
404 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 400 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
405 $(LIB_GNURL) \ 401 $(LIB_GNURL) \
406 $(top_builddir)/src/nat/libgnunetnat.la \
407 $(top_builddir)/src/util/libgnunetutil.la 402 $(top_builddir)/src/util/libgnunetutil.la
408libgnunet_plugin_transport_https_client_la_LDFLAGS = \ 403libgnunet_plugin_transport_https_client_la_LDFLAGS = \
409 $(GN_PLUGIN_LDFLAGS) 404 $(GN_PLUGIN_LDFLAGS)
@@ -419,7 +414,7 @@ libgnunet_plugin_transport_https_server_la_LIBADD = \
419 $(top_builddir)/src/hello/libgnunethello.la \ 414 $(top_builddir)/src/hello/libgnunethello.la \
420 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 415 $(top_builddir)/src/statistics/libgnunetstatistics.la \
421 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 416 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
422 $(top_builddir)/src/nat/libgnunetnat.la \ 417 $(top_builddir)/src/nat/libgnunetnatnew.la \
423 $(top_builddir)/src/util/libgnunetutil.la 418 $(top_builddir)/src/util/libgnunetutil.la
424libgnunet_plugin_transport_https_server_la_LDFLAGS = \ 419libgnunet_plugin_transport_https_server_la_LDFLAGS = \
425 $(GN_LIBMHD) \ 420 $(GN_LIBMHD) \
@@ -1176,7 +1171,6 @@ test_quota_compliance_wlan_asymmetric_LDADD = \
1176test_quota_compliance_bluetooth_SOURCES = \ 1171test_quota_compliance_bluetooth_SOURCES = \
1177 test_quota_compliance.c 1172 test_quota_compliance.c
1178test_quota_compliance_bluetooth_LDADD = \ 1173test_quota_compliance_bluetooth_LDADD = \
1179 $(top_builddir)/src/nat/libgnunetnat.la \
1180 libgnunettransport.la \ 1174 libgnunettransport.la \
1181 $(top_builddir)/src/hello/libgnunethello.la \ 1175 $(top_builddir)/src/hello/libgnunethello.la \
1182 $(top_builddir)/src/ats/libgnunetats.la \ 1176 $(top_builddir)/src/ats/libgnunetats.la \
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c
index d82112e03..e1e4f56f8 100644
--- a/src/transport/gnunet-service-transport_neighbours.c
+++ b/src/transport/gnunet-service-transport_neighbours.c
@@ -2236,6 +2236,14 @@ GST_neighbours_handle_session_syn (const struct GNUNET_MessageHeader *message,
2236 scm = (const struct TransportSynMessage *) message; 2236 scm = (const struct TransportSynMessage *) message;
2237 GNUNET_break_op (0 == ntohl (scm->reserved)); 2237 GNUNET_break_op (0 == ntohl (scm->reserved));
2238 ts = GNUNET_TIME_absolute_ntoh (scm->timestamp); 2238 ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
2239 if (0 ==
2240 memcmp (&GST_my_identity,
2241 peer,
2242 sizeof (struct GNUNET_PeerIdentity)))
2243 {
2244 /* loopback connection-to-self, ignore */
2245 return GNUNET_SYSERR;
2246 }
2239 n = lookup_neighbour (peer); 2247 n = lookup_neighbour (peer);
2240 if (NULL == n) 2248 if (NULL == n)
2241 { 2249 {
diff --git a/src/transport/gnunet-transport.c b/src/transport/gnunet-transport.c
index e928cf660..fcfc94ac8 100644
--- a/src/transport/gnunet-transport.c
+++ b/src/transport/gnunet-transport.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2011-2014, 2016 GNUnet e.V. 3 Copyright (C) 2011-2014, 2016, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -23,9 +23,6 @@
23 * @brief Tool to help configure, measure and control the transport subsystem. 23 * @brief Tool to help configure, measure and control the transport subsystem.
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * @author Nathan Evans 25 * @author Nathan Evans
26 *
27 * This utility can be used to test if a transport mechanism for
28 * GNUnet is properly configured.
29 */ 26 */
30#include "platform.h" 27#include "platform.h"
31#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
@@ -33,13 +30,6 @@
33#include "gnunet_protocols.h" 30#include "gnunet_protocols.h"
34#include "gnunet_transport_service.h" 31#include "gnunet_transport_service.h"
35#include "gnunet_transport_core_service.h" 32#include "gnunet_transport_core_service.h"
36#include "gnunet_nat_lib.h"
37
38/**
39 * How long do we wait for the NAT test to report success?
40 * Should match NAT_SERVER_TIMEOUT in 'nat_test.c'.
41 */
42#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
43 33
44/** 34/**
45 * Timeout for a name resolution 35 * Timeout for a name resolution
@@ -172,49 +162,6 @@ struct PeerResolutionContext
172 162
173 163
174/** 164/**
175 * Context for a plugin test.
176 */
177struct TestContext
178{
179 /**
180 * Previous in DLL
181 */
182 struct TestContext *prev;
183
184 /**
185 * Next in DLL
186 */
187 struct TestContext *next;
188
189 /**
190 * Handle to the active NAT test.
191 */
192 struct GNUNET_NAT_Test *tst;
193
194 /**
195 * Task identifier for the timeout.
196 */
197 struct GNUNET_SCHEDULER_Task * tsk;
198
199 /**
200 * Name of plugin under test.
201 */
202 char *name;
203
204 /**
205 * Bound port
206 */
207 unsigned long long bnd_port;
208
209 /**
210 * Advertised ports
211 */
212 unsigned long long adv_port;
213
214};
215
216
217/**
218 * Benchmarking block size in KB 165 * Benchmarking block size in KB
219 */ 166 */
220#define BLOCKSIZE 4 167#define BLOCKSIZE 4
@@ -265,11 +212,6 @@ static int iterate_connections;
265static int iterate_all; 212static int iterate_all;
266 213
267/** 214/**
268 * Option -t.
269 */
270static int test_configuration;
271
272/**
273 * Option -c. 215 * Option -c.
274 */ 216 */
275static int monitor_connects; 217static int monitor_connects;
@@ -366,16 +308,6 @@ struct GNUNET_OS_Process *resolver;
366static unsigned int address_resolutions; 308static unsigned int address_resolutions;
367 309
368/** 310/**
369 * DLL for NAT Test Contexts: head
370 */
371static struct TestContext *head;
372
373/**
374 * DLL for NAT Test Contexts: tail
375 */
376static struct TestContext *tail;
377
378/**
379 * DLL: head of validation resolution entries 311 * DLL: head of validation resolution entries
380 */ 312 */
381static struct ValidationResolutionContext *vc_head; 313static struct ValidationResolutionContext *vc_head;
@@ -553,11 +485,13 @@ operation_timeout (void *cls)
553 _("Failed to resolve address for peer `%s'\n"), 485 _("Failed to resolve address for peer `%s'\n"),
554 GNUNET_i2s (&cur->addrcp->peer)); 486 GNUNET_i2s (&cur->addrcp->peer));
555 487
556 GNUNET_CONTAINER_DLL_remove(rc_head, rc_tail, cur); 488 GNUNET_CONTAINER_DLL_remove(rc_head,
489 rc_tail,
490 cur);
557 GNUNET_TRANSPORT_address_to_string_cancel (cur->asc); 491 GNUNET_TRANSPORT_address_to_string_cancel (cur->asc);
558 GNUNET_free(cur->transport); 492 GNUNET_free (cur->transport);
559 GNUNET_free(cur->addrcp); 493 GNUNET_free (cur->addrcp);
560 GNUNET_free(cur); 494 GNUNET_free (cur);
561 495
562 } 496 }
563 FPRINTF (stdout, 497 FPRINTF (stdout,
@@ -570,158 +504,6 @@ operation_timeout (void *cls)
570} 504}
571 505
572 506
573static void
574run_nat_test (void);
575
576
577/**
578 * Display the result of the test.
579 *
580 * @param tc test context
581 * @param result #GNUNET_YES on success
582 */
583static void
584display_test_result (struct TestContext *tc,
585 enum GNUNET_NAT_StatusCode result)
586{
587 FPRINTF (stderr,
588 _("NAT plugin `%s' reports: %s\n"),
589 tc->name,
590 GNUNET_NAT_status2string (result));
591 if (NULL != tc->tsk)
592 {
593 GNUNET_SCHEDULER_cancel (tc->tsk);
594 tc->tsk = NULL;
595 }
596 if (NULL != tc->tst)
597 {
598 GNUNET_NAT_test_stop (tc->tst);
599 tc->tst = NULL;
600 }
601
602 GNUNET_CONTAINER_DLL_remove (head, tail, tc);
603 GNUNET_free (tc->name);
604 GNUNET_free (tc);
605
606 if ((NULL == head) && (NULL != resolver))
607 {
608 GNUNET_break (0 == GNUNET_OS_process_kill (resolver,
609 GNUNET_TERM_SIG));
610 GNUNET_OS_process_destroy (resolver);
611 resolver = NULL;
612 }
613 if (NULL != head)
614 run_nat_test ();
615}
616
617
618/**
619 * Function called by NAT to report the outcome of the nat-test.
620 * Clean up and update GUI.
621 *
622 * @param cls test context
623 * @param result status code
624 */
625static void
626result_callback (void *cls,
627 enum GNUNET_NAT_StatusCode result)
628{
629 struct TestContext *tc = cls;
630
631 display_test_result (tc,
632 result);
633}
634
635
636static void
637run_nat_test ()
638{
639 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
640 "Running test for plugin `%s' using bind port %u and advertised port %u \n",
641 head->name,
642 (uint16_t) head->bnd_port,
643 (uint16_t) head->adv_port);
644
645 head->tst = GNUNET_NAT_test_start (cfg,
646 (0 == strcasecmp (head->name, "udp"))
647 ? GNUNET_NO : GNUNET_YES,
648 (uint16_t) head->bnd_port,
649 (uint16_t) head->adv_port,
650 TIMEOUT,
651 &result_callback, head);
652}
653
654
655/**
656 * Test our plugin's configuration (NAT traversal, etc.).
657 *
658 * @param cfg configuration to test
659 */
660static void
661do_test_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
662{
663 char *plugins;
664 char *tok;
665 unsigned long long bnd_port;
666 unsigned long long adv_port;
667 struct TestContext *tc;
668 char *binary;
669
670 if (GNUNET_OK
671 != GNUNET_CONFIGURATION_get_value_string (cfg, "transport", "plugins",
672 &plugins))
673 {
674 FPRINTF (stderr, "%s", _
675 ("No transport plugins configured, peer will never communicate\n"));
676 ret = 4;
677 return;
678 }
679
680 for (tok = strtok (plugins, " "); tok != NULL ; tok = strtok (NULL, " "))
681 {
682 char section[12 + strlen (tok)];
683 GNUNET_snprintf (section, sizeof(section), "transport-%s", tok);
684 if (GNUNET_OK
685 != GNUNET_CONFIGURATION_get_value_number (cfg, section, "PORT",
686 &bnd_port))
687 {
688 FPRINTF (stderr,
689 _("No port configured for plugin `%s', cannot test it\n"), tok);
690 continue;
691 }
692 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, section,
693 "ADVERTISED_PORT", &adv_port))
694 adv_port = bnd_port;
695
696 tc = GNUNET_new (struct TestContext);
697 tc->name = GNUNET_strdup (tok);
698 tc->adv_port = adv_port;
699 tc->bnd_port = bnd_port;
700 GNUNET_CONTAINER_DLL_insert_tail (head, tail, tc);
701 }
702 GNUNET_free(plugins);
703
704 if ((NULL != head) && (NULL == resolver))
705 {
706 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
707 resolver = GNUNET_OS_start_process (GNUNET_YES,
708 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
709 NULL, NULL, NULL,
710 binary,
711 "gnunet-service-resolver", NULL);
712 if (NULL == resolver)
713 {
714 FPRINTF (stderr, _("Failed to start resolver!\n"));
715 return;
716 }
717
718 GNUNET_free(binary);
719 GNUNET_RESOLVER_connect (cfg);
720 run_nat_test ();
721 }
722}
723
724
725/** 507/**
726 * Function called to notify a client about the socket 508 * Function called to notify a client about the socket
727 * begin ready to queue more data. Sends another message. 509 * begin ready to queue more data. Sends another message.
@@ -1041,7 +823,9 @@ process_peer_string (void *cls,
1041 } 823 }
1042 GNUNET_free (rc->transport); 824 GNUNET_free (rc->transport);
1043 GNUNET_free (rc->addrcp); 825 GNUNET_free (rc->addrcp);
1044 GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, rc); 826 GNUNET_CONTAINER_DLL_remove (rc_head,
827 rc_tail,
828 rc);
1045 GNUNET_free (rc); 829 GNUNET_free (rc);
1046 if ((0 == address_resolutions) && (iterate_connections)) 830 if ((0 == address_resolutions) && (iterate_connections))
1047 { 831 {
@@ -1461,11 +1245,6 @@ run (void *cls,
1461 ret = 1; 1245 ret = 1;
1462 1246
1463 cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; 1247 cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg;
1464 if (test_configuration)
1465 {
1466 do_test_configuration (cfg);
1467 return;
1468 }
1469 if ( (NULL != cpid) && 1248 if ( (NULL != cpid) &&
1470 (GNUNET_OK != 1249 (GNUNET_OK !=
1471 GNUNET_CRYPTO_eddsa_public_key_from_string (cpid, 1250 GNUNET_CRYPTO_eddsa_public_key_from_string (cpid,
@@ -1691,9 +1470,6 @@ main (int argc,
1691 { 's', "send", NULL, gettext_noop 1470 { 's', "send", NULL, gettext_noop
1692 ("send data for benchmarking to the other peer (until CTRL-C)"), 0, 1471 ("send data for benchmarking to the other peer (until CTRL-C)"), 0,
1693 &GNUNET_GETOPT_set_one, &benchmark_send }, 1472 &GNUNET_GETOPT_set_one, &benchmark_send },
1694 { 't', "test", NULL,
1695 gettext_noop ("test transport configuration (involves external server)"),
1696 0, &GNUNET_GETOPT_set_one, &test_configuration },
1697 GNUNET_GETOPT_OPTION_VERBOSE (&verbosity), 1473 GNUNET_GETOPT_OPTION_VERBOSE (&verbosity),
1698 GNUNET_GETOPT_OPTION_END 1474 GNUNET_GETOPT_OPTION_END
1699 }; 1475 };
@@ -1706,7 +1482,7 @@ main (int argc,
1706 gettext_noop ("Direct access to transport service."), 1482 gettext_noop ("Direct access to transport service."),
1707 options, 1483 options,
1708 &run, NULL); 1484 &run, NULL);
1709 GNUNET_free((void *) argv); 1485 GNUNET_free ((void *) argv);
1710 if (GNUNET_OK == res) 1486 if (GNUNET_OK == res)
1711 return ret; 1487 return ret;
1712 return 1; 1488 return 1;
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c
index 5088f2e77..63c67b81c 100644
--- a/src/transport/plugin_transport_http_server.c
+++ b/src/transport/plugin_transport_http_server.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2002-2014 GNUnet e.V. 3 Copyright (C) 2002-2014, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -29,7 +29,7 @@
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
31#include "gnunet_transport_plugin.h" 31#include "gnunet_transport_plugin.h"
32#include "gnunet_nat_lib.h" 32#include "gnunet_nat_service.h"
33#include "plugin_transport_http_common.h" 33#include "plugin_transport_http_common.h"
34#include <microhttpd.h> 34#include <microhttpd.h>
35#include <regex.h> 35#include <regex.h>
@@ -2473,12 +2473,14 @@ server_remove_address (void *cls,
2473 * @param cls closure, the 'struct LocalAddrList' 2473 * @param cls closure, the 'struct LocalAddrList'
2474 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean 2474 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
2475 * the previous (now invalid) one 2475 * the previous (now invalid) one
2476 * @param ac address class the address belongs to
2476 * @param addr either the previous or the new public IP address 2477 * @param addr either the previous or the new public IP address
2477 * @param addrlen actual lenght of the address 2478 * @param addrlen actual lenght of the address
2478 */ 2479 */
2479static void 2480static void
2480server_nat_port_map_callback (void *cls, 2481server_nat_port_map_callback (void *cls,
2481 int add_remove, 2482 int add_remove,
2483 enum GNUNET_NAT_AddressClass ac,
2482 const struct sockaddr *addr, 2484 const struct sockaddr *addr,
2483 socklen_t addrlen) 2485 socklen_t addrlen)
2484{ 2486{
@@ -2498,7 +2500,8 @@ server_nat_port_map_callback (void *cls,
2498 2500
2499 if ((NULL != plugin->server_addr_v4) && 2501 if ((NULL != plugin->server_addr_v4) &&
2500 (0 != memcmp (&plugin->server_addr_v4->sin_addr, 2502 (0 != memcmp (&plugin->server_addr_v4->sin_addr,
2501 &s4->sin_addr, sizeof (struct in_addr)))) 2503 &s4->sin_addr,
2504 sizeof (struct in_addr))))
2502 { 2505 {
2503 LOG (GNUNET_ERROR_TYPE_DEBUG, 2506 LOG (GNUNET_ERROR_TYPE_DEBUG,
2504 "Skipping address `%s' (not bindto address)\n", 2507 "Skipping address `%s' (not bindto address)\n",
@@ -2754,14 +2757,16 @@ server_start_report_addresses (struct HTTP_Server_Plugin *plugin)
2754 return; 2757 return;
2755 } 2758 }
2756 2759
2757 plugin->nat = 2760 plugin->nat
2758 GNUNET_NAT_register (plugin->env->cfg, 2761 = GNUNET_NAT_register (plugin->env->cfg,
2759 GNUNET_YES, 2762 "transport-http_server",
2760 plugin->port, 2763 IPPROTO_TCP,
2761 (unsigned int) res, 2764 (unsigned int) res,
2762 (const struct sockaddr **) addrs, addrlens, 2765 (const struct sockaddr **) addrs,
2763 &server_nat_port_map_callback, NULL, 2766 addrlens,
2764 plugin, NULL); 2767 &server_nat_port_map_callback,
2768 NULL,
2769 plugin);
2765 while (res > 0) 2770 while (res > 0)
2766 { 2771 {
2767 res--; 2772 res--;
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 79c70138f..eca62a8ca 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -26,7 +26,7 @@
26#include "gnunet_hello_lib.h" 26#include "gnunet_hello_lib.h"
27#include "gnunet_constants.h" 27#include "gnunet_constants.h"
28#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
29#include "gnunet_nat_lib.h" 29#include "gnunet_nat_service.h"
30#include "gnunet_protocols.h" 30#include "gnunet_protocols.h"
31#include "gnunet_resolver_service.h" 31#include "gnunet_resolver_service.h"
32#include "gnunet_signatures.h" 32#include "gnunet_signatures.h"
@@ -945,13 +945,15 @@ notify_session_monitor (struct Plugin *plugin,
945 * @param cls closure, the `struct Plugin` 945 * @param cls closure, the `struct Plugin`
946 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean 946 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
947 * the previous (now invalid) one 947 * the previous (now invalid) one
948 * @param ac address class the address belongs to
948 * @param addr either the previous or the new public IP address 949 * @param addr either the previous or the new public IP address
949 * @param addrlen actual length of @a addr 950 * @param addrlen actual length of @a addr
950 */ 951 */
951static void 952static void
952tcp_nat_port_map_callback (void *cls, 953tcp_nat_port_map_callback (void *cls,
953 int add_remove, 954 int add_remove,
954 const struct sockaddr *addr, 955 enum GNUNET_NAT_AddressClass ac,
956 const struct sockaddr *addr,
955 socklen_t addrlen) 957 socklen_t addrlen)
956{ 958{
957 struct Plugin *plugin = cls; 959 struct Plugin *plugin = cls;
@@ -961,10 +963,10 @@ tcp_nat_port_map_callback (void *cls,
961 void *arg; 963 void *arg;
962 size_t args; 964 size_t args;
963 965
964 LOG(GNUNET_ERROR_TYPE_INFO, 966 LOG (GNUNET_ERROR_TYPE_INFO,
965 "NAT notification to %s address `%s'\n", 967 "NAT notification to %s address `%s'\n",
966 (GNUNET_YES == add_remove) ? "add" : "remove", 968 (GNUNET_YES == add_remove) ? "add" : "remove",
967 GNUNET_a2s (addr, addrlen)); 969 GNUNET_a2s (addr, addrlen));
968 /* convert 'addr' to our internal format */ 970 /* convert 'addr' to our internal format */
969 switch (addr->sa_family) 971 switch (addr->sa_family)
970 { 972 {
@@ -980,8 +982,9 @@ tcp_nat_port_map_callback (void *cls,
980 case AF_INET6: 982 case AF_INET6:
981 GNUNET_assert(addrlen == sizeof(struct sockaddr_in6)); 983 GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
982 memset (&t6, 0, sizeof(t6)); 984 memset (&t6, 0, sizeof(t6));
983 GNUNET_memcpy (&t6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr, 985 GNUNET_memcpy (&t6.ipv6_addr,
984 sizeof(struct in6_addr)); 986 &((struct sockaddr_in6 *) addr)->sin6_addr,
987 sizeof(struct in6_addr));
985 t6.options = htonl (plugin->myoptions); 988 t6.options = htonl (plugin->myoptions);
986 t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port; 989 t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
987 arg = &t6; 990 arg = &t6;
@@ -993,11 +996,17 @@ tcp_nat_port_map_callback (void *cls,
993 } 996 }
994 /* modify our published address list */ 997 /* modify our published address list */
995 GNUNET_assert ((args == sizeof (struct IPv4TcpAddress)) || 998 GNUNET_assert ((args == sizeof (struct IPv4TcpAddress)) ||
996 (args == sizeof (struct IPv6TcpAddress))); 999 (args == sizeof (struct IPv6TcpAddress)));
1000 /* TODO: use 'ac' here in the future... */
997 address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, 1001 address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
998 PLUGIN_NAME, arg, args, GNUNET_HELLO_ADDRESS_INFO_NONE); 1002 PLUGIN_NAME,
999 plugin->env->notify_address (plugin->env->cls, add_remove, address); 1003 arg,
1000 GNUNET_HELLO_address_free(address); 1004 args,
1005 GNUNET_HELLO_ADDRESS_INFO_NONE);
1006 plugin->env->notify_address (plugin->env->cls,
1007 add_remove,
1008 address);
1009 GNUNET_HELLO_address_free (address);
1001} 1010}
1002 1011
1003 1012
@@ -2068,6 +2077,8 @@ tcp_plugin_get_session (void *cls,
2068 GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns, 2077 GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
2069 &address->peer))) 2078 &address->peer)))
2070 { 2079 {
2080 struct sockaddr_in local_sa;
2081
2071 LOG (GNUNET_ERROR_TYPE_DEBUG, 2082 LOG (GNUNET_ERROR_TYPE_DEBUG,
2072 "Found valid IPv4 NAT address (creating session)!\n"); 2083 "Found valid IPv4 NAT address (creating session)!\n");
2073 session = create_session (plugin, 2084 session = create_session (plugin,
@@ -2085,23 +2096,29 @@ tcp_plugin_get_session (void *cls,
2085 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 2096 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2086 2097
2087 LOG (GNUNET_ERROR_TYPE_DEBUG, 2098 LOG (GNUNET_ERROR_TYPE_DEBUG,
2088 "Created NAT WAIT connection to `%4s' at `%s'\n", 2099 "Created NAT WAIT connection to `%s' at `%s'\n",
2089 GNUNET_i2s (&session->target), 2100 GNUNET_i2s (&session->target),
2090 GNUNET_a2s (sb, sbs)); 2101 GNUNET_a2s (sb, sbs));
2091 if (GNUNET_OK == GNUNET_NAT_run_client (plugin->nat, &a4)) 2102 memset (&local_sa,
2092 { 2103 0,
2104 sizeof (local_sa));
2105 local_sa.sin_family = AF_INET;
2106 local_sa.sin_port = htons (plugin->open_port);
2107 /* We leave sin_address at 0, let the kernel figure it out,
2108 even if our bind() is more specific. (May want to reconsider
2109 later.) */
2110 if (GNUNET_OK ==
2111 GNUNET_NAT_request_reversal (plugin->nat,
2112 &local_sa,
2113 &a4))
2093 return session; 2114 return session;
2094 } 2115 LOG (GNUNET_ERROR_TYPE_DEBUG,
2095 else 2116 "Running NAT client for `%s' at `%s' failed\n",
2096 { 2117 GNUNET_i2s (&session->target),
2097 LOG(GNUNET_ERROR_TYPE_DEBUG, 2118 GNUNET_a2s (sb, sbs));
2098 "Running NAT client for `%4s' at `%s' failed\n", 2119 tcp_plugin_disconnect_session (plugin,
2099 GNUNET_i2s (&session->target), 2120 session);
2100 GNUNET_a2s (sb, sbs)); 2121 return NULL;
2101 tcp_plugin_disconnect_session (plugin,
2102 session);
2103 return NULL;
2104 }
2105 } 2122 }
2106 2123
2107 /* create new outbound session */ 2124 /* create new outbound session */
@@ -2396,27 +2413,6 @@ tcp_plugin_address_pretty_printer (void *cls,
2396 2413
2397 2414
2398/** 2415/**
2399 * Check if the given port is plausible (must be either our listen
2400 * port or our advertised port), or any port if we are behind NAT
2401 * and do not have a port open. If it is neither, we return
2402 * #GNUNET_SYSERR.
2403 *
2404 * @param plugin global variables
2405 * @param in_port port number to check
2406 * @return #GNUNET_OK if port is either open_port or adv_port
2407 */
2408static int
2409check_port (struct Plugin *plugin,
2410 uint16_t in_port)
2411{
2412 if ( (in_port == plugin->adv_port) ||
2413 (in_port == plugin->open_port) )
2414 return GNUNET_OK;
2415 return GNUNET_SYSERR;
2416}
2417
2418
2419/**
2420 * Function that will be called to check if a binary address for this 2416 * Function that will be called to check if a binary address for this
2421 * plugin is well-formed and corresponds to an address for THIS peer 2417 * plugin is well-formed and corresponds to an address for THIS peer
2422 * (as per our configuration). Naturally, if absolutely necessary, 2418 * (as per our configuration). Naturally, if absolutely necessary,
@@ -2449,6 +2445,8 @@ tcp_plugin_check_address (void *cls,
2449 2445
2450 if (addrlen == sizeof(struct IPv4TcpAddress)) 2446 if (addrlen == sizeof(struct IPv4TcpAddress))
2451 { 2447 {
2448 struct sockaddr_in s4;
2449
2452 v4 = (const struct IPv4TcpAddress *) addr; 2450 v4 = (const struct IPv4TcpAddress *) addr;
2453 if (0 != memcmp (&v4->options, 2451 if (0 != memcmp (&v4->options,
2454 &plugin->myoptions, 2452 &plugin->myoptions,
@@ -2457,17 +2455,24 @@ tcp_plugin_check_address (void *cls,
2457 GNUNET_break (0); 2455 GNUNET_break (0);
2458 return GNUNET_SYSERR; 2456 return GNUNET_SYSERR;
2459 } 2457 }
2460 if (GNUNET_OK != check_port (plugin, 2458 memset (&s4, 0, sizeof (s4));
2461 ntohs (v4->t4_port))) 2459 s4.sin_family = AF_INET;
2462 return GNUNET_SYSERR; 2460#if HAVE_SOCKADDR_IN_SIN_LEN
2461 s4.sin_len = sizeof (s4);
2462#endif
2463 s4.sin_port = v4->t4_port;
2464 s4.sin_addr.s_addr = v4->ipv4_addr;
2465
2463 if (GNUNET_OK != 2466 if (GNUNET_OK !=
2464 GNUNET_NAT_test_address (plugin->nat, 2467 GNUNET_NAT_test_address (plugin->nat,
2465 &v4->ipv4_addr, 2468 &s4,
2466 sizeof (struct in_addr))) 2469 sizeof (struct sockaddr_in)))
2467 return GNUNET_SYSERR; 2470 return GNUNET_SYSERR;
2468 } 2471 }
2469 else 2472 else
2470 { 2473 {
2474 struct sockaddr_in6 s6;
2475
2471 v6 = (const struct IPv6TcpAddress *) addr; 2476 v6 = (const struct IPv6TcpAddress *) addr;
2472 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr)) 2477 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
2473 { 2478 {
@@ -2481,13 +2486,18 @@ tcp_plugin_check_address (void *cls,
2481 GNUNET_break (0); 2486 GNUNET_break (0);
2482 return GNUNET_SYSERR; 2487 return GNUNET_SYSERR;
2483 } 2488 }
2484 if (GNUNET_OK != check_port (plugin, 2489 memset (&s6, 0, sizeof (s6));
2485 ntohs (v6->t6_port))) 2490 s6.sin6_family = AF_INET6;
2486 return GNUNET_SYSERR; 2491#if HAVE_SOCKADDR_IN_SIN_LEN
2492 s6.sin6_len = sizeof (s6);
2493#endif
2494 s6.sin6_port = v6->t6_port;
2495 s6.sin6_addr = v6->ipv6_addr;
2496
2487 if (GNUNET_OK != 2497 if (GNUNET_OK !=
2488 GNUNET_NAT_test_address (plugin->nat, 2498 GNUNET_NAT_test_address (plugin->nat,
2489 &v6->ipv6_addr, 2499 &s6,
2490 sizeof(struct in6_addr))) 2500 sizeof(struct sockaddr_in6)))
2491 return GNUNET_SYSERR; 2501 return GNUNET_SYSERR;
2492 } 2502 }
2493 return GNUNET_OK; 2503 return GNUNET_OK;
@@ -3388,15 +3398,14 @@ libgnunet_plugin_transport_tcp_init (void *cls)
3388 GNUNET_a2s (addrs[ret], addrlens[ret])); 3398 GNUNET_a2s (addrs[ret], addrlens[ret]));
3389 plugin->nat 3399 plugin->nat
3390 = GNUNET_NAT_register (env->cfg, 3400 = GNUNET_NAT_register (env->cfg,
3391 GNUNET_YES, 3401 "transport-tcp",
3392 aport, 3402 IPPROTO_TCP,
3393 (unsigned int) ret_s, 3403 (unsigned int) ret_s,
3394 (const struct sockaddr **) addrs, 3404 (const struct sockaddr **) addrs,
3395 addrlens, 3405 addrlens,
3396 &tcp_nat_port_map_callback, 3406 &tcp_nat_port_map_callback,
3397 &try_connection_reversal, 3407 &try_connection_reversal,
3398 plugin, 3408 plugin);
3399 NULL);
3400 for (ret = ret_s -1; ret >= 0; ret--) 3409 for (ret = ret_s -1; ret >= 0; ret--)
3401 GNUNET_free (addrs[ret]); 3410 GNUNET_free (addrs[ret]);
3402 GNUNET_free_non_null (addrs); 3411 GNUNET_free_non_null (addrs);
@@ -3405,15 +3414,14 @@ libgnunet_plugin_transport_tcp_init (void *cls)
3405 else 3414 else
3406 { 3415 {
3407 plugin->nat = GNUNET_NAT_register (plugin->env->cfg, 3416 plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
3408 GNUNET_YES, 3417 "transport-tcp",
3409 0, 3418 IPPROTO_TCP,
3410 0, 3419 0,
3411 NULL, 3420 NULL,
3412 NULL, 3421 NULL,
3413 NULL, 3422 NULL,
3414 &try_connection_reversal, 3423 &try_connection_reversal,
3415 plugin, 3424 plugin);
3416 NULL);
3417 } 3425 }
3418 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); 3426 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
3419 api->cls = plugin; 3427 api->cls = plugin;
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 35ae92460..fd8493e5f 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V. 3 Copyright (C) 2010-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -30,7 +30,7 @@
30#include "gnunet_hello_lib.h" 30#include "gnunet_hello_lib.h"
31#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
32#include "gnunet_fragmentation_lib.h" 32#include "gnunet_fragmentation_lib.h"
33#include "gnunet_nat_lib.h" 33#include "gnunet_nat_service.h"
34#include "gnunet_protocols.h" 34#include "gnunet_protocols.h"
35#include "gnunet_resolver_service.h" 35#include "gnunet_resolver_service.h"
36#include "gnunet_signatures.h" 36#include "gnunet_signatures.h"
@@ -1245,31 +1245,48 @@ udp_plugin_check_address (void *cls,
1245 1245
1246 if (sizeof(struct IPv4UdpAddress) == addrlen) 1246 if (sizeof(struct IPv4UdpAddress) == addrlen)
1247 { 1247 {
1248 struct sockaddr_in s4;
1249
1248 v4 = (const struct IPv4UdpAddress *) addr; 1250 v4 = (const struct IPv4UdpAddress *) addr;
1249 if (GNUNET_OK != check_port (plugin, 1251 if (GNUNET_OK != check_port (plugin,
1250 ntohs (v4->u4_port))) 1252 ntohs (v4->u4_port)))
1251 return GNUNET_SYSERR; 1253 return GNUNET_SYSERR;
1254 memset (&s4, 0, sizeof (s4));
1255 s4.sin_family = AF_INET;
1256#if HAVE_SOCKADDR_IN_SIN_LEN
1257 s4.sin_len = sizeof (s4);
1258#endif
1259 s4.sin_port = v4->u4_port;
1260 s4.sin_addr.s_addr = v4->ipv4_addr;
1261
1252 if (GNUNET_OK != 1262 if (GNUNET_OK !=
1253 GNUNET_NAT_test_address (plugin->nat, 1263 GNUNET_NAT_test_address (plugin->nat,
1254 &v4->ipv4_addr, 1264 &s4,
1255 sizeof (struct in_addr))) 1265 sizeof (struct sockaddr_in)))
1256 return GNUNET_SYSERR; 1266 return GNUNET_SYSERR;
1257 } 1267 }
1258 else if (sizeof(struct IPv6UdpAddress) == addrlen) 1268 else if (sizeof(struct IPv6UdpAddress) == addrlen)
1259 { 1269 {
1270 struct sockaddr_in6 s6;
1271
1260 v6 = (const struct IPv6UdpAddress *) addr; 1272 v6 = (const struct IPv6UdpAddress *) addr;
1261 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr)) 1273 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1262 { 1274 {
1263 GNUNET_break_op (0); 1275 GNUNET_break_op (0);
1264 return GNUNET_SYSERR; 1276 return GNUNET_SYSERR;
1265 } 1277 }
1266 if (GNUNET_OK != check_port (plugin, 1278 memset (&s6, 0, sizeof (s6));
1267 ntohs (v6->u6_port))) 1279 s6.sin6_family = AF_INET6;
1268 return GNUNET_SYSERR; 1280#if HAVE_SOCKADDR_IN_SIN_LEN
1281 s6.sin6_len = sizeof (s6);
1282#endif
1283 s6.sin6_port = v6->u6_port;
1284 s6.sin6_addr = v6->ipv6_addr;
1285
1269 if (GNUNET_OK != 1286 if (GNUNET_OK !=
1270 GNUNET_NAT_test_address (plugin->nat, 1287 GNUNET_NAT_test_address (plugin->nat,
1271 &v6->ipv6_addr, 1288 &s6,
1272 sizeof (struct in6_addr))) 1289 sizeof(struct sockaddr_in6)))
1273 return GNUNET_SYSERR; 1290 return GNUNET_SYSERR;
1274 } 1291 }
1275 else 1292 else
@@ -1287,12 +1304,14 @@ udp_plugin_check_address (void *cls,
1287 * @param cls closure, the `struct Plugin` 1304 * @param cls closure, the `struct Plugin`
1288 * @param add_remove #GNUNET_YES to mean the new public IP address, 1305 * @param add_remove #GNUNET_YES to mean the new public IP address,
1289 * #GNUNET_NO to mean the previous (now invalid) one 1306 * #GNUNET_NO to mean the previous (now invalid) one
1307 * @param ac address class the address belongs to
1290 * @param addr either the previous or the new public IP address 1308 * @param addr either the previous or the new public IP address
1291 * @param addrlen actual length of the @a addr 1309 * @param addrlen actual length of the @a addr
1292 */ 1310 */
1293static void 1311static void
1294udp_nat_port_map_callback (void *cls, 1312udp_nat_port_map_callback (void *cls,
1295 int add_remove, 1313 int add_remove,
1314 enum GNUNET_NAT_AddressClass ac,
1296 const struct sockaddr *addr, 1315 const struct sockaddr *addr,
1297 socklen_t addrlen) 1316 socklen_t addrlen)
1298{ 1317{
@@ -1359,6 +1378,7 @@ udp_nat_port_map_callback (void *cls,
1359 return; 1378 return;
1360 } 1379 }
1361 /* modify our published address list */ 1380 /* modify our published address list */
1381 /* TODO: use 'ac' here in the future... */
1362 address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, 1382 address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1363 PLUGIN_NAME, 1383 PLUGIN_NAME,
1364 arg, 1384 arg,
@@ -3032,8 +3052,7 @@ read_process_fragment (struct Plugin *plugin,
3032 msg)) 3052 msg))
3033 { 3053 {
3034 /* keep this 'rc' from expiring */ 3054 /* keep this 'rc' from expiring */
3035 GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs, 3055 GNUNET_CONTAINER_heap_update_cost (d_ctx->hnode,
3036 d_ctx->hnode,
3037 (GNUNET_CONTAINER_HeapCostType) now.abs_value_us); 3056 (GNUNET_CONTAINER_HeapCostType) now.abs_value_us);
3038 } 3057 }
3039 if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) > 3058 if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) >
@@ -3082,7 +3101,7 @@ udp_select_read (struct Plugin *plugin,
3082 sizeof(addr)); 3101 sizeof(addr));
3083 size = GNUNET_NETWORK_socket_recvfrom (rsock, 3102 size = GNUNET_NETWORK_socket_recvfrom (rsock,
3084 buf, 3103 buf,
3085 sizeof(buf), 3104 sizeof (buf),
3086 (struct sockaddr *) &addr, 3105 (struct sockaddr *) &addr,
3087 &fromlen); 3106 &fromlen);
3088 sa = (const struct sockaddr *) &addr; 3107 sa = (const struct sockaddr *) &addr;
@@ -3111,9 +3130,12 @@ udp_select_read (struct Plugin *plugin,
3111 } 3130 }
3112 3131
3113 /* Check if this is a STUN packet */ 3132 /* Check if this is a STUN packet */
3114 if (GNUNET_NAT_is_valid_stun_packet (plugin->nat, 3133 if (GNUNET_NO !=
3115 (uint8_t *)buf, 3134 GNUNET_NAT_stun_handle_packet (plugin->nat,
3116 size)) 3135 (const struct sockaddr *) &addr,
3136 fromlen,
3137 buf,
3138 size))
3117 return; /* was STUN, do not process further */ 3139 return; /* was STUN, do not process further */
3118 3140
3119 if (size < sizeof(struct GNUNET_MessageHeader)) 3141 if (size < sizeof(struct GNUNET_MessageHeader))
@@ -3516,7 +3538,7 @@ udp_plugin_select_v4 (void *cls)
3516{ 3538{
3517 struct Plugin *plugin = cls; 3539 struct Plugin *plugin = cls;
3518 const struct GNUNET_SCHEDULER_TaskContext *tc; 3540 const struct GNUNET_SCHEDULER_TaskContext *tc;
3519 3541
3520 plugin->select_task_v4 = NULL; 3542 plugin->select_task_v4 = NULL;
3521 if (NULL == plugin->sockv4) 3543 if (NULL == plugin->sockv4)
3522 return; 3544 return;
@@ -3572,13 +3594,13 @@ udp_plugin_select_v6 (void *cls)
3572 * @param bind_v4 IPv4 address to bind to (can be NULL, for 'any') 3594 * @param bind_v4 IPv4 address to bind to (can be NULL, for 'any')
3573 * @return number of sockets that were successfully bound 3595 * @return number of sockets that were successfully bound
3574 */ 3596 */
3575static int 3597static unsigned int
3576setup_sockets (struct Plugin *plugin, 3598setup_sockets (struct Plugin *plugin,
3577 const struct sockaddr_in6 *bind_v6, 3599 const struct sockaddr_in6 *bind_v6,
3578 const struct sockaddr_in *bind_v4) 3600 const struct sockaddr_in *bind_v4)
3579{ 3601{
3580 int tries; 3602 int tries;
3581 int sockets_created = 0; 3603 unsigned int sockets_created = 0;
3582 struct sockaddr_in6 server_addrv6; 3604 struct sockaddr_in6 server_addrv6;
3583 struct sockaddr_in server_addrv4; 3605 struct sockaddr_in server_addrv4;
3584 const struct sockaddr *server_addr; 3606 const struct sockaddr *server_addr;
@@ -3788,15 +3810,14 @@ setup_sockets (struct Plugin *plugin,
3788 schedule_select_v4 (plugin); 3810 schedule_select_v4 (plugin);
3789 schedule_select_v6 (plugin); 3811 schedule_select_v6 (plugin);
3790 plugin->nat = GNUNET_NAT_register (plugin->env->cfg, 3812 plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
3791 GNUNET_NO, 3813 "transport-udp",
3792 plugin->port, 3814 IPPROTO_UDP,
3793 sockets_created, 3815 sockets_created,
3794 addrs, 3816 addrs,
3795 addrlens, 3817 addrlens,
3796 &udp_nat_port_map_callback, 3818 &udp_nat_port_map_callback,
3797 NULL, 3819 NULL,
3798 plugin, 3820 plugin);
3799 plugin->sockv4);
3800 return sockets_created; 3821 return sockets_created;
3801} 3822}
3802 3823
@@ -3825,7 +3846,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
3825 struct GNUNET_TIME_Relative interval; 3846 struct GNUNET_TIME_Relative interval;
3826 struct sockaddr_in server_addrv4; 3847 struct sockaddr_in server_addrv4;
3827 struct sockaddr_in6 server_addrv6; 3848 struct sockaddr_in6 server_addrv6;
3828 int res; 3849 unsigned int res;
3829 int have_bind4; 3850 int have_bind4;
3830 int have_bind6; 3851 int have_bind6;
3831 3852
diff --git a/src/transport/plugin_transport_udp.h b/src/transport/plugin_transport_udp.h
index c6799ba74..152b16099 100644
--- a/src/transport/plugin_transport_udp.h
+++ b/src/transport/plugin_transport_udp.h
@@ -32,7 +32,6 @@
32#include "gnunet_hello_lib.h" 32#include "gnunet_hello_lib.h"
33#include "gnunet_util_lib.h" 33#include "gnunet_util_lib.h"
34#include "gnunet_fragmentation_lib.h" 34#include "gnunet_fragmentation_lib.h"
35#include "gnunet_nat_lib.h"
36#include "gnunet_protocols.h" 35#include "gnunet_protocols.h"
37#include "gnunet_resolver_service.h" 36#include "gnunet_resolver_service.h"
38#include "gnunet_signatures.h" 37#include "gnunet_signatures.h"
diff --git a/src/transport/plugin_transport_udp_broadcasting.c b/src/transport/plugin_transport_udp_broadcasting.c
index 8ef001ddb..a440830fd 100644
--- a/src/transport/plugin_transport_udp_broadcasting.c
+++ b/src/transport/plugin_transport_udp_broadcasting.c
@@ -29,7 +29,6 @@
29#include "gnunet_hello_lib.h" 29#include "gnunet_hello_lib.h"
30#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
31#include "gnunet_fragmentation_lib.h" 31#include "gnunet_fragmentation_lib.h"
32#include "gnunet_nat_lib.h"
33#include "gnunet_protocols.h" 32#include "gnunet_protocols.h"
34#include "gnunet_resolver_service.h" 33#include "gnunet_resolver_service.h"
35#include "gnunet_signatures.h" 34#include "gnunet_signatures.h"
diff --git a/src/transport/transport.conf.in b/src/transport/transport.conf.in
index 95e3f9944..7b5413bbe 100644
--- a/src/transport/transport.conf.in
+++ b/src/transport/transport.conf.in
@@ -38,7 +38,17 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM;
38[transport-tcp] 38[transport-tcp]
39# Use 0 to ONLY advertise as a peer behind NAT (no port binding) 39# Use 0 to ONLY advertise as a peer behind NAT (no port binding)
40PORT = 2086 40PORT = 2086
41
42# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
41ADVERTISED_PORT = 2086 43ADVERTISED_PORT = 2086
44
45# If we have a manually punched NAT, what is the external IP and port?
46# Can use DNS names for DynDNS-based detection of external IP.
47# Can use IPv6 addresses ([fefc::]:PORT).
48# Use "AUTO" for the hostname to automatically detect external IP.
49# Do not set if NAT is not manually punched.
50# HOLE_EXTERNAL = AUTO:2086
51
42TESTING_IGNORE_KEYS = ACCEPT_FROM; 52TESTING_IGNORE_KEYS = ACCEPT_FROM;
43 53
44# Maximum number of open TCP connections allowed 54# Maximum number of open TCP connections allowed
@@ -55,6 +65,9 @@ MAX_CONNECTIONS = 128
55# Enable TCP stealth? 65# Enable TCP stealth?
56TCP_STEALTH = NO 66TCP_STEALTH = NO
57 67
68# Configuration for manually punched holes in NAT.
69# HOLE_EXTERNAL = auto:2086
70
58[transport-udp] 71[transport-udp]
59# Use PORT = 0 to autodetect a port available 72# Use PORT = 0 to autodetect a port available
60PORT = 2086 73PORT = 2086
@@ -69,6 +82,14 @@ BROADCAST_INTERVAL = 30 s
69MAX_BPS = 1000000 82MAX_BPS = 1000000
70TESTING_IGNORE_KEYS = ACCEPT_FROM; 83TESTING_IGNORE_KEYS = ACCEPT_FROM;
71 84
85# If we have a manually punched NAT, what is the external IP and port?
86# Can use DNS names for DynDNS-based detection of external IP.
87# Can use IPv6 addresses ([fefc::]:PORT).
88# Use "AUTO" for the hostname to automatically detect external IP.
89# Do not set if NAT is not manually punched.
90# HOLE_EXTERNAL = AUTO:2086
91
92
72[transport-http_client] 93[transport-http_client]
73MAX_CONNECTIONS = 128 94MAX_CONNECTIONS = 128
74TESTING_IGNORE_KEYS = ACCEPT_FROM; 95TESTING_IGNORE_KEYS = ACCEPT_FROM;
@@ -92,13 +113,27 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM;
92[transport-http_server] 113[transport-http_server]
93#EXTERNAL_HOSTNAME = <your hostname/path> 114#EXTERNAL_HOSTNAME = <your hostname/path>
94PORT = 1080 115PORT = 1080
116
117# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
95ADVERTISED_PORT = 1080 118ADVERTISED_PORT = 1080
119
120# If we have a manually punched NAT, what is the external IP and port?
121# Can use DNS names for DynDNS-based detection of external IP.
122# Can use IPv6 addresses ([fefc::]:PORT).
123# Use "AUTO" for the hostname to automatically detect external IP.
124# Do not set if NAT is not manually punched.
125# HOLE_EXTERNAL = AUTO:2086
126
127
96MAX_CONNECTIONS = 128 128MAX_CONNECTIONS = 128
97TESTING_IGNORE_KEYS = ACCEPT_FROM; 129TESTING_IGNORE_KEYS = ACCEPT_FROM;
98 130
99# Enable TCP stealth? 131# Enable TCP stealth?
100TCP_STEALTH = NO 132TCP_STEALTH = NO
101 133
134# Configuration for manually punched holes in NAT.
135# HOLE_EXTERNAL = auto:2086
136
102[transport-https_client] 137[transport-https_client]
103MAX_CONNECTIONS = 128 138MAX_CONNECTIONS = 128
104TESTING_IGNORE_KEYS = ACCEPT_FROM; 139TESTING_IGNORE_KEYS = ACCEPT_FROM;
@@ -130,7 +165,17 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM;
130# Does the external hostname use the same port? 165# Does the external hostname use the same port?
131# EXTERNAL_HOSTNAME_USE_PORT = YES 166# EXTERNAL_HOSTNAME_USE_PORT = YES
132PORT = 4433 167PORT = 4433
168
169# Obsolete option, to be replaced by HOLE_EXTERNAL (soon)
133ADVERTISED_PORT = 4433 170ADVERTISED_PORT = 4433
171
172# If we have a manually punched NAT, what is the external IP and port?
173# Can use DNS names for DynDNS-based detection of external IP.
174# Can use IPv6 addresses ([fefc::]:PORT).
175# Use "AUTO" for the hostname to automatically detect external IP.
176# Do not set if NAT is not manually punched.
177# HOLE_EXTERNAL = AUTO:2086
178
134CRYPTO_INIT = NORMAL 179CRYPTO_INIT = NORMAL
135KEY_FILE = $GNUNET_DATA_HOME/transport/https.key 180KEY_FILE = $GNUNET_DATA_HOME/transport/https.key
136CERT_FILE = $GNUNET_DATA_HOME/transport/https.cert 181CERT_FILE = $GNUNET_DATA_HOME/transport/https.cert
@@ -140,6 +185,10 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM;
140# Enable TCP stealth? 185# Enable TCP stealth?
141TCP_STEALTH = NO 186TCP_STEALTH = NO
142 187
188# Configuration for manually punched holes in NAT.
189# HOLE_EXTERNAL = auto:2086
190
191
143[transport-wlan] 192[transport-wlan]
144# Name of the interface in monitor mode (typically monX) 193# Name of the interface in monitor mode (typically monX)
145INTERFACE = mon0 194INTERFACE = mon0
diff --git a/src/transport/transport_api_address_to_string.c b/src/transport/transport_api_address_to_string.c
index fd30230f7..b9c72dcb3 100644
--- a/src/transport/transport_api_address_to_string.c
+++ b/src/transport/transport_api_address_to_string.c
@@ -210,7 +210,7 @@ GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle *cf
210 } 210 }
211 alc->cb = aluc; 211 alc->cb = aluc;
212 alc->cb_cls = aluc_cls; 212 alc->cb_cls = aluc_cls;
213 alc->mq = GNUNET_CLIENT_connecT (cfg, 213 alc->mq = GNUNET_CLIENT_connect (cfg,
214 "transport", 214 "transport",
215 handlers, 215 handlers,
216 &mq_error_handler, 216 &mq_error_handler,
diff --git a/src/transport/transport_api_blacklist.c b/src/transport/transport_api_blacklist.c
index 4b758f9dc..7b1bf526e 100644
--- a/src/transport/transport_api_blacklist.c
+++ b/src/transport/transport_api_blacklist.c
@@ -132,7 +132,7 @@ reconnect (struct GNUNET_TRANSPORT_Blacklist *br)
132 132
133 if (NULL != br->mq) 133 if (NULL != br->mq)
134 GNUNET_MQ_destroy (br->mq); 134 GNUNET_MQ_destroy (br->mq);
135 br->mq = GNUNET_CLIENT_connecT (br->cfg, 135 br->mq = GNUNET_CLIENT_connect (br->cfg,
136 "transport", 136 "transport",
137 handlers, 137 handlers,
138 &mq_error_handler, 138 &mq_error_handler,
diff --git a/src/transport/transport_api_core.c b/src/transport/transport_api_core.c
index de18a140c..a693cb889 100644
--- a/src/transport/transport_api_core.c
+++ b/src/transport/transport_api_core.c
@@ -805,7 +805,7 @@ reconnect (void *cls)
805 LOG (GNUNET_ERROR_TYPE_DEBUG, 805 LOG (GNUNET_ERROR_TYPE_DEBUG,
806 "Connecting to transport service.\n"); 806 "Connecting to transport service.\n");
807 GNUNET_assert (NULL == h->mq); 807 GNUNET_assert (NULL == h->mq);
808 h->mq = GNUNET_CLIENT_connecT (h->cfg, 808 h->mq = GNUNET_CLIENT_connect (h->cfg,
809 "transport", 809 "transport",
810 handlers, 810 handlers,
811 &mq_error_handler, 811 &mq_error_handler,
diff --git a/src/transport/transport_api_hello_get.c b/src/transport/transport_api_hello_get.c
index 9c3a3e786..c53dd7a9a 100644
--- a/src/transport/transport_api_hello_get.c
+++ b/src/transport/transport_api_hello_get.c
@@ -182,7 +182,7 @@ reconnect (void *cls)
182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
183 "Connecting to transport service.\n"); 183 "Connecting to transport service.\n");
184 GNUNET_assert (NULL == ghh->mq); 184 GNUNET_assert (NULL == ghh->mq);
185 ghh->mq = GNUNET_CLIENT_connecT (ghh->cfg, 185 ghh->mq = GNUNET_CLIENT_connect (ghh->cfg,
186 "transport", 186 "transport",
187 handlers, 187 handlers,
188 &mq_error_handler, 188 &mq_error_handler,
diff --git a/src/transport/transport_api_manipulation.c b/src/transport/transport_api_manipulation.c
index 6325354cb..fd5849a7e 100644
--- a/src/transport/transport_api_manipulation.c
+++ b/src/transport/transport_api_manipulation.c
@@ -121,7 +121,7 @@ reconnect (void *cls)
121 "Connecting to transport service.\n"); 121 "Connecting to transport service.\n");
122 GNUNET_assert (NULL == h->mq); 122 GNUNET_assert (NULL == h->mq);
123 h->reconnecting = GNUNET_NO; 123 h->reconnecting = GNUNET_NO;
124 h->mq = GNUNET_CLIENT_connecT (h->cfg, 124 h->mq = GNUNET_CLIENT_connect (h->cfg,
125 "transport", 125 "transport",
126 handlers, 126 handlers,
127 &mq_error_handler, 127 &mq_error_handler,
diff --git a/src/transport/transport_api_monitor_peers.c b/src/transport/transport_api_monitor_peers.c
index 345f2ad60..38e6e0d7c 100644
--- a/src/transport/transport_api_monitor_peers.c
+++ b/src/transport/transport_api_monitor_peers.c
@@ -360,7 +360,7 @@ do_peer_connect (void *cls)
360 struct GNUNET_MQ_Envelope *env; 360 struct GNUNET_MQ_Envelope *env;
361 361
362 pal_ctx->reconnect_task = NULL; 362 pal_ctx->reconnect_task = NULL;
363 pal_ctx->mq = GNUNET_CLIENT_connecT (pal_ctx->cfg, 363 pal_ctx->mq = GNUNET_CLIENT_connect (pal_ctx->cfg,
364 "transport", 364 "transport",
365 handlers, 365 handlers,
366 &mq_error_handler, 366 &mq_error_handler,
diff --git a/src/transport/transport_api_monitor_plugins.c b/src/transport/transport_api_monitor_plugins.c
index 7547a3402..e81664c41 100644
--- a/src/transport/transport_api_monitor_plugins.c
+++ b/src/transport/transport_api_monitor_plugins.c
@@ -388,7 +388,7 @@ do_plugin_connect (void *cls)
388 struct GNUNET_MQ_Envelope *env; 388 struct GNUNET_MQ_Envelope *env;
389 389
390 pm->reconnect_task = NULL; 390 pm->reconnect_task = NULL;
391 pm->mq = GNUNET_CLIENT_connecT (pm->cfg, 391 pm->mq = GNUNET_CLIENT_connect (pm->cfg,
392 "transport", 392 "transport",
393 handlers, 393 handlers,
394 &mq_error_handler, 394 &mq_error_handler,
diff --git a/src/transport/transport_api_offer_hello.c b/src/transport/transport_api_offer_hello.c
index 951ab9ba4..e1dca14e3 100644
--- a/src/transport/transport_api_offer_hello.c
+++ b/src/transport/transport_api_offer_hello.c
@@ -104,7 +104,7 @@ GNUNET_TRANSPORT_offer_hello (const struct GNUNET_CONFIGURATION_Handle *cfg,
104 GNUNET_free (ohh); 104 GNUNET_free (ohh);
105 return NULL; 105 return NULL;
106 } 106 }
107 ohh->mq = GNUNET_CLIENT_connecT (cfg, 107 ohh->mq = GNUNET_CLIENT_connect (cfg,
108 "transport", 108 "transport",
109 NULL, 109 NULL,
110 NULL, 110 NULL,
diff --git a/src/tun/.gitignore b/src/tun/.gitignore
new file mode 100644
index 000000000..b26685596
--- /dev/null
+++ b/src/tun/.gitignore
@@ -0,0 +1,2 @@
1test_regex
2test_tun
diff --git a/src/util/.gitignore b/src/util/.gitignore
index cbb349827..87b379746 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -7,3 +7,58 @@ gnunet-resolver
7gnunet-scrypt 7gnunet-scrypt
8gnunet-service-resolver 8gnunet-service-resolver
9gnunet-uri 9gnunet-uri
10test_bio
11test_client.nc
12test_client_unix.nc
13test_common_allocation
14test_common_endian
15test_common_logging
16test_common_logging_runtime_loglevels
17test_configuration
18test_connection.nc
19test_connection_addressing.nc
20test_connection_receive_cancel.nc
21test_connection_timeout.nc
22test_connection_timeout_no_connect.nc
23test_connection_transmit_cancel.nc
24test_container_bloomfilter
25test_container_heap
26test_container_meta_data
27test_container_multihashmap
28test_container_multihashmap32
29test_container_multipeermap
30test_crypto_crc
31test_crypto_ecc_dlog
32test_crypto_ecdh_eddsa
33test_crypto_ecdhe
34test_crypto_ecdsa
35test_crypto_eddsa
36test_crypto_hash
37test_crypto_hash_context
38test_crypto_hkdf
39test_crypto_kdf
40test_crypto_paillier
41test_crypto_random
42test_crypto_rsa
43test_crypto_symmetric
44test_disk
45test_getopt
46test_mq
47test_os_network
48test_os_start_process
49test_peer
50test_plugin
51test_program
52test_resolver_api.nc
53test_scheduler
54test_scheduler_delay
55test_server.nc
56test_server_disconnect.nc
57test_server_mst_interrupt.nc
58test_server_with_client.nc
59test_server_with_client_unix
60test_service
61test_speedup
62test_strings
63test_strings_to_data
64test_time
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 65818640c..f49aee17f 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -59,7 +59,7 @@ test_common_logging_dummy_LDADD = \
59libgnunetutil_la_SOURCES = \ 59libgnunetutil_la_SOURCES = \
60 bandwidth.c \ 60 bandwidth.c \
61 bio.c \ 61 bio.c \
62 client_new.c \ 62 client.c \
63 common_allocation.c \ 63 common_allocation.c \
64 common_endian.c \ 64 common_endian.c \
65 common_logging.c \ 65 common_logging.c \
@@ -70,6 +70,7 @@ libgnunetutil_la_SOURCES = \
70 container_heap.c \ 70 container_heap.c \
71 container_meta_data.c \ 71 container_meta_data.c \
72 container_multihashmap.c \ 72 container_multihashmap.c \
73 container_multishortmap.c \
73 container_multipeermap.c \ 74 container_multipeermap.c \
74 container_multihashmap32.c \ 75 container_multihashmap32.c \
75 crypto_symmetric.c \ 76 crypto_symmetric.c \
diff --git a/src/util/client_new.c b/src/util/client.c
index 337d06734..4fd971040 100644
--- a/src/util/client_new.c
+++ b/src/util/client.c
@@ -213,9 +213,6 @@ start_connect (void *cls);
213static void 213static void
214connect_fail_continuation (struct ClientState *cstate) 214connect_fail_continuation (struct ClientState *cstate)
215{ 215{
216 LOG (GNUNET_ERROR_TYPE_WARNING,
217 "Failed to establish connection to `%s', no further addresses to try.\n",
218 cstate->service_name);
219 GNUNET_break (NULL == cstate->ap_head); 216 GNUNET_break (NULL == cstate->ap_head);
220 GNUNET_break (NULL == cstate->ap_tail); 217 GNUNET_break (NULL == cstate->ap_tail);
221 GNUNET_break (NULL == cstate->dns_active); 218 GNUNET_break (NULL == cstate->dns_active);
@@ -225,6 +222,11 @@ connect_fail_continuation (struct ClientState *cstate)
225 // GNUNET_assert (NULL == cstate->proxy_handshake); 222 // GNUNET_assert (NULL == cstate->proxy_handshake);
226 223
227 cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off); 224 cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off);
225 LOG (GNUNET_ERROR_TYPE_DEBUG,
226 "Failed to establish connection to `%s', no further addresses to try, will try again in %s.\n",
227 cstate->service_name,
228 GNUNET_STRINGS_relative_time_to_string (cstate->back_off,
229 GNUNET_YES));
228 cstate->retry_task 230 cstate->retry_task
229 = GNUNET_SCHEDULER_add_delayed (cstate->back_off, 231 = GNUNET_SCHEDULER_add_delayed (cstate->back_off,
230 &start_connect, 232 &start_connect,
@@ -271,7 +273,7 @@ transmit_ready (void *cls)
271 cstate->sock, 273 cstate->sock,
272 &transmit_ready, 274 &transmit_ready,
273 cstate); 275 cstate);
274 if (notify_in_flight) 276 if (notify_in_flight)
275 GNUNET_MQ_impl_send_in_flight (cstate->mq); 277 GNUNET_MQ_impl_send_in_flight (cstate->mq);
276 return; 278 return;
277 } 279 }
@@ -583,7 +585,7 @@ try_connect_using_address (void *cls,
583{ 585{
584 struct ClientState *cstate = cls; 586 struct ClientState *cstate = cls;
585 struct AddressProbe *ap; 587 struct AddressProbe *ap;
586 588
587 if (NULL == addr) 589 if (NULL == addr)
588 { 590 {
589 cstate->dns_active = NULL; 591 cstate->dns_active = NULL;
@@ -739,7 +741,7 @@ start_connect (void *cls)
739 { 741 {
740 connect_success_continuation (cstate); 742 connect_success_continuation (cstate);
741 return; 743 return;
742 } 744 }
743 } 745 }
744 if ( (NULL == cstate->hostname) || 746 if ( (NULL == cstate->hostname) ||
745 (0 == cstate->port) ) 747 (0 == cstate->port) )
@@ -821,7 +823,7 @@ connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
821 * @return the message queue, NULL on error 823 * @return the message queue, NULL on error
822 */ 824 */
823struct GNUNET_MQ_Handle * 825struct GNUNET_MQ_Handle *
824GNUNET_CLIENT_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg, 826GNUNET_CLIENT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
825 const char *service_name, 827 const char *service_name,
826 const struct GNUNET_MQ_MessageHandler *handlers, 828 const struct GNUNET_MQ_MessageHandler *handlers,
827 GNUNET_MQ_ErrorHandler error_handler, 829 GNUNET_MQ_ErrorHandler error_handler,
diff --git a/src/util/common_logging.c b/src/util/common_logging.c
index 5989db00c..ce229826e 100644
--- a/src/util/common_logging.c
+++ b/src/util/common_logging.c
@@ -1153,6 +1153,29 @@ GNUNET_h2s (const struct GNUNET_HashCode * hc)
1153 1153
1154 1154
1155/** 1155/**
1156 * @ingroup logging
1157 * Convert a short hash value to a string (for printing debug messages).
1158 * This is one of the very few calls in the entire API that is
1159 * NOT reentrant!
1160 *
1161 * @param shc the hash code
1162 * @return string
1163 */
1164const char *
1165GNUNET_sh2s (const struct GNUNET_ShortHashCode *shc)
1166{
1167 static char buf[32];
1168
1169 GNUNET_STRINGS_data_to_string (shc,
1170 sizeof (*shc),
1171 buf,
1172 sizeof (buf));
1173 buf[6] = '\0';
1174 return (const char *) buf;
1175}
1176
1177
1178/**
1156 * Convert a hash to a string (for printing debug messages). 1179 * Convert a hash to a string (for printing debug messages).
1157 * This is one of the very few calls in the entire API that is 1180 * This is one of the very few calls in the entire API that is
1158 * NOT reentrant! 1181 * NOT reentrant!
diff --git a/src/util/container_heap.c b/src/util/container_heap.c
index 4f82fb076..1ead5ec6d 100644
--- a/src/util/container_heap.c
+++ b/src/util/container_heap.c
@@ -541,36 +541,23 @@ GNUNET_CONTAINER_heap_remove_node (struct GNUNET_CONTAINER_HeapNode *node)
541/** 541/**
542 * Updates the cost of any node in the tree 542 * Updates the cost of any node in the tree
543 * 543 *
544 * @param heap heap to modify
545 * @param node node for which the cost is to be changed 544 * @param node node for which the cost is to be changed
546 * @param new_cost new cost for the node 545 * @param new_cost new cost for the node
547 */ 546 */
548void 547void
549GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_Heap *heap, 548GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_HeapNode *node,
550 struct GNUNET_CONTAINER_HeapNode *node,
551 GNUNET_CONTAINER_HeapCostType new_cost) 549 GNUNET_CONTAINER_HeapCostType new_cost)
552{ 550{
553#if EXTRA_CHECKS 551 struct GNUNET_CONTAINER_Heap *heap = node->heap;
554 GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) || 552
555 (heap->size == heap->root->tree_size + 1));
556 CHECK (heap->root);
557#endif
558 remove_node (node); 553 remove_node (node);
559#if EXTRA_CHECKS
560 CHECK (heap->root);
561 GNUNET_assert (((heap->size == 1) && (heap->root == NULL)) ||
562 (heap->size == heap->root->tree_size + 2));
563#endif
564 node->cost = new_cost; 554 node->cost = new_cost;
565 if (heap->root == NULL) 555 if (NULL == heap->root)
566 heap->root = node; 556 heap->root = node;
567 else 557 else
568 insert_node (heap, heap->root, node); 558 insert_node (heap,
569#if EXTRA_CHECKS 559 heap->root,
570 CHECK (heap->root); 560 node);
571 GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) ||
572 (heap->size == heap->root->tree_size + 1));
573#endif
574} 561}
575 562
576 563
diff --git a/src/util/container_multishortmap.c b/src/util/container_multishortmap.c
new file mode 100644
index 000000000..5e8a47b09
--- /dev/null
+++ b/src/util/container_multishortmap.c
@@ -0,0 +1,965 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2008, 2012 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file util/container_multishortmap.c
22 * @brief hash map where the same key may be present multiple times
23 * @author Christian Grothoff
24 */
25
26#include "platform.h"
27#include "gnunet_util_lib.h"
28
29#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
30
31/**
32 * An entry in the hash map with the full key.
33 */
34struct BigMapEntry
35{
36
37 /**
38 * Value of the entry.
39 */
40 void *value;
41
42 /**
43 * If there is a hash collision, we create a linked list.
44 */
45 struct BigMapEntry *next;
46
47 /**
48 * Key for the entry.
49 */
50 struct GNUNET_ShortHashCode key;
51
52};
53
54
55/**
56 * An entry in the hash map with just a pointer to the key.
57 */
58struct SmallMapEntry
59{
60
61 /**
62 * Value of the entry.
63 */
64 void *value;
65
66 /**
67 * If there is a hash collision, we create a linked list.
68 */
69 struct SmallMapEntry *next;
70
71 /**
72 * Key for the entry.
73 */
74 const struct GNUNET_ShortHashCode *key;
75
76};
77
78
79/**
80 * Entry in the map.
81 */
82union MapEntry
83{
84 /**
85 * Variant used if map entries only contain a pointer to the key.
86 */
87 struct SmallMapEntry *sme;
88
89 /**
90 * Variant used if map entries contain the full key.
91 */
92 struct BigMapEntry *bme;
93};
94
95
96/**
97 * Internal representation of the hash map.
98 */
99struct GNUNET_CONTAINER_MultiShortmap
100{
101 /**
102 * All of our buckets.
103 */
104 union MapEntry *map;
105
106 /**
107 * Number of entries in the map.
108 */
109 unsigned int size;
110
111 /**
112 * Length of the "map" array.
113 */
114 unsigned int map_length;
115
116 /**
117 * GNUNET_NO if the map entries are of type 'struct BigMapEntry',
118 * GNUNET_YES if the map entries are of type 'struct SmallMapEntry'.
119 */
120 int use_small_entries;
121
122 /**
123 * Counts the destructive modifications (grow, remove)
124 * to the map, so that iterators can check if they are still valid.
125 */
126 unsigned int modification_counter;
127};
128
129
130/**
131 * Cursor into a multishortmap.
132 * Allows to enumerate elements asynchronously.
133 */
134struct GNUNET_CONTAINER_MultiShortmapIterator
135{
136 /**
137 * Position in the bucket 'idx'
138 */
139 union MapEntry me;
140
141 /**
142 * Current bucket index.
143 */
144 unsigned int idx;
145
146 /**
147 * Modification counter as observed on the map when the iterator
148 * was created.
149 */
150 unsigned int modification_counter;
151
152 /**
153 * Map that we are iterating over.
154 */
155 const struct GNUNET_CONTAINER_MultiShortmap *map;
156};
157
158
159/**
160 * Create a multi hash map.
161 *
162 * @param len initial size (map will grow as needed)
163 * @param do_not_copy_keys GNUNET_NO is always safe and should be used by default;
164 * GNUNET_YES means that on 'put', the 'key' does not have
165 * to be copied as the destination of the pointer is
166 * guaranteed to be life as long as the value is stored in
167 * the hashmap. This can significantly reduce memory
168 * consumption, but of course is also a recipie for
169 * heap corruption if the assumption is not true. Only
170 * use this if (1) memory use is important in this case and
171 * (2) you have triple-checked that the invariant holds
172 * @return NULL on error
173 */
174struct GNUNET_CONTAINER_MultiShortmap *
175GNUNET_CONTAINER_multishortmap_create (unsigned int len,
176 int do_not_copy_keys)
177{
178 struct GNUNET_CONTAINER_MultiShortmap *map;
179
180 GNUNET_assert (len > 0);
181 map = GNUNET_new (struct GNUNET_CONTAINER_MultiShortmap);
182 map->map = GNUNET_malloc (len * sizeof (union MapEntry));
183 map->map_length = len;
184 map->use_small_entries = do_not_copy_keys;
185 return map;
186}
187
188
189/**
190 * Destroy a hash map. Will not free any values
191 * stored in the hash map!
192 *
193 * @param map the map
194 */
195void
196GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap
197 *map)
198{
199 unsigned int i;
200 union MapEntry me;
201
202 for (i = 0; i < map->map_length; i++)
203 {
204 me = map->map[i];
205 if (map->use_small_entries)
206 {
207 struct SmallMapEntry *sme;
208 struct SmallMapEntry *nxt;
209
210 nxt = me.sme;
211 while (NULL != (sme = nxt))
212 {
213 nxt = sme->next;
214 GNUNET_free (sme);
215 }
216 me.sme = NULL;
217 }
218 else
219 {
220 struct BigMapEntry *bme;
221 struct BigMapEntry *nxt;
222
223 nxt = me.bme;
224 while (NULL != (bme = nxt))
225 {
226 nxt = bme->next;
227 GNUNET_free (bme);
228 }
229 me.bme = NULL;
230 }
231 }
232 GNUNET_free (map->map);
233 GNUNET_free (map);
234}
235
236
237/**
238 * Compute the index of the bucket for the given key.
239 *
240 * @param map hash map for which to compute the index
241 * @param key what key should the index be computed for
242 * @return offset into the "map" array of "map"
243 */
244static unsigned int
245idx_of (const struct GNUNET_CONTAINER_MultiShortmap *map,
246 const struct GNUNET_ShortHashCode *key)
247{
248 unsigned int kx;
249
250 GNUNET_assert (NULL != map);
251 GNUNET_memcpy (&kx, key, sizeof (kx));
252 return kx % map->map_length;
253}
254
255
256/**
257 * Get the number of key-value pairs in the map.
258 *
259 * @param map the map
260 * @return the number of key value pairs
261 */
262unsigned int
263GNUNET_CONTAINER_multishortmap_size (const struct GNUNET_CONTAINER_MultiShortmap *map)
264{
265 return map->size;
266}
267
268
269/**
270 * Given a key find a value in the map matching the key.
271 *
272 * @param map the map
273 * @param key what to look for
274 * @return NULL if no value was found; note that
275 * this is indistinguishable from values that just
276 * happen to be NULL; use "contains" to test for
277 * key-value pairs with value NULL
278 */
279void *
280GNUNET_CONTAINER_multishortmap_get (const struct GNUNET_CONTAINER_MultiShortmap *map,
281 const struct GNUNET_ShortHashCode *key)
282{
283 union MapEntry me;
284
285 me = map->map[idx_of (map, key)];
286 if (map->use_small_entries)
287 {
288 struct SmallMapEntry *sme;
289
290 for (sme = me.sme; NULL != sme; sme = sme->next)
291 if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
292 return sme->value;
293 }
294 else
295 {
296 struct BigMapEntry *bme;
297
298 for (bme = me.bme; NULL != bme; bme = bme->next)
299 if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
300 return bme->value;
301 }
302 return NULL;
303}
304
305
306/**
307 * Iterate over all entries in the map.
308 *
309 * @param map the map
310 * @param it function to call on each entry
311 * @param it_cls extra argument to @a it
312 * @return the number of key value pairs processed,
313 * #GNUNET_SYSERR if it aborted iteration
314 */
315int
316GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map,
317 GNUNET_CONTAINER_ShortmapIterator it,
318 void *it_cls)
319{
320 int count;
321 unsigned int i;
322 union MapEntry me;
323 struct GNUNET_ShortHashCode kc;
324
325 count = 0;
326 GNUNET_assert (NULL != map);
327 for (i = 0; i < map->map_length; i++)
328 {
329 me = map->map[i];
330 if (map->use_small_entries)
331 {
332 struct SmallMapEntry *sme;
333 struct SmallMapEntry *nxt;
334
335 nxt = me.sme;
336 while (NULL != (sme = nxt))
337 {
338 nxt = sme->next;
339 if (NULL != it)
340 {
341 if (GNUNET_OK != it (it_cls, sme->key, sme->value))
342 return GNUNET_SYSERR;
343 }
344 count++;
345 }
346 }
347 else
348 {
349 struct BigMapEntry *bme;
350 struct BigMapEntry *nxt;
351
352 nxt = me.bme;
353 while (NULL != (bme = nxt))
354 {
355 nxt = bme->next;
356 if (NULL != it)
357 {
358 kc = bme->key;
359 if (GNUNET_OK != it (it_cls, &kc, bme->value))
360 return GNUNET_SYSERR;
361 }
362 count++;
363 }
364 }
365 }
366 return count;
367}
368
369
370/**
371 * Remove the given key-value pair from the map. Note that if the
372 * key-value pair is in the map multiple times, only one of the pairs
373 * will be removed.
374 *
375 * @param map the map
376 * @param key key of the key-value pair
377 * @param value value of the key-value pair
378 * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair
379 * is not in the map
380 */
381int
382GNUNET_CONTAINER_multishortmap_remove (struct GNUNET_CONTAINER_MultiShortmap *map,
383 const struct GNUNET_ShortHashCode *key,
384 const void *value)
385{
386 union MapEntry me;
387 unsigned int i;
388
389 map->modification_counter++;
390
391 i = idx_of (map, key);
392 me = map->map[i];
393 if (map->use_small_entries)
394 {
395 struct SmallMapEntry *sme;
396 struct SmallMapEntry *p;
397
398 p = NULL;
399 for (sme = me.sme; NULL != sme; sme = sme->next)
400 {
401 if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) &&
402 (value == sme->value))
403 {
404 if (NULL == p)
405 map->map[i].sme = sme->next;
406 else
407 p->next = sme->next;
408 GNUNET_free (sme);
409 map->size--;
410 return GNUNET_YES;
411 }
412 p = sme;
413 }
414 }
415 else
416 {
417 struct BigMapEntry *bme;
418 struct BigMapEntry *p;
419
420 p = NULL;
421 for (bme = me.bme; NULL != bme; bme = bme->next)
422 {
423 if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) &&
424 (value == bme->value))
425 {
426 if (NULL == p)
427 map->map[i].bme = bme->next;
428 else
429 p->next = bme->next;
430 GNUNET_free (bme);
431 map->size--;
432 return GNUNET_YES;
433 }
434 p = bme;
435 }
436 }
437 return GNUNET_NO;
438}
439
440
441/**
442 * Remove all entries for the given key from the map.
443 * Note that the values would not be "freed".
444 *
445 * @param map the map
446 * @param key identifies values to be removed
447 * @return number of values removed
448 */
449int
450GNUNET_CONTAINER_multishortmap_remove_all (struct GNUNET_CONTAINER_MultiShortmap *map,
451 const struct GNUNET_ShortHashCode *key)
452{
453 union MapEntry me;
454 unsigned int i;
455 int ret;
456
457 map->modification_counter++;
458
459 ret = 0;
460 i = idx_of (map, key);
461 me = map->map[i];
462 if (map->use_small_entries)
463 {
464 struct SmallMapEntry *sme;
465 struct SmallMapEntry *p;
466
467 p = NULL;
468 sme = me.sme;
469 while (NULL != sme)
470 {
471 if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
472 {
473 if (NULL == p)
474 map->map[i].sme = sme->next;
475 else
476 p->next = sme->next;
477 GNUNET_free (sme);
478 map->size--;
479 if (NULL == p)
480 sme = map->map[i].sme;
481 else
482 sme = p->next;
483 ret++;
484 }
485 else
486 {
487 p = sme;
488 sme = sme->next;
489 }
490 }
491 }
492 else
493 {
494 struct BigMapEntry *bme;
495 struct BigMapEntry *p;
496
497 p = NULL;
498 bme = me.bme;
499 while (NULL != bme)
500 {
501 if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
502 {
503 if (NULL == p)
504 map->map[i].bme = bme->next;
505 else
506 p->next = bme->next;
507 GNUNET_free (bme);
508 map->size--;
509 if (NULL == p)
510 bme = map->map[i].bme;
511 else
512 bme = p->next;
513 ret++;
514 }
515 else
516 {
517 p = bme;
518 bme = bme->next;
519 }
520 }
521 }
522 return ret;
523}
524
525
526/**
527 * Check if the map contains any value under the given
528 * key (including values that are NULL).
529 *
530 * @param map the map
531 * @param key the key to test if a value exists for it
532 * @return #GNUNET_YES if such a value exists,
533 * #GNUNET_NO if not
534 */
535int
536GNUNET_CONTAINER_multishortmap_contains (const struct GNUNET_CONTAINER_MultiShortmap *map,
537 const struct GNUNET_ShortHashCode *key)
538{
539 union MapEntry me;
540
541 me = map->map[idx_of (map, key)];
542 if (map->use_small_entries)
543 {
544 struct SmallMapEntry *sme;
545
546 for (sme = me.sme; NULL != sme; sme = sme->next)
547 if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
548 return GNUNET_YES;
549 }
550 else
551 {
552 struct BigMapEntry *bme;
553
554 for (bme = me.bme; NULL != bme; bme = bme->next)
555 if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
556 return GNUNET_YES;
557 }
558 return GNUNET_NO;
559}
560
561
562/**
563 * Check if the map contains the given value under the given
564 * key.
565 *
566 * @param map the map
567 * @param key the key to test if a value exists for it
568 * @param value value to test for
569 * @return #GNUNET_YES if such a value exists,
570 * #GNUNET_NO if not
571 */
572int
573GNUNET_CONTAINER_multishortmap_contains_value (const struct GNUNET_CONTAINER_MultiShortmap *map,
574 const struct GNUNET_ShortHashCode *key,
575 const void *value)
576{
577 union MapEntry me;
578
579 me = map->map[idx_of (map, key)];
580 if (map->use_small_entries)
581 {
582 struct SmallMapEntry *sme;
583
584 for (sme = me.sme; NULL != sme; sme = sme->next)
585 if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) &&
586 (sme->value == value) )
587 return GNUNET_YES;
588 }
589 else
590 {
591 struct BigMapEntry *bme;
592
593 for (bme = me.bme; NULL != bme; bme = bme->next)
594 if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) &&
595 (bme->value == value) )
596 return GNUNET_YES;
597 }
598 return GNUNET_NO;
599}
600
601
602/**
603 * Grow the given map to a more appropriate size.
604 *
605 * @param map the hash map to grow
606 */
607static void
608grow (struct GNUNET_CONTAINER_MultiShortmap *map)
609{
610 union MapEntry *old_map;
611 union MapEntry *new_map;
612 unsigned int old_len;
613 unsigned int new_len;
614 unsigned int idx;
615 unsigned int i;
616
617 map->modification_counter++;
618
619 old_map = map->map;
620 old_len = map->map_length;
621 new_len = old_len * 2;
622 new_map = GNUNET_malloc (sizeof (union MapEntry) * new_len);
623 map->map_length = new_len;
624 map->map = new_map;
625 for (i = 0; i < old_len; i++)
626 {
627 if (map->use_small_entries)
628 {
629 struct SmallMapEntry *sme;
630
631 while (NULL != (sme = old_map[i].sme))
632 {
633 old_map[i].sme = sme->next;
634 idx = idx_of (map, sme->key);
635 sme->next = new_map[idx].sme;
636 new_map[idx].sme = sme;
637 }
638 }
639 else
640 {
641 struct BigMapEntry *bme;
642
643 while (NULL != (bme = old_map[i].bme))
644 {
645 old_map[i].bme = bme->next;
646 idx = idx_of (map, &bme->key);
647 bme->next = new_map[idx].bme;
648 new_map[idx].bme = bme;
649 }
650 }
651 }
652 GNUNET_free (old_map);
653}
654
655
656/**
657 * Store a key-value pair in the map.
658 *
659 * @param map the map
660 * @param key key to use
661 * @param value value to use
662 * @param opt options for put
663 * @return #GNUNET_OK on success,
664 * #GNUNET_NO if a value was replaced (with REPLACE)
665 * #GNUNET_SYSERR if GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the
666 * value already exists
667 */
668int
669GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map,
670 const struct GNUNET_ShortHashCode *key,
671 void *value,
672 enum GNUNET_CONTAINER_MultiHashMapOption opt)
673{
674 union MapEntry me;
675 unsigned int i;
676
677 i = idx_of (map, key);
678 if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) &&
679 (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
680 {
681 me = map->map[i];
682 if (map->use_small_entries)
683 {
684 struct SmallMapEntry *sme;
685
686 for (sme = me.sme; NULL != sme; sme = sme->next)
687 if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
688 {
689 if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)
690 return GNUNET_SYSERR;
691 sme->value = value;
692 return GNUNET_NO;
693 }
694 }
695 else
696 {
697 struct BigMapEntry *bme;
698
699 for (bme = me.bme; NULL != bme; bme = bme->next)
700 if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
701 {
702 if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)
703 return GNUNET_SYSERR;
704 bme->value = value;
705 return GNUNET_NO;
706 }
707 }
708 }
709 if (map->size / 3 >= map->map_length / 4)
710 {
711 grow (map);
712 i = idx_of (map, key);
713 }
714 if (map->use_small_entries)
715 {
716 struct SmallMapEntry *sme;
717
718 sme = GNUNET_new (struct SmallMapEntry);
719 sme->key = key;
720 sme->value = value;
721 sme->next = map->map[i].sme;
722 map->map[i].sme = sme;
723 }
724 else
725 {
726 struct BigMapEntry *bme;
727
728 bme = GNUNET_new (struct BigMapEntry);
729 bme->key = *key;
730 bme->value = value;
731 bme->next = map->map[i].bme;
732 map->map[i].bme = bme;
733 }
734 map->size++;
735 return GNUNET_OK;
736}
737
738
739/**
740 * Iterate over all entries in the map that match a particular key.
741 *
742 * @param map the map
743 * @param key key that the entries must correspond to
744 * @param it function to call on each entry
745 * @param it_cls extra argument to @a it
746 * @return the number of key value pairs processed,
747 * #GNUNET_SYSERR if it aborted iteration
748 */
749int
750GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map,
751 const struct GNUNET_ShortHashCode *key,
752 GNUNET_CONTAINER_ShortmapIterator it,
753 void *it_cls)
754{
755 int count;
756 union MapEntry me;
757
758 count = 0;
759 me = map->map[idx_of (map, key)];
760 if (map->use_small_entries)
761 {
762 struct SmallMapEntry *sme;
763 struct SmallMapEntry *nxt;
764
765 nxt = me.sme;
766 while (NULL != (sme = nxt))
767 {
768 nxt = sme->next;
769 if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode)))
770 continue;
771 if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value)))
772 return GNUNET_SYSERR;
773 count++;
774 }
775 }
776 else
777 {
778 struct BigMapEntry *bme;
779 struct BigMapEntry *nxt;
780
781 nxt = me.bme;
782 while (NULL != (bme = nxt))
783 {
784 nxt = bme->next;
785 if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode)))
786 continue;
787 if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value)))
788 return GNUNET_SYSERR;
789 count++;
790 }
791 }
792 return count;
793}
794
795
796/**
797 * @ingroup hashmap
798 * Call @a it on a random value from the map, or not at all
799 * if the map is empty. Note that this function has linear
800 * complexity (in the size of the map).
801 *
802 * @param map the map
803 * @param it function to call on a random entry
804 * @param it_cls extra argument to @a it
805 * @return the number of key value pairs processed, zero or one.
806 */
807unsigned int
808GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiShortmap *map,
809 GNUNET_CONTAINER_ShortmapIterator it,
810 void *it_cls)
811{
812 unsigned int off;
813 unsigned int idx;
814 union MapEntry me;
815
816 if (0 == map->size)
817 return 0;
818 if (NULL == it)
819 return 1;
820 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
821 map->size);
822 for (idx = 0; idx < map->map_length; idx++)
823 {
824 me = map->map[idx];
825 if (map->use_small_entries)
826 {
827 struct SmallMapEntry *sme;
828 struct SmallMapEntry *nxt;
829
830 nxt = me.sme;
831 while (NULL != (sme = nxt))
832 {
833 nxt = sme->next;
834 if (0 == off)
835 {
836 if (GNUNET_OK != it (it_cls,
837 sme->key,
838 sme->value))
839 return GNUNET_SYSERR;
840 return 1;
841 }
842 off--;
843 }
844 }
845 else
846 {
847 struct BigMapEntry *bme;
848 struct BigMapEntry *nxt;
849
850 nxt = me.bme;
851 while (NULL != (bme = nxt))
852 {
853 nxt = bme->next;
854 if (0 == off)
855 {
856 if (GNUNET_OK != it (it_cls,
857 &bme->key, bme->value))
858 return GNUNET_SYSERR;
859 return 1;
860 }
861 off--;
862 }
863 }
864 }
865 GNUNET_break (0);
866 return GNUNET_SYSERR;
867}
868
869
870/**
871 * Create an iterator for a multishortmap.
872 * The iterator can be used to retrieve all the elements in the multishortmap
873 * one by one, without having to handle all elements at once (in contrast to
874 * #GNUNET_CONTAINER_multishortmap_iterate). Note that the iterator can not be
875 * used anymore if elements have been removed from 'map' after the creation of
876 * the iterator, or 'map' has been destroyed. Adding elements to 'map' may
877 * result in skipped or repeated elements.
878 *
879 * @param map the map to create an iterator for
880 * @return an iterator over the given multishortmap 'map'
881 */
882struct GNUNET_CONTAINER_MultiShortmapIterator *
883GNUNET_CONTAINER_multishortmap_iterator_create (const struct GNUNET_CONTAINER_MultiShortmap *map)
884{
885 struct GNUNET_CONTAINER_MultiShortmapIterator *iter;
886
887 iter = GNUNET_new (struct GNUNET_CONTAINER_MultiShortmapIterator);
888 iter->map = map;
889 iter->modification_counter = map->modification_counter;
890 iter->me = map->map[0];
891 return iter;
892}
893
894
895/**
896 * Retrieve the next element from the hash map at the iterator's position.
897 * If there are no elements left, GNUNET_NO is returned, and 'key' and 'value'
898 * are not modified.
899 * This operation is only allowed if no elements have been removed from the
900 * multishortmap since the creation of 'iter', and the map has not been destroyed.
901 * Adding elements may result in repeating or skipping elements.
902 *
903 * @param iter the iterator to get the next element from
904 * @param key pointer to store the key in, can be NULL
905 * @param value pointer to store the value in, can be NULL
906 * @return #GNUNET_YES we returned an element,
907 * #GNUNET_NO if we are out of elements
908 */
909int
910GNUNET_CONTAINER_multishortmap_iterator_next (struct GNUNET_CONTAINER_MultiShortmapIterator *iter,
911 struct GNUNET_ShortHashCode *key,
912 const void **value)
913{
914 /* make sure the map has not been modified */
915 GNUNET_assert (iter->modification_counter == iter->map->modification_counter);
916
917 /* look for the next entry, skipping empty buckets */
918 while (1)
919 {
920 if (iter->idx >= iter->map->map_length)
921 return GNUNET_NO;
922 if (GNUNET_YES == iter->map->use_small_entries)
923 {
924 if (NULL != iter->me.sme)
925 {
926 if (NULL != key)
927 *key = *iter->me.sme->key;
928 if (NULL != value)
929 *value = iter->me.sme->value;
930 iter->me.sme = iter->me.sme->next;
931 return GNUNET_YES;
932 }
933 }
934 else
935 {
936 if (NULL != iter->me.bme)
937 {
938 if (NULL != key)
939 *key = iter->me.bme->key;
940 if (NULL != value)
941 *value = iter->me.bme->value;
942 iter->me.bme = iter->me.bme->next;
943 return GNUNET_YES;
944 }
945 }
946 iter->idx += 1;
947 if (iter->idx < iter->map->map_length)
948 iter->me = iter->map->map[iter->idx];
949 }
950}
951
952
953/**
954 * Destroy a multishortmap iterator.
955 *
956 * @param iter the iterator to destroy
957 */
958void
959GNUNET_CONTAINER_multishortmap_iterator_destroy (struct GNUNET_CONTAINER_MultiShortmapIterator *iter)
960{
961 GNUNET_free (iter);
962}
963
964
965/* end of container_multishortmap.c */
diff --git a/src/util/mq.c b/src/util/mq.c
index ae13ff601..985e86331 100644
--- a/src/util/mq.c
+++ b/src/util/mq.c
@@ -58,7 +58,7 @@ struct GNUNET_MQ_Envelope
58 /** 58 /**
59 * Called after the message was sent irrevocably. 59 * Called after the message was sent irrevocably.
60 */ 60 */
61 GNUNET_MQ_NotifyCallback sent_cb; 61 GNUNET_SCHEDULER_TaskCallback sent_cb;
62 62
63 /** 63 /**
64 * Closure for @e send_cb 64 * Closure for @e send_cb
@@ -128,10 +128,10 @@ struct GNUNET_MQ_Handle
128 void *error_handler_cls; 128 void *error_handler_cls;
129 129
130 /** 130 /**
131 * Task to asynchronously run #impl_send_continue(). 131 * Task to asynchronously run #impl_send_continue().
132 */ 132 */
133 struct GNUNET_SCHEDULER_Task *send_task; 133 struct GNUNET_SCHEDULER_Task *send_task;
134 134
135 /** 135 /**
136 * Linked list of messages pending to be sent 136 * Linked list of messages pending to be sent
137 */ 137 */
@@ -414,7 +414,7 @@ static void
414impl_send_continue (void *cls) 414impl_send_continue (void *cls)
415{ 415{
416 struct GNUNET_MQ_Handle *mq = cls; 416 struct GNUNET_MQ_Handle *mq = cls;
417 417
418 mq->send_task = NULL; 418 mq->send_task = NULL;
419 /* call is only valid if we're actually currently sending 419 /* call is only valid if we're actually currently sending
420 * a message */ 420 * a message */
@@ -441,8 +441,8 @@ void
441GNUNET_MQ_impl_send_continue (struct GNUNET_MQ_Handle *mq) 441GNUNET_MQ_impl_send_continue (struct GNUNET_MQ_Handle *mq)
442{ 442{
443 struct GNUNET_MQ_Envelope *current_envelope; 443 struct GNUNET_MQ_Envelope *current_envelope;
444 GNUNET_MQ_NotifyCallback cb; 444 GNUNET_SCHEDULER_TaskCallback cb;
445 445
446 GNUNET_assert (0 < mq->queue_length); 446 GNUNET_assert (0 < mq->queue_length);
447 mq->queue_length--; 447 mq->queue_length--;
448 mq->in_flight = GNUNET_NO; 448 mq->in_flight = GNUNET_NO;
@@ -456,7 +456,7 @@ GNUNET_MQ_impl_send_continue (struct GNUNET_MQ_Handle *mq)
456 { 456 {
457 current_envelope->sent_cb = NULL; 457 current_envelope->sent_cb = NULL;
458 cb (current_envelope->sent_cls); 458 cb (current_envelope->sent_cls);
459 } 459 }
460 GNUNET_free (current_envelope); 460 GNUNET_free (current_envelope);
461} 461}
462 462
@@ -475,8 +475,8 @@ void
475GNUNET_MQ_impl_send_in_flight (struct GNUNET_MQ_Handle *mq) 475GNUNET_MQ_impl_send_in_flight (struct GNUNET_MQ_Handle *mq)
476{ 476{
477 struct GNUNET_MQ_Envelope *current_envelope; 477 struct GNUNET_MQ_Envelope *current_envelope;
478 GNUNET_MQ_NotifyCallback cb; 478 GNUNET_SCHEDULER_TaskCallback cb;
479 479
480 mq->in_flight = GNUNET_YES; 480 mq->in_flight = GNUNET_YES;
481 /* call is only valid if we're actually currently sending 481 /* call is only valid if we're actually currently sending
482 * a message */ 482 * a message */
@@ -812,7 +812,7 @@ GNUNET_MQ_assoc_remove (struct GNUNET_MQ_Handle *mq,
812 */ 812 */
813void 813void
814GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *mqm, 814GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *mqm,
815 GNUNET_MQ_NotifyCallback cb, 815 GNUNET_SCHEDULER_TaskCallback cb,
816 void *cb_cls) 816 void *cb_cls)
817{ 817{
818 mqm->sent_cb = cb; 818 mqm->sent_cb = cb;
@@ -953,7 +953,7 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev)
953 953
954 GNUNET_assert (NULL != mq); 954 GNUNET_assert (NULL != mq);
955 GNUNET_assert (NULL != mq->cancel_impl); 955 GNUNET_assert (NULL != mq->cancel_impl);
956 956
957 mq->evacuate_called = GNUNET_NO; 957 mq->evacuate_called = GNUNET_NO;
958 958
959 if (mq->current_envelope == ev) 959 if (mq->current_envelope == ev)
diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c
index 481e99157..fdeaed006 100644
--- a/src/util/resolver_api.c
+++ b/src/util/resolver_api.c
@@ -735,7 +735,7 @@ reconnect_task (void *cls)
735 return; /* no work pending */ 735 return; /* no work pending */
736 LOG (GNUNET_ERROR_TYPE_DEBUG, 736 LOG (GNUNET_ERROR_TYPE_DEBUG,
737 "Trying to connect to DNS service\n"); 737 "Trying to connect to DNS service\n");
738 mq = GNUNET_CLIENT_connecT (resolver_cfg, 738 mq = GNUNET_CLIENT_connect (resolver_cfg,
739 "resolver", 739 "resolver",
740 handlers, 740 handlers,
741 &mq_error_handler, 741 &mq_error_handler,
diff --git a/src/util/test_client.c b/src/util/test_client.c
index aa4d84495..f60e5b7f7 100644
--- a/src/util/test_client.c
+++ b/src/util/test_client.c
@@ -98,12 +98,12 @@ task (void *cls,
98 98
99 /* test that ill-configured client fails instantly */ 99 /* test that ill-configured client fails instantly */
100 GNUNET_assert (NULL == 100 GNUNET_assert (NULL ==
101 GNUNET_CLIENT_connecT (cfg, 101 GNUNET_CLIENT_connect (cfg,
102 "invalid-service", 102 "invalid-service",
103 NULL, 103 NULL,
104 &mq_error_handler, 104 &mq_error_handler,
105 NULL)); 105 NULL));
106 client_mq = GNUNET_CLIENT_connecT (cfg, 106 client_mq = GNUNET_CLIENT_connect (cfg,
107 "test_client", 107 "test_client",
108 chandlers, 108 chandlers,
109 &mq_error_handler, 109 &mq_error_handler,
diff --git a/src/util/test_container_heap.c b/src/util/test_container_heap.c
index f115159bf..82b0e9523 100644
--- a/src/util/test_container_heap.c
+++ b/src/util/test_container_heap.c
@@ -28,7 +28,8 @@
28#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
29 29
30static int 30static int
31iterator_callback (void *cls, struct GNUNET_CONTAINER_HeapNode *node, 31iterator_callback (void *cls,
32 struct GNUNET_CONTAINER_HeapNode *node,
32 void *element, GNUNET_CONTAINER_HeapCostType cost) 33 void *element, GNUNET_CONTAINER_HeapCostType cost)
33{ 34{
34 return GNUNET_OK; 35 return GNUNET_OK;
@@ -93,12 +94,12 @@ check ()
93 GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); 94 GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL);
94 95
95 n3 = GNUNET_CONTAINER_heap_insert (myHeap, "15", 5); 96 n3 = GNUNET_CONTAINER_heap_insert (myHeap, "15", 5);
96 GNUNET_CONTAINER_heap_update_cost (myHeap, n3, 15); 97 GNUNET_CONTAINER_heap_update_cost (n3, 15);
97 GNUNET_assert (2 == GNUNET_CONTAINER_heap_get_size (myHeap)); 98 GNUNET_assert (2 == GNUNET_CONTAINER_heap_get_size (myHeap));
98 GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); 99 GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL);
99 100
100 n4 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50); 101 n4 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50);
101 GNUNET_CONTAINER_heap_update_cost (myHeap, n4, 50); 102 GNUNET_CONTAINER_heap_update_cost (n4, 50);
102 GNUNET_assert (3 == GNUNET_CONTAINER_heap_get_size (myHeap)); 103 GNUNET_assert (3 == GNUNET_CONTAINER_heap_get_size (myHeap));
103 GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); 104 GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL);
104 105
@@ -109,7 +110,7 @@ check ()
109 r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n1 */ 110 r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n1 */
110 GNUNET_assert (NULL != r); 111 GNUNET_assert (NULL != r);
111 GNUNET_assert (0 == strcmp ("11", r)); 112 GNUNET_assert (0 == strcmp ("11", r));
112 GNUNET_CONTAINER_heap_update_cost (myHeap, n6, 200); 113 GNUNET_CONTAINER_heap_update_cost (n6, 200);
113 GNUNET_CONTAINER_heap_remove_node (n3); 114 GNUNET_CONTAINER_heap_remove_node (n3);
114 r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n4 */ 115 r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n4 */
115 GNUNET_assert (NULL != r); 116 GNUNET_assert (NULL != r);
@@ -128,7 +129,7 @@ check ()
128 myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 129 myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
129 130
130 n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); 131 n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10);
131 GNUNET_CONTAINER_heap_update_cost (myHeap, n1, 15); 132 GNUNET_CONTAINER_heap_update_cost (n1, 15);
132 133
133 r = GNUNET_CONTAINER_heap_remove_node (n1); 134 r = GNUNET_CONTAINER_heap_remove_node (n1);
134 GNUNET_assert (NULL != r); 135 GNUNET_assert (NULL != r);
@@ -213,7 +214,7 @@ check ()
213 myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); 214 myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX);
214 215
215 n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); 216 n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10);
216 GNUNET_CONTAINER_heap_update_cost (myHeap, n1, 15); 217 GNUNET_CONTAINER_heap_update_cost (n1, 15);
217 218
218 GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); 219 GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1)));
219 220
diff --git a/src/util/test_server.c b/src/util/test_server.c
index eac45fc69..8003adbf4 100644
--- a/src/util/test_server.c
+++ b/src/util/test_server.c
@@ -267,7 +267,7 @@ task (void *cls)
267 "resolver", 267 "resolver",
268 "HOSTNAME", 268 "HOSTNAME",
269 "localhost"); 269 "localhost");
270 mq = GNUNET_CLIENT_connecT (cfg, 270 mq = GNUNET_CLIENT_connect (cfg,
271 "test-server", 271 "test-server",
272 chandlers, 272 chandlers,
273 &mq_error_handler, 273 &mq_error_handler,
diff --git a/src/util/test_server_disconnect.c b/src/util/test_server_disconnect.c
index de9c4722d..c3d003e90 100644
--- a/src/util/test_server_disconnect.c
+++ b/src/util/test_server_disconnect.c
@@ -125,7 +125,7 @@ task (void *cls)
125 "localhost"); 125 "localhost");
126 GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", 126 GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME",
127 "localhost"); 127 "localhost");
128 mq = GNUNET_CLIENT_connecT (cfg, 128 mq = GNUNET_CLIENT_connect (cfg,
129 "test-server", 129 "test-server",
130 NULL, 130 NULL,
131 NULL, 131 NULL,
diff --git a/src/util/test_server_with_client.c b/src/util/test_server_with_client.c
index 59f9b6afd..63bfda00c 100644
--- a/src/util/test_server_with_client.c
+++ b/src/util/test_server_with_client.c
@@ -166,7 +166,7 @@ task (void *cls)
166 GNUNET_CONFIGURATION_set_value_string (cfg, "test", "HOSTNAME", "localhost"); 166 GNUNET_CONFIGURATION_set_value_string (cfg, "test", "HOSTNAME", "localhost");
167 GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", 167 GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME",
168 "localhost"); 168 "localhost");
169 mq = GNUNET_CLIENT_connecT (cfg, 169 mq = GNUNET_CLIENT_connect (cfg,
170 "test", 170 "test",
171 NULL, 171 NULL,
172 NULL, 172 NULL,
diff --git a/src/util/test_server_with_client_unix.c b/src/util/test_server_with_client_unix.c
index ef48aabce..d240f1a88 100644
--- a/src/util/test_server_with_client_unix.c
+++ b/src/util/test_server_with_client_unix.c
@@ -144,7 +144,7 @@ task (void *cls)
144 GNUNET_CONFIGURATION_set_value_string (cfg, "test", "UNIXPATH", unixpath); 144 GNUNET_CONFIGURATION_set_value_string (cfg, "test", "UNIXPATH", unixpath);
145 GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", 145 GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME",
146 "localhost"); 146 "localhost");
147 mq = GNUNET_CLIENT_connecT (cfg, 147 mq = GNUNET_CLIENT_connect (cfg,
148 "test", 148 "test",
149 NULL, 149 NULL,
150 NULL, 150 NULL,
diff --git a/src/util/test_service.c b/src/util/test_service.c
index dc9d16ed9..d2136b42f 100644
--- a/src/util/test_service.c
+++ b/src/util/test_service.c
@@ -107,7 +107,7 @@ service_init (void *cls,
107 struct GNUNET_MQ_Envelope *env; 107 struct GNUNET_MQ_Envelope *env;
108 struct GNUNET_MessageHeader *msg; 108 struct GNUNET_MessageHeader *msg;
109 109
110 mq = GNUNET_CLIENT_connecT (cfg, 110 mq = GNUNET_CLIENT_connect (cfg,
111 service_name, 111 service_name,
112 NULL, 112 NULL,
113 NULL, 113 NULL,
diff --git a/src/util/test_socks.c b/src/util/test_socks.c
index 416f32f62..cb70f916f 100644
--- a/src/util/test_socks.c
+++ b/src/util/test_socks.c
@@ -160,7 +160,7 @@ task (void *cls)
160 handlers[0].callback_cls = cls; 160 handlers[0].callback_cls = cls;
161 handlers[1].callback_cls = cls; 161 handlers[1].callback_cls = cls;
162 GNUNET_SERVER_add_handlers (server, handlers); 162 GNUNET_SERVER_add_handlers (server, handlers);
163 mq = GNUNET_CLIENT_connecT (cfg, 163 mq = GNUNET_CLIENT_connect (cfg,
164 MYNAME, 164 MYNAME,
165 chandlers, 165 chandlers,
166 &mq_error_handler, 166 &mq_error_handler,
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index 4c0978d5c..c66023c85 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -1129,8 +1129,7 @@ route_packet (struct DestinationEntry *destination,
1129 } 1129 }
1130 else 1130 else
1131 { 1131 {
1132 GNUNET_CONTAINER_heap_update_cost (channel_heap, 1132 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1133 ts->heap_node,
1134 GNUNET_TIME_absolute_get ().abs_value_us); 1133 GNUNET_TIME_absolute_get ().abs_value_us);
1135 } 1134 }
1136 if (NULL == ts->channel) 1135 if (NULL == ts->channel)
@@ -2062,8 +2061,7 @@ receive_icmp_back (void *cls,
2062 default: 2061 default:
2063 GNUNET_assert (0); 2062 GNUNET_assert (0);
2064 } 2063 }
2065 GNUNET_CONTAINER_heap_update_cost (channel_heap, 2064 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
2066 ts->heap_node,
2067 GNUNET_TIME_absolute_get ().abs_value_us); 2065 GNUNET_TIME_absolute_get ().abs_value_us);
2068 GNUNET_CADET_receive_done (channel); 2066 GNUNET_CADET_receive_done (channel);
2069 return GNUNET_OK; 2067 return GNUNET_OK;
@@ -2218,8 +2216,7 @@ receive_udp_back (void *cls,
2218 default: 2216 default:
2219 GNUNET_assert (0); 2217 GNUNET_assert (0);
2220 } 2218 }
2221 GNUNET_CONTAINER_heap_update_cost (channel_heap, 2219 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
2222 ts->heap_node,
2223 GNUNET_TIME_absolute_get ().abs_value_us); 2220 GNUNET_TIME_absolute_get ().abs_value_us);
2224 GNUNET_CADET_receive_done (channel); 2221 GNUNET_CADET_receive_done (channel);
2225 return GNUNET_OK; 2222 return GNUNET_OK;
@@ -2361,8 +2358,7 @@ receive_tcp_back (void *cls,
2361 } 2358 }
2362 break; 2359 break;
2363 } 2360 }
2364 GNUNET_CONTAINER_heap_update_cost (channel_heap, 2361 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
2365 ts->heap_node,
2366 GNUNET_TIME_absolute_get ().abs_value_us); 2362 GNUNET_TIME_absolute_get ().abs_value_us);
2367 GNUNET_CADET_receive_done (channel); 2363 GNUNET_CADET_receive_done (channel);
2368 return GNUNET_OK; 2364 return GNUNET_OK;
diff --git a/src/vpn/vpn.conf.in b/src/vpn/vpn.conf.in
index 000300084..585131554 100644
--- a/src/vpn/vpn.conf.in
+++ b/src/vpn/vpn.conf.in
@@ -6,7 +6,7 @@ BINARY = gnunet-service-vpn
6ACCEPT_FROM = 127.0.0.1; 6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1; 7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn.sock 8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn.sock
9UNIX_MATCH_UID = YES 9UNIX_MATCH_UID = NO
10UNIX_MATCH_GID = YES 10UNIX_MATCH_GID = YES
11 11
12IPV6ADDR = 1234::1 12IPV6ADDR = 1234::1
diff --git a/src/vpn/vpn_api.c b/src/vpn/vpn_api.c
index 4add41ce4..bc77865a8 100644
--- a/src/vpn/vpn_api.c
+++ b/src/vpn/vpn_api.c
@@ -324,7 +324,7 @@ connect_task (void *cls)
324 struct GNUNET_VPN_RedirectionRequest *rr; 324 struct GNUNET_VPN_RedirectionRequest *rr;
325 325
326 vh->rt = NULL; 326 vh->rt = NULL;
327 vh->mq = GNUNET_CLIENT_connecT (vh->cfg, 327 vh->mq = GNUNET_CLIENT_connect (vh->cfg,
328 "vpn", 328 "vpn",
329 handlers, 329 handlers,
330 &mq_error_handler, 330 &mq_error_handler,
diff --git a/src/zonemaster/.gitignore b/src/zonemaster/.gitignore
new file mode 100644
index 000000000..1a0e22b66
--- /dev/null
+++ b/src/zonemaster/.gitignore
@@ -0,0 +1 @@
gnunet-service-zonemaster
diff --git a/src/zonemaster/Makefile.am b/src/zonemaster/Makefile.am
new file mode 100644
index 000000000..21f986498
--- /dev/null
+++ b/src/zonemaster/Makefile.am
@@ -0,0 +1,35 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8libexecdir= $(pkglibdir)/libexec/
9
10pkgcfg_DATA = \
11 zonemaster.conf
12
13if MINGW
14 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
15endif
16
17if USE_COVERAGE
18 AM_CFLAGS = --coverage -O0
19 XLIBS = -lgcov
20endif
21
22libexec_PROGRAMS = \
23 gnunet-service-zonemaster
24
25gnunet_service_zonemaster_SOURCES = \
26 gnunet-service-zonemaster.c
27
28gnunet_service_zonemaster_LDADD = \
29 $(top_builddir)/src/dht/libgnunetdht.la \
30 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
31 $(top_builddir)/src/statistics/libgnunetstatistics.la \
32 $(top_builddir)/src/util/libgnunetutil.la \
33 $(top_builddir)/src/namestore/libgnunetnamestore.la \
34 $(GN_LIBINTL)
35
diff --git a/src/zonemaster/gnunet-service-zonemaster.c b/src/zonemaster/gnunet-service-zonemaster.c
new file mode 100644
index 000000000..08a09de34
--- /dev/null
+++ b/src/zonemaster/gnunet-service-zonemaster.c
@@ -0,0 +1,776 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file zonemaster/gnunet-service-zonemaster.c
23 * @brief publish records from namestore to GNUnet name system
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_dnsparser_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_namestore_service.h"
31#include "gnunet_statistics_service.h"
32#include "gnunet_namestore_plugin.h"
33#include "gnunet_signatures.h"
34
35
36#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
37
38
39
40/**
41 * The initial interval in milliseconds btween puts in
42 * a zone iteration
43 */
44#define INITIAL_PUT_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS
45
46/**
47 * The lower bound for the zone iteration interval
48 */
49#define MINIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_SECONDS
50
51/**
52 * The upper bound for the zone iteration interval
53 */
54#define MAXIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
55
56/**
57 * The default put interval for the zone iteration. In case
58 * no option is found
59 */
60#define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
61
62/**
63 * The factor the current zone iteration interval is divided by for each
64 * additional new record
65 */
66#define LATE_ITERATION_SPEEDUP_FACTOR 2
67
68/**
69 * How long until a DHT PUT attempt should time out?
70 */
71#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
72
73/**
74 * What replication level do we use for DHT PUT operations?
75 */
76#define DHT_GNS_REPLICATION_LEVEL 5
77
78
79/**
80 * Handle for DHT PUT activity triggered from the namestore monitor.
81 */
82struct MonitorActivity
83{
84 /**
85 * Kept in a DLL.
86 */
87 struct MonitorActivity *next;
88
89 /**
90 * Kept in a DLL.
91 */
92 struct MonitorActivity *prev;
93
94 /**
95 * Handle for the DHT PUT operation.
96 */
97 struct GNUNET_DHT_PutHandle *ph;
98};
99
100
101/**
102 * Handle to the statistics service
103 */
104static struct GNUNET_STATISTICS_Handle *statistics;
105
106/**
107 * Our handle to the DHT
108 */
109static struct GNUNET_DHT_Handle *dht_handle;
110
111/**
112 * Active DHT put operation (or NULL)
113 */
114static struct GNUNET_DHT_PutHandle *active_put;
115
116/**
117 * Our handle to the namestore service
118 */
119static struct GNUNET_NAMESTORE_Handle *namestore_handle;
120
121/**
122 * Handle to iterate over our authoritative zone in namestore
123 */
124static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
125
126/**
127 * Handle to monitor namestore changes to instant propagation.
128 */
129static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
130
131/**
132 * Head of monitor activities; kept in a DLL.
133 */
134static struct MonitorActivity *ma_head;
135
136/**
137 * Tail of monitor activities; kept in a DLL.
138 */
139static struct MonitorActivity *ma_tail;
140
141/**
142 * Useful for zone update for DHT put
143 */
144static unsigned long long num_public_records;
145
146/**
147 * Last seen record count
148 */
149static unsigned long long last_num_public_records;
150
151/**
152 * Minimum relative expiration time of records seem during the current
153 * zone iteration.
154 */
155static struct GNUNET_TIME_Relative min_relative_record_time;
156
157/**
158 * Zone iteration PUT interval.
159 */
160static struct GNUNET_TIME_Relative put_interval;
161
162/**
163 * Default time window for zone iteration
164 */
165static struct GNUNET_TIME_Relative zone_publish_time_window_default;
166
167/**
168 * Time window for zone iteration, adjusted based on relative record
169 * expiration times in our zone.
170 */
171static struct GNUNET_TIME_Relative zone_publish_time_window;
172
173/**
174 * zone publish task
175 */
176static struct GNUNET_SCHEDULER_Task *zone_publish_task;
177
178/**
179 * #GNUNET_YES if zone has never been published before
180 */
181static int first_zone_iteration;
182
183/**
184 * Task run during shutdown.
185 *
186 * @param cls unused
187 * @param tc unused
188 */
189static void
190shutdown_task (void *cls)
191{
192 struct MonitorActivity *ma;
193
194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
195 "Shutting down!\n");
196 while (NULL != (ma = ma_head))
197 {
198 GNUNET_DHT_put_cancel (ma->ph);
199 GNUNET_CONTAINER_DLL_remove (ma_head,
200 ma_tail,
201 ma);
202 GNUNET_free (ma);
203 }
204 if (NULL != statistics)
205 {
206 GNUNET_STATISTICS_destroy (statistics,
207 GNUNET_NO);
208 statistics = NULL;
209 }
210 if (NULL != zone_publish_task)
211 {
212 GNUNET_SCHEDULER_cancel (zone_publish_task);
213 zone_publish_task = NULL;
214 }
215 if (NULL != namestore_iter)
216 {
217 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
218 namestore_iter = NULL;
219 }
220 if (NULL != zmon)
221 {
222 GNUNET_NAMESTORE_zone_monitor_stop (zmon);
223 zmon = NULL;
224 }
225 if (NULL != namestore_handle)
226 {
227 GNUNET_NAMESTORE_disconnect (namestore_handle);
228 namestore_handle = NULL;
229 }
230 if (NULL != active_put)
231 {
232 GNUNET_DHT_put_cancel (active_put);
233 active_put = NULL;
234 }
235 if (NULL != dht_handle)
236 {
237 GNUNET_DHT_disconnect (dht_handle);
238 dht_handle = NULL;
239 }
240}
241
242
243/**
244 * Method called periodically that triggers iteration over authoritative records
245 *
246 * @param cls closure
247 */
248static void
249publish_zone_dht_next (void *cls)
250{
251 zone_publish_task = NULL;
252 GNUNET_assert (NULL != namestore_iter);
253 GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
254}
255
256
257/**
258 * Periodically iterate over our zone and store everything in dht
259 *
260 * @param cls NULL
261 */
262static void
263publish_zone_dht_start (void *cls);
264
265
266/**
267 * Continuation called from DHT once the PUT operation is done.
268 *
269 * @param cls closure, NULL if called from regular iteration,
270 * `struct MonitorActivity` if called from #handle_monitor_event.
271 * @param success #GNUNET_OK on success
272 */
273static void
274dht_put_continuation (void *cls,
275 int success)
276{
277 struct MonitorActivity *ma = cls;
278 struct GNUNET_TIME_Relative next_put_interval;
279
280 num_public_records++;
281 if (NULL == ma)
282 {
283 active_put = NULL;
284 if ( (num_public_records > last_num_public_records) &&
285 (GNUNET_NO == first_zone_iteration) )
286 {
287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
288 "Last record count was lower than current record count. Reducing interval.\n");
289 put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
290 num_public_records);
291 next_put_interval = GNUNET_TIME_relative_divide (put_interval,
292 LATE_ITERATION_SPEEDUP_FACTOR);
293 }
294 else
295 next_put_interval = put_interval;
296 next_put_interval = GNUNET_TIME_relative_min (next_put_interval,
297 MAXIMUM_ZONE_ITERATION_INTERVAL);
298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
299 "PUT complete, next PUT in %s!\n",
300 GNUNET_STRINGS_relative_time_to_string (next_put_interval,
301 GNUNET_YES));
302
303 GNUNET_STATISTICS_set (statistics,
304 "Current zone iteration interval (ms)",
305 next_put_interval.rel_value_us / 1000LL,
306 GNUNET_NO);
307 GNUNET_assert (NULL == zone_publish_task);
308 zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval,
309 &publish_zone_dht_next,
310 NULL);
311 }
312 else
313 {
314 GNUNET_CONTAINER_DLL_remove (ma_head,
315 ma_tail,
316 ma);
317 GNUNET_free (ma);
318 }
319}
320
321
322/**
323 * Convert namestore records from the internal format to that
324 * suitable for publication (removes private records, converts
325 * to absolute expiration time).
326 *
327 * @param rd input records
328 * @param rd_count size of the @a rd and @a rd_public arrays
329 * @param rd_public where to write the converted records
330 * @return number of records written to @a rd_public
331 */
332static unsigned int
333convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
334 unsigned int rd_count,
335 struct GNUNET_GNSRECORD_Data *rd_public)
336{
337 struct GNUNET_TIME_Absolute now;
338 unsigned int rd_public_count;
339 unsigned int i;
340
341 rd_public_count = 0;
342 now = GNUNET_TIME_absolute_get ();
343 for (i=0;i<rd_count;i++)
344 if (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
345 {
346 rd_public[rd_public_count] = rd[i];
347 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
348 {
349 /* GNUNET_GNSRECORD_block_create will convert to absolute time;
350 we just need to adjust our iteration frequency */
351 min_relative_record_time.rel_value_us =
352 GNUNET_MIN (rd_public[rd_public_count].expiration_time,
353 min_relative_record_time.rel_value_us);
354 }
355 else if (rd_public[rd_public_count].expiration_time < now.abs_value_us)
356 {
357 /* record already expired, skip it */
358 continue;
359 }
360 rd_public_count++;
361 }
362 return rd_public_count;
363}
364
365
366/**
367 * Store GNS records in the DHT.
368 *
369 * @param key key of the zone
370 * @param label label to store under
371 * @param rd_public public record data
372 * @param rd_public_count number of records in @a rd_public
373 * @param pc_arg closure argument to pass to the #dht_put_continuation
374 * @return DHT PUT handle, NULL on error
375 */
376static struct GNUNET_DHT_PutHandle *
377perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
378 const char *label,
379 const struct GNUNET_GNSRECORD_Data *rd_public,
380 unsigned int rd_public_count,
381 void *pc_arg)
382{
383 struct GNUNET_GNSRECORD_Block *block;
384 struct GNUNET_HashCode query;
385 struct GNUNET_TIME_Absolute expire;
386 size_t block_size;
387 struct GNUNET_DHT_PutHandle *ret;
388
389 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
390 rd_public);
391 block = GNUNET_GNSRECORD_block_create (key,
392 expire,
393 label,
394 rd_public,
395 rd_public_count);
396 if (NULL == block)
397 return NULL; /* whoops */
398 block_size = ntohl (block->purpose.size)
399 + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)
400 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
401 GNUNET_GNSRECORD_query_from_private_key (key,
402 label,
403 &query);
404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
405 "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n",
406 rd_public_count,
407 label,
408 GNUNET_STRINGS_absolute_time_to_string (expire),
409 GNUNET_h2s (&query));
410 ret = GNUNET_DHT_put (dht_handle,
411 &query,
412 DHT_GNS_REPLICATION_LEVEL,
413 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
414 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
415 block_size,
416 block,
417 expire,
418 &dht_put_continuation,
419 pc_arg);
420 GNUNET_free (block);
421 return ret;
422}
423
424
425/**
426 * We encountered an error in our zone iteration.
427 */
428static void
429zone_iteration_error (void *cls)
430{
431 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
432 "Got disconnected from namestore database, retrying.\n");
433 namestore_iter = NULL;
434 /* We end up here on error/disconnect/shutdown, so potentially
435 while a zone publish task or a DHT put is still running; hence
436 we need to cancel those. */
437 if (NULL != zone_publish_task)
438 {
439 GNUNET_SCHEDULER_cancel (zone_publish_task);
440 zone_publish_task = NULL;
441 }
442 if (NULL != active_put)
443 {
444 GNUNET_DHT_put_cancel (active_put);
445 active_put = NULL;
446 }
447 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
448 NULL);
449}
450
451
452/**
453 * Zone iteration is completed.
454 */
455static void
456zone_iteration_finished (void *cls)
457{
458 /* we're done with one iteration, calculate when to do the next one */
459 namestore_iter = NULL;
460 last_num_public_records = num_public_records;
461 first_zone_iteration = GNUNET_NO;
462 if (0 == num_public_records)
463 {
464 /**
465 * If no records are known (startup) or none present
466 * we can safely set the interval to the value for a single
467 * record
468 */
469 put_interval = zone_publish_time_window;
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
471 "No records in namestore database.\n");
472 }
473 else
474 {
475 /* If records are present, next publication is based on the minimum
476 * relative expiration time of the records published divided by 4
477 */
478 zone_publish_time_window
479 = GNUNET_TIME_relative_min (GNUNET_TIME_relative_divide (min_relative_record_time, 4),
480 zone_publish_time_window_default);
481 put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
482 num_public_records);
483 }
484 /* reset for next iteration */
485 min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL;
486 put_interval = GNUNET_TIME_relative_max (MINIMUM_ZONE_ITERATION_INTERVAL,
487 put_interval);
488 put_interval = GNUNET_TIME_relative_min (put_interval,
489 MAXIMUM_ZONE_ITERATION_INTERVAL);
490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491 "Zone iteration finished. Adjusted zone iteration interval to %s\n",
492 GNUNET_STRINGS_relative_time_to_string (put_interval,
493 GNUNET_YES));
494 GNUNET_STATISTICS_set (statistics,
495 "Current zone iteration interval (in ms)",
496 put_interval.rel_value_us / 1000LL,
497 GNUNET_NO);
498 GNUNET_STATISTICS_update (statistics,
499 "Number of zone iterations",
500 1,
501 GNUNET_NO);
502 GNUNET_STATISTICS_set (statistics,
503 "Number of public records in DHT",
504 last_num_public_records,
505 GNUNET_NO);
506 GNUNET_assert (NULL == zone_publish_task);
507 if (0 == num_public_records)
508 zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval,
509 &publish_zone_dht_start,
510 NULL);
511 else
512 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
513 NULL);
514}
515
516
517/**
518 * Function used to put all records successively into the DHT.
519 *
520 * @param cls the closure (NULL)
521 * @param key the private key of the authority (ours)
522 * @param label the name of the records, NULL once the iteration is done
523 * @param rd_count the number of records in @a rd
524 * @param rd the record data
525 */
526static void
527put_gns_record (void *cls,
528 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
529 const char *label,
530 unsigned int rd_count,
531 const struct GNUNET_GNSRECORD_Data *rd)
532{
533 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
534 unsigned int rd_public_count;
535
536 rd_public_count = convert_records_for_export (rd,
537 rd_count,
538 rd_public);
539
540 if (0 == rd_public_count)
541 {
542 GNUNET_assert (NULL == zone_publish_task);
543 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
544 "Record set empty, moving to next record set\n");
545 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next,
546 NULL);
547 return;
548 }
549 /* We got a set of records to publish */
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
551 "Starting DHT PUT\n");
552 active_put = perform_dht_put (key,
553 label,
554 rd_public,
555 rd_public_count,
556 NULL);
557 if (NULL == active_put)
558 {
559 GNUNET_break (0);
560 dht_put_continuation (NULL, GNUNET_NO);
561 }
562}
563
564
565/**
566 * Periodically iterate over all zones and store everything in DHT
567 *
568 * @param cls NULL
569 */
570static void
571publish_zone_dht_start (void *cls)
572{
573 zone_publish_task = NULL;
574
575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
576 "Starting DHT zone update!\n");
577 /* start counting again */
578 num_public_records = 0;
579 GNUNET_assert (NULL == namestore_iter);
580 namestore_iter
581 = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
582 NULL, /* All zones */
583 &zone_iteration_error,
584 NULL,
585 &put_gns_record,
586 NULL,
587 &zone_iteration_finished,
588 NULL);
589}
590
591
592/**
593 * Process a record that was stored in the namestore
594 * (invoked by the monitor).
595 *
596 * @param cls closure, NULL
597 * @param zone private key of the zone; NULL on disconnect
598 * @param label label of the records; NULL on disconnect
599 * @param rd_count number of entries in @a rd array, 0 if label was deleted
600 * @param rd array of records with data to store
601 */
602static void
603handle_monitor_event (void *cls,
604 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
605 const char *label,
606 unsigned int rd_count,
607 const struct GNUNET_GNSRECORD_Data *rd)
608{
609 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
610 unsigned int rd_public_count;
611 struct MonitorActivity *ma;
612
613 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
614 "Received %u records for label `%s' via namestore monitor\n",
615 rd_count,
616 label);
617 /* filter out records that are not public, and convert to
618 absolute expiration time. */
619 rd_public_count = convert_records_for_export (rd,
620 rd_count,
621 rd_public);
622 if (0 == rd_public_count)
623 return; /* nothing to do */
624 ma = GNUNET_new (struct MonitorActivity);
625 ma->ph = perform_dht_put (zone,
626 label,
627 rd,
628 rd_count,
629 ma);
630 if (NULL == ma->ph)
631 {
632 /* PUT failed, do not remember operation */
633 GNUNET_free (ma);
634 return;
635 }
636 GNUNET_CONTAINER_DLL_insert (ma_head,
637 ma_tail,
638 ma);
639}
640
641
642/**
643 * The zone monitor is now in SYNC with the current state of the
644 * name store. Start to perform periodic iterations.
645 *
646 * @param cls NULL
647 */
648static void
649monitor_sync_event (void *cls)
650{
651 GNUNET_assert (NULL == zone_publish_task);
652 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
653 NULL);
654}
655
656
657/**
658 * The zone monitor is now in SYNC with the current state of the
659 * name store. Start to perform periodic iterations.
660 *
661 * @param cls NULL
662 */
663static void
664handle_monitor_error (void *cls)
665{
666 if (NULL != zone_publish_task)
667 {
668 GNUNET_SCHEDULER_cancel (zone_publish_task);
669 zone_publish_task = NULL;
670 }
671 if (NULL != namestore_iter)
672 {
673 GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
674 namestore_iter = NULL;
675 }
676 if (NULL != active_put)
677 {
678 GNUNET_DHT_put_cancel (active_put);
679 active_put = NULL;
680 }
681 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
682 NULL);
683}
684
685
686/**
687 * Performe zonemaster duties: watch namestore, publish records.
688 *
689 * @param cls closure
690 * @param server the initialized server
691 * @param c configuration to use
692 */
693static void
694run (void *cls,
695 const struct GNUNET_CONFIGURATION_Handle *c,
696 struct GNUNET_SERVICE_Handle *service)
697{
698 unsigned long long max_parallel_bg_queries = 128;
699
700 min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL;
701 namestore_handle = GNUNET_NAMESTORE_connect (c);
702 if (NULL == namestore_handle)
703 {
704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
705 _("Failed to connect to the namestore!\n"));
706 GNUNET_SCHEDULER_shutdown ();
707 return;
708 }
709
710 put_interval = INITIAL_PUT_INTERVAL;
711 zone_publish_time_window_default = DEFAULT_ZONE_PUBLISH_TIME_WINDOW;
712 if (GNUNET_OK ==
713 GNUNET_CONFIGURATION_get_value_time (c,
714 "zonemaster",
715 "ZONE_PUBLISH_TIME_WINDOW",
716 &zone_publish_time_window_default))
717 {
718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719 "Time window for zone iteration: %s\n",
720 GNUNET_STRINGS_relative_time_to_string (zone_publish_time_window,
721 GNUNET_YES));
722 }
723 zone_publish_time_window = zone_publish_time_window_default;
724 if (GNUNET_OK ==
725 GNUNET_CONFIGURATION_get_value_number (c,
726 "zonemaster",
727 "MAX_PARALLEL_BACKGROUND_QUERIES",
728 &max_parallel_bg_queries))
729 {
730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
731 "Number of allowed parallel background queries: %llu\n",
732 max_parallel_bg_queries);
733 }
734 if (0 == max_parallel_bg_queries)
735 max_parallel_bg_queries = 1;
736 dht_handle = GNUNET_DHT_connect (c,
737 (unsigned int) max_parallel_bg_queries);
738 if (NULL == dht_handle)
739 {
740 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
741 _("Could not connect to DHT!\n"));
742 GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
743 return;
744 }
745
746 /* Schedule periodic put for our records. */
747 first_zone_iteration = GNUNET_YES;\
748 statistics = GNUNET_STATISTICS_create ("zonemaster", c);
749 zmon = GNUNET_NAMESTORE_zone_monitor_start (c,
750 NULL,
751 GNUNET_NO,
752 &handle_monitor_error,
753 NULL,
754 &handle_monitor_event,
755 NULL,
756 &monitor_sync_event,
757 NULL);
758 GNUNET_break (NULL != zmon);
759 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
760}
761
762
763/**
764 * Define "main" method using service macro.
765 */
766GNUNET_SERVICE_MAIN
767("zonemaster",
768 GNUNET_SERVICE_OPTION_NONE,
769 &run,
770 NULL,
771 NULL,
772 NULL,
773 GNUNET_MQ_handler_end());
774
775
776/* end of gnunet-service-zonemaster.c */
diff --git a/src/zonemaster/zonemaster.conf.in b/src/zonemaster/zonemaster.conf.in
new file mode 100644
index 000000000..871eb9c8f
--- /dev/null
+++ b/src/zonemaster/zonemaster.conf.in
@@ -0,0 +1,25 @@
1[zonemaster]
2AUTOSTART = @AUTOSTART@
3FORCESTART = YES
4HOSTNAME = localhost
5BINARY = gnunet-service-zonemaster
6UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-zonemaster.sock
7@JAVAPORT@PORT = 2123
8
9# Do we require users that want to access GNS to run this process
10# (usually not a good idea)
11UNIX_MATCH_UID = NO
12
13# Do we require users that want to access GNS to be in the 'gnunet' group?
14UNIX_MATCH_GID = NO
15
16# How many queries is GNS allowed to perform in the background at the same time?
17MAX_PARALLEL_BACKGROUND_QUERIES = 1000
18
19# How frequently do we try to publish our full zone?
20ZONE_PUBLISH_TIME_WINDOW = 4 h
21
22# Using caching or always ask DHT
23# USE_CACHE = YES
24
25# PREFIX = valgrind --leak-check=full --track-origins=yes