aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/arm/arm_api.c8
-rw-r--r--src/ats-tests/Makefile.am1
-rw-r--r--src/block/block.c9
-rw-r--r--src/cadet/gnunet-service-cadet.c3
-rw-r--r--src/cadet/gnunet-service-cadet_channel.c1
-rw-r--r--src/datacache/datacache.c24
-rw-r--r--src/gns/Makefile.am3
-rw-r--r--src/gns/gns.conf.in3
-rw-r--r--src/gns/gnunet-bcd.c22
-rw-r--r--src/gns/gnunet-dns2gns.c8
-rw-r--r--src/gns/gnunet-gns-proxy.c23
-rw-r--r--src/gns/gnunet-service-gns_interceptor.c1
-rw-r--r--src/gns/gnunet-service-gns_resolver.c27
-rw-r--r--src/gns/plugin_rest_gns.c4
-rw-r--r--src/gnsrecord/gnsrecord.c13
-rw-r--r--src/gnsrecord/gnsrecord_misc.c17
-rw-r--r--src/gnsrecord/gnunet-gnsrecord-tvg.c2
-rw-r--r--src/hello/hello-ng.c9
-rw-r--r--src/hello/test_hello-ng.c2
-rw-r--r--src/include/Makefile.am3
-rw-r--r--src/include/gnu_name_system_record_types.h138
-rw-r--r--src/include/gnunet_gnsrecord_lib.h104
-rw-r--r--src/include/gnunet_messenger_service.h240
-rw-r--r--src/include/gnunet_plugin_lib.h22
-rw-r--r--src/include/gnunet_testbed_ng_service.h216
-rw-r--r--src/include/gnunet_testbed_service.h2
-rw-r--r--src/include/gnunet_testing_ng_lib.h833
-rw-r--r--src/json/json_helper.c105
-rw-r--r--src/messenger/.gitignore10
-rw-r--r--src/messenger/Makefile.am152
-rwxr-xr-x[-rw-r--r--]src/messenger/gnunet-messenger.c146
-rwxr-xr-x[-rw-r--r--]src/messenger/gnunet-service-messenger.c183
-rw-r--r--src/messenger/gnunet-service-messenger.h20
-rw-r--r--src/messenger/gnunet-service-messenger_basement.c4
-rw-r--r--src/messenger/gnunet-service-messenger_basement.h24
-rw-r--r--src/messenger/gnunet-service-messenger_contact.c96
-rw-r--r--src/messenger/gnunet-service-messenger_contact.h112
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.c295
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.h152
-rw-r--r--src/messenger/gnunet-service-messenger_handle.c449
-rw-r--r--src/messenger/gnunet-service-messenger_handle.h120
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.c16
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.h42
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.c76
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.h42
-rwxr-xr-xsrc/messenger/gnunet-service-messenger_member.c385
-rw-r--r--src/messenger/gnunet-service-messenger_member.h170
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c743
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.h288
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.c250
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.h151
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.c124
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.h100
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.c69
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.h58
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.c219
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.h128
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.c88
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.h122
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.c109
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.h63
-rwxr-xr-x[-rw-r--r--]src/messenger/gnunet-service-messenger_message_store.c369
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.h92
-rw-r--r--src/messenger/gnunet-service-messenger_operation.c214
-rw-r--r--src/messenger/gnunet-service-messenger_operation.h129
-rwxr-xr-xsrc/messenger/gnunet-service-messenger_operation_store.c226
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.h131
-rw-r--r--src/messenger/gnunet-service-messenger_room.c1224
-rw-r--r--src/messenger/gnunet-service-messenger_room.h318
-rw-r--r--src/messenger/gnunet-service-messenger_service.c306
-rw-r--r--src/messenger/gnunet-service-messenger_service.h162
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.c249
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.h107
-rw-r--r--src/messenger/messenger_api.c266
-rw-r--r--src/messenger/messenger_api_contact.c44
-rw-r--r--src/messenger/messenger_api_contact.h45
-rwxr-xr-xsrc/messenger/messenger_api_contact_store.c185
-rw-r--r--src/messenger/messenger_api_contact_store.h122
-rw-r--r--src/messenger/messenger_api_ego.h2
-rw-r--r--src/messenger/messenger_api_handle.c99
-rw-r--r--src/messenger/messenger_api_handle.h69
-rw-r--r--src/messenger/messenger_api_list_tunnels.c74
-rw-r--r--src/messenger/messenger_api_list_tunnels.h44
-rwxr-xr-x[-rw-r--r--]src/messenger/messenger_api_message.c423
-rw-r--r--src/messenger/messenger_api_message.h119
-rwxr-xr-x[-rw-r--r--]src/messenger/messenger_api_room.c224
-rwxr-xr-x[-rw-r--r--]src/messenger/messenger_api_room.h60
-rw-r--r--src/messenger/messenger_api_util.c (renamed from src/messenger/gnunet-service-messenger_util.c)30
-rw-r--r--src/messenger/messenger_api_util.h (renamed from src/messenger/gnunet-service-messenger_util.h)27
-rw-r--r--src/messenger/test_messenger.c40
-rw-r--r--src/messenger/test_messenger_adapt.c47
-rw-r--r--src/messenger/test_messenger_anonymous.c34
-rw-r--r--src/messenger/test_messenger_api.conf32
-rw-r--r--src/messenger/test_messenger_async_client.c47
-rw-r--r--src/messenger/test_messenger_async_p2p.c47
-rw-r--r--src/messenger/test_messenger_comm0.c252
-rw-r--r--src/messenger/test_messenger_growth.c47
-rw-r--r--src/messenger/test_messenger_ring.c47
-rw-r--r--src/messenger/test_messenger_server.c47
-rw-r--r--src/messenger/test_messenger_sync_client.c47
-rw-r--r--src/messenger/test_messenger_sync_p2p.c47
-rw-r--r--src/messenger/test_messenger_worst_client.c47
-rw-r--r--src/messenger/test_messenger_worst_p2p.c47
-rw-r--r--src/messenger/testing_messenger_barrier.c170
-rw-r--r--src/messenger/testing_messenger_barrier.h131
-rw-r--r--src/messenger/testing_messenger_setup.c528
-rw-r--r--src/messenger/testing_messenger_setup.h39
-rw-r--r--src/namestore/gnunet-service-namestore.c16
-rw-r--r--src/namestore/namestore_api.c6
-rw-r--r--src/namestore/plugin_rest_namestore.c2
-rw-r--r--src/peerinfo-tool/plugin_rest_peerinfo.c4
-rw-r--r--src/peerstore/gnunet-service-peerstore.c15
-rw-r--r--src/peerstore/peerstore_api.c5
-rw-r--r--src/peerstore/test_peerstore_api_sync.c87
-rw-r--r--src/reclaim/gnunet-service-reclaim.c5
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.c15
-rw-r--r--src/reclaim/oidc_helper.c14
-rw-r--r--src/reclaim/pabc_helper.c3
-rw-r--r--src/reclaim/plugin_gnsrecord_reclaim.c3
-rw-r--r--src/reclaim/plugin_reclaim_credential_pabc.c168
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c50
-rw-r--r--src/reclaim/plugin_rest_pabc.c32
-rw-r--r--src/reclaim/plugin_rest_reclaim.c131
-rw-r--r--src/reclaim/reclaim_api.c20
-rw-r--r--src/reclaim/reclaim_attribute.c9
-rw-r--r--src/reclaim/reclaim_credential.c9
-rw-r--r--src/rest/gnunet-rest-server.c9
-rw-r--r--src/rest/plugin_rest_copying.c6
-rw-r--r--src/revocation/gnunet-revocation.c14
-rw-r--r--src/revocation/gnunet-service-revocation.c12
-rw-r--r--src/revocation/plugin_block_revocation.c9
-rw-r--r--src/revocation/revocation_api.c9
-rw-r--r--src/rps/gnunet-rps-profiler.c7
-rw-r--r--src/rps/gnunet-service-rps.c18
-rw-r--r--src/rps/gnunet-service-rps_custommap.c9
-rw-r--r--src/rps/rps-test_util.c16
-rw-r--r--src/setu/.gitignore1
-rw-r--r--src/setu/Makefile.am12
-rw-r--r--src/setu/gnunet-service-setu.c209
-rw-r--r--src/setu/gnunet-service-setu_strata_estimator.c42
-rw-r--r--src/setu/ibf.c68
-rw-r--r--src/setu/perf_setu_api.c428
-rw-r--r--src/setu/setu.h1
-rw-r--r--src/setu/test_setu_api.c62
-rw-r--r--src/testbed/Makefile.am8
-rw-r--r--src/testbed/testbed_api_cmd_controller.c293
-rw-r--r--src/testbed/testbed_api_cmd_peer.c281
-rw-r--r--src/testbed/testbed_api_cmd_peer_store.c60
-rw-r--r--src/testbed/testbed_api_cmd_tng_connect.c55
-rw-r--r--src/testbed/testbed_api_cmd_tng_service.c276
-rw-r--r--src/testing/Makefile.am17
-rw-r--r--src/testing/test_testing_hello_world.c68
-rw-r--r--src/testing/testing.h74
-rw-r--r--src/testing/testing_api_cmd_batch.c256
-rw-r--r--src/testing/testing_api_cmd_hello_world.c121
-rw-r--r--src/testing/testing_api_cmd_hello_world_birth.c159
-rw-r--r--src/testing/testing_api_loop.c510
-rw-r--r--src/testing/testing_api_trait_cmd.c79
-rw-r--r--src/testing/testing_api_trait_process.c81
-rw-r--r--src/testing/testing_api_traits.c81
-rw-r--r--src/transport/Makefile.am4
-rw-r--r--src/transport/gnunet-communicator-tcp.c92
-rw-r--r--src/transport/gnunet-communicator-udp.c13
-rw-r--r--src/transport/gnunet-service-tng.c348
-rw-r--r--src/transport/test_transport_api2_tcp_peer1.conf23
-rw-r--r--src/transport/test_transport_api2_tcp_peer2.conf22
-rw-r--r--src/transport/transport-testing-communicator.c5
-rw-r--r--src/transport/transport-testing-ng.h71
-rw-r--r--src/transport/transport-testing2.c91
-rw-r--r--src/transport/transport-testing2.h10
-rw-r--r--src/transport/transport_api2_communication.c2
-rw-r--r--src/util/.gitignore1
-rw-r--r--src/util/Makefile.am27
-rw-r--r--src/util/configuration.c1
-rw-r--r--src/util/container_meta_data.c7
-rw-r--r--src/util/crypto_ecc.c20
-rw-r--r--src/util/crypto_rsa.c1
-rw-r--r--src/util/gnunet-base32.c152
-rw-r--r--src/util/gnunet-crypto-tvg.c124
-rw-r--r--src/util/gnunet-scrypt.c7
-rw-r--r--src/util/mq.c2
-rw-r--r--src/util/os_installation.c5
-rw-r--r--src/util/plugin.c33
-rw-r--r--src/util/time.c249
185 files changed, 14912 insertions, 4254 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index d8a869acb..564923e28 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,10 @@ if HAVE_POSTGRESQL
45 POSTGRES_DIR = pq 45 POSTGRES_DIR = pq
46endif 46endif
47 47
48if HAVE_NOLIBGCRYPT19
49 SCALARPRODUCT_DIR = scalarproduct
50endif
51
48REST_DIR = rest 52REST_DIR = rest
49 53
50 54
@@ -93,7 +97,7 @@ SUBDIRS = \
93 seti \ 97 seti \
94 setu \ 98 setu \
95 consensus \ 99 consensus \
96 scalarproduct \ 100 $(SCALARPRODUCT_DIR) \
97 revocation \ 101 revocation \
98 vpn \ 102 vpn \
99 gns \ 103 gns \
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index 899b6f152..2ec913a0a 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -951,7 +951,8 @@ GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h,
951 * 2) We're not connected to ARM. 951 * 2) We're not connected to ARM.
952 * Cancel any reconnection attempts temporarily, then perform 952 * Cancel any reconnection attempts temporarily, then perform
953 * a service test. 953 * a service test.
954 */if (GNUNET_YES == h->currently_up) 954 */
955 if (GNUNET_YES == h->currently_up)
955 { 956 {
956 LOG (GNUNET_ERROR_TYPE_DEBUG, 957 LOG (GNUNET_ERROR_TYPE_DEBUG,
957 "ARM is already running\n"); 958 "ARM is already running\n");
@@ -970,7 +971,8 @@ GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h,
970 yet complete the MQ handshake. However, given that users 971 yet complete the MQ handshake. However, given that users
971 are unlikely to hammer 'gnunet-arm -s' on a busy system, 972 are unlikely to hammer 'gnunet-arm -s' on a busy system,
972 the above check should catch 99.99% of the cases where ARM 973 the above check should catch 99.99% of the cases where ARM
973 is already running. */LOG (GNUNET_ERROR_TYPE_DEBUG, 974 is already running. */
975 LOG (GNUNET_ERROR_TYPE_DEBUG,
974 "Starting ARM service\n"); 976 "Starting ARM service\n");
975 if (NULL == (sig = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE))) 977 if (NULL == (sig = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE)))
976 { 978 {
@@ -1003,13 +1005,13 @@ GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h,
1003 op->rfd, 1005 op->rfd,
1004 &notify_starting, 1006 &notify_starting,
1005 op); 1007 op);
1008 GNUNET_DISK_pipe_close (sig);
1006 } 1009 }
1007 else 1010 else
1008 { 1011 {
1009 op->async = GNUNET_SCHEDULER_add_now (&notify_starting, 1012 op->async = GNUNET_SCHEDULER_add_now (&notify_starting,
1010 op); 1013 op);
1011 } 1014 }
1012 GNUNET_DISK_pipe_close (sig);
1013 return op; 1015 return op;
1014} 1016}
1015 1017
diff --git a/src/ats-tests/Makefile.am b/src/ats-tests/Makefile.am
index cc30f660a..00a312a72 100644
--- a/src/ats-tests/Makefile.am
+++ b/src/ats-tests/Makefile.am
@@ -41,6 +41,7 @@ libgnunetatstesting_la_SOURCES = \
41 ats-testing-experiment.c ats-testing-preferences.c 41 ats-testing-experiment.c ats-testing-preferences.c
42libgnunetatstesting_la_LIBADD = \ 42libgnunetatstesting_la_LIBADD = \
43 $(top_builddir)/src/testbed/libgnunettestbed.la \ 43 $(top_builddir)/src/testbed/libgnunettestbed.la \
44 $(top_builddir)/src/testing/libgnunettesting.la \
44 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 45 $(top_builddir)/src/statistics/libgnunetstatistics.la \
45 $(top_builddir)/src/core/libgnunetcore.la \ 46 $(top_builddir)/src/core/libgnunetcore.la \
46 $(top_builddir)/src/transport/libgnunettransport.la \ 47 $(top_builddir)/src/transport/libgnunettransport.la \
diff --git a/src/block/block.c b/src/block/block.c
index 5abe64e69..975c0f747 100644
--- a/src/block/block.c
+++ b/src/block/block.c
@@ -134,10 +134,11 @@ GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
134 134
135 ctx = GNUNET_new (struct GNUNET_BLOCK_Context); 135 ctx = GNUNET_new (struct GNUNET_BLOCK_Context);
136 ctx->cfg = cfg; 136 ctx->cfg = cfg;
137 GNUNET_PLUGIN_load_all ("libgnunet_plugin_block_", 137 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
138 (void *) cfg, 138 "libgnunet_plugin_block_",
139 &add_plugin, 139 (void *) cfg,
140 ctx); 140 &add_plugin,
141 ctx);
141 return ctx; 142 return ctx;
142} 143}
143 144
diff --git a/src/cadet/gnunet-service-cadet.c b/src/cadet/gnunet-service-cadet.c
index 2d3b548dd..c8d69e43d 100644
--- a/src/cadet/gnunet-service-cadet.c
+++ b/src/cadet/gnunet-service-cadet.c
@@ -1027,7 +1027,8 @@ handle_drop_message (void *cls,
1027 ch = lookup_channel (c, 1027 ch = lookup_channel (c,
1028 message->ccn); 1028 message->ccn);
1029 1029
1030 GCCH_assign_type_to_drop (ch, message); 1030 if (NULL != ch)
1031 GCCH_assign_type_to_drop (ch, message);
1031 1032
1032 GNUNET_SERVICE_client_continue (c->client); 1033 GNUNET_SERVICE_client_continue (c->client);
1033} 1034}
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c
index 6b22ae2b4..ae5d9210f 100644
--- a/src/cadet/gnunet-service-cadet_channel.c
+++ b/src/cadet/gnunet-service-cadet_channel.c
@@ -1858,6 +1858,7 @@ GCCH_handle_local_data (struct CadetChannel *ch,
1858 } 1858 }
1859 else 1859 else
1860 { 1860 {
1861 GNUNET_free (env);
1861 GNUNET_break (0); 1862 GNUNET_break (0);
1862 return GNUNET_SYSERR; 1863 return GNUNET_SYSERR;
1863 } 1864 }
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 1ae228b86..5fc5a7481 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -138,6 +138,7 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
138 struct GNUNET_DATACACHE_Handle *ret; 138 struct GNUNET_DATACACHE_Handle *ret;
139 char *libname; 139 char *libname;
140 char *name; 140 char *name;
141 const struct GNUNET_OS_ProjectData *pd;
141 142
142 if (GNUNET_OK != 143 if (GNUNET_OK !=
143 GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota)) 144 GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota))
@@ -190,14 +191,25 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
190 GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name); 191 GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name);
191 ret->short_name = name; 192 ret->short_name = name;
192 ret->lib_name = libname; 193 ret->lib_name = libname;
194 /* Load the plugin within GNUnet's default context */
195 pd = GNUNET_OS_project_data_get ();
196 GNUNET_OS_init(GNUNET_OS_project_data_default ());
193 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 197 ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
194 if (ret->api == NULL) 198 GNUNET_OS_init(pd);
199 if (NULL == ret->api)
195 { 200 {
196 LOG (GNUNET_ERROR_TYPE_ERROR, 201 /* Try to load the plugin within the application's context
197 _ ("Failed to load datacache plugin for `%s'\n"), 202 This normally happens when the application is not GNUnet itself but a
198 name); 203 third party; inside GNUnet this is effectively a double failure. */
199 GNUNET_DATACACHE_destroy (ret); 204 ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
200 return NULL; 205 if (NULL == ret->api)
206 {
207 LOG (GNUNET_ERROR_TYPE_ERROR,
208 _ ("Failed to load datacache plugin for `%s'\n"),
209 name);
210 GNUNET_DATACACHE_destroy (ret);
211 return NULL;
212 }
201 } 213 }
202 return ret; 214 return ret;
203} 215}
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 9f03311e1..3aaa734f2 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -80,9 +80,7 @@ bin_PROGRAMS = \
80noinst_PROGRAMS = \ 80noinst_PROGRAMS = \
81 gnunet-gns-benchmark 81 gnunet-gns-benchmark
82 82
83if LINUX
84bin_PROGRAMS += gnunet-bcd 83bin_PROGRAMS += gnunet-bcd
85endif
86 84
87REST_PLUGIN = libgnunet_plugin_rest_gns.la 85REST_PLUGIN = libgnunet_plugin_rest_gns.la
88 86
@@ -156,6 +154,7 @@ gnunet_bcd_SOURCES = \
156 gnunet-bcd.c 154 gnunet-bcd.c
157gnunet_bcd_LDADD = \ 155gnunet_bcd_LDADD = \
158 $(top_builddir)/src/util/libgnunetutil.la \ 156 $(top_builddir)/src/util/libgnunetutil.la \
157 $(top_builddir)/src/identity/libgnunetidentity.la \
159 $(GN_LIBINTL) $(MHD_LIBS) 158 $(GN_LIBINTL) $(MHD_LIBS)
160gnunet_bcd_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) 159gnunet_bcd_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
161 160
diff --git a/src/gns/gns.conf.in b/src/gns/gns.conf.in
index 829a52d63..a458f69a2 100644
--- a/src/gns/gns.conf.in
+++ b/src/gns/gns.conf.in
@@ -25,8 +25,7 @@ INTERCEPT_DNS = NO
25# PREFIX = valgrind --leak-check=full --track-origins=yes 25# PREFIX = valgrind --leak-check=full --track-origins=yes
26 26
27# Zones 27# Zones
28.pin = DWJASSPE33MRN8T6Q0PENRNBTQY0E6ZYGTRCDP5DGPBF2CRJMJEG 28.pin = 000G001MF6DVMZZ4Y8XRZQDXM1PB3D3VGEK29ZHXBA57EPSNW1QBPKT8J0
29#.fr = TFDAXBXMAN40MCG4E8Y9Y1C6D16JCMDPH2VMD30KMB92SECEMYGG
30 29
31[gns-proxy] 30[gns-proxy]
32BINARY = gnunet-gns-proxy 31BINARY = gnunet-gns-proxy
diff --git a/src/gns/gnunet-bcd.c b/src/gns/gnunet-bcd.c
index f71f477ef..a2e94089c 100644
--- a/src/gns/gnunet-bcd.c
+++ b/src/gns/gnunet-bcd.c
@@ -27,6 +27,7 @@
27#include "platform.h" 27#include "platform.h"
28#include <microhttpd.h> 28#include <microhttpd.h>
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h"
30#include "gnunet_mhd_compat.h" 31#include "gnunet_mhd_compat.h"
31 32
32/** 33/**
@@ -148,7 +149,7 @@ access_handler_callback (void *cls,
148 char *p; 149 char *p;
149 char *tmp; 150 char *tmp;
150 char *deffile; 151 char *deffile;
151 struct GNUNET_CRYPTO_EcdsaPublicKey pub; 152 struct GNUNET_IDENTITY_PublicKey pub;
152 size_t slen; 153 size_t slen;
153 FILE *f; 154 FILE *f;
154 struct stat st; 155 struct stat st;
@@ -166,9 +167,8 @@ access_handler_callback (void *cls,
166 MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnskey"); 167 MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnskey");
167 if ((NULL == gnskey) || 168 if ((NULL == gnskey) ||
168 (GNUNET_OK != 169 (GNUNET_OK !=
169 GNUNET_CRYPTO_ecdsa_public_key_from_string (gnskey, 170 GNUNET_IDENTITY_public_key_from_string (gnskey,
170 strlen (gnskey), 171 &pub)))
171 &pub)))
172 { 172 {
173 return MHD_queue_response (connection, 173 return MHD_queue_response (connection,
174 MHD_HTTP_OK, 174 MHD_HTTP_OK,
@@ -218,10 +218,10 @@ access_handler_callback (void *cls,
218 (NULL == gns_nick) ? "" : gns_nick); 218 (NULL == gns_nick) ? "" : gns_nick);
219 fclose (f); 219 fclose (f);
220 GNUNET_asprintf ( 220 GNUNET_asprintf (
221 &p, 221 &p,
222 "cd %s; cp %s gns-bcd.tex | pdflatex --enable-write18 gns-bcd.tex > /dev/null 2> /dev/null", 222 "cd %s; cp %s gns-bcd.tex | pdflatex --enable-write18 gns-bcd.tex > /dev/null 2> /dev/null",
223 tmp, 223 tmp,
224 resfile); 224 resfile);
225 GNUNET_free (deffile); 225 GNUNET_free (deffile);
226 ret = system (p); 226 ret = system (p);
227 if (WIFSIGNALED (ret) || (0 != WEXITSTATUS (ret))) 227 if (WIFSIGNALED (ret) || (0 != WEXITSTATUS (ret)))
@@ -506,7 +506,7 @@ main (int argc, char *const *argv)
506 "port", 506 "port",
507 "PORT", 507 "PORT",
508 gettext_noop ( 508 gettext_noop (
509 "Run HTTP serve on port PORT (default is 8888)"), 509 "Run HTTP serve on port PORT (default is 8888)"),
510 &port), 510 &port),
511 GNUNET_GETOPT_OPTION_END 511 GNUNET_GETOPT_OPTION_END
512 }; 512 };
@@ -523,8 +523,8 @@ main (int argc, char *const *argv)
523 options, 523 options,
524 &run, 524 &run,
525 NULL)) 525 NULL))
526 ? 0 526 ? 0
527 : 1; 527 : 1;
528 GNUNET_free_nz ((void *) argv); 528 GNUNET_free_nz ((void *) argv);
529 return ret; 529 return ret;
530} 530}
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c
index 0a9b7c861..06f4c9841 100644
--- a/src/gns/gnunet-dns2gns.c
+++ b/src/gns/gnunet-dns2gns.c
@@ -309,6 +309,14 @@ dns_result_processor (void *cls,
309 } 309 }
310 request->packet = GNUNET_DNSPARSER_parse ((char *) dns, 310 request->packet = GNUNET_DNSPARSER_parse ((char *) dns,
311 r); 311 r);
312 if (NULL == request->packet)
313 {
314 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
315 _ ("Failed to parse DNS response!\n"));
316 GNUNET_SCHEDULER_cancel (request->timeout_task);
317 do_timeout (request);
318 return;
319 }
312 GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup); 320 GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup);
313 send_response (request); 321 send_response (request);
314} 322}
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c
index 833a8da01..d02f0f576 100644
--- a/src/gns/gnunet-gns-proxy.c
+++ b/src/gns/gnunet-gns-proxy.c
@@ -1841,6 +1841,7 @@ create_response (void *cls,
1841 char *curlurl; 1841 char *curlurl;
1842 char ipstring[INET6_ADDRSTRLEN]; 1842 char ipstring[INET6_ADDRSTRLEN];
1843 char ipaddr[INET6_ADDRSTRLEN + 2]; 1843 char ipaddr[INET6_ADDRSTRLEN + 2];
1844 char *curl_hosts;
1844 const struct sockaddr *sa; 1845 const struct sockaddr *sa;
1845 const struct sockaddr_in *s4; 1846 const struct sockaddr_in *s4;
1846 const struct sockaddr_in6 *s6; 1847 const struct sockaddr_in6 *s6;
@@ -1900,6 +1901,14 @@ create_response (void *cls,
1900 GNUNET_break (0); 1901 GNUNET_break (0);
1901 return MHD_NO; 1902 return MHD_NO;
1902 } 1903 }
1904 GNUNET_asprintf (&curl_hosts,
1905 "%s:%d:%s",
1906 s5r->leho,
1907 port,
1908 ipaddr);
1909 s5r->hosts = curl_slist_append (NULL,
1910 curl_hosts);
1911 GNUNET_free (curl_hosts);
1903 } 1912 }
1904 else 1913 else
1905 { 1914 {
@@ -1949,21 +1958,13 @@ create_response (void *cls,
1949 * Pre-populate cache to resolve Hostname. 1958 * Pre-populate cache to resolve Hostname.
1950 * This is necessary as the DNS name in the CURLOPT_URL is used 1959 * This is necessary as the DNS name in the CURLOPT_URL is used
1951 * for SNI http://de.wikipedia.org/wiki/Server_Name_Indication 1960 * for SNI http://de.wikipedia.org/wiki/Server_Name_Indication
1952 */if (NULL != s5r->leho) 1961 */
1962 if ((NULL != s5r->leho) &&
1963 (NULL != s5r->hosts))
1953 { 1964 {
1954 char *curl_hosts;
1955
1956 GNUNET_asprintf (&curl_hosts,
1957 "%s:%d:%s",
1958 s5r->leho,
1959 port,
1960 ipaddr);
1961 s5r->hosts = curl_slist_append (NULL,
1962 curl_hosts);
1963 curl_easy_setopt (s5r->curl, 1965 curl_easy_setopt (s5r->curl,
1964 CURLOPT_RESOLVE, 1966 CURLOPT_RESOLVE,
1965 s5r->hosts); 1967 s5r->hosts);
1966 GNUNET_free (curl_hosts);
1967 } 1968 }
1968 if (s5r->is_gns) 1969 if (s5r->is_gns)
1969 { 1970 {
diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c
index b53f4af6b..255f85598 100644
--- a/src/gns/gnunet-service-gns_interceptor.c
+++ b/src/gns/gnunet-service-gns_interceptor.c
@@ -323,7 +323,6 @@ handle_dns_request (void *cls,
323 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 323 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
324 "Received malformed DNS packet, leaving it untouched.\n"); 324 "Received malformed DNS packet, leaving it untouched.\n");
325 GNUNET_DNS_request_forward (rh); 325 GNUNET_DNS_request_forward (rh);
326 GNUNET_DNSPARSER_free_packet (p);
327 return; 326 return;
328 } 327 }
329 328
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
index 49c1b340a..2f8a55804 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -764,6 +764,7 @@ transmit_lookup_dns_result (struct GNS_ResolverHandle *rh)
764 rd[i].data = pos->data; 764 rd[i].data = pos->data;
765 rd[i].data_size = pos->data_size; 765 rd[i].data_size = pos->data_size;
766 rd[i].record_type = pos->record_type; 766 rd[i].record_type = pos->record_type;
767 rd[i].flags = GNUNET_GNSRECORD_RF_NONE;
767 /** 768 /**
768 * If this is a LEHO, we added this before. It must be a supplemental 769 * If this is a LEHO, we added this before. It must be a supplemental
769 * record #LSD0001 770 * record #LSD0001
@@ -772,12 +773,11 @@ transmit_lookup_dns_result (struct GNS_ResolverHandle *rh)
772 rd[i].flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL; 773 rd[i].flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
773 if (0 == pos->expiration_time) 774 if (0 == pos->expiration_time)
774 { 775 {
775 rd[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; 776 rd[i].flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
776 rd[i].expiration_time = 0; 777 rd[i].expiration_time = 0;
777 } 778 }
778 else 779 else
779 { 780 {
780 rd[i].flags = GNUNET_GNSRECORD_RF_NONE;
781 rd[i].expiration_time = pos->expiration_time; 781 rd[i].expiration_time = pos->expiration_time;
782 } 782 }
783 i++; 783 i++;
@@ -1764,6 +1764,8 @@ recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
1764 /** 1764 /**
1765 * Records other than GNS2DNS not allowed 1765 * Records other than GNS2DNS not allowed
1766 */ 1766 */
1767 if (NULL != ns)
1768 GNUNET_free (ns);
1767 return GNUNET_SYSERR; 1769 return GNUNET_SYSERR;
1768 } 1770 }
1769 off = 0; 1771 off = 0;
@@ -1771,15 +1773,22 @@ recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
1771 rd[i].data_size, 1773 rd[i].data_size,
1772 &off); 1774 &off);
1773 ip = GNUNET_strdup (&((const char *) rd[i].data)[off]); 1775 ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1776 if ((NULL == n) ||
1777 (NULL == ip))
1778 {
1779 GNUNET_break_op (0);
1780 if (NULL != n)
1781 GNUNET_free (n);
1782 if (NULL != ip)
1783 GNUNET_free (ip);
1784 continue;
1785 }
1786
1774 off += strlen (ip) + 1; 1787 off += strlen (ip) + 1;
1775 1788
1776 if ((NULL == n) || 1789 if (off != rd[i].data_size)
1777 (NULL == ip) ||
1778 (off != rd[i].data_size))
1779 { 1790 {
1780 GNUNET_break_op (0); 1791 GNUNET_break_op (0);
1781 GNUNET_free (n);
1782 GNUNET_free (ip);
1783 continue; 1792 continue;
1784 } 1793 }
1785 /* resolve 'ip' to determine the IP(s) of the DNS 1794 /* resolve 'ip' to determine the IP(s) of the DNS
@@ -1909,6 +1918,8 @@ recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
1909 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1918 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1910 _ ("Name `%s' cannot be converted to IDNA."), 1919 _ ("Name `%s' cannot be converted to IDNA."),
1911 tmp); 1920 tmp);
1921 GNUNET_free (tmp);
1922 GNUNET_free (ac);
1912 return GNUNET_SYSERR; 1923 return GNUNET_SYSERR;
1913 } 1924 }
1914 GNUNET_free (tmp); 1925 GNUNET_free (tmp);
@@ -1922,6 +1933,8 @@ recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
1922 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1933 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1923 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"), 1934 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1924 ac->label); 1935 ac->label);
1936 GNUNET_free (ac->label);
1937 GNUNET_free (ac);
1925 return GNUNET_SYSERR; 1938 return GNUNET_SYSERR;
1926 } 1939 }
1927 continue_with_gns2dns (ac); 1940 continue_with_gns2dns (ac);
diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c
index 2ccb5be2b..3a35c9999 100644
--- a/src/gns/plugin_rest_gns.c
+++ b/src/gns/plugin_rest_gns.c
@@ -270,7 +270,9 @@ handle_gns_response (void *cls,
270 result = json_dumps (result_obj, 0); 270 result = json_dumps (result_obj, 0);
271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); 271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
272 resp = GNUNET_REST_create_response (result); 272 resp = GNUNET_REST_create_response (result);
273 MHD_add_response_header (resp, "Content-Type", "application/json"); 273 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
274 "Content-Type",
275 "application/json"));
274 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 276 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
275 GNUNET_free (result); 277 GNUNET_free (result);
276 json_decref (result_obj); 278 json_decref (result_obj);
diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c
index 8d5a6d95b..31749a629 100644
--- a/src/gnsrecord/gnsrecord.c
+++ b/src/gnsrecord/gnsrecord.c
@@ -102,15 +102,12 @@ init ()
102 if (1 == once) 102 if (1 == once)
103 return; 103 return;
104 once = 1; 104 once = 1;
105 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
106 const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default ();
107 105
108 if (pd != dpd) 106 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
109 GNUNET_OS_init (dpd); 107 "libgnunet_plugin_gnsrecord_",
110 GNUNET_PLUGIN_load_all ("libgnunet_plugin_gnsrecord_", NULL, 108 NULL,
111 &add_plugin, NULL); 109 &add_plugin,
112 if (pd != dpd) 110 NULL);
113 GNUNET_OS_init (pd);
114} 111}
115 112
116 113
diff --git a/src/gnsrecord/gnsrecord_misc.c b/src/gnsrecord/gnsrecord_misc.c
index 82c38f19a..b907eed27 100644
--- a/src/gnsrecord/gnsrecord_misc.c
+++ b/src/gnsrecord/gnsrecord_misc.c
@@ -296,15 +296,20 @@ GNUNET_GNSRECORD_data_from_identity (const struct
296 size_t *data_size, 296 size_t *data_size,
297 uint32_t *type) 297 uint32_t *type)
298{ 298{
299 char *tmp;
299 *type = ntohl (key->type); 300 *type = ntohl (key->type);
300 *data_size = GNUNET_IDENTITY_key_get_length (key); 301 *data_size = GNUNET_IDENTITY_key_get_length (key);
301 if (0 == *data_size) 302 if (0 == *data_size)
302 return GNUNET_SYSERR; 303 return GNUNET_SYSERR;
303 *data = GNUNET_malloc (*data_size); 304 tmp = GNUNET_malloc (*data_size);
304 return (GNUNET_IDENTITY_write_key_to_buffer (key, *data, *data_size) == 305 if (GNUNET_IDENTITY_write_key_to_buffer (key, tmp, *data_size)
305 *data_size? 306 != *data_size) {
306 GNUNET_OK : 307 GNUNET_free (tmp);
307 GNUNET_SYSERR); 308 *data_size = 0;
309 return GNUNET_SYSERR;
310 }
311 *data = tmp;
312 return GNUNET_OK;
308} 313}
309 314
310 315
@@ -350,7 +355,7 @@ GNUNET_GNSRECORD_block_get_expiration (const struct
350 case GNUNET_GNSRECORD_TYPE_PKEY: 355 case GNUNET_GNSRECORD_TYPE_PKEY:
351 return GNUNET_TIME_absolute_ntoh (block->ecdsa_block.expiration_time); 356 return GNUNET_TIME_absolute_ntoh (block->ecdsa_block.expiration_time);
352 default: 357 default:
353 return GNUNET_TIME_absolute_get_zero_ (); 358 GNUNET_break (0); /* Hopefully we never get here, but we might */
354 } 359 }
355 return GNUNET_TIME_absolute_get_zero_ (); 360 return GNUNET_TIME_absolute_get_zero_ ();
356 361
diff --git a/src/gnsrecord/gnunet-gnsrecord-tvg.c b/src/gnsrecord/gnunet-gnsrecord-tvg.c
index 47b13bdab..d6b35544c 100644
--- a/src/gnsrecord/gnunet-gnsrecord-tvg.c
+++ b/src/gnsrecord/gnunet-gnsrecord-tvg.c
@@ -172,7 +172,7 @@ run (void *cls,
172 fprintf (stdout, "RRBLOCK:\n"); 172 fprintf (stdout, "RRBLOCK:\n");
173 print_bytes (rrblock, block_size, 8); 173 print_bytes (rrblock, block_size, 8);
174 fprintf (stdout, "\n"); 174 fprintf (stdout, "\n");
175 175 GNUNET_free (rdata);
176} 176}
177 177
178 178
diff --git a/src/hello/hello-ng.c b/src/hello/hello-ng.c
index 85b304e18..96856a692 100644
--- a/src/hello/hello-ng.c
+++ b/src/hello/hello-ng.c
@@ -30,6 +30,7 @@
30#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
31#include "gnunet_ats_service.h" 31#include "gnunet_ats_service.h"
32 32
33GNUNET_NETWORK_STRUCT_BEGIN
33/** 34/**
34 * Binary block we sign when we sign an address. 35 * Binary block we sign when we sign an address.
35 */ 36 */
@@ -48,9 +49,9 @@ struct SignedAddress
48 /** 49 /**
49 * Hash of the address. 50 * Hash of the address.
50 */ 51 */
51 struct GNUNET_HashCode h_addr; 52 struct GNUNET_HashCode addr_hash GNUNET_PACKED;
52}; 53};
53 54GNUNET_NETWORK_STRUCT_END
54 55
55/** 56/**
56 * Build address record by signing raw information with private key. 57 * Build address record by signing raw information with private key.
@@ -78,7 +79,7 @@ GNUNET_HELLO_sign_address (
78 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS); 79 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
79 sa.purpose.size = htonl (sizeof(sa)); 80 sa.purpose.size = htonl (sizeof(sa));
80 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time); 81 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
81 GNUNET_CRYPTO_hash (address, strlen (address), &sa.h_addr); 82 GNUNET_CRYPTO_hash (address, strlen (address), &sa.addr_hash);
82 GNUNET_CRYPTO_eddsa_sign (private_key, &sa, &sig); 83 GNUNET_CRYPTO_eddsa_sign (private_key, &sa, &sig);
83 sig_str = NULL; 84 sig_str = NULL;
84 (void) GNUNET_STRINGS_base64_encode (&sig, sizeof(sig), &sig_str); 85 (void) GNUNET_STRINGS_base64_encode (&sig, sizeof(sig), &sig_str);
@@ -161,7 +162,7 @@ GNUNET_HELLO_extract_address (const void *raw,
161 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS); 162 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
162 sa.purpose.size = htonl (sizeof(sa)); 163 sa.purpose.size = htonl (sizeof(sa));
163 sa.mono_time = GNUNET_TIME_absolute_hton (raw_mono_time); 164 sa.mono_time = GNUNET_TIME_absolute_hton (raw_mono_time);
164 GNUNET_CRYPTO_hash (raw_addr, strlen (raw_addr), &sa.h_addr); 165 GNUNET_CRYPTO_hash (raw_addr, strlen (raw_addr), &sa.addr_hash);
165 if (GNUNET_YES != 166 if (GNUNET_YES !=
166 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS, 167 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS,
167 &sa, 168 &sa,
diff --git a/src/hello/test_hello-ng.c b/src/hello/test_hello-ng.c
index 82b1ab6c6..e6b1d42a0 100644
--- a/src/hello/test_hello-ng.c
+++ b/src/hello/test_hello-ng.c
@@ -26,7 +26,7 @@ main (int argc,
26 (void**)&res, 26 (void**)&res,
27 &res_len); 27 &res_len);
28 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 28 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
29 "%s", res); 29 "%s\n", res);
30 GNUNET_assert (NULL != 30 GNUNET_assert (NULL !=
31 GNUNET_HELLO_extract_address ((void**)res, 31 GNUNET_HELLO_extract_address ((void**)res,
32 res_len, 32 res_len,
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 5569c87ed..faef696a7 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -53,6 +53,7 @@ gnunetinclude_HEADERS = \
53 gnunet_gnsrecord_lib.h \ 53 gnunet_gnsrecord_lib.h \
54 gnunet_gnsrecord_json_lib.h \ 54 gnunet_gnsrecord_json_lib.h \
55 gnunet_gnsrecord_plugin.h \ 55 gnunet_gnsrecord_plugin.h \
56 gnu_name_system_record_types.h \
56 gnunet_hello_lib.h \ 57 gnunet_hello_lib.h \
57 gnunet_helper_lib.h \ 58 gnunet_helper_lib.h \
58 gnunet_identity_service.h \ 59 gnunet_identity_service.h \
@@ -112,7 +113,9 @@ gnunetinclude_HEADERS = \
112 gnunet_strings_lib.h \ 113 gnunet_strings_lib.h \
113 gnunet_testbed_service.h \ 114 gnunet_testbed_service.h \
114 gnunet_testbed_logger_service.h \ 115 gnunet_testbed_logger_service.h \
116 gnunet_testbed_ng_service.h \
115 gnunet_testing_lib.h \ 117 gnunet_testing_lib.h \
118 gnunet_testing_ng_lib.h \
116 gnunet_time_lib.h \ 119 gnunet_time_lib.h \
117 gnunet_transport_service.h \ 120 gnunet_transport_service.h \
118 gnunet_transport_application_service.h \ 121 gnunet_transport_application_service.h \
diff --git a/src/include/gnu_name_system_record_types.h b/src/include/gnu_name_system_record_types.h
new file mode 100644
index 000000000..b2cf45dc8
--- /dev/null
+++ b/src/include/gnu_name_system_record_types.h
@@ -0,0 +1,138 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20#ifndef GNU_NAME_SYSTEM_RECORD_TYPES_H
21#define GNU_NAME_SYSTEM_RECORD_TYPES_H
22
23/**
24 * WARNING:
25 * This header is generated!
26 * In order to add GNS record types, you must register
27 * them in GANA, and then use the header generation script
28 * to create an update of this file. You may then replace this
29 * file with the update.
30 */
31
32#ifdef __cplusplus
33extern "C" {
34#if 0 /* keep Emacsens' auto-indent happy */
35}
36#endif
37#endif
38
39
40/**
41 * GNS zone transfer
42 */
43#define GNUNET_GNSRECORD_TYPE_PKEY 65536
44
45/**
46 * GNS nick names
47 */
48#define GNUNET_GNSRECORD_TYPE_NICK 65537
49
50/**
51 * legacy hostnames
52 */
53#define GNUNET_GNSRECORD_TYPE_LEHO 65538
54
55/**
56 * VPN resolution
57 */
58#define GNUNET_GNSRECORD_TYPE_VPN 65539
59
60/**
61 * Delegation to DNS
62 */
63#define GNUNET_GNSRECORD_TYPE_GNS2DNS 65540
64
65/**
66 * Boxed records (see TLSA/SRV handling in GNS)
67 */
68#define GNUNET_GNSRECORD_TYPE_BOX 65541
69
70/**
71 * social place for SecuShare
72 */
73#define GNUNET_GNSRECORD_TYPE_PLACE 65542
74
75/**
76 * Endpoint for conversation
77 */
78#define GNUNET_GNSRECORD_TYPE_PHONE 65543
79
80/**
81 * identity attribute
82 */
83#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE 65544
84
85/**
86 * local ticket reference
87 */
88#define GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET 65545
89
90/**
91 * For ABD policies
92 */
93#define GNUNET_GNSRECORD_TYPE_DELEGATE 65548
94
95/**
96 * For ABD reverse lookups
97 */
98#define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549
99
100/**
101 * for reclaim records
102 */
103#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF 65550
104
105/**
106 * For reclaim OIDC client names.
107 */
108#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT 65552
109
110/**
111 * Used reclaimID OIDC client redirect URIs.
112 */
113#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT 65553
114
115/**
116 * Record type for an attribute attestation (e.g. JWT).
117 */
118#define GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL 65554
119
120/**
121 * Record type for a presentation of a credential.
122 */
123#define GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION 65555
124
125/**
126 * Record type for EDKEY zone delegations.
127 */
128#define GNUNET_GNSRECORD_TYPE_EDKEY 65556
129
130
131#if 0 /* keep Emacsens' auto-indent happy */
132{
133#endif
134#ifdef __cplusplus
135}
136#endif
137
138#endif
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index 0bf2ceed7..aff56146e 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -55,109 +55,9 @@ extern "C" {
55#define GNUNET_GNSRECORD_TYPE_ANY 0 55#define GNUNET_GNSRECORD_TYPE_ANY 0
56 56
57/** 57/**
58 * Record type for GNS zone transfer ("PKEY"). 58 * Include the record types generated from GANA
59 */ 59 */
60#define GNUNET_GNSRECORD_TYPE_PKEY GNUNET_IDENTITY_TYPE_ECDSA 60#include "gnu_name_system_record_types.h"
61
62/**
63 * Record type for GNS nick names ("NICK").
64 */
65#define GNUNET_GNSRECORD_TYPE_NICK 65537
66
67/**
68 * Record type for GNS legacy hostnames ("LEHO").
69 */
70#define GNUNET_GNSRECORD_TYPE_LEHO 65538
71
72/**
73 * Record type for VPN resolution
74 */
75#define GNUNET_GNSRECORD_TYPE_VPN 65539
76
77/**
78 * Record type for delegation to DNS.
79 */
80#define GNUNET_GNSRECORD_TYPE_GNS2DNS 65540
81
82/**
83 * Record type for a boxed record (see TLSA/SRV handling in GNS).
84 */
85#define GNUNET_GNSRECORD_TYPE_BOX 65541
86
87/**
88 * Record type for a social place.
89 */
90#define GNUNET_GNSRECORD_TYPE_PLACE 65542
91
92/**
93 * Record type for a phone (of CONVERSATION).
94 */
95#define GNUNET_GNSRECORD_TYPE_PHONE 65543
96
97/**
98 * Record type for identity attributes (of RECLAIM).
99 */
100#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE 65544
101
102/**
103 * Record type for local ticket references
104 */
105#define GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET 65545
106
107/**
108 * 65546 reserved
109 */
110
111/**
112 * 65547 deleted, free to use
113 */
114
115/**
116 * Record type for policies
117 */
118#define GNUNET_GNSRECORD_TYPE_DELEGATE 65548
119
120/**
121 * Record type for reverse lookups
122 */
123#define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549
124
125/**
126 * Record type for reclaim records
127 */
128#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF 65550
129
130/**
131 * Record type for RECLAIM master
132 */
133#define GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER 65551
134
135/**
136 * Record type for reclaim OIDC clients
137 */
138#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT 65552
139
140/**
141 * Record type for reclaim OIDC redirect URIs
142 */
143#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT 65553
144
145/**
146 * Record type for an attribute attestation
147 */
148#define GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL 65554
149
150/**
151 * Record type for a presentation of a credential (used
152 * in a ticket record set)
153 */
154#define GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION 65555
155
156/**
157 * Record type for EDKEY delegations.
158 */
159#define GNUNET_GNSRECORD_TYPE_EDKEY GNUNET_IDENTITY_TYPE_EDDSA
160
161 61
162/** 62/**
163 * Flags that can be set for a record. 63 * Flags that can be set for a record.
diff --git a/src/include/gnunet_messenger_service.h b/src/include/gnunet_messenger_service.h
index 389b6b8fd..99d4cf267 100644
--- a/src/include/gnunet_messenger_service.h
+++ b/src/include/gnunet_messenger_service.h
@@ -48,6 +48,14 @@ extern "C" {
48#include "gnunet_scheduler_lib.h" 48#include "gnunet_scheduler_lib.h"
49#include "gnunet_time_lib.h" 49#include "gnunet_time_lib.h"
50 50
51/**
52 * Version number of GNUnet Messenger API.
53 */
54#define GNUNET_MESSENGER_VERSION 0x00000001
55
56/**
57 * Identifier of GNUnet MESSENGER Service.
58 */
51#define GNUNET_MESSENGER_SERVICE_NAME "messenger" 59#define GNUNET_MESSENGER_SERVICE_NAME "messenger"
52 60
53/** 61/**
@@ -141,11 +149,18 @@ enum GNUNET_MESSENGER_MessageKind
141 GNUNET_MESSENGER_KIND_PRIVATE = 14, 149 GNUNET_MESSENGER_KIND_PRIVATE = 14,
142 150
143 /** 151 /**
152 * The delete kind. The message contains a #GNUNET_MESSENGER_MessageDelete body.
153 */
154 GNUNET_MESSENGER_KIND_DELETE = 15,
155
156 /**
144 * The unknown kind. The message contains an unknown body. 157 * The unknown kind. The message contains an unknown body.
145 */ 158 */
146 GNUNET_MESSENGER_KIND_UNKNOWN = 0 159 GNUNET_MESSENGER_KIND_UNKNOWN = 0
147}; 160};
148 161
162#define GNUNET_MESSENGER_KIND_MAX (GNUNET_MESSENGER_KIND_DELETE)
163
149/** 164/**
150 * Get the name of a message <i>kind</i>. 165 * Get the name of a message <i>kind</i>.
151 * 166 *
@@ -157,6 +172,9 @@ GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind);
157 172
158/** 173/**
159 * The header of a #GNUNET_MESSENGER_Message. 174 * The header of a #GNUNET_MESSENGER_Message.
175 * This allows authentification of the sender, temporal ordering and finding potentially missed messages.
176 *
177 * Message-header-size: 40+ bytes
160 */ 178 */
161struct GNUNET_MESSENGER_MessageHeader 179struct GNUNET_MESSENGER_MessageHeader
162{ 180{
@@ -188,6 +206,9 @@ struct GNUNET_MESSENGER_MessageHeader
188 206
189/** 207/**
190 * An info message body. 208 * An info message body.
209 * This allows ensuring member ids are unique and this first message can be verified.
210 *
211 * Message-body-size: 8+ bytes
191 */ 212 */
192struct GNUNET_MESSENGER_MessageInfo 213struct GNUNET_MESSENGER_MessageInfo
193{ 214{
@@ -197,13 +218,16 @@ struct GNUNET_MESSENGER_MessageInfo
197 struct GNUNET_IDENTITY_PublicKey host_key; 218 struct GNUNET_IDENTITY_PublicKey host_key;
198 219
199 /** 220 /**
200 * The new unique id for the receiver in a room. 221 * The version of GNUnet Messenger API.
201 */ 222 */
202 struct GNUNET_ShortHashCode unique_id; 223 uint32_t messenger_version;
203}; 224};
204 225
205/** 226/**
206 * A join message body. 227 * A join message body.
228 * This allows informing others about joining the room with a given key pair.
229 *
230 * Message-body-size: 4+ bytes
207 */ 231 */
208struct GNUNET_MESSENGER_MessageJoin 232struct GNUNET_MESSENGER_MessageJoin
209{ 233{
@@ -215,6 +239,9 @@ struct GNUNET_MESSENGER_MessageJoin
215 239
216/** 240/**
217 * A leave message body. 241 * A leave message body.
242 * This allows informing others about leaving the room.
243 *
244 * Message-body-size: 0 bytes
218 */ 245 */
219struct GNUNET_MESSENGER_MessageLeave 246struct GNUNET_MESSENGER_MessageLeave
220{ 247{
@@ -222,6 +249,9 @@ struct GNUNET_MESSENGER_MessageLeave
222 249
223/** 250/**
224 * A name message body. 251 * A name message body.
252 * This allows replacing the current name with another one.
253 *
254 * Message-body-size: 0+ bytes
225 */ 255 */
226struct GNUNET_MESSENGER_MessageName 256struct GNUNET_MESSENGER_MessageName
227{ 257{
@@ -233,6 +263,9 @@ struct GNUNET_MESSENGER_MessageName
233 263
234/** 264/**
235 * A key message body. 265 * A key message body.
266 * This allows replacing the current key pair with another one.
267 *
268 * Message-body-size: 4+ bytes
236 */ 269 */
237struct GNUNET_MESSENGER_MessageKey 270struct GNUNET_MESSENGER_MessageKey
238{ 271{
@@ -244,6 +277,9 @@ struct GNUNET_MESSENGER_MessageKey
244 277
245/** 278/**
246 * A peer message body. 279 * A peer message body.
280 * This allows informing others to open a peer as a door to the current room.
281 *
282 * Message-body-size: 32 bytes
247 */ 283 */
248struct GNUNET_MESSENGER_MessagePeer 284struct GNUNET_MESSENGER_MessagePeer
249{ 285{
@@ -255,6 +291,9 @@ struct GNUNET_MESSENGER_MessagePeer
255 291
256/** 292/**
257 * An id message body. 293 * An id message body.
294 * This allows replacing the member id with a newly unique generated one.
295 *
296 * Message-body-size: 8 bytes
258 */ 297 */
259struct GNUNET_MESSENGER_MessageId 298struct GNUNET_MESSENGER_MessageId
260{ 299{
@@ -266,6 +305,9 @@ struct GNUNET_MESSENGER_MessageId
266 305
267/** 306/**
268 * A miss message body. 307 * A miss message body.
308 * This allows informing others about a disconnection of any door.
309 *
310 * Message-body-size: 32 bytes
269 */ 311 */
270struct GNUNET_MESSENGER_MessageMiss 312struct GNUNET_MESSENGER_MessageMiss
271{ 313{
@@ -277,6 +319,9 @@ struct GNUNET_MESSENGER_MessageMiss
277 319
278/** 320/**
279 * A merge message body. 321 * A merge message body.
322 * This allows merging message history branches together.
323 *
324 * Message-body-size: 16 bytes
280 */ 325 */
281struct GNUNET_MESSENGER_MessageMerge 326struct GNUNET_MESSENGER_MessageMerge
282{ 327{
@@ -288,6 +333,9 @@ struct GNUNET_MESSENGER_MessageMerge
288 333
289/** 334/**
290 * A request message body. 335 * A request message body.
336 * This allows requesting the content of a specific message which is currently missing.
337 *
338 * Message-body-size: 16 bytes
291 */ 339 */
292struct GNUNET_MESSENGER_MessageRequest 340struct GNUNET_MESSENGER_MessageRequest
293{ 341{
@@ -299,6 +347,9 @@ struct GNUNET_MESSENGER_MessageRequest
299 347
300/** 348/**
301 * An invite message body. 349 * An invite message body.
350 * This allows sharing information about other rooms in form of an invitation.
351 *
352 * Message-body-size: 48 bytes
302 */ 353 */
303struct GNUNET_MESSENGER_MessageInvite 354struct GNUNET_MESSENGER_MessageInvite
304{ 355{
@@ -315,6 +366,9 @@ struct GNUNET_MESSENGER_MessageInvite
315 366
316/** 367/**
317 * A text message body. 368 * A text message body.
369 * This allows general communication in text form.
370 *
371 * Message-body-size: 0+ bytes
318 */ 372 */
319struct GNUNET_MESSENGER_MessageText 373struct GNUNET_MESSENGER_MessageText
320{ 374{
@@ -326,6 +380,9 @@ struct GNUNET_MESSENGER_MessageText
326 380
327/** 381/**
328 * A file message body. 382 * A file message body.
383 * This allows sending necessary details about an uploaded encrypted file to allow access to it.
384 *
385 * Message-body-size: 335+ bytes
329 */ 386 */
330struct GNUNET_MESSENGER_MessageFile 387struct GNUNET_MESSENGER_MessageFile
331{ 388{
@@ -352,6 +409,9 @@ struct GNUNET_MESSENGER_MessageFile
352 409
353/** 410/**
354 * A private message body. 411 * A private message body.
412 * This allows to encapsulate any message to be encrypted for only one specific member to receive in a room.
413 *
414 * Message-body-size: 32+ bytes
355 */ 415 */
356struct GNUNET_MESSENGER_MessagePrivate 416struct GNUNET_MESSENGER_MessagePrivate
357{ 417{
@@ -372,6 +432,25 @@ struct GNUNET_MESSENGER_MessagePrivate
372}; 432};
373 433
374/** 434/**
435 * A delete message body
436 * This allows deletion of an own previous message with any custom automatic delay.
437 *
438 * Message-body-size: 24 bytes
439 */
440struct GNUNET_MESSENGER_MessageDelete
441{
442 /**
443 * The hash of the message to delete.
444 */
445 struct GNUNET_HashCode hash;
446
447 /**
448 * The delay of the delete operation to get processed.
449 */
450 struct GNUNET_TIME_RelativeNBO delay;
451};
452
453/**
375 * The unified body of a #GNUNET_MESSENGER_Message. 454 * The unified body of a #GNUNET_MESSENGER_Message.
376 */ 455 */
377struct GNUNET_MESSENGER_MessageBody 456struct GNUNET_MESSENGER_MessageBody
@@ -392,6 +471,7 @@ struct GNUNET_MESSENGER_MessageBody
392 struct GNUNET_MESSENGER_MessageText text; 471 struct GNUNET_MESSENGER_MessageText text;
393 struct GNUNET_MESSENGER_MessageFile file; 472 struct GNUNET_MESSENGER_MessageFile file;
394 struct GNUNET_MESSENGER_MessagePrivate private; 473 struct GNUNET_MESSENGER_MessagePrivate private;
474 struct GNUNET_MESSENGER_MessageDelete delete;
395 }; 475 };
396}; 476};
397 477
@@ -412,11 +492,27 @@ struct GNUNET_MESSENGER_Message
412}; 492};
413 493
414/** 494/**
495 * Enum for the different supported flags used by message handling
496 */
497enum GNUNET_MESSENGER_MessageFlags
498{
499 /**
500 * The none flag. The flag indicates that the message is not affected by any special context.
501 */
502 GNUNET_MESSENGER_FLAG_NONE = 0,
503
504 /**
505 * The private flag. The flag indicates that the message was privately encrypted.
506 */
507 GNUNET_MESSENGER_FLAG_PRIVATE = 1,
508};
509
510/**
415 * Method called whenever the EGO of a <i>handle</i> changes or if the first connection fails 511 * Method called whenever the EGO of a <i>handle</i> changes or if the first connection fails
416 * to load a valid EGO and the anonymous key pair will be used instead. 512 * to load a valid EGO and the anonymous key pair will be used instead.
417 * 513 *
418 * @param cls Closure from <i>GNUNET_MESSENGER_connect</i> 514 * @param[in/out] cls Closure from #GNUNET_MESSENGER_connect
419 * @param handle Messenger handle 515 * @param[in/out] handle Messenger handle
420 */ 516 */
421typedef void 517typedef void
422(*GNUNET_MESSENGER_IdentityCallback) (void *cls, struct GNUNET_MESSENGER_Handle *handle); 518(*GNUNET_MESSENGER_IdentityCallback) (void *cls, struct GNUNET_MESSENGER_Handle *handle);
@@ -424,25 +520,45 @@ typedef void
424/** 520/**
425 * Method called whenever a message is sent or received from a <i>room</i>. 521 * Method called whenever a message is sent or received from a <i>room</i>.
426 * 522 *
427 * @param cls Closure from <i>GNUNET_MESSENGER_connect</i> 523 * The flag <i>private_message</i> will be #GNUNET_YES if a message was
428 * @param room Room handle 524 * received privately, otherwise #GNUNET_NO.
429 * @param message Newly received or sent message 525 *
430 * @param hash Hash identifying the message 526 * @param[in/out] cls Closure from #GNUNET_MESSENGER_connect
527 * @param[in] room Room handle
528 * @param[in] sender Sender of message
529 * @param[in] message Newly received or sent message
530 * @param[in] hash Hash identifying the message
531 * @param[in] flags Flags of the message
431 */ 532 */
432typedef void 533typedef void
433(*GNUNET_MESSENGER_MessageCallback) (void *cls, const struct GNUNET_MESSENGER_Room *room, 534(*GNUNET_MESSENGER_MessageCallback) (void *cls, struct GNUNET_MESSENGER_Room *room,
434 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 535 const struct GNUNET_MESSENGER_Contact *sender,
536 const struct GNUNET_MESSENGER_Message *message,
537 const struct GNUNET_HashCode *hash,
538 enum GNUNET_MESSENGER_MessageFlags flags);
539
540/**
541 * Method called for each member in a <i>room</i> during iteration. If the method returns
542 * #GNUNET_YES the iteration continues, otherwise it will quit the iteration.
543 *
544 * @param[in/out] cls Closure from #GNUNET_MESSENGER_iterate_members
545 * @param[in] room Room handle
546 * @param[in] contact Contact handle
547 */
548typedef int
549(*GNUNET_MESSENGER_MemberCallback) (void* cls, struct GNUNET_MESSENGER_Room *room,
550 const struct GNUNET_MESSENGER_Contact *contact);
435 551
436/** 552/**
437 * Set up a handle for the messenger related functions and connects to all necessary services. It will look up the ego 553 * Set up a handle for the messenger related functions and connects to all necessary services. It will look up the ego
438 * key identified by its <i>name</i> and use it for signing all messages from the handle. 554 * key identified by its <i>name</i> and use it for signing all messages from the handle.
439 * 555 *
440 * @param cfg Configuration to use 556 * @param[in] cfg Configuration to use
441 * @param name Name to look up an ego or NULL to stay anonymous 557 * @param[in] name Name to look up an ego or NULL to stay anonymous
442 * @param identity_callback Function called when the EGO of the handle changes 558 * @param[in] identity_callback Function called when the EGO of the handle changes
443 * @param identity_cls Closure for the <i>identity_callback</i> handler 559 * @param[in/out] identity_cls Closure for the <i>identity_callback</i> handler
444 * @param msg_callback Function called when a new message is sent or received 560 * @param[in] msg_callback Function called when a new message is sent or received
445 * @param msg_cls Closure for the <i>msg_callback</i> handler 561 * @param[in/out] msg_cls Closure for the <i>msg_callback</i> handler
446 * @return Messenger handle to use, NULL on error 562 * @return Messenger handle to use, NULL on error
447 */ 563 */
448struct GNUNET_MESSENGER_Handle* 564struct GNUNET_MESSENGER_Handle*
@@ -458,8 +574,8 @@ GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const c
458 * Keep in mind that this will fully delete the old ego key (if any is used) even if any other service wants to use it 574 * Keep in mind that this will fully delete the old ego key (if any is used) even if any other service wants to use it
459 * as default. 575 * as default.
460 * 576 *
461 * @param handle Messenger handle to use 577 * @param[in/out] handle Messenger handle to use
462 * @return GNUNET_OK on success, GNUNET_SYSERR on failure 578 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
463 */ 579 */
464int 580int
465GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle); 581GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle);
@@ -467,7 +583,7 @@ GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle);
467/** 583/**
468 * Disconnect all of the messengers used services and clears up its used memory. 584 * Disconnect all of the messengers used services and clears up its used memory.
469 * 585 *
470 * @param handle Messenger handle to use 586 * @param[in/out] handle Messenger handle to use
471 */ 587 */
472void 588void
473GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle); 589GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle);
@@ -475,7 +591,7 @@ GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle);
475/** 591/**
476 * Get the name (if specified, otherwise NULL) used by the messenger. 592 * Get the name (if specified, otherwise NULL) used by the messenger.
477 * 593 *
478 * @param handle Messenger handle to use 594 * @param[in] handle Messenger handle to use
479 * @return Name used by the messenger or NULL 595 * @return Name used by the messenger or NULL
480 */ 596 */
481const char* 597const char*
@@ -483,21 +599,21 @@ GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle);
483 599
484/** 600/**
485 * Set the name for the messenger. This will rename the currently used ego and move all stored files related to the current 601 * Set the name for the messenger. This will rename the currently used ego and move all stored files related to the current
486 * name to its new directory. If anything fails during this process the function returns GNUNET_NO and the name for 602 * name to its new directory. If anything fails during this process the function returns #GNUNET_NO and the name for
487 * the messenger won't change as specified. 603 * the messenger won't change as specified.
488 * 604 *
489 * @param handle Messenger handle to use 605 * @param[in/out] handle Messenger handle to use
490 * @param name Name for the messenger to change to 606 * @param[in] name Name for the messenger to change to
491 * @return GNUNET_YES on success, GNUNET_NO on failure and GNUNET_SYSERR if <i>handle</i> is NULL 607 * @return #GNUNET_YES on success, #GNUNET_NO on failure and #GNUNET_SYSERR if <i>handle</i> is NULL
492 */ 608 */
493int 609int
494GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *name); 610GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *name);
495 611
496/** 612/**
497 * Get the public key used by the messenger. 613 * Get the public key used by the messenger or NULL if the anonymous key was used.
498 * 614 *
499 * @param handle Messenger handle to use 615 * @param[in] handle Messenger handle to use
500 * @return Used ego's public key 616 * @return Used ego's public key or NULL
501 */ 617 */
502const struct GNUNET_IDENTITY_PublicKey* 618const struct GNUNET_IDENTITY_PublicKey*
503GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle); 619GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle);
@@ -509,38 +625,38 @@ GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle);
509 * Notice that there can only be one room related to a specific <i>key</i>. So trying to open two rooms with the same 625 * Notice that there can only be one room related to a specific <i>key</i>. So trying to open two rooms with the same
510 * <i>key</i> will result in opening the room once but returning the handle both times because the room stays open. 626 * <i>key</i> will result in opening the room once but returning the handle both times because the room stays open.
511 * 627 *
512 * You can also open a room after entering it through a <b>door</b> using <i>GNUNET_MESSENGER_entry_room(...)</i>. This 628 * You can also open a room after entering it through a <b>door</b> using #GNUNET_MESSENGER_enter_room. This
513 * will notify all entered <b>doors</b> to list you as new <b>door</b>. 629 * will notify all entered <b>doors</b> to list you as new <b>door</b>.
514 * 630 *
515 * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. ) 631 * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. )
516 * 632 *
517 * @param handle Messenger handle to use 633 * @param[in/out] handle Messenger handle to use
518 * @param key Hash identifying the port 634 * @param[in] key Hash identifying the port
519 * @return Room handle, NULL on error 635 * @return Room handle, NULL on error
520 */ 636 */
521struct GNUNET_MESSENGER_Room* 637struct GNUNET_MESSENGER_Room*
522GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); 638GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
523 639
524/** 640/**
525 * Enter a room to send and receive messages through a <b>door</b> opened using <i>GNUNET_MESSENGER_open_room(...)</i>. 641 * Enter a room to send and receive messages through a <b>door</b> opened using #GNUNET_MESSENGER_open_room.
526 * 642 *
527 * Notice that there can only be one room related to a specific <i>key</i>. So trying to enter two rooms with the same 643 * Notice that there can only be one room related to a specific <i>key</i>. So trying to enter two rooms with the same
528 * <i>key</i> will result in entering the room once but returning the handle both times because the room stays entered. 644 * <i>key</i> will result in entering the room once but returning the handle both times because the room stays entered.
529 * You can however enter a room through multiple <b>doors</b> in parallel which results in connecting both ends. But 645 * You can however enter a room through multiple <b>doors</b> in parallel which results in connecting both ends. But
530 * entering the room through the same <b>door</b> won't have any effect after the first time. 646 * entering the room through the same <b>door</b> won't have any effect after the first time.
531 * 647 *
532 * You can also enter a room through a <b>door</b> after opening it using <i>GNUNET_MESSENGER_open_room(...)</i>. But the 648 * You can also enter a room through a <b>door</b> after opening it using #GNUNET_MESSENGER_open_room. But the
533 * <b>door</b> may not be your own peer identity. 649 * <b>door</b> may not be your own peer identity.
534 * 650 *
535 * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. ) 651 * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. )
536 * 652 *
537 * @param handle Messenger handle to use 653 * @param[in/out] handle Messenger handle to use
538 * @param door Peer identity of an open <b>door</b> 654 * @param[in] door Peer identity of an open <b>door</b>
539 * @param key Hash identifying the port 655 * @param[in] key Hash identifying the port
540 * @return Room handle, NULL on error 656 * @return Room handle, NULL on error
541 */ 657 */
542struct GNUNET_MESSENGER_Room* 658struct GNUNET_MESSENGER_Room*
543GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, 659GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
544 const struct GNUNET_HashCode *key); 660 const struct GNUNET_HashCode *key);
545 661
546/** 662/**
@@ -550,37 +666,37 @@ GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struc
550 * ( After a member closes a <b>door</b>, all members entered through that specific <b>door</b> have to use another one 666 * ( After a member closes a <b>door</b>, all members entered through that specific <b>door</b> have to use another one
551 * or open the room on their own. ) 667 * or open the room on their own. )
552 * 668 *
553 * @param room Room handle 669 * @param[in/out] room Room handle
554 */ 670 */
555void 671void
556GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room); 672GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room);
557 673
558/** 674/**
559 * Get the contact of a member in a <i>room</i> identified by their <i>id</i>. 675 * Get the contact of a member in a <i>room</i> which sent a specific message identified with a given <i>hash</i>.
560 * 676 *
561 * Notice that contacts are independent of rooms but will be removed if all rooms containing these contacts get closed. 677 * Notice that contacts are independent of rooms but will be removed if all rooms containing these contacts get closed.
562 * 678 *
563 * @param room Room handle 679 * @param[in] room Room handle
564 * @param id Hash identifying a member 680 * @param[in] hash Hash identifying a message
565 * @return Contact handle, NULL if <i>id</i> is not in use 681 * @return Contact handle, NULL otherwise
566 */ 682 */
567struct GNUNET_MESSENGER_Contact* 683struct GNUNET_MESSENGER_Contact*
568GNUNET_MESSENGER_get_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id); 684GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
569 685
570/** 686/**
571 * Get the name used by the <i>contact</i>. 687 * Get the name used by the <i>contact</i>.
572 * 688 *
573 * @param contact Contact handle 689 * @param[in] contact Contact handle
574 * @return Name of <i>contact</i> or NULL 690 * @return Name of <i>contact</i> or NULL
575 */ 691 */
576const char* 692const char*
577GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact); 693GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact);
578 694
579/** 695/**
580 * Get the public key used by the <i>contact</i>. 696 * Get the public key used by the <i>contact</i> or NULL if the anonymous key was used.
581 * 697 *
582 * @param contact Contact handle 698 * @param[in] contact Contact handle
583 * @return Public key of the ego used by <i>contact</i> 699 * @return Public key of the ego used by <i>contact</i> or NULL
584 */ 700 */
585const struct GNUNET_IDENTITY_PublicKey* 701const struct GNUNET_IDENTITY_PublicKey*
586GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact); 702GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact);
@@ -593,22 +709,44 @@ GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact
593 * 709 *
594 * Notice that all messages sent and received are also stored and can be propagated to new members entering the room. 710 * Notice that all messages sent and received are also stored and can be propagated to new members entering the room.
595 * 711 *
596 * @param room Room handle 712 * If you provide a specific <i>contact</i> as receiver of the given message, the message will automatically be
597 * @param message New message to send 713 * encrypted and sent as a private message (see #GNUNET_MESSENGER_MessagePrivate). Therefore the selected contact
714 * will be the only member receiving the actual message.
715 *
716 * Sending a message to all members in a given room can be done by providing NULL as contact.
717 *
718 * @param[in/out] room Room handle
719 * @param[in] message New message to send
720 * @param[in] contact Contact or NULL
598 */ 721 */
599void 722void
600GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message); 723GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
724 const struct GNUNET_MESSENGER_Contact* contact);
601 725
602/** 726/**
603 * Get the message in a <i>room</i> identified by its <i>hash</i>. 727 * Get the message in a <i>room</i> identified by its <i>hash</i>.
604 * 728 *
605 * @param room Room handle 729 * @param[in] room Room handle
606 * @param hash Hash identifying a message 730 * @param[in] hash Hash identifying a message
607 * @return Message struct or NULL if no message with that hash is known 731 * @return Message struct or NULL if no message with that hash is known
608 */ 732 */
609const struct GNUNET_MESSENGER_Message* 733const struct GNUNET_MESSENGER_Message*
610GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash); 734GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
611 735
736/**
737 * Iterates through all members of a given <i>room</i> and calls a selected <i>callback</i>
738 * for each of them with a provided closure. The callback will receive the contact of each
739 * member. The function returns the amount of members iterated with the given callback.
740 *
741 * @param[in] room Room handle
742 * @param[in] callback Function called for each member
743 * @param[in] cls Closure for the <i>callback</i> handler
744 * @return Amount of members iterated
745 */
746int
747GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
748 void* cls);
749
612#if 0 /* keep Emacsens' auto-indent happy */ 750#if 0 /* keep Emacsens' auto-indent happy */
613{ 751{
614#endif 752#endif
diff --git a/src/include/gnunet_plugin_lib.h b/src/include/gnunet_plugin_lib.h
index ffffcab8b..d265eb343 100644
--- a/src/include/gnunet_plugin_lib.h
+++ b/src/include/gnunet_plugin_lib.h
@@ -122,6 +122,28 @@ GNUNET_PLUGIN_load_all (const char *basename,
122 122
123 123
124/** 124/**
125 * Load all compatible plugins with the given base name while inside the given
126 * context (i.e. a specific project data structure.)
127 *
128 * Note that the library must export symbols called `basename_ANYTHING_init`
129 * and `basename_ANYTHING__done`. These will be called when the library is
130 * loaded and unloaded respectively.
131 *
132 * @param ctx the context used to find the plugins
133 * @param basename basename of the plugins to load
134 * @param arg argument to the plugin initialization function
135 * @param cb function to call for each plugin found
136 * @param cb_cls closure for @a cb
137 */
138void
139GNUNET_PLUGIN_load_all_in_context (const struct GNUNET_OS_ProjectData *ctx,
140 const char *basename,
141 void *arg,
142 GNUNET_PLUGIN_LoaderCallback cb,
143 void *cb_cls);
144
145
146/**
125 * Unload plugin (runs the "done" callback and returns whatever "done" 147 * Unload plugin (runs the "done" callback and returns whatever "done"
126 * returned). The plugin is then unloaded. 148 * returned). The plugin is then unloaded.
127 * 149 *
diff --git a/src/include/gnunet_testbed_ng_service.h b/src/include/gnunet_testbed_ng_service.h
new file mode 100644
index 000000000..370617e68
--- /dev/null
+++ b/src/include/gnunet_testbed_ng_service.h
@@ -0,0 +1,216 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @author t3sserakt
23 *
24 * @file
25 * API for writing tests and creating large-scale emulation testbeds for GNUnet with command pattern.
26 *
27 * @defgroup testbed Testbed service
28 * Writing tests and creating large-scale emulation testbeds for GNUnet with command pattern.
29 *
30 * @see [Documentation](https://docs.gnunet.org/handbook/gnunet.html#TESTBED-NG-Subsystem)
31 *
32 * @{
33 */
34
35#ifndef GNUNET_TESTBED_NG_SERVICE_H
36#define GNUNET_TESTBED_NG_SERVICE_H
37
38#include "gnunet_util_lib.h"
39#include "gnunet_testing_ng_lib.h"
40
41struct TngState;
42
43struct PeerCmdState
44{
45 /**
46 * The label of a controller command.
47 */
48 const char *controller_label;
49
50 /**
51 * Handle to operation
52 */
53 struct GNUNET_TESTBED_Operation *operation;
54
55 /**
56 * Name of the host, use "NULL" for localhost.
57 */
58 const char *hostname;
59
60 /**
61 * Username to use for the login; may be NULL.
62 */
63 const char *username;
64
65 /**
66 * Port number to use for ssh; use 0 to let ssh decide.
67 */
68 uint16_t port;
69
70 /**
71 * The configuration to use as a template while starting a controller
72 * on this host. Operation queue sizes specific to a host are also
73 * read from this configuration handle.
74 */
75 struct GNUNET_CONFIGURATION_Handle *cfg;
76
77 /**
78 * The host to run peers and controllers on
79 */
80 struct GNUNET_TESTBED_Host *host;
81
82 /**
83 * Abort task identifier
84 */
85 struct GNUNET_SCHEDULER_Task *abort_task;
86
87 /**
88 * Flag indicating if peer is ready.
89 */
90 int peer_ready;
91
92 /**
93 * Flag indicating controller is going down.
94 */
95 int peer_going_down;
96
97 /**
98 * Interpreter state.
99 */
100 struct GNUNET_TESTING_Interpreter *is;
101
102 /**
103 * Peer to start
104 */
105 struct GNUNET_TESTBED_Peer *peer;
106};
107
108struct ControllerState
109{
110 /**
111 * The ip address of the controller which will be set as TRUSTED
112 * HOST(all connections form this ip are permitted by the testbed) when
113 * starting testbed controller at host. This can either be a single ip
114 * address or a network address in CIDR notation.
115 */
116 const char *trusted_ip;
117
118 /**
119 * Name of the host, use "NULL" for localhost.
120 */
121 const char *hostname;
122
123 /**
124 * Username to use for the login; may be NULL.
125 */
126 const char *username;
127
128 /**
129 * Port number to use for ssh; use 0 to let ssh decide.
130 */
131 uint16_t port;
132
133 /**
134 * The configuration to use as a template while starting a controller
135 * on this host. Operation queue sizes specific to a host are also
136 * read from this configuration handle.
137 */
138 struct GNUNET_CONFIGURATION_Handle *cfg;
139
140 /**
141 * The host to run peers and controllers on
142 */
143 struct GNUNET_TESTBED_Host *host;
144
145 /**
146 * The controller process
147 */
148 struct GNUNET_TESTBED_ControllerProc *cp;
149
150 /**
151 * The controller handle
152 */
153 struct GNUNET_TESTBED_Controller *controller;
154
155 /**
156 * A bit mask with set of events to call the controller for.
157 */
158 uint64_t event_mask;
159
160 /**
161 * Abort task identifier
162 */
163 struct GNUNET_SCHEDULER_Task *abort_task;
164
165 /**
166 * Handle for host registration
167 */
168 struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
169
170 /**
171 * Flag indicating if host create with controller is ready.
172 */
173 int host_ready;
174
175 /**
176 * Flag indicating controller is going down.
177 */
178 int controller_going_down;
179
180 /**
181 * Interpreter state.
182 */
183 struct GNUNET_TESTING_Interpreter *is;
184};
185
186/**
187 * Offer data from trait
188 *
189 * @param cmd command to extract the controller from.
190 * @param pt pointer to controller.
191 * @return #GNUNET_OK on success.
192 */
193int
194GNUNET_TESTBED_get_trait_controller (const struct GNUNET_TESTING_Command *cmd,
195 struct GNUNET_TESTBED_Controller **
196 controller);
197
198struct GNUNET_TESTING_Command
199GNUNET_TESTBED_cmd_controller (const char *label,
200 const char *trusted_ip,
201 const char *hostname,
202 const char *username,
203 uint16_t port,
204 struct GNUNET_CONFIGURATION_Handle *cfg,
205 uint64_t event_mask);
206
207void
208GNUNET_TESTBED_shutdown_controller (struct ControllerState *cs);
209
210void
211GNUNET_TESTBED_shutdown_peer (struct PeerCmdState *ps);
212
213void
214GNUNET_TESTBED_shutdown_service (struct TngState *ss);
215
216#endif
diff --git a/src/include/gnunet_testbed_service.h b/src/include/gnunet_testbed_service.h
index 70cbfa90d..acdfb2034 100644
--- a/src/include/gnunet_testbed_service.h
+++ b/src/include/gnunet_testbed_service.h
@@ -27,7 +27,7 @@
27 * @defgroup testbed Testbed service 27 * @defgroup testbed Testbed service
28 * Writing tests and creating large-scale emulation testbeds for GNUnet. 28 * Writing tests and creating large-scale emulation testbeds for GNUnet.
29 * 29 *
30 * @see [Documentation](https://gnunet.org/gnunet-testbed-subsystem) 30 * @see [Documentation](https://docs.gnunet.org/handbook/gnunet.html#TESTBED-Subsystem)
31 * 31 *
32 * @{ 32 * @{
33 */ 33 */
diff --git a/src/include/gnunet_testing_ng_lib.h b/src/include/gnunet_testing_ng_lib.h
new file mode 100644
index 000000000..001d92aad
--- /dev/null
+++ b/src/include/gnunet_testing_ng_lib.h
@@ -0,0 +1,833 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @brief API for writing an interpreter to test GNUnet components
23 * @author Christian Grothoff <christian@grothoff.org>
24 * @author Marcello Stanisci
25 * @author t3sserakt
26 */
27#ifndef GNUNET_TESTING_NG_LIB_H
28#define GNUNET_TESTING_NG_LIB_H
29
30#include "gnunet_util_lib.h"
31
32
33/* ********************* Helper functions ********************* */
34
35/**
36 * Print failing line number and trigger shutdown. Useful
37 * quite any time after the command "run" method has been called.
38 */
39#define GNUNET_TESTING_FAIL(is) \
40 do \
41 { \
42 GNUNET_break (0); \
43 GNUNET_TESTING_interpreter_fail (is); \
44 return; \
45 } while (0)
46
47
48/* ******************* Generic interpreter logic ************ */
49
50/**
51 * Global state of the interpreter, used by a command
52 * to access information about other commands.
53 */
54struct GNUNET_TESTING_Interpreter;
55
56/**
57 * A command to be run by the interpreter.
58 */
59struct GNUNET_TESTING_Command
60{
61
62 /**
63 * Closure for all commands with command-specific context information.
64 */
65 void *cls;
66
67 /**
68 * Label for the command.
69 */
70 const char *label;
71
72 /**
73 * Runs the command. Note that upon return, the interpreter
74 * will not automatically run the next command, as the command
75 * may continue asynchronously in other scheduler tasks. Thus,
76 * the command must ensure to eventually call
77 * #GNUNET_TESTING_interpreter_next() or
78 * #GNUNET_TESTING_interpreter_fail().
79 *
80 * If this function creates some asynchronous activity, it should
81 * initialize @e finish to a function that can be used to wait for
82 * the asynchronous activity to terminate.
83 *
84 * @param cls closure
85 * @param cmd command being run
86 * @param i interpreter state
87 */
88 void
89 (*run)(void *cls,
90 const struct GNUNET_TESTING_Command *cmd,
91 struct GNUNET_TESTING_Interpreter *i);
92
93 /**
94 * Wait for any asynchronous execution of @e run to conclude,
95 * then call finish_cont. Finish may only be called once per command.
96 *
97 * This member may be NULL if this command is a synchronous command,
98 * and also should be set to NULL once the command has finished.
99 *
100 * @param cls closure
101 * @param cont function to call upon completion, can be NULL
102 * @param cont_cls closure for @a cont
103 */
104 bool
105 (*finish)(void *cls,
106 GNUNET_SCHEDULER_TaskCallback cont,
107 void *cont_cls);
108
109 /**
110 * Task for running the finish function.
111 */
112 struct GNUNET_SCHEDULER_Task *finish_task;
113
114 /**
115 * Clean up after the command. Run during forced termination
116 * (CTRL-C) or test failure or test success.
117 *
118 * @param cls closure
119 * @param cmd command being cleaned up
120 */
121 void
122 (*cleanup)(void *cls,
123 const struct GNUNET_TESTING_Command *cmd);
124
125 /**
126 * Extract information from a command that is useful for other
127 * commands.
128 *
129 * @param cls closure
130 * @param[out] ret result (could be anything)
131 * @param trait name of the trait
132 * @param index index number of the object to extract.
133 * @return #GNUNET_OK on success
134 */
135 int
136 (*traits)(void *cls,
137 const void **ret,
138 const char *trait,
139 unsigned int index);
140
141 /**
142 * When did the execution of this command start?
143 */
144 struct GNUNET_TIME_Absolute start_time;
145
146 /**
147 * When did the execution of this command finish?
148 */
149 struct GNUNET_TIME_Absolute finish_time;
150
151 /**
152 * When did we start the last run of this command? Delta to @e finish_time
153 * gives the latency for the last successful run. Useful in case @e
154 * num_tries was positive and the command was run multiple times. In that
155 * case, the @e start_time gives the time when we first tried to run the
156 * command, so the difference between @e start_time and @e finish_time would
157 * be the time all of the @e num_tries took, while the delta to @e
158 * last_req_time is the time the last (successful) execution took.
159 */
160 struct GNUNET_TIME_Absolute last_req_time;
161
162 /**
163 * How often did we try to execute this command? (In case it is a request
164 * that is repated.) Note that a command must have some build-in retry
165 * mechanism for this value to be useful.
166 */
167 unsigned int num_tries;
168
169 /**
170 * In case @e asynchronous_finish is true, how long should we wait for this
171 * command to complete? If @e finish did not complete after this amount of
172 * time, the interpreter will fail. Should be set generously to ensure
173 * tests do not fail on slow systems.
174 */
175 struct GNUNET_TIME_Relative default_timeout;
176
177 /**
178 * If "true", the interpreter should not immediately call
179 * @e finish, even if @e finish is non-NULL. Otherwise,
180 * #TALER_TESTING_cmd_finish() must be used
181 * to ensure that a command actually completed.
182 */
183 bool asynchronous_finish;
184
185};
186
187
188/**
189 * Struct to use for command-specific context information closure of a command waiting
190 * for another command.
191 */
192struct SyncState
193{
194 /**
195 * Closure for all commands with command-specific context information.
196 */
197 void *cls;
198
199 /**
200 * The asynchronous command the synchronous command of this closure waits for.
201 */
202 const struct GNUNET_TESTING_Command *async_cmd;
203
204 /**
205 * Task for running the finish method of the asynchronous task the command is waiting for.
206 */
207 struct GNUNET_SCHEDULER_Task *finish_task;
208
209 /**
210 * When did the execution of this commands finish function start?
211 */
212 struct GNUNET_TIME_Absolute start_finish_time;
213};
214
215/**
216 * Lookup command by label.
217 *
218 * @param label label of the command to lookup.
219 * @return the command, if it is found, or NULL.
220 */
221const struct GNUNET_TESTING_Command *
222GNUNET_TESTING_interpreter_lookup_command (
223 const char *label);
224
225
226/**
227 * Obtain label of the command being now run.
228 *
229 * @param is interpreter state.
230 * @return the label.
231 */
232const char *
233GNUNET_TESTING_interpreter_get_current_label (
234 struct GNUNET_TESTING_Interpreter *is);
235
236
237/**
238 * Current command failed, clean up and fail the test case.
239 *
240 * @param is interpreter state.
241 */
242void
243GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is);
244
245
246/**
247 * Create command array terminator.
248 *
249 * @return a end-command.
250 */
251struct GNUNET_TESTING_Command
252GNUNET_TESTING_cmd_end (void);
253
254
255/**
256 * Turn asynchronous command into non blocking command by setting asynchronous_finish to true.
257 *
258 * @param cmd command to make synchronous.
259 * @return a finish-command.
260 */
261const struct GNUNET_TESTING_Command
262GNUNET_TESTING_cmd_make_unblocking (const struct GNUNET_TESTING_Command cmd);
263
264
265/**
266 * Create (synchronous) command that waits for another command to finish.
267 * If @a cmd_ref did not finish after @a timeout, this command will fail
268 * the test case.
269 *
270 * @param finish_label label for this command
271 * @param cmd_ref reference to a previous command which we should
272 * wait for (call `finish()` on)
273 * @param timeout how long to wait at most for @a cmd_ref to finish
274 * @return a finish-command.
275 */
276const struct GNUNET_TESTING_Command
277GNUNET_TESTING_cmd_finish (const char *finish_label,
278 const char *cmd_ref,
279 struct GNUNET_TIME_Relative timeout);
280
281
282/**
283 * Make the instruction pointer point to @a target_label
284 * only if @a counter is greater than zero.
285 *
286 * @param label command label
287 * @param target_label label of the new instruction pointer's destination after the jump;
288 * must be before the current instruction
289 * @param counter counts how many times the rewinding is to happen.
290 */
291struct GNUNET_TESTING_Command
292GNUNET_TESTING_cmd_rewind_ip (const char *label,
293 const char *target_label,
294 unsigned int counter);
295
296
297/**
298 * Wait until we receive SIGCHLD signal. Then obtain the process trait of the
299 * current command, wait on the the zombie and continue with the next command.
300 *
301 * @param is interpreter state.
302 */
303// void
304// GNUNET_TESTING_wait_for_sigchld (struct GNUNET_TESTING_Interpreter *is);
305// => replace with child_management.c
306
307
308/**
309 * Start scheduling loop with signal handlers and run the
310 * test suite with the @a commands.
311 *
312 * @param cfg_name name of configuration file to use
313 * @param commands the list of command to execute
314 * @param timeout how long to wait for each command to execute
315 * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
316 * non-GNUNET_OK codes are #GNUNET_SYSERR most of the
317 * times.
318 */
319int
320GNUNET_TESTING_run (const char *cfg_filename,
321 struct GNUNET_TESTING_Command *commands,
322 struct GNUNET_TIME_Relative timeout);
323
324
325/**
326 * Look for substring in a programs' name.
327 *
328 * @param prog program's name to look into
329 * @param marker chunk to find in @a prog
330 */
331int
332GNUNET_TESTING_has_in_name (const char *prog,
333 const char *marker);
334
335
336/* ************** Specific interpreter commands ************ */
337
338/**
339 * Create a "signal" CMD.
340 *
341 * @param label command label.
342 * @param process_label label of a command that has a process trait
343 * @param process_index index of the process trait at @a process_label
344 * @param signal signal to send to @a process.
345 * @return the command.
346 */
347struct GNUNET_TESTING_Command
348GNUNET_TESTING_cmd_signal (const char *label,
349 const char *process_label,
350 unsigned int process_index,
351 int signal);
352
353
354/**
355 * Sleep for @a duration.
356 *
357 * @param label command label.
358 * @param duration time to sleep
359 * @return the command.
360 */
361struct GNUNET_TESTING_Command
362GNUNET_TESTING_cmd_sleep (const char *label,
363 struct GNUNET_TIME_Relative duration);
364
365
366/**
367 * Create a "batch" command. Such command takes a end_CMD-terminated array of
368 * CMDs and executed them. Once it hits the end CMD, it passes the control to
369 * the next top-level CMD, regardless of it being another batch or ordinary
370 * CMD.
371 *
372 * @param label the command label.
373 * @param batch array of CMDs to execute.
374 * @return the command.
375 */
376struct GNUNET_TESTING_Command
377GNUNET_TESTING_cmd_batch (const char *label,
378 struct GNUNET_TESTING_Command *batch);
379
380
381/**
382 * Test if this command is a batch command.
383 *
384 * @return false if not, true if it is a batch command
385 */
386// TODO: figure out if this needs to be exposed in the public API.
387int
388GNUNET_TESTING_cmd_is_batch (const struct GNUNET_TESTING_Command *cmd);
389
390
391/**
392 * Advance internal pointer to next command.
393 *
394 * @param is interpreter state.
395 */
396// TODO: figure out if this needs to be exposed in the public API.
397void
398GNUNET_TESTING_cmd_batch_next (struct GNUNET_TESTING_Interpreter *is);
399
400
401/**
402 * Obtain what command the batch is at.
403 *
404 * @return cmd current batch command
405 */
406// TODO: figure out if this needs to be exposed in the public API.
407struct GNUNET_TESTING_Command *
408GNUNET_TESTING_cmd_batch_get_current (const struct GNUNET_TESTING_Command *cmd);
409
410
411/**
412 * Set what command the batch should be at.
413 *
414 * @param cmd current batch command
415 * @param new_ip where to move the IP
416 */
417// TODO: figure out if this needs to be exposed in the public API.
418void
419GNUNET_TESTING_cmd_batch_set_current (const struct GNUNET_TESTING_Command *cmd,
420 unsigned int new_ip);
421
422
423/**
424 * Performance counter.
425 */
426struct GNUNET_TESTING_Timer
427{
428 /**
429 * For which type of commands.
430 */
431 const char *prefix;
432
433 /**
434 * Total time spend in all commands of this type.
435 */
436 struct GNUNET_TIME_Relative total_duration;
437
438 /**
439 * Total time spend waiting for the *successful* exeuction
440 * in all commands of this type.
441 */
442 struct GNUNET_TIME_Relative success_latency;
443
444 /**
445 * Number of commands summed up.
446 */
447 unsigned int num_commands;
448
449 /**
450 * Number of retries summed up.
451 */
452 unsigned int num_retries;
453};
454
455
456/**
457 * Obtain performance data from the interpreter.
458 *
459 * @param timers what commands (by label) to obtain runtimes for
460 * @return the command
461 */
462struct GNUNET_TESTING_Command
463GNUNET_TESTING_cmd_stat (struct GNUNET_TESTING_Timer *timers);
464
465
466/* *** Generic trait logic for implementing traits ********* */
467
468/**
469 * A trait.
470 */
471struct GNUNET_TESTING_Trait
472{
473 /**
474 * Index number associated with the trait. This gives the
475 * possibility to have _multiple_ traits on offer under the
476 * same name.
477 */
478 unsigned int index;
479
480 /**
481 * Trait type, for example "reserve-pub" or "coin-priv".
482 */
483 const char *trait_name;
484
485 /**
486 * Pointer to the piece of data to offer.
487 */
488 const void *ptr;
489};
490
491
492/**
493 * "end" trait. Because traits are offered into arrays,
494 * this type of trait is used to mark the end of such arrays;
495 * useful when iterating over those.
496 */
497struct GNUNET_TESTING_Trait
498GNUNET_TESTING_trait_end (void);
499
500
501/**
502 * Extract a trait.
503 *
504 * @param traits the array of all the traits.
505 * @param[out] ret where to store the result.
506 * @param trait type of the trait to extract.
507 * @param index index number of the trait to extract.
508 * @return #GNUNET_OK when the trait is found.
509 */
510int
511GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits,
512 const void **ret,
513 const char *trait,
514 unsigned int index);
515
516
517/* ****** Specific traits supported by this component ******* */
518
519/**
520 * Obtain location where a command stores a pointer to a process.
521 *
522 * @param cmd command to extract trait from.
523 * @param index which process to pick if @a cmd
524 * has multiple on offer.
525 * @param[out] processp set to the address of the pointer to the
526 * process.
527 * @return #GNUNET_OK on success.
528 */
529int
530GNUNET_TESTING_get_trait_process (const struct GNUNET_TESTING_Command *cmd,
531 unsigned int index,
532 struct GNUNET_OS_Process ***processp);
533
534
535/**
536 * Offer location where a command stores a pointer to a process.
537 *
538 * @param index offered location index number, in case there are
539 * multiple on offer.
540 * @param processp process location to offer.
541 * @return the trait.
542 */
543struct GNUNET_TESTING_Trait
544GNUNET_TESTING_make_trait_process (unsigned int index,
545 struct GNUNET_OS_Process **processp);
546
547
548/**
549 * Offer number trait, 32-bit version.
550 *
551 * @param index the number's index number.
552 * @param n number to offer.
553 */
554struct GNUNET_TESTING_Trait
555GNUNET_TESTING_make_trait_uint32 (unsigned int index,
556 const uint32_t *n);
557
558
559/**
560 * Obtain a "number" value from @a cmd, 32-bit version.
561 *
562 * @param cmd command to extract the number from.
563 * @param index the number's index number.
564 * @param[out] n set to the number coming from @a cmd.
565 * @return #GNUNET_OK on success.
566 */
567int
568GNUNET_TESTING_get_trait_uint32 (const struct GNUNET_TESTING_Command *cmd,
569 unsigned int index,
570 const uint32_t **n);
571
572
573/**
574 * Offer number trait, 64-bit version.
575 *
576 * @param index the number's index number.
577 * @param n number to offer.
578 */
579struct GNUNET_TESTING_Trait
580GNUNET_TESTING_make_trait_uint64 (unsigned int index,
581 const uint64_t *n);
582
583
584/**
585 * Obtain a "number" value from @a cmd, 64-bit version.
586 *
587 * @param cmd command to extract the number from.
588 * @param index the number's index number.
589 * @param[out] n set to the number coming from @a cmd.
590 * @return #GNUNET_OK on success.
591 */
592int
593GNUNET_TESTING_get_trait_uint64 (const struct GNUNET_TESTING_Command *cmd,
594 unsigned int index,
595 const uint64_t **n);
596
597
598/**
599 * Offer number trait, 64-bit signed version.
600 *
601 * @param index the number's index number.
602 * @param n number to offer.
603 */
604struct GNUNET_TESTING_Trait
605GNUNET_TESTING_make_trait_int64 (unsigned int index,
606 const int64_t *n);
607
608
609/**
610 * Obtain a "number" value from @a cmd, 64-bit signed version.
611 *
612 * @param cmd command to extract the number from.
613 * @param index the number's index number.
614 * @param[out] n set to the number coming from @a cmd.
615 * @return #GNUNET_OK on success.
616 */
617int
618GNUNET_TESTING_get_trait_int64 (const struct GNUNET_TESTING_Command *cmd,
619 unsigned int index,
620 const int64_t **n);
621
622
623/**
624 * Offer a number.
625 *
626 * @param index the number's index number.
627 * @param n the number to offer.
628 * @return #GNUNET_OK on success.
629 */
630struct GNUNET_TESTING_Trait
631GNUNET_TESTING_make_trait_uint (unsigned int index,
632 const unsigned int *i);
633
634
635/**
636 * Obtain a number from @a cmd.
637 *
638 * @param cmd command to extract the number from.
639 * @param index the number's index number.
640 * @param[out] n set to the number coming from @a cmd.
641 * @return #GNUNET_OK on success.
642 */
643int
644GNUNET_TESTING_get_trait_uint (const struct GNUNET_TESTING_Command *cmd,
645 unsigned int index,
646 const unsigned int **n);
647
648/**
649 * Obtain a string from @a cmd.
650 *
651 * @param cmd command to extract the subject from.
652 * @param index index number associated with the transfer
653 * subject to offer.
654 * @param[out] s where to write the offered
655 * string.
656 * @return #GNUNET_OK on success.
657 */
658int
659GNUNET_TESTING_get_trait_string (
660 const struct GNUNET_TESTING_Command *cmd,
661 unsigned int index,
662 const char **s);
663
664
665/**
666 * Offer string subject.
667 *
668 * @param index index number associated with the transfer
669 * subject being offered.
670 * @param s string to offer.
671 * @return the trait.
672 */
673struct GNUNET_TESTING_Trait
674GNUNET_TESTING_make_trait_string (unsigned int index,
675 const char *s);
676
677/**
678 * Offer a command in a trait.
679 *
680 * @param index always zero. Commands offering this
681 * kind of traits do not need this index. For
682 * example, a "meta" CMD returns always the
683 * CMD currently being executed.
684 * @param cmd wire details to offer.
685 *
686 * @return the trait.
687 */
688struct GNUNET_TESTING_Trait
689GNUNET_TESTING_make_trait_cmd (unsigned int index,
690 const struct GNUNET_TESTING_Command *cmd);
691
692
693/**
694 * Obtain a command from @a cmd.
695 *
696 * @param cmd command to extract the command from.
697 * @param index always zero. Commands offering this
698 * kind of traits do not need this index. For
699 * example, a "meta" CMD returns always the
700 * CMD currently being executed.
701 * @param[out] _cmd where to write the wire details.
702 * @return #GNUNET_OK on success.
703 */
704int
705GNUNET_TESTING_get_trait_cmd (const struct GNUNET_TESTING_Command *cmd,
706 unsigned int index,
707 struct GNUNET_TESTING_Command **_cmd);
708
709
710/**
711 * Obtain a uuid from @a cmd.
712 *
713 * @param cmd command to extract the uuid from.
714 * @param index which amount to pick if @a cmd has multiple
715 * on offer
716 * @param[out] uuid where to write the uuid.
717 * @return #GNUNET_OK on success.
718 */
719int
720GNUNET_TESTING_get_trait_uuid (const struct GNUNET_TESTING_Command *cmd,
721 unsigned int index,
722 struct GNUNET_Uuid **uuid);
723
724
725/**
726 * Offer a uuid in a trait.
727 *
728 * @param index which uuid to offer, in case there are
729 * multiple available.
730 * @param uuid the uuid to offer.
731 *
732 * @return the trait.
733 */
734struct GNUNET_TESTING_Trait
735GNUNET_TESTING_make_trait_uuid (unsigned int index,
736 const struct GNUNET_Uuid *uuid);
737
738
739/**
740 * Obtain a absolute time from @a cmd.
741 *
742 * @param cmd command to extract trait from
743 * @param index which time stamp to pick if
744 * @a cmd has multiple on offer.
745 * @param[out] time set to the wanted WTID.
746 * @return #GNUNET_OK on success
747 */
748int
749GNUNET_TESTING_get_trait_absolute_time (
750 const struct GNUNET_TESTING_Command *cmd,
751 unsigned int index,
752 const struct GNUNET_TIME_Absolute **time);
753
754
755/**
756 * Offer a absolute time.
757 *
758 * @param index associate the object with this index
759 * @param time which object should be returned
760 * @return the trait.
761 */
762struct GNUNET_TESTING_Trait
763GNUNET_TESTING_make_trait_absolute_time (
764 unsigned int index,
765 const struct GNUNET_TIME_Absolute *time);
766
767
768/**
769 * Obtain a relative time from @a cmd.
770 *
771 * @param cmd command to extract trait from
772 * @param index which time to pick if
773 * @a cmd has multiple on offer.
774 * @param[out] time set to the wanted WTID.
775 * @return #GNUNET_OK on success
776 */
777int
778GNUNET_TESTING_get_trait_relative_time (
779 const struct GNUNET_TESTING_Command *cmd,
780 unsigned int index,
781 const struct GNUNET_TIME_Relative **time);
782
783
784/**
785 * Offer a relative time.
786 *
787 * @param index associate the object with this index
788 * @param time which object should be returned
789 * @return the trait.
790 */
791struct GNUNET_TESTING_Trait
792GNUNET_TESTING_make_trait_relative_time (
793 unsigned int index,
794 const struct GNUNET_TIME_Relative *time);
795
796
797/**
798 * Create command.
799 *
800 * @param label name for command.
801 * @param now when the command was started.
802 * @return command.
803 */
804struct GNUNET_TESTING_Command
805GNUNET_TESTING_cmd_hello_world_birth (const char *label,
806 struct GNUNET_TIME_Absolute *now);
807
808/**
809 * Create command.
810 *
811 * @param label name for command.
812 * @param message initial message.
813 * @return command.
814 */
815struct GNUNET_TESTING_Command
816GNUNET_TESTING_cmd_hello_world (const char *label,
817 const char *birthLabel,
818 char *message);
819
820/**
821 * Offer data from trait
822 *
823 * @param cmd command to extract the url from.
824 * @param pt which url is to be picked, in case
825 * multiple are offered.
826 * @param[out] url where to write the url.
827 * @return #GNUNET_OK on success.
828 */
829int
830GNUNET_TESTING_get_trait_what_am_i (const struct GNUNET_TESTING_Command *cmd,
831 char **what_am_i);
832
833#endif
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 621487f0a..32b262a87 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -28,9 +28,6 @@
28#include "gnunet_json_lib.h" 28#include "gnunet_json_lib.h"
29 29
30 30
31/**
32 * End of a parser specification.
33 */
34struct GNUNET_JSON_Specification 31struct GNUNET_JSON_Specification
35GNUNET_JSON_spec_end () 32GNUNET_JSON_spec_end ()
36{ 33{
@@ -84,14 +81,6 @@ parse_fixed_data (void *cls,
84} 81}
85 82
86 83
87/**
88 * Variable size object (in network byte order, encoded using Crockford
89 * Base32hex encoding).
90 *
91 * @param name name of the JSON field
92 * @param[out] obj pointer where to write the data, must have @a size bytes
93 * @param size number of bytes expected in @a obj
94 */
95struct GNUNET_JSON_Specification 84struct GNUNET_JSON_Specification
96GNUNET_JSON_spec_fixed (const char *name, 85GNUNET_JSON_spec_fixed (const char *name,
97 void *obj, 86 void *obj,
@@ -168,6 +157,7 @@ static void
168clean_variable_data (void *cls, 157clean_variable_data (void *cls,
169 struct GNUNET_JSON_Specification *spec) 158 struct GNUNET_JSON_Specification *spec)
170{ 159{
160 (void) cls;
171 if (0 != *spec->size_ptr) 161 if (0 != *spec->size_ptr)
172 { 162 {
173 GNUNET_free (*(void **) spec->ptr); 163 GNUNET_free (*(void **) spec->ptr);
@@ -177,14 +167,6 @@ clean_variable_data (void *cls,
177} 167}
178 168
179 169
180/**
181 * Variable size object (in network byte order, encoded using
182 * Crockford Base32hex encoding).
183 *
184 * @param name name of the JSON field
185 * @param[out] obj pointer where to write the data, will be allocated
186 * @param[out] size where to store the number of bytes allocated for @a obj
187 */
188struct GNUNET_JSON_Specification 170struct GNUNET_JSON_Specification
189GNUNET_JSON_spec_varsize (const char *name, 171GNUNET_JSON_spec_varsize (const char *name,
190 void **obj, 172 void **obj,
@@ -221,6 +203,7 @@ parse_string (void *cls,
221{ 203{
222 const char *str; 204 const char *str;
223 205
206 (void) cls;
224 str = json_string_value (root); 207 str = json_string_value (root);
225 if (NULL == str) 208 if (NULL == str)
226 { 209 {
@@ -232,12 +215,6 @@ parse_string (void *cls,
232} 215}
233 216
234 217
235/**
236 * The expected field stores a string.
237 *
238 * @param name name of the JSON field
239 * @param strptr where to store a pointer to the field
240 */
241struct GNUNET_JSON_Specification 218struct GNUNET_JSON_Specification
242GNUNET_JSON_spec_string (const char *name, 219GNUNET_JSON_spec_string (const char *name,
243 const char **strptr) 220 const char **strptr)
@@ -301,12 +278,6 @@ clean_object (void *cls,
301} 278}
302 279
303 280
304/**
305 * JSON object.
306 *
307 * @param name name of the JSON field
308 * @param[out] jsonp where to store the JSON found under @a name
309 */
310struct GNUNET_JSON_Specification 281struct GNUNET_JSON_Specification
311GNUNET_JSON_spec_json (const char *name, 282GNUNET_JSON_spec_json (const char *name,
312 json_t **jsonp) 283 json_t **jsonp)
@@ -356,12 +327,6 @@ parse_bool (void *cls,
356} 327}
357 328
358 329
359/**
360 * boolean.
361 *
362 * @param name name of the JSON field
363 * @param[out] b where to store the boolean found under @a name
364 */
365struct GNUNET_JSON_Specification 330struct GNUNET_JSON_Specification
366GNUNET_JSON_spec_bool (const char *name, 331GNUNET_JSON_spec_bool (const char *name,
367 bool *b) 332 bool *b)
@@ -412,12 +377,6 @@ parse_u8 (void *cls,
412} 377}
413 378
414 379
415/**
416 * 8-bit integer.
417 *
418 * @param name name of the JSON field
419 * @param[out] u8 where to store the integer found under @a name
420 */
421struct GNUNET_JSON_Specification 380struct GNUNET_JSON_Specification
422GNUNET_JSON_spec_uint8 (const char *name, 381GNUNET_JSON_spec_uint8 (const char *name,
423 uint8_t *u8) 382 uint8_t *u8)
@@ -468,12 +427,6 @@ parse_u16 (void *cls,
468} 427}
469 428
470 429
471/**
472 * 16-bit integer.
473 *
474 * @param name name of the JSON field
475 * @param[out] u16 where to store the integer found under @a name
476 */
477struct GNUNET_JSON_Specification 430struct GNUNET_JSON_Specification
478GNUNET_JSON_spec_uint16 (const char *name, 431GNUNET_JSON_spec_uint16 (const char *name,
479 uint16_t *u16) 432 uint16_t *u16)
@@ -524,12 +477,6 @@ parse_u32 (void *cls,
524} 477}
525 478
526 479
527/**
528 * 32-bit integer.
529 *
530 * @param name name of the JSON field
531 * @param[out] u32 where to store the integer found under @a name
532 */
533struct GNUNET_JSON_Specification 480struct GNUNET_JSON_Specification
534GNUNET_JSON_spec_uint32 (const char *name, 481GNUNET_JSON_spec_uint32 (const char *name,
535 uint32_t *u32) 482 uint32_t *u32)
@@ -575,12 +522,6 @@ parse_u64 (void *cls,
575} 522}
576 523
577 524
578/**
579 * 64-bit integer.
580 *
581 * @param name name of the JSON field
582 * @param[out] u64 where to store the integer found under @a name
583 */
584struct GNUNET_JSON_Specification 525struct GNUNET_JSON_Specification
585GNUNET_JSON_spec_uint64 (const char *name, 526GNUNET_JSON_spec_uint64 (const char *name,
586 uint64_t *u64) 527 uint64_t *u64)
@@ -626,12 +567,6 @@ parse_i64 (void *cls,
626} 567}
627 568
628 569
629/**
630 * 64-bit signed integer.
631 *
632 * @param name name of the JSON field
633 * @param[out] i64 where to store the integer found under @a name
634 */
635struct GNUNET_JSON_Specification 570struct GNUNET_JSON_Specification
636GNUNET_JSON_spec_int64 (const char *name, 571GNUNET_JSON_spec_int64 (const char *name,
637 int64_t *i64) 572 int64_t *i64)
@@ -705,12 +640,6 @@ parse_abs_time (void *cls,
705} 640}
706 641
707 642
708/**
709 * Absolute time.
710 *
711 * @param name name of the JSON field
712 * @param[out] at where to store the absolute time found under @a name
713 */
714struct GNUNET_JSON_Specification 643struct GNUNET_JSON_Specification
715GNUNET_JSON_spec_absolute_time (const char *name, 644GNUNET_JSON_spec_absolute_time (const char *name,
716 struct GNUNET_TIME_Absolute *at) 645 struct GNUNET_TIME_Absolute *at)
@@ -759,12 +688,6 @@ parse_abs_time_nbo (void *cls,
759} 688}
760 689
761 690
762/**
763 * Absolute time in network byte order.
764 *
765 * @param name name of the JSON field
766 * @param[out] at where to store the absolute time found under @a name
767 */
768struct GNUNET_JSON_Specification 691struct GNUNET_JSON_Specification
769GNUNET_JSON_spec_absolute_time_nbo (const char *name, 692GNUNET_JSON_spec_absolute_time_nbo (const char *name,
770 struct GNUNET_TIME_AbsoluteNBO *at) 693 struct GNUNET_TIME_AbsoluteNBO *at)
@@ -836,12 +759,6 @@ parse_rel_time (void *cls,
836} 759}
837 760
838 761
839/**
840 * Relative time.
841 *
842 * @param name name of the JSON field
843 * @param[out] rt where to store the relative time found under @a name
844 */
845struct GNUNET_JSON_Specification 762struct GNUNET_JSON_Specification
846GNUNET_JSON_spec_relative_time (const char *name, 763GNUNET_JSON_spec_relative_time (const char *name,
847 struct GNUNET_TIME_Relative *rt) 764 struct GNUNET_TIME_Relative *rt)
@@ -929,12 +846,6 @@ clean_rsa_public_key (void *cls,
929} 846}
930 847
931 848
932/**
933 * Specification for parsing an RSA public key.
934 *
935 * @param name name of the JSON field
936 * @param pk where to store the RSA key found under @a name
937 */
938struct GNUNET_JSON_Specification 849struct GNUNET_JSON_Specification
939GNUNET_JSON_spec_rsa_public_key (const char *name, 850GNUNET_JSON_spec_rsa_public_key (const char *name,
940 struct GNUNET_CRYPTO_RsaPublicKey **pk) 851 struct GNUNET_CRYPTO_RsaPublicKey **pk)
@@ -1023,12 +934,6 @@ clean_rsa_signature (void *cls,
1023} 934}
1024 935
1025 936
1026/**
1027 * Specification for parsing an RSA signature.
1028 *
1029 * @param name name of the JSON field
1030 * @param sig where to store the RSA signature found under @a name
1031 */
1032struct GNUNET_JSON_Specification 937struct GNUNET_JSON_Specification
1033GNUNET_JSON_spec_rsa_signature (const char *name, 938GNUNET_JSON_spec_rsa_signature (const char *name,
1034 struct GNUNET_CRYPTO_RsaSignature **sig) 939 struct GNUNET_CRYPTO_RsaSignature **sig)
@@ -1073,12 +978,6 @@ parse_boolean (void *cls,
1073} 978}
1074 979
1075 980
1076/**
1077 * Boolean (true mapped to GNUNET_YES, false mapped to GNUNET_NO).
1078 *
1079 * @param name name of the JSON field
1080 * @param[out] boolean where to store the boolean found under @a name
1081 */
1082struct GNUNET_JSON_Specification 981struct GNUNET_JSON_Specification
1083GNUNET_JSON_spec_boolean (const char *name, 982GNUNET_JSON_spec_boolean (const char *name,
1084 int *boolean) 983 int *boolean)
diff --git a/src/messenger/.gitignore b/src/messenger/.gitignore
index 9de3fb304..ed78c5562 100644
--- a/src/messenger/.gitignore
+++ b/src/messenger/.gitignore
@@ -2,3 +2,13 @@ gnunet-service-messenger
2gnunet-messenger 2gnunet-messenger
3test_messenger_api 3test_messenger_api
4test_messenger_anonymous 4test_messenger_anonymous
5test_messenger_sync_client
6test_messenger_async_client
7test_messenger_worst_client
8test_messenger_sync_p2p
9test_messenger_async_p2p
10test_messenger_worst_p2p
11test_messenger_server
12test_messenger_growth
13test_messenger_ring
14test_messenger_adapt
diff --git a/src/messenger/Makefile.am b/src/messenger/Makefile.am
index d9694420b..3fc532e7e 100644
--- a/src/messenger/Makefile.am
+++ b/src/messenger/Makefile.am
@@ -25,32 +25,23 @@ bin_PROGRAMS = \
25 gnunet-messenger 25 gnunet-messenger
26 26
27lib_LTLIBRARIES = \ 27lib_LTLIBRARIES = \
28 libgnunetmessenger_common.la \
29 libgnunetmessenger.la \ 28 libgnunetmessenger.la \
30 $(EXP_LIB) 29 $(EXP_LIB)
31 30
32libgnunetmessenger_common_la_SOURCES = \
33 messenger_api_ego.h \
34 messenger_api_message.c messenger_api_message.h \
35 messenger_api_list_tunnels.c messenger_api_list_tunnels.h
36libgnunetmessenger_common_la_LIBADD = \
37 $(top_builddir)/src/util/libgnunetutil.la \
38 $(top_builddir)/src/identity/libgnunetidentity.la \
39 $(XLIB) \
40 $(LTLIBINTL)
41libgnunetmessenger_common_la_LDFLAGS = \
42 $(GN_LIB_LDFLAGS) \
43 -version-info 0:0:0
44
45libgnunetmessenger_la_SOURCES = \ 31libgnunetmessenger_la_SOURCES = \
46 messenger_api.c \ 32 messenger_api.c \
33 messenger_api_ego.h \
47 messenger_api_contact.c messenger_api_contact.h \ 34 messenger_api_contact.c messenger_api_contact.h \
35 messenger_api_contact_store.c messenger_api_contact_store.h \
36 messenger_api_message.c messenger_api_message.h \
37 messenger_api_list_tunnels.c messenger_api_list_tunnels.h \
38 messenger_api_util.c messenger_api_util.h \
48 messenger_api_handle.c messenger_api_handle.h \ 39 messenger_api_handle.c messenger_api_handle.h \
49 messenger_api_room.c messenger_api_room.h 40 messenger_api_room.c messenger_api_room.h
50libgnunetmessenger_la_LIBADD = \ 41libgnunetmessenger_la_LIBADD = \
51 $(top_builddir)/src/util/libgnunetutil.la \ 42 $(top_builddir)/src/util/libgnunetutil.la \
43 $(top_builddir)/src/cadet/libgnunetcadet.la \
52 $(top_builddir)/src/identity/libgnunetidentity.la \ 44 $(top_builddir)/src/identity/libgnunetidentity.la \
53 libgnunetmessenger_common.la \
54 $(XLIB) \ 45 $(XLIB) \
55 $(LTLIBINTL) 46 $(LTLIBINTL)
56libgnunetmessenger_la_LDFLAGS = \ 47libgnunetmessenger_la_LDFLAGS = \
@@ -60,10 +51,8 @@ libgnunetmessenger_la_LDFLAGS = \
60gnunet_messenger_SOURCES = \ 51gnunet_messenger_SOURCES = \
61 gnunet-messenger.c 52 gnunet-messenger.c
62gnunet_messenger_LDADD = \ 53gnunet_messenger_LDADD = \
63 libgnunetmessenger_common.la \
64 libgnunetmessenger.la \ 54 libgnunetmessenger.la \
65 $(top_builddir)/src/util/libgnunetutil.la \ 55 $(top_builddir)/src/util/libgnunetutil.la
66 $(top_builddir)/src/identity/libgnunetidentity.la
67gnunet_messenger_LDFLAGS = \ 56gnunet_messenger_LDFLAGS = \
68 $(GN_LIBINTL) 57 $(GN_LIBINTL)
69 58
@@ -72,29 +61,42 @@ gnunet_service_messenger_SOURCES = \
72 gnunet-service-messenger_service.c gnunet-service-messenger_service.h \ 61 gnunet-service-messenger_service.c gnunet-service-messenger_service.h \
73 gnunet-service-messenger_list_handles.c gnunet-service-messenger_list_handles.h \ 62 gnunet-service-messenger_list_handles.c gnunet-service-messenger_list_handles.h \
74 gnunet-service-messenger_list_messages.c gnunet-service-messenger_list_messages.h \ 63 gnunet-service-messenger_list_messages.c gnunet-service-messenger_list_messages.h \
64 gnunet-service-messenger_member_session.c gnunet-service-messenger_member_session.h \
65 gnunet-service-messenger_member.c gnunet-service-messenger_member.h \
66 gnunet-service-messenger_member_store.c gnunet-service-messenger_member_store.h \
75 gnunet-service-messenger_message_handle.c gnunet-service-messenger_message_handle.h \ 67 gnunet-service-messenger_message_handle.c gnunet-service-messenger_message_handle.h \
76 gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \ 68 gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \
77 gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \ 69 gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \
78 gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \ 70 gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \
71 gnunet-service-messenger_message_state.c gnunet-service-messenger_message_state.h \
79 gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \ 72 gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \
73 gnunet-service-messenger_operation_store.c gnunet-service-messenger_operation_store.h \
74 gnunet-service-messenger_operation.c gnunet-service-messenger_operation.h \
80 gnunet-service-messenger_basement.c gnunet-service-messenger_basement.h \ 75 gnunet-service-messenger_basement.c gnunet-service-messenger_basement.h \
81 gnunet-service-messenger_contact.c gnunet-service-messenger_contact.h \ 76 gnunet-service-messenger_ego_store.c gnunet-service-messenger_ego_store.h \
82 gnunet-service-messenger_handle.c gnunet-service-messenger_handle.h \ 77 gnunet-service-messenger_handle.c gnunet-service-messenger_handle.h \
83 gnunet-service-messenger_room.c gnunet-service-messenger_room.h \ 78 gnunet-service-messenger_room.c gnunet-service-messenger_room.h \
84 gnunet-service-messenger_tunnel.c gnunet-service-messenger_tunnel.h \ 79 gnunet-service-messenger_tunnel.c gnunet-service-messenger_tunnel.h
85 gnunet-service-messenger_util.c gnunet-service-messenger_util.h
86gnunet_service_messenger_LDADD = \ 80gnunet_service_messenger_LDADD = \
81 libgnunetmessenger.la \
87 $(top_builddir)/src/util/libgnunetutil.la \ 82 $(top_builddir)/src/util/libgnunetutil.la \
88 $(top_builddir)/src/cadet/libgnunetcadet.la \ 83 $(top_builddir)/src/cadet/libgnunetcadet.la \
89 $(top_builddir)/src/identity/libgnunetidentity.la \ 84 $(top_builddir)/src/identity/libgnunetidentity.la \
90 libgnunetmessenger_common.la \
91 libgnunetmessenger.la \
92 $(GN_LIBINTL) 85 $(GN_LIBINTL)
93 86
94check_PROGRAMS = \ 87check_PROGRAMS = \
95 test_messenger_api \ 88 test_messenger_api \
96 test_messenger_anonymous \ 89 test_messenger_anonymous \
97 test_messenger_comm0 90 test_messenger_sync_client \
91 test_messenger_async_client \
92 test_messenger_worst_client \
93 test_messenger_sync_p2p \
94 test_messenger_async_p2p \
95 test_messenger_worst_p2p \
96 test_messenger_server \
97 test_messenger_growth \
98 test_messenger_ring \
99 test_messenger_adapt
98 100
99if ENABLE_TEST_RUN 101if ENABLE_TEST_RUN
100AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 102AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
@@ -105,7 +107,6 @@ endif
105test_messenger_api_SOURCES = \ 107test_messenger_api_SOURCES = \
106 test_messenger.c 108 test_messenger.c
107test_messenger_api_LDADD = \ 109test_messenger_api_LDADD = \
108 libgnunetmessenger_common.la \
109 libgnunetmessenger.la \ 110 libgnunetmessenger.la \
110 $(top_builddir)/src/testing/libgnunettesting.la \ 111 $(top_builddir)/src/testing/libgnunettesting.la \
111 $(top_builddir)/src/util/libgnunetutil.la 112 $(top_builddir)/src/util/libgnunetutil.la
@@ -113,18 +114,107 @@ test_messenger_api_LDADD = \
113test_messenger_anonymous_SOURCES = \ 114test_messenger_anonymous_SOURCES = \
114 test_messenger_anonymous.c 115 test_messenger_anonymous.c
115test_messenger_anonymous_LDADD = \ 116test_messenger_anonymous_LDADD = \
116 libgnunetmessenger_common.la \
117 libgnunetmessenger.la \ 117 libgnunetmessenger.la \
118 $(top_builddir)/src/testing/libgnunettesting.la \ 118 $(top_builddir)/src/testing/libgnunettesting.la \
119 $(top_builddir)/src/util/libgnunetutil.la 119 $(top_builddir)/src/util/libgnunetutil.la
120 120
121test_messenger_comm0_SOURCES = \ 121test_messenger_sync_client_SOURCES = \
122 test_messenger_comm0.c 122 test_messenger_sync_client.c \
123test_messenger_comm0_LDADD = \ 123 testing_messenger_barrier.c testing_messenger_barrier.h \
124 libgnunetmessenger_common.la \ 124 testing_messenger_setup.c testing_messenger_setup.h
125test_messenger_sync_client_LDADD = \
126 libgnunetmessenger.la \
127 $(top_builddir)/src/testbed/libgnunettestbed.la \
128 $(top_builddir)/src/testing/libgnunettesting.la \
129 $(top_builddir)/src/util/libgnunetutil.la
130
131test_messenger_async_client_SOURCES = \
132 test_messenger_async_client.c \
133 testing_messenger_barrier.c testing_messenger_barrier.h \
134 testing_messenger_setup.c testing_messenger_setup.h
135test_messenger_async_client_LDADD = \
136 libgnunetmessenger.la \
137 $(top_builddir)/src/testbed/libgnunettestbed.la \
138 $(top_builddir)/src/testing/libgnunettesting.la \
139 $(top_builddir)/src/util/libgnunetutil.la
140
141test_messenger_worst_client_SOURCES = \
142 test_messenger_worst_client.c \
143 testing_messenger_barrier.c testing_messenger_barrier.h \
144 testing_messenger_setup.c testing_messenger_setup.h
145test_messenger_worst_client_LDADD = \
146 libgnunetmessenger.la \
147 $(top_builddir)/src/testbed/libgnunettestbed.la \
148 $(top_builddir)/src/testing/libgnunettesting.la \
149 $(top_builddir)/src/util/libgnunetutil.la
150
151test_messenger_sync_p2p_SOURCES = \
152 test_messenger_sync_p2p.c \
153 testing_messenger_barrier.c testing_messenger_barrier.h \
154 testing_messenger_setup.c testing_messenger_setup.h
155test_messenger_sync_p2p_LDADD = \
156 libgnunetmessenger.la \
157 $(top_builddir)/src/testbed/libgnunettestbed.la \
158 $(top_builddir)/src/testing/libgnunettesting.la \
159 $(top_builddir)/src/util/libgnunetutil.la
160
161test_messenger_async_p2p_SOURCES = \
162 test_messenger_async_p2p.c \
163 testing_messenger_barrier.c testing_messenger_barrier.h \
164 testing_messenger_setup.c testing_messenger_setup.h
165test_messenger_async_p2p_LDADD = \
166 libgnunetmessenger.la \
167 $(top_builddir)/src/testbed/libgnunettestbed.la \
168 $(top_builddir)/src/testing/libgnunettesting.la \
169 $(top_builddir)/src/util/libgnunetutil.la
170
171test_messenger_worst_p2p_SOURCES = \
172 test_messenger_worst_p2p.c \
173 testing_messenger_barrier.c testing_messenger_barrier.h \
174 testing_messenger_setup.c testing_messenger_setup.h
175test_messenger_worst_p2p_LDADD = \
176 libgnunetmessenger.la \
177 $(top_builddir)/src/testbed/libgnunettestbed.la \
178 $(top_builddir)/src/testing/libgnunettesting.la \
179 $(top_builddir)/src/util/libgnunetutil.la
180
181test_messenger_server_SOURCES = \
182 test_messenger_server.c \
183 testing_messenger_barrier.c testing_messenger_barrier.h \
184 testing_messenger_setup.c testing_messenger_setup.h
185test_messenger_server_LDADD = \
186 libgnunetmessenger.la \
187 $(top_builddir)/src/testbed/libgnunettestbed.la \
188 $(top_builddir)/src/testing/libgnunettesting.la \
189 $(top_builddir)/src/util/libgnunetutil.la
190
191test_messenger_growth_SOURCES = \
192 test_messenger_growth.c \
193 testing_messenger_barrier.c testing_messenger_barrier.h \
194 testing_messenger_setup.c testing_messenger_setup.h
195test_messenger_growth_LDADD = \
196 libgnunetmessenger.la \
197 $(top_builddir)/src/testbed/libgnunettestbed.la \
198 $(top_builddir)/src/testing/libgnunettesting.la \
199 $(top_builddir)/src/util/libgnunetutil.la
200
201test_messenger_ring_SOURCES = \
202 test_messenger_ring.c \
203 testing_messenger_barrier.c testing_messenger_barrier.h \
204 testing_messenger_setup.c testing_messenger_setup.h
205test_messenger_ring_LDADD = \
206 libgnunetmessenger.la \
207 $(top_builddir)/src/testbed/libgnunettestbed.la \
208 $(top_builddir)/src/testing/libgnunettesting.la \
209 $(top_builddir)/src/util/libgnunetutil.la
210
211test_messenger_adapt_SOURCES = \
212 test_messenger_adapt.c \
213 testing_messenger_barrier.c testing_messenger_barrier.h \
214 testing_messenger_setup.c testing_messenger_setup.h
215test_messenger_adapt_LDADD = \
125 libgnunetmessenger.la \ 216 libgnunetmessenger.la \
126 $(top_builddir)/src/testbed/libgnunettestbed.la \ 217 $(top_builddir)/src/testbed/libgnunettestbed.la \
127 $(top_builddir)/src/testbed-logger/libgnunettestbedlogger.la \
128 $(top_builddir)/src/testing/libgnunettesting.la \ 218 $(top_builddir)/src/testing/libgnunettesting.la \
129 $(top_builddir)/src/util/libgnunetutil.la 219 $(top_builddir)/src/util/libgnunetutil.la
130 220
diff --git a/src/messenger/gnunet-messenger.c b/src/messenger/gnunet-messenger.c
index 579e5c3ad..094ae398d 100644..100755
--- a/src/messenger/gnunet-messenger.c
+++ b/src/messenger/gnunet-messenger.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -34,29 +34,38 @@ struct GNUNET_MESSENGER_Handle *messenger;
34/** 34/**
35 * Function called whenever a message is received or sent. 35 * Function called whenever a message is received or sent.
36 * 36 *
37 * @param cls Closure 37 * @param[in/out] cls Closure
38 * @param room Room 38 * @param[in] room Room
39 * @param message Message 39 * @param[in] sender Sender of message
40 * @param hash Hash of message 40 * @param[in] message Message
41 * @param[in] hash Hash of message
42 * @param[in] flags Flags of message
41 */ 43 */
42void 44void
43on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 45on_message (void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *sender,
44 const struct GNUNET_HashCode *hash) 46 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
47 enum GNUNET_MESSENGER_MessageFlags flags)
45{ 48{
46 struct GNUNET_MESSENGER_Contact *sender = GNUNET_MESSENGER_get_member (room, &(message->header.sender_id));
47
48 const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender); 49 const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender);
49 50
50 if (!sender_name) 51 if (!sender_name)
51 sender_name = "anonymous"; 52 sender_name = "anonymous";
52 53
54 printf ("[%s] ", GNUNET_sh2s(&(message->header.sender_id)));
55
56 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
57 printf ("*");
58
53 switch (message->header.kind) 59 switch (message->header.kind)
54 { 60 {
55 case GNUNET_MESSENGER_KIND_JOIN: 61 case GNUNET_MESSENGER_KIND_JOIN:
56 { 62 {
57 printf ("* '%s' joined the room! [ %u %u %u %u ]\n", sender_name, message->body.join.key.ecdsa_key.q_y[0], 63 printf ("* '%s' joined the room!\n", sender_name);
58 message->body.join.key.ecdsa_key.q_y[1], message->body.join.key.ecdsa_key.q_y[2], 64 break;
59 message->body.join.key.ecdsa_key.q_y[3]); 65 }
66 case GNUNET_MESSENGER_KIND_NAME:
67 {
68 printf ("* '%s' gets renamed to '%s'\n", sender_name, message->body.name.name);
60 break; 69 break;
61 } 70 }
62 case GNUNET_MESSENGER_KIND_LEAVE: 71 case GNUNET_MESSENGER_KIND_LEAVE:
@@ -76,6 +85,7 @@ on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GN
76 } 85 }
77 default: 86 default:
78 { 87 {
88 printf ("~ message: %s\n", GNUNET_MESSENGER_name_of_kind(message->header.kind));
79 break; 89 break;
80 } 90 }
81 } 91 }
@@ -86,7 +96,7 @@ struct GNUNET_SCHEDULER_Task *read_task;
86/** 96/**
87 * Task to shut down this application. 97 * Task to shut down this application.
88 * 98 *
89 * @param cls Closure 99 * @param[in/out] cls Closure
90 */ 100 */
91static void 101static void
92shutdown_hook (void *cls) 102shutdown_hook (void *cls)
@@ -108,10 +118,24 @@ listen_stdio (void *cls);
108 118
109#define MAX_BUFFER_SIZE 60000 119#define MAX_BUFFER_SIZE 60000
110 120
121static int
122iterate_send_private_message (void *cls, struct GNUNET_MESSENGER_Room *room,
123 const struct GNUNET_MESSENGER_Contact *contact)
124{
125 struct GNUNET_MESSENGER_Message *message = cls;
126
127 if (GNUNET_MESSENGER_contact_get_key(contact))
128 GNUNET_MESSENGER_send_message (room, message, contact);
129
130 return GNUNET_YES;
131}
132
133int private_mode;
134
111/** 135/**
112 * Task run in stdio mode, after some data is available at stdin. 136 * Task run in stdio mode, after some data is available at stdin.
113 * 137 *
114 * @param cls Closure 138 * @param[in/out] cls Closure
115 */ 139 */
116static void 140static void
117read_stdio (void *cls) 141read_stdio (void *cls)
@@ -140,7 +164,10 @@ read_stdio (void *cls)
140 message.header.kind = GNUNET_MESSENGER_KIND_TEXT; 164 message.header.kind = GNUNET_MESSENGER_KIND_TEXT;
141 message.body.text.text = buffer; 165 message.body.text.text = buffer;
142 166
143 GNUNET_MESSENGER_send_message (room, &message); 167 if (GNUNET_YES == private_mode)
168 GNUNET_MESSENGER_iterate_members(room, iterate_send_private_message, &message);
169 else
170 GNUNET_MESSENGER_send_message (room, &message, NULL);
144 171
145 read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls); 172 read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls);
146} 173}
@@ -148,7 +175,7 @@ read_stdio (void *cls)
148/** 175/**
149 * Wait for input on STDIO and send it out over the #ch. 176 * Wait for input on STDIO and send it out over the #ch.
150 * 177 *
151 * @param cls Closure 178 * @param[in/out] cls Closure
152 */ 179 */
153static void 180static void
154listen_stdio (void *cls) 181listen_stdio (void *cls)
@@ -160,10 +187,8 @@ listen_stdio (void *cls)
160 GNUNET_NETWORK_fdset_set_native (rs, 0); 187 GNUNET_NETWORK_fdset_set_native (rs, 0);
161 188
162 read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 189 read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
163 GNUNET_TIME_UNIT_FOREVER_REL, 190 GNUNET_TIME_UNIT_FOREVER_REL, rs,
164 rs, 191 NULL, &read_stdio, cls);
165 NULL,
166 &read_stdio, cls);
167 192
168 GNUNET_NETWORK_fdset_destroy (rs); 193 GNUNET_NETWORK_fdset_destroy (rs);
169} 194}
@@ -171,7 +196,7 @@ listen_stdio (void *cls)
171/** 196/**
172 * Initial task to startup application. 197 * Initial task to startup application.
173 * 198 *
174 * @param cls Closure 199 * @param[in/out] cls Closure
175 */ 200 */
176static void 201static void
177idle (void *cls) 202idle (void *cls)
@@ -192,8 +217,8 @@ struct GNUNET_SCHEDULER_Task *shutdown_task;
192/** 217/**
193 * Function called when an identity is retrieved. 218 * Function called when an identity is retrieved.
194 * 219 *
195 * @param cls Closure 220 * @param[in/out] cls Closure
196 * @param handle Handle of messenger service 221 * @param[in/out] handle Handle of messenger service
197 */ 222 */
198static void 223static void
199on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle) 224on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
@@ -204,18 +229,12 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
204 if (room_key) 229 if (room_key)
205 GNUNET_CRYPTO_hash (room_key, strlen (room_key), &key); 230 GNUNET_CRYPTO_hash (room_key, strlen (room_key), &key);
206 231
232 struct GNUNET_PeerIdentity door_peer;
207 struct GNUNET_PeerIdentity *door = NULL; 233 struct GNUNET_PeerIdentity *door = NULL;
208 234
209 if (door_id) 235 if ((door_id) &&
210 { 236 (GNUNET_OK == GNUNET_CRYPTO_eddsa_public_key_from_string (door_id, strlen (door_id), &(door_peer.public_key))))
211 door = GNUNET_new(struct GNUNET_PeerIdentity); 237 door = &door_peer;
212
213 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (door_id, strlen (door_id), &(door->public_key)))
214 {
215 GNUNET_free(door);
216 door = NULL;
217 }
218 }
219 238
220 const char *name = GNUNET_MESSENGER_get_name (handle); 239 const char *name = GNUNET_MESSENGER_get_name (handle);
221 240
@@ -230,7 +249,7 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
230 { 249 {
231 printf ("* You try to entry a room...\n"); 250 printf ("* You try to entry a room...\n");
232 251
233 room = GNUNET_MESSENGER_entry_room (messenger, door, &key); 252 room = GNUNET_MESSENGER_enter_room (messenger, door, &key);
234 } 253 }
235 else 254 else
236 { 255 {
@@ -246,17 +265,26 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
246 if (!room) 265 if (!room)
247 GNUNET_SCHEDULER_shutdown (); 266 GNUNET_SCHEDULER_shutdown ();
248 else 267 else
268 {
269 struct GNUNET_MESSENGER_Message message;
270 message.header.kind = GNUNET_MESSENGER_KIND_NAME;
271 message.body.name.name = GNUNET_strdup(name);
272
273 GNUNET_MESSENGER_send_message (room, &message, NULL);
274 GNUNET_free(message.body.name.name);
275
249 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_IDLE, idle, 276 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_IDLE, idle,
250 room); 277 room);
278 }
251} 279}
252 280
253/** 281/**
254 * Main function that will be run by the scheduler. 282 * Main function that will be run by the scheduler.
255 * 283 *
256 * @param cls closure 284 * @param[in/out] cls closure
257 * @param args remaining command-line arguments 285 * @param[in] args remaining command-line arguments
258 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 286 * @param[in] cfgfile name of the configuration file used (for saving, can be NULL!)
259 * @param cfg configuration 287 * @param[in] cfg configuration
260 */ 288 */
261static void 289static void
262run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) 290run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
@@ -269,38 +297,24 @@ run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFI
269/** 297/**
270 * The main function to obtain messenger information. 298 * The main function to obtain messenger information.
271 * 299 *
272 * @param argc number of arguments from the command line 300 * @param[in] argc number of arguments from the command line
273 * @param argv command line arguments 301 * @param[in] argv command line arguments
274 * @return 0 ok, 1 on error 302 * @return #EXIT_SUCCESS ok, #EXIT_FAILURE on error
275 */ 303 */
276int 304int
277main (int argc, char **argv) 305main (int argc, char **argv)
278{ 306{
279 const char *description = "Open and connect to rooms using the MESSENGER to chat."; 307 const char *description = "Open and connect to rooms using the MESSENGER to chat.";
280 308
281 struct GNUNET_GETOPT_CommandLineOption options[] = { 309 struct GNUNET_GETOPT_CommandLineOption options[] =
282 GNUNET_GETOPT_option_string ('d', 310 {
283 "door", 311 GNUNET_GETOPT_option_string ('d', "door", "PEERIDENTITY", "peer identity to entry into the room", &door_id),
284 "PEERIDENTITY", 312 GNUNET_GETOPT_option_string ('e', "ego", "IDENTITY", "identity to use for messaging", &ego_name),
285 "peer identity to entry into the room", 313 GNUNET_GETOPT_option_string ('r', "room", "ROOMKEY", "key of the room to connect to", &room_key),
286 &door_id), 314 GNUNET_GETOPT_option_flag ('p', "private", "flag to enable private mode", &private_mode),
287 GNUNET_GETOPT_option_string ('e', 315 GNUNET_GETOPT_OPTION_END
288 "ego", 316 };
289 "IDENTITY", 317
290 "identity to use for messaging", 318 return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-messenger\0", gettext_noop(description), options, &run,
291 &ego_name), 319 NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
292 GNUNET_GETOPT_option_string ('r',
293 "room",
294 "ROOMKEY",
295 "key of the room to connect to",
296 &room_key),
297 GNUNET_GETOPT_OPTION_END };
298
299 return (GNUNET_OK == GNUNET_PROGRAM_run (argc,
300 argv,
301 "gnunet-messenger\0",
302 gettext_noop(description),
303 options,
304 &run,
305 NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
306} 320}
diff --git a/src/messenger/gnunet-service-messenger.c b/src/messenger/gnunet-service-messenger.c
index 2c92305c4..7edd76d32 100644..100755
--- a/src/messenger/gnunet-service-messenger.c
+++ b/src/messenger/gnunet-service-messenger.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -25,6 +25,8 @@
25 25
26#include "gnunet-service-messenger.h" 26#include "gnunet-service-messenger.h"
27 27
28#include "gnunet-service-messenger_handle.h"
29#include "gnunet-service-messenger_message_kind.h"
28#include "gnunet-service-messenger_service.h" 30#include "gnunet-service-messenger_service.h"
29#include "messenger_api_message.h" 31#include "messenger_api_message.h"
30 32
@@ -52,7 +54,7 @@ handle_create (void *cls, const struct GNUNET_MESSENGER_CreateMessage *msg)
52 54
53 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name); 55 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name);
54 56
55 setup_handle_name (msg_client->handle, strlen (name) > 0? name : NULL); 57 setup_handle_name (msg_client->handle, strlen (name) > 0 ? name : NULL);
56 58
57 GNUNET_SERVICE_client_continue (msg_client->client); 59 GNUNET_SERVICE_client_continue (msg_client->client);
58} 60}
@@ -62,8 +64,7 @@ handle_update (void *cls, const struct GNUNET_MESSENGER_UpdateMessage *msg)
62{ 64{
63 struct GNUNET_MESSENGER_Client *msg_client = cls; 65 struct GNUNET_MESSENGER_Client *msg_client = cls;
64 66
65 if (GNUNET_OK != update_handle (msg_client->handle)) 67 update_handle (msg_client->handle);
66 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Name is required to update key!\n");
67 68
68 GNUNET_SERVICE_client_continue (msg_client->client); 69 GNUNET_SERVICE_client_continue (msg_client->client);
69} 70}
@@ -92,8 +93,7 @@ handle_set_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg)
92 93
93 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name); 94 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name);
94 95
95 if (GNUNET_YES != set_handle_name (msg_client->handle, name)) 96 set_handle_name (msg_client->handle, name);
96 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No valid name: %s\n", name);
97 97
98 GNUNET_SERVICE_client_continue (msg_client->client); 98 GNUNET_SERVICE_client_continue (msg_client->client);
99} 99}
@@ -103,15 +103,13 @@ handle_room_open (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
103{ 103{
104 struct GNUNET_MESSENGER_Client *msg_client = cls; 104 struct GNUNET_MESSENGER_Client *msg_client = cls;
105 105
106 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", 106 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", GNUNET_h2s (&(msg->key)));
107 GNUNET_h2s (&(msg->key)));
108 107
109 if (GNUNET_YES == open_handle_room (msg_client->handle, &(msg->key))) 108 if (GNUNET_YES == open_handle_room (msg_client->handle, &(msg->key)))
110 { 109 {
111 const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); 110 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
112 111
113 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room with member id: %s\n", 112 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room with member id: %s\n", GNUNET_sh2s (member_id));
114 GNUNET_sh2s (member_id));
115 113
116 struct GNUNET_MESSENGER_RoomMessage *response; 114 struct GNUNET_MESSENGER_RoomMessage *response;
117 struct GNUNET_MQ_Envelope *env; 115 struct GNUNET_MQ_Envelope *env;
@@ -121,8 +119,7 @@ handle_room_open (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
121 GNUNET_MQ_send (msg_client->handle->mq, env); 119 GNUNET_MQ_send (msg_client->handle->mq, env);
122 } 120 }
123 else 121 else
124 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Opening room failed: %s\n", 122 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Opening room failed: %s\n", GNUNET_h2s (&(msg->key)));
125 GNUNET_h2s (&(msg->key)));
126 123
127 GNUNET_SERVICE_client_continue (msg_client->client); 124 GNUNET_SERVICE_client_continue (msg_client->client);
128} 125}
@@ -132,15 +129,13 @@ handle_room_entry (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
132{ 129{
133 struct GNUNET_MESSENGER_Client *msg_client = cls; 130 struct GNUNET_MESSENGER_Client *msg_client = cls;
134 131
135 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", 132 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door)));
136 GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door)));
137 133
138 if (GNUNET_YES == entry_handle_room (msg_client->handle, &(msg->door), &(msg->key))) 134 if (GNUNET_YES == entry_handle_room (msg_client->handle, &(msg->door), &(msg->key)))
139 { 135 {
140 const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); 136 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
141 137
142 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room with member id: %s\n", 138 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room with member id: %s\n", GNUNET_sh2s (member_id));
143 GNUNET_sh2s (member_id));
144 139
145 struct GNUNET_MESSENGER_RoomMessage *response; 140 struct GNUNET_MESSENGER_RoomMessage *response;
146 struct GNUNET_MQ_Envelope *env; 141 struct GNUNET_MQ_Envelope *env;
@@ -151,8 +146,8 @@ handle_room_entry (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
151 GNUNET_MQ_send (msg_client->handle->mq, env); 146 GNUNET_MQ_send (msg_client->handle->mq, env);
152 } 147 }
153 else 148 else
154 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Entrance into room failed: %s, %s\n", 149 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Entrance into room failed: %s, %s\n", GNUNET_h2s (&(msg->key)),
155 GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door))); 150 GNUNET_i2s (&(msg->door)));
156 151
157 GNUNET_SERVICE_client_continue (msg_client->client); 152 GNUNET_SERVICE_client_continue (msg_client->client);
158} 153}
@@ -166,10 +161,9 @@ handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
166 161
167 if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key))) 162 if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key)))
168 { 163 {
169 const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); 164 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
170 165
171 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room with member id: %s\n", 166 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room with member id: %s\n", GNUNET_sh2s (member_id));
172 GNUNET_sh2s (member_id));
173 167
174 struct GNUNET_MESSENGER_RoomMessage *response; 168 struct GNUNET_MESSENGER_RoomMessage *response;
175 struct GNUNET_MQ_Envelope *env; 169 struct GNUNET_MQ_Envelope *env;
@@ -187,17 +181,43 @@ handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
187static int 181static int
188check_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg) 182check_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg)
189{ 183{
190 const uint16_t full_length = ntohs (msg->header.size) - sizeof(msg->header); 184 const uint16_t full_length = ntohs (msg->header.size);
191 185
192 if (full_length < sizeof(msg->key)) 186 if (full_length < sizeof(*msg))
193 return GNUNET_NO; 187 return GNUNET_NO;
194 188
195 const uint16_t length = full_length - sizeof(msg->key); 189 const enum GNUNET_MESSENGER_MessageFlags flags = (
190 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
191 );
192
193 const uint16_t length = full_length - sizeof(*msg);
196 const char *buffer = ((const char*) msg) + sizeof(*msg); 194 const char *buffer = ((const char*) msg) + sizeof(*msg);
197 195
196 ssize_t key_length = 0;
197
198 if (!(flags & GNUNET_MESSENGER_FLAG_PRIVATE))
199 goto check_for_message;
200
201 struct GNUNET_IDENTITY_PublicKey public_key;
202
203 key_length = GNUNET_IDENTITY_read_key_from_buffer(&public_key, buffer, length);
204
205check_for_message:
206 if (key_length < 0)
207 return GNUNET_NO;
208
209 const uint16_t msg_length = length - key_length;
210 const char* msg_buffer = buffer + key_length;
211
198 struct GNUNET_MESSENGER_Message message; 212 struct GNUNET_MESSENGER_Message message;
199 213
200 if (GNUNET_YES != decode_message (&message, length, buffer)) 214 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
215 return GNUNET_NO;
216
217 if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL))
218 return GNUNET_NO;
219
220 if (GNUNET_YES != filter_message_sending(&message))
201 return GNUNET_NO; 221 return GNUNET_NO;
202 222
203 return GNUNET_OK; 223 return GNUNET_OK;
@@ -208,42 +228,115 @@ handle_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg)
208{ 228{
209 struct GNUNET_MESSENGER_Client *msg_client = cls; 229 struct GNUNET_MESSENGER_Client *msg_client = cls;
210 230
231 const enum GNUNET_MESSENGER_MessageFlags flags = (
232 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
233 );
234
211 const struct GNUNET_HashCode *key = &(msg->key); 235 const struct GNUNET_HashCode *key = &(msg->key);
212 const char *buffer = ((const char*) msg) + sizeof(*msg); 236 const char *buffer = ((const char*) msg) + sizeof(*msg);
213 237
214 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg); 238 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
239 ssize_t key_length = 0;
240
241 struct GNUNET_IDENTITY_PublicKey public_key;
242
243 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
244 key_length = GNUNET_IDENTITY_read_key_from_buffer(
245 &public_key, buffer, length
246 );
247
248 const uint16_t msg_length = length - key_length;
249 const char* msg_buffer = buffer + key_length;
215 250
216 struct GNUNET_MESSENGER_Message message; 251 struct GNUNET_MESSENGER_Message message;
217 decode_message (&message, length, buffer); 252 decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL);
253
254 if ((flags & GNUNET_MESSENGER_FLAG_PRIVATE) &&
255 (GNUNET_YES != encrypt_message(&message, &public_key)))
256 {
257 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Encrypting message failed: Message got dropped!\n");
258
259 goto end_handling;
260 }
218 261
219 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n", 262 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n",
220 GNUNET_MESSENGER_name_of_kind (message.header.kind), 263 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (key));
221 GNUNET_h2s (key));
222 264
223 if (GNUNET_YES != send_handle_message (msg_client->handle, key, &message)) 265 if (GNUNET_YES != send_handle_message (msg_client->handle, key, &message))
224 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n", 266 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n",
225 GNUNET_MESSENGER_name_of_kind (message.header.kind), 267 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (key));
226 GNUNET_h2s (key));
227 268
269end_handling:
228 GNUNET_SERVICE_client_continue (msg_client->client); 270 GNUNET_SERVICE_client_continue (msg_client->client);
229} 271}
230 272
231static void 273static void
232handle_get_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) 274callback_found_message (void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
275 const struct GNUNET_MESSENGER_Message *message,
276 const struct GNUNET_HashCode *hash)
277{
278 struct GNUNET_MESSENGER_Client *msg_client = cls;
279
280 if (!message)
281 {
282 send_room_message(room, msg_client->handle, create_message_request(hash));
283 return;
284 }
285
286 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
287
288 struct GNUNET_MESSENGER_Member *member = get_store_member_of(store, message);
289
290 if (!member)
291 {
292 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n", GNUNET_h2s (hash));
293 return;
294 }
295
296 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
297
298 if (session)
299 notify_handle_message (msg_client->handle, get_room_key(room), session, message, hash);
300}
301
302static void
303handle_get_message (void *cls, const struct GNUNET_MESSENGER_GetMessage *msg)
233{ 304{
234 struct GNUNET_MESSENGER_Client *msg_client = cls; 305 struct GNUNET_MESSENGER_Client *msg_client = cls;
235 306
236 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Requesting message from room: %s\n", 307 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Requesting message from room: %s\n", GNUNET_h2s (&(msg->key)));
237 GNUNET_h2s (&(msg->key)));
238 308
239 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (messenger, &(msg->key)); 309 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (messenger, &(msg->key));
240 310
241 if (room) 311 if (!room)
242 get_room_message (room, msg_client->handle, &(msg->hash), GNUNET_YES); 312 {
243 else 313 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found: %s\n", GNUNET_h2s (&(msg->key)));
244 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found: %s\n", 314 goto end_handling;
245 GNUNET_h2s (&(msg->key))); 315 }
316
317 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
318
319 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, get_handle_member_id(
320 msg_client->handle, &(msg->key)
321 ));
322
323 if (!member)
324 {
325 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Member not valid to request a message!\n");
326 goto end_handling;
327 }
328
329 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_handle_ego(msg_client->handle)->pub));
330
331 if (!session)
332 {
333 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Session not valid to request a message!\n");
334 goto end_handling;
335 }
336
337 request_room_message (room, &(msg->hash), session, callback_found_message, msg_client);
246 338
339end_handling:
247 GNUNET_SERVICE_client_continue (msg_client->client); 340 GNUNET_SERVICE_client_continue (msg_client->client);
248} 341}
249 342
@@ -271,16 +364,16 @@ callback_client_disconnect (void *cls, struct GNUNET_SERVICE_Client *client, voi
271/** 364/**
272 * Setup MESSENGER internals. 365 * Setup MESSENGER internals.
273 * 366 *
274 * @param cls closure 367 * @param[in/out] cls closure
275 * @param config configuration to use 368 * @param[in] config configuration to use
276 * @param service the initialized service 369 * @param[in/out] service the initialized service
277 */ 370 */
278static void 371static void
279run (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service) 372run (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service)
280{ 373{
281 messenger = create_service (config, service); 374 messenger = create_service (config, service);
282 375
283 if ((!messenger) || (!messenger->cadet) || (!messenger->identity)) 376 if (!messenger)
284 GNUNET_SCHEDULER_shutdown (); 377 GNUNET_SCHEDULER_shutdown ();
285} 378}
286 379
@@ -302,5 +395,5 @@ GNUNET_SERVICE_MAIN(
302 GNUNET_MQ_hd_fixed_size( room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, struct GNUNET_MESSENGER_RoomMessage, NULL ), 395 GNUNET_MQ_hd_fixed_size( room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, struct GNUNET_MESSENGER_RoomMessage, NULL ),
303 GNUNET_MQ_hd_fixed_size( room_close, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, struct GNUNET_MESSENGER_RoomMessage, NULL ), 396 GNUNET_MQ_hd_fixed_size( room_close, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, struct GNUNET_MESSENGER_RoomMessage, NULL ),
304 GNUNET_MQ_hd_var_size( send_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE, struct GNUNET_MESSENGER_SendMessage, NULL ), 397 GNUNET_MQ_hd_var_size( send_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE, struct GNUNET_MESSENGER_SendMessage, NULL ),
305 GNUNET_MQ_hd_fixed_size( get_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE, struct GNUNET_MESSENGER_RecvMessage, NULL ), 398 GNUNET_MQ_hd_fixed_size( get_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE, struct GNUNET_MESSENGER_GetMessage, NULL ),
306 GNUNET_MQ_handler_end()); 399 GNUNET_MQ_handler_end());
diff --git a/src/messenger/gnunet-service-messenger.h b/src/messenger/gnunet-service-messenger.h
index 85a1d2549..253fbaadb 100644
--- a/src/messenger/gnunet-service-messenger.h
+++ b/src/messenger/gnunet-service-messenger.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -74,7 +74,6 @@ struct GNUNET_MESSENGER_NameMessage
74struct GNUNET_MESSENGER_KeyMessage 74struct GNUNET_MESSENGER_KeyMessage
75{ 75{
76 struct GNUNET_MessageHeader header; 76 struct GNUNET_MessageHeader header;
77 struct GNUNET_IDENTITY_PublicKey pubkey;
78}; 77};
79 78
80/** 79/**
@@ -105,7 +104,20 @@ struct GNUNET_MESSENGER_MemberMessage
105struct GNUNET_MESSENGER_SendMessage 104struct GNUNET_MESSENGER_SendMessage
106{ 105{
107 struct GNUNET_MessageHeader header; 106 struct GNUNET_MessageHeader header;
107
108 struct GNUNET_HashCode key; 108 struct GNUNET_HashCode key;
109 uint32_t flags;
110};
111
112/**
113 * Message to request something from a room
114 */
115struct GNUNET_MESSENGER_GetMessage
116{
117 struct GNUNET_MessageHeader header;
118
119 struct GNUNET_HashCode key;
120 struct GNUNET_HashCode hash;
109}; 121};
110 122
111/** 123/**
@@ -114,8 +126,12 @@ struct GNUNET_MESSENGER_SendMessage
114struct GNUNET_MESSENGER_RecvMessage 126struct GNUNET_MESSENGER_RecvMessage
115{ 127{
116 struct GNUNET_MessageHeader header; 128 struct GNUNET_MessageHeader header;
129
117 struct GNUNET_HashCode key; 130 struct GNUNET_HashCode key;
131 struct GNUNET_HashCode sender;
132 struct GNUNET_HashCode context;
118 struct GNUNET_HashCode hash; 133 struct GNUNET_HashCode hash;
134 uint32_t flags;
119}; 135};
120 136
121#endif //GNUNET_SERVICE_MESSENGER_H 137#endif //GNUNET_SERVICE_MESSENGER_H
diff --git a/src/messenger/gnunet-service-messenger_basement.c b/src/messenger/gnunet-service-messenger_basement.c
index 190cf2de5..f302c8d66 100644
--- a/src/messenger/gnunet-service-messenger_basement.c
+++ b/src/messenger/gnunet-service-messenger_basement.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -28,6 +28,8 @@
28size_t 28size_t
29count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels) 29count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels)
30{ 30{
31 GNUNET_assert(tunnels);
32
31 const struct GNUNET_MESSENGER_ListTunnel *element; 33 const struct GNUNET_MESSENGER_ListTunnel *element;
32 size_t count = 0; 34 size_t count = 0;
33 35
diff --git a/src/messenger/gnunet-service-messenger_basement.h b/src/messenger/gnunet-service-messenger_basement.h
index 0a1a9b126..b19aec405 100644
--- a/src/messenger/gnunet-service-messenger_basement.h
+++ b/src/messenger/gnunet-service-messenger_basement.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -31,34 +31,34 @@
31/** 31/**
32 * Returns the count of peers in a list (typically from the basement of a room). 32 * Returns the count of peers in a list (typically from the basement of a room).
33 * 33 *
34 * @param tunnels List of peer identities 34 * @param[in] tunnels List of peer identities
35 * @return Count of the entries in the list 35 * @return Count of the entries in the list
36 */ 36 */
37size_t 37size_t
38count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels); 38count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels);
39 39
40/** 40/**
41 * Returns GNUNET_YES or GNUNET_NO to determine if the peer at index <i>src</i> should 41 * Returns #GNUNET_YES or #GNUNET_NO to determine if the peer at index <i>src</i> should
42 * or should not connect outgoing to the peer at index <i>dst</i> to construct a complete 42 * or should not connect outgoing to the peer at index <i>dst</i> to construct a complete
43 * basement with a given <i>count</i> of peers. 43 * basement with a given <i>count</i> of peers.
44 * 44 *
45 * @param count Count of peers 45 * @param[in] count Count of peers
46 * @param src Source index 46 * @param[in] src Source index
47 * @param dst Destination index 47 * @param[in] dst Destination index
48 * @return GNUNET_YES or GNUNET_NO based on topologic requirement 48 * @return #GNUNET_YES or #GNUNET_NO based on topologic requirement
49 */ 49 */
50int 50int
51should_connect_tunnel_to (size_t count, size_t src, size_t dst); 51should_connect_tunnel_to (size_t count, size_t src, size_t dst);
52 52
53/** 53/**
54 * Returns GNUNET_YES or GNUNET_NO to determine if the peers of index <i>src</i> and 54 * Returns #GNUNET_YES or #GNUNET_NO to determine if the peers of index <i>src</i> and
55 * index <i>dst</i> should be connected in any direction to construct a complete 55 * index <i>dst</i> should be connected in any direction to construct a complete
56 * basement with a given <i>count</i> of peers. 56 * basement with a given <i>count</i> of peers.
57 * 57 *
58 * @param count Count of peers 58 * @param[in] count Count of peers
59 * @param src Source index 59 * @param[in] src Source index
60 * @param dst Destination index 60 * @param[in] dst Destination index
61 * @return GNUNET_YES or GNUNET_NO based on topologic requirement 61 * @return #GNUNET_YES or #GNUNET_NO based on topologic requirement
62 */ 62 */
63int 63int
64required_connection_between (size_t count, size_t src, size_t dst); 64required_connection_between (size_t count, size_t src, size_t dst);
diff --git a/src/messenger/gnunet-service-messenger_contact.c b/src/messenger/gnunet-service-messenger_contact.c
deleted file mode 100644
index 1ec125402..000000000
--- a/src/messenger/gnunet-service-messenger_contact.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_contact.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_contact.h"
27
28struct GNUNET_MESSENGER_SrvContact*
29create_contact (const struct GNUNET_IDENTITY_PublicKey *key)
30{
31 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_new(struct GNUNET_MESSENGER_SrvContact);
32
33 contact->name = NULL;
34 contact->rc = 0;
35
36 GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key));
37
38 return contact;
39}
40
41void
42destroy_contact (struct GNUNET_MESSENGER_SrvContact *contact)
43{
44 if (contact->name)
45 GNUNET_free(contact->name);
46
47 GNUNET_free(contact);
48}
49
50const char*
51get_contact_name (const struct GNUNET_MESSENGER_SrvContact *contact)
52{
53 return contact->name;
54}
55
56void
57set_contact_name (struct GNUNET_MESSENGER_SrvContact *contact, const char *name)
58{
59 GNUNET_assert(name);
60
61 if (contact->name)
62 GNUNET_free(contact->name);
63
64 contact->name = GNUNET_strdup(name);
65}
66
67const struct GNUNET_IDENTITY_PublicKey*
68get_contact_key (const struct GNUNET_MESSENGER_SrvContact *contact)
69{
70 return &(contact->public_key);
71}
72
73void
74increase_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact)
75{
76 contact->rc++;
77}
78
79int
80decrease_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact)
81{
82 if (contact->rc > 0)
83 contact->rc--;
84
85 return contact->rc ? GNUNET_NO : GNUNET_YES;
86}
87
88const struct GNUNET_HashCode*
89get_contact_id_from_key (const struct GNUNET_MESSENGER_SrvContact *contact)
90{
91 static struct GNUNET_HashCode id;
92
93 GNUNET_CRYPTO_hash (&(contact->public_key), sizeof(contact->public_key), &id);
94
95 return &id;
96}
diff --git a/src/messenger/gnunet-service-messenger_contact.h b/src/messenger/gnunet-service-messenger_contact.h
deleted file mode 100644
index 4a4f8bf0f..000000000
--- a/src/messenger/gnunet-service-messenger_contact.h
+++ /dev/null
@@ -1,112 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_contact.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_CONTACT_H
27#define GNUNET_SERVICE_MESSENGER_CONTACT_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_identity_service.h"
32
33struct GNUNET_MESSENGER_SrvContact
34{
35 char *name;
36 size_t rc;
37
38 struct GNUNET_IDENTITY_PublicKey public_key;
39};
40
41/**
42 * Creates and allocates a new contact with a given public <i>key</i> from an EGO.
43 *
44 * @param key Public key
45 * @return New contact
46 */
47struct GNUNET_MESSENGER_SrvContact*
48create_contact (const struct GNUNET_IDENTITY_PublicKey *key);
49
50/**
51 * Destroys a contact and frees its memory fully.
52 *
53 * @param contact Contact
54 */
55void
56destroy_contact (struct GNUNET_MESSENGER_SrvContact *contact);
57
58/**
59 * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet.
60 *
61 * @param contact Contact
62 * @return Name of the contact or NULL
63 */
64const char*
65get_contact_name (const struct GNUNET_MESSENGER_SrvContact *contact);
66
67/**
68 * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>.
69 *
70 * @param contact Contact
71 * @param name Valid name (may not be NULL!)
72 */
73void
74set_contact_name (struct GNUNET_MESSENGER_SrvContact *contact, const char *name);
75
76/**
77 * Returns the public key of a given <i>contact</i>.
78 *
79 * @param contact Contact
80 * @return Public key of the contact
81 */
82const struct GNUNET_IDENTITY_PublicKey*
83get_contact_key (const struct GNUNET_MESSENGER_SrvContact *contact);
84
85/**
86 * Increases the reference counter of a given <i>contact</i> which is zero as default.
87 *
88 * @param contact Contact
89 */
90void
91increase_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact);
92
93/**
94 * Decreases the reference counter if possible (can not underflow!) of a given <i>contact</i>
95 * and returns GNUNET_YES if the counter is equal to zero, otherwise GNUNET_NO.
96 *
97 * @param contact Contact
98 * @return GNUNET_YES or GNUNET_NO depending on the reference counter
99 */
100int
101decrease_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact);
102
103/**
104 * Returns the resulting hashcode of the public key from a given <i>contact</i>.
105 *
106 * @param contact Contact
107 * @return Hash of the contacts public key
108 */
109const struct GNUNET_HashCode*
110get_contact_id_from_key (const struct GNUNET_MESSENGER_SrvContact *contact);
111
112#endif //GNUNET_SERVICE_MESSENGER_CONTACT_H
diff --git a/src/messenger/gnunet-service-messenger_ego_store.c b/src/messenger/gnunet-service-messenger_ego_store.c
new file mode 100644
index 000000000..3b069fcf5
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_ego_store.c
@@ -0,0 +1,295 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_ego_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_ego_store.h"
27
28#include "gnunet-service-messenger_handle.h"
29
30static void
31callback_update_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
32{
33 if ((!ego) || (!identifier))
34 return;
35
36 struct GNUNET_MESSENGER_EgoStore *store = cls;
37
38 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier);
39
40 update_store_ego (store, identifier, GNUNET_IDENTITY_ego_get_private_key (ego));
41}
42
43void
44init_ego_store(struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config)
45{
46 GNUNET_assert ((store) && (config));
47
48 store->cfg = config;
49 store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego, store);
50 store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
51
52 store->lu_start = NULL;
53 store->lu_end = NULL;
54
55 store->op_start = NULL;
56 store->op_end = NULL;
57}
58
59
60static int
61iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value)
62{
63 struct GNUNET_MESSENGER_Ego *ego = value;
64 GNUNET_free(ego);
65 return GNUNET_YES;
66}
67
68void
69clear_ego_store(struct GNUNET_MESSENGER_EgoStore *store)
70{
71 GNUNET_assert (store);
72
73 struct GNUNET_MESSENGER_EgoOperation *op;
74
75 while (store->op_start)
76 {
77 op = store->op_start;
78
79 GNUNET_IDENTITY_cancel (op->operation);
80 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op);
81
82 if (op->identifier)
83 GNUNET_free (op->identifier);
84
85 GNUNET_free (op);
86 }
87
88 struct GNUNET_MESSENGER_EgoLookup *lu;
89
90 while (store->lu_start)
91 {
92 lu = store->lu_start;
93
94 GNUNET_IDENTITY_ego_lookup_cancel(lu->lookup);
95 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu);
96
97 if (lu->identifier)
98 GNUNET_free(lu->identifier);
99
100 GNUNET_free (lu);
101 }
102
103 GNUNET_CONTAINER_multihashmap_iterate (store->egos, iterate_destroy_egos, NULL);
104 GNUNET_CONTAINER_multihashmap_destroy (store->egos);
105
106 if (store->identity)
107 {
108 GNUNET_IDENTITY_disconnect (store->identity);
109
110 store->identity = NULL;
111 }
112}
113
114static void
115callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg)
116{
117 struct GNUNET_MESSENGER_EgoOperation *element = cls;
118 struct GNUNET_MESSENGER_EgoStore *store = element->store;
119
120 GNUNET_assert(element->identifier);
121
122 if (emsg)
123 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
124
125 if (key)
126 {
127 struct GNUNET_MESSENGER_SrvHandle *handle = element->handle;
128
129 struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store, element->identifier, key);
130
131 set_handle_ego (handle, msg_ego);
132 }
133 else
134 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n");
135
136 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
137 GNUNET_free (element->identifier);
138 GNUNET_free (element);
139}
140
141void
142create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
143 void *handle)
144{
145 GNUNET_assert ((store) && (identifier));
146
147 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
148
149 element->store = store;
150 element->handle = handle;
151
152 element->identifier = GNUNET_strdup (identifier);
153
154 element->operation = GNUNET_IDENTITY_create (store->identity, identifier, NULL,
155 GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, element);
156
157 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
158}
159
160static void
161callback_ego_lookup (void *cls, struct GNUNET_IDENTITY_Ego *ego)
162{
163 struct GNUNET_MESSENGER_EgoLookup *element = cls;
164 struct GNUNET_MESSENGER_EgoStore *store = element->store;
165
166 GNUNET_assert(element->identifier);
167
168 struct GNUNET_MESSENGER_Ego *msg_ego;
169
170 if (ego)
171 msg_ego = update_store_ego (
172 store, element->identifier, GNUNET_IDENTITY_ego_get_private_key(ego)
173 );
174 else
175 msg_ego = NULL;
176
177 if (element->cb)
178 element->cb(element->cls, element->identifier, msg_ego);
179
180 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element);
181 GNUNET_free (element->identifier);
182 GNUNET_free (element);
183}
184
185void
186lookup_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
187 GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls)
188{
189 GNUNET_assert (store);
190
191 if (!identifier)
192 {
193 lookup(cls, identifier, NULL);
194 return;
195 }
196
197 struct GNUNET_HashCode hash;
198 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
199
200 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
201
202 if (ego)
203 lookup(cls, identifier, ego);
204 else
205 {
206 struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct GNUNET_MESSENGER_EgoLookup);
207
208 element->store = store;
209
210 element->cb = lookup;
211 element->cls = cls;
212
213 element->identifier = GNUNET_strdup (identifier);
214
215 element->lookup = GNUNET_IDENTITY_ego_lookup(store->cfg, identifier, callback_ego_lookup, element);
216
217 GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element);
218 }
219}
220
221struct GNUNET_MESSENGER_Ego*
222update_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
223 const struct GNUNET_IDENTITY_PrivateKey *key)
224{
225 GNUNET_assert ((store) && (identifier) && (key));
226
227 struct GNUNET_HashCode hash;
228 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
229
230 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
231
232 if (!ego)
233 {
234 ego = GNUNET_new(struct GNUNET_MESSENGER_Ego);
235 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
236 }
237
238 GNUNET_memcpy(&(ego->priv), key, sizeof(*key));
239
240 if (GNUNET_OK != GNUNET_IDENTITY_key_get_public (key, &(ego->pub)))
241 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n");
242
243 return ego;
244}
245
246static void
247callback_ego_rename (void *cls, const char *emsg)
248{
249 struct GNUNET_MESSENGER_EgoOperation *element = cls;
250 struct GNUNET_MESSENGER_EgoStore *store = element->store;
251
252 GNUNET_assert(element->identifier);
253
254 if (emsg)
255 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
256
257 struct GNUNET_HashCode hash;
258 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
259
260 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
261
262 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego))
263 {
264 GNUNET_CRYPTO_hash ((char*) element->handle, strlen ((char*) element->handle), &hash);
265
266 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego,
267 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
268 }
269 else
270 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n");
271
272 GNUNET_free (element->handle);
273
274 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
275 GNUNET_free (element->identifier);
276 GNUNET_free (element);
277}
278
279void
280rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier,
281 const char *new_identifier)
282{
283 GNUNET_assert ((store) && (old_identifier) && (new_identifier));
284
285 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
286
287 element->store = store;
288 element->handle = GNUNET_strdup (new_identifier);
289
290 element->identifier = GNUNET_strdup (old_identifier);
291
292 element->operation = GNUNET_IDENTITY_rename (store->identity, old_identifier, new_identifier, callback_ego_rename, element);
293
294 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
295}
diff --git a/src/messenger/gnunet-service-messenger_ego_store.h b/src/messenger/gnunet-service-messenger_ego_store.h
new file mode 100644
index 000000000..41f14fff2
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_ego_store.h
@@ -0,0 +1,152 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_ego_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_EGO_STORE_H
27#define GNUNET_SERVICE_MESSENGER_EGO_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31
32#include "messenger_api_ego.h"
33
34struct GNUNET_MESSENGER_Ego;
35struct GNUNET_MESSENGER_EgoStore;
36
37typedef void
38(*GNUNET_MESSENGER_EgoLookupCallback) (void *cls, const char *identifier,
39 const struct GNUNET_MESSENGER_Ego *ego);
40
41struct GNUNET_MESSENGER_EgoLookup
42{
43 struct GNUNET_MESSENGER_EgoLookup *prev;
44 struct GNUNET_MESSENGER_EgoLookup *next;
45
46 struct GNUNET_IDENTITY_EgoLookup *lookup;
47
48 struct GNUNET_MESSENGER_EgoStore *store;
49
50 GNUNET_MESSENGER_EgoLookupCallback cb;
51 void *cls;
52
53 char *identifier;
54};
55
56struct GNUNET_MESSENGER_EgoOperation
57{
58 struct GNUNET_MESSENGER_EgoOperation *prev;
59 struct GNUNET_MESSENGER_EgoOperation *next;
60
61 struct GNUNET_IDENTITY_Operation *operation;
62
63 struct GNUNET_MESSENGER_EgoStore *store;
64 void *handle;
65
66 char *identifier;
67};
68
69struct GNUNET_MESSENGER_EgoStore
70{
71 const struct GNUNET_CONFIGURATION_Handle *cfg;
72
73 struct GNUNET_IDENTITY_Handle *identity;
74 struct GNUNET_CONTAINER_MultiHashMap *egos;
75
76 struct GNUNET_MESSENGER_EgoLookup *lu_start;
77 struct GNUNET_MESSENGER_EgoLookup *lu_end;
78
79 struct GNUNET_MESSENGER_EgoOperation *op_start;
80 struct GNUNET_MESSENGER_EgoOperation *op_end;
81};
82
83/**
84 * Initializes an EGO-store as fully empty.
85 *
86 * @param[out] store EGO-store
87 * @param[in] config Configuration handle
88 */
89void
90init_ego_store (struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config);
91
92/**
93 * Clears an EGO-store, wipes its content and deallocates its memory.
94 *
95 * @param[in/out] store EGO-store
96 */
97void
98clear_ego_store (struct GNUNET_MESSENGER_EgoStore *store);
99
100/**
101 * Creates a new EGO which will be registered to a <i>store</i> under
102 * a specific <i>identifier</i>. A given <i>handle</i> will be informed
103 * about the creation and changes its EGO accordingly.
104 *
105 * @param[in/out] store EGO-store
106 * @param[in] identifier Identifier string
107 * @param[in/out] handle Handle or NULL
108 */
109void
110create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
111 void *handle);
112
113/**
114 * Lookups an EGO which was registered to a <i>store</i> under
115 * a specific <i>identifier</i>.
116 *
117 * @param[in/out] store EGO-store
118 * @param[in] identifier Identifier string
119 * @param[in] lookup Lookup callback (non-NULL)
120 * @param[in] cls Closure
121 */
122void
123lookup_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
124 GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls);
125
126/**
127 * Updates the registration of an EGO to a <i>store</i> under
128 * a specific <i>identifier</i> with a new <i>key</i>.
129 *
130 * @param[in/out] store EGO-store
131 * @param[in] identifier Identifier string
132 * @param[in] key Private EGO key
133 * @return Updated EGO
134 */
135struct GNUNET_MESSENGER_Ego*
136update_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
137 const struct GNUNET_IDENTITY_PrivateKey *key);
138
139/**
140 * Updates the location of a registered EGO in a <i>store</i> to
141 * a different one under a specific <i>new_identifier<i> replacing
142 * its old one.
143 *
144 * @param[in/out] store EGO-store
145 * @param[in] old_identifier Old identifier string
146 * @param[in] new_identifier New identifier string
147 */
148void
149rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier,
150 const char *new_identifier);
151
152#endif //GNUNET_SERVICE_MESSENGER_EGO_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_handle.c b/src/messenger/gnunet-service-messenger_handle.c
index 38ad6fbb4..4d2318d62 100644
--- a/src/messenger/gnunet-service-messenger_handle.c
+++ b/src/messenger/gnunet-service-messenger_handle.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -28,18 +28,19 @@
28#include "gnunet-service-messenger.h" 28#include "gnunet-service-messenger.h"
29#include "gnunet-service-messenger_message_kind.h" 29#include "gnunet-service-messenger_message_kind.h"
30 30
31#include "messenger_api_util.h"
32
31struct GNUNET_MESSENGER_SrvHandle* 33struct GNUNET_MESSENGER_SrvHandle*
32create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq) 34create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq)
33{ 35{
36 GNUNET_assert((service) && (mq));
37
34 struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle); 38 struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle);
35 39
36 handle->service = service; 40 handle->service = service;
37 handle->mq = mq; 41 handle->mq = mq;
38 42
39 handle->name = NULL; 43 handle->name = NULL;
40
41 handle->operation = NULL;
42
43 handle->ego = NULL; 44 handle->ego = NULL;
44 45
45 handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 46 handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
@@ -58,11 +59,10 @@ iterate_free_member_ids (void *cls, const struct GNUNET_HashCode *key, void *val
58void 59void
59destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle) 60destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
60{ 61{
61 if (handle->service->dir) 62 GNUNET_assert(handle);
62 save_handle_configuration(handle);
63 63
64 if (handle->operation) 64 if (handle->service->dir)
65 GNUNET_IDENTITY_cancel (handle->operation); 65 save_handle_configuration (handle);
66 66
67 if (handle->name) 67 if (handle->name)
68 GNUNET_free(handle->name); 68 GNUNET_free(handle->name);
@@ -74,8 +74,10 @@ destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
74} 74}
75 75
76void 76void
77get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir) 77get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir)
78{ 78{
79 GNUNET_assert((handle) && (dir));
80
79 if (name) 81 if (name)
80 GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities", 82 GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities",
81 DIR_SEPARATOR, name, DIR_SEPARATOR); 83 DIR_SEPARATOR, name, DIR_SEPARATOR);
@@ -87,11 +89,15 @@ get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *n
87static int 89static int
88create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) 90create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
89{ 91{
90 struct GNUNET_ShortHashCode *random_id = generate_service_new_member_id (handle->service, key); 92 GNUNET_assert((handle) && (key));
93
94 struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
91 95
92 if (!random_id) 96 if (!random_id)
93 return GNUNET_NO; 97 return GNUNET_NO;
94 98
99 generate_free_member_id (random_id, NULL);
100
95 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id, 101 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id,
96 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 102 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
97 { 103 {
@@ -99,8 +105,8 @@ create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const
99 return GNUNET_NO; 105 return GNUNET_NO;
100 } 106 }
101 107
102 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", 108 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", GNUNET_sh2s (random_id),
103 GNUNET_sh2s(random_id), GNUNET_h2s(key)); 109 GNUNET_h2s (key));
104 110
105 return GNUNET_YES; 111 return GNUNET_YES;
106} 112}
@@ -108,48 +114,61 @@ create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const
108const struct GNUNET_ShortHashCode* 114const struct GNUNET_ShortHashCode*
109get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) 115get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
110{ 116{
117 GNUNET_assert((handle) && (key));
118
111 return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key); 119 return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
112} 120}
113 121
114void 122int
115change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, 123change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
116 const struct GNUNET_ShortHashCode *unique_id) 124 const struct GNUNET_ShortHashCode *unique_id)
117{ 125{
118 struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key); 126 GNUNET_assert((handle) && (key) && (unique_id));
119
120 if (member_id)
121 {
122 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Changed a member id (%s) for room (%s) ",
123 GNUNET_sh2s(member_id), GNUNET_h2s(key));
124 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "into (%s).\n",
125 GNUNET_sh2s(unique_id));
126
127 GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
128
129 struct GNUNET_MESSENGER_MemberMessage *msg;
130 struct GNUNET_MQ_Envelope *env;
131 127
132 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID); 128 struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
133
134 GNUNET_memcpy(&(msg->key), key, sizeof(*key));
135 GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
136 129
137 GNUNET_MQ_send (handle->mq, env); 130 if (!member_id)
138 }
139 else
140 { 131 {
141 member_id = GNUNET_new(struct GNUNET_ShortHashCode); 132 member_id = GNUNET_new(struct GNUNET_ShortHashCode);
142 GNUNET_memcpy(member_id, unique_id, sizeof(*member_id)); 133 GNUNET_memcpy(member_id, unique_id, sizeof(*member_id));
143 134
144 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id, 135 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id,
145 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 136 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
137 {
146 GNUNET_free(member_id); 138 GNUNET_free(member_id);
139 return GNUNET_SYSERR;
140 }
147 } 141 }
142
143 if (0 == GNUNET_memcmp(unique_id, member_id))
144 goto send_message_to_client;
145
146 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Change a member id (%s) for room (%s).\n", GNUNET_sh2s (member_id),
147 GNUNET_h2s (key));
148
149 GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
150
151 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member id changed to (%s).\n", GNUNET_sh2s (unique_id));
152
153 struct GNUNET_MESSENGER_MemberMessage *msg;
154 struct GNUNET_MQ_Envelope *env;
155
156send_message_to_client:
157
158 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
159
160 GNUNET_memcpy(&(msg->key), key, sizeof(*key));
161 GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
162
163 GNUNET_MQ_send (handle->mq, env);
164 return GNUNET_OK;
148} 165}
149 166
150static void 167static void
151change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) 168change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
152{ 169{
170 GNUNET_assert(handle);
171
153 if (handle->name) 172 if (handle->name)
154 GNUNET_free(handle->name); 173 GNUNET_free(handle->name);
155 174
@@ -173,25 +192,67 @@ change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
173} 192}
174 193
175static void 194static void
176change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, struct GNUNET_MESSENGER_Ego *ego) 195change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego)
177{ 196{
197 GNUNET_assert(handle);
198
178 handle->ego = ego; 199 handle->ego = ego;
179 200
180 ego = get_handle_ego(handle); 201 ego = get_handle_ego (handle);
202
203 const uint16_t length = GNUNET_IDENTITY_key_get_length(&(ego->pub));
181 204
182 struct GNUNET_MESSENGER_KeyMessage *msg; 205 struct GNUNET_MESSENGER_KeyMessage *msg;
183 struct GNUNET_MQ_Envelope *env; 206 struct GNUNET_MQ_Envelope *env;
184 207
185 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY); 208 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY);
186 209
187 GNUNET_memcpy(&(msg->pubkey), &(ego->pub), sizeof(ego->pub)); 210 char *extra = ((char*) msg) + sizeof(*msg);
211
212 if (GNUNET_IDENTITY_write_key_to_buffer(&(ego->pub), extra, length) < 0)
213 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Could not write key to buffer.\n");
188 214
189 GNUNET_MQ_send (handle->mq, env); 215 GNUNET_MQ_send (handle->mq, env);
190} 216}
191 217
192struct GNUNET_MESSENGER_Ego* 218struct GNUNET_MESSENGER_MessageHandle
193get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle) 219{
220 struct GNUNET_MESSENGER_SrvHandle *handle;
221 struct GNUNET_MESSENGER_Message *message;
222};
223
224static int
225iterate_send_message (void *cls, const struct GNUNET_HashCode *key, void *value)
226{
227 struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls;
228
229 send_handle_message (msg_handle->handle, key, msg_handle->message);
230
231 return GNUNET_YES;
232}
233
234void
235set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego)
236{
237 GNUNET_assert((handle) && (ego));
238
239 struct GNUNET_MESSENGER_MessageHandle msg_handle;
240
241 msg_handle.handle = handle;
242 msg_handle.message = create_message_key (&(ego->priv));
243
244 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
245
246 destroy_message (msg_handle.message);
247
248 change_handle_ego (handle, ego);
249}
250
251const struct GNUNET_MESSENGER_Ego*
252get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle)
194{ 253{
254 GNUNET_assert(handle);
255
195 static struct GNUNET_MESSENGER_Ego anonymous; 256 static struct GNUNET_MESSENGER_Ego anonymous;
196 static int read_keys = 0; 257 static int read_keys = 0;
197 258
@@ -200,99 +261,86 @@ get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle)
200 261
201 if (!read_keys) 262 if (!read_keys)
202 { 263 {
203 struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous (); 264 struct GNUNET_IDENTITY_Ego *ego = GNUNET_IDENTITY_ego_get_anonymous ();
204 GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key(ego), sizeof(anonymous.priv)); 265 GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key (ego), sizeof(anonymous.priv));
205 GNUNET_IDENTITY_ego_get_public_key(ego, &(anonymous.pub)); 266 GNUNET_IDENTITY_ego_get_public_key (ego, &(anonymous.pub));
206 read_keys = 1; 267 read_keys = 1;
207 } 268 }
208 269
209 return &anonymous; 270 return &anonymous;
210} 271}
211 272
212void 273static void
213setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) 274callback_setup_handle_name (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
214{ 275{
276 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
277
278 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting up handle...\n");
279
215 change_handle_name (handle, name); 280 change_handle_name (handle, name);
216 change_handle_ego (handle, handle->name? lookup_service_ego(handle->service, handle->name) : NULL); 281 change_handle_ego (handle, ego);
217 282
218 if (handle->service->dir) 283 if (handle->service->dir)
219 load_handle_configuration(handle); 284 load_handle_configuration (handle);
220} 285}
221 286
222struct GNUNET_MESSENGER_MessageHandle 287void
223{ 288setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
224 struct GNUNET_MESSENGER_SrvHandle *handle;
225 struct GNUNET_MESSENGER_Message *message;
226};
227
228static int
229iterate_send_message (void *cls, const struct GNUNET_HashCode *key, void *value)
230{ 289{
231 struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls; 290 GNUNET_assert(handle);
232 291
233 send_handle_message (msg_handle->handle, key, msg_handle->message); 292 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
234 293
235 return GNUNET_YES; 294 lookup_store_ego (store, name, callback_setup_handle_name, handle);
236} 295}
237 296
238static void 297static void
239callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg) 298callback_update_handle (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
240{ 299{
241 struct GNUNET_MESSENGER_SrvHandle *handle = cls; 300 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
242 301
243 handle->operation = NULL; 302 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating handle...\n");
244 303
245 if (emsg) 304 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
246 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
247 305
248 if (key) 306 if (!ego)
249 { 307 create_store_ego(store, handle->name, handle);
250 struct GNUNET_MESSENGER_MessageHandle msg_handle; 308 else
251 309 change_handle_ego (handle, ego);
252 msg_handle.handle = handle;
253 msg_handle.message = create_message_key (key);
254
255 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
256
257 destroy_message (msg_handle.message);
258
259 update_service_ego(handle->service, handle->name, key);
260
261 change_handle_ego (handle, lookup_service_ego(handle->service, handle->name));
262 }
263} 310}
264 311
265int 312void
266update_handle (struct GNUNET_MESSENGER_SrvHandle *handle) 313update_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
267{ 314{
268 GNUNET_assert(handle); 315 GNUNET_assert(handle);
269 316
270 if (!handle->name) 317 if (!handle->name)
271 return GNUNET_SYSERR; 318 {
272 319 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating handle failed: Name is required!\n");
273 struct GNUNET_MESSENGER_Ego *ego = lookup_service_ego(handle->service, handle->name); 320 return;
321 }
274 322
275 if (!ego) 323 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
276 handle->operation = GNUNET_IDENTITY_create (handle->service->identity, handle->name, NULL,
277 GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, handle);
278 else
279 change_handle_ego (handle, ego);
280 324
281 return GNUNET_OK; 325 lookup_store_ego (store, handle->name, callback_update_handle, handle);
282} 326}
283 327
284int 328static void
285set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) 329callback_set_handle_name (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
286{ 330{
287 GNUNET_assert(handle); 331 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
288 332
289 if ((name) && (lookup_service_ego(handle->service, name))) 333 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Renaming handle...\n");
290 return GNUNET_NO; 334
335 if (ego)
336 {
337 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is occupied! (%s)\n", name);
338 return;
339 }
291 340
292 struct GNUNET_IDENTITY_Operation *operation = handle->operation; 341 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
293 342
294 if (handle->name) 343 int rename_ego_in_store = handle->ego? GNUNET_YES : GNUNET_NO;
295 handle->operation = GNUNET_IDENTITY_rename (handle->service->identity, handle->name, name, NULL, NULL);
296 344
297 char *old_dir; 345 char *old_dir;
298 get_handle_data_subdir (handle, handle->name, &old_dir); 346 get_handle_data_subdir (handle, handle->name, &old_dir);
@@ -323,29 +371,42 @@ set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
323 destroy_message (msg_handle.message); 371 destroy_message (msg_handle.message);
324 372
325 change_handle_name (handle, name); 373 change_handle_name (handle, name);
326
327 if (operation)
328 GNUNET_IDENTITY_cancel (operation);
329 } 374 }
330 else 375 else
376 rename_ego_in_store = GNUNET_NO;
377
378 GNUNET_free(old_dir);
379 GNUNET_free(new_dir);
380
381 if (GNUNET_YES == rename_ego_in_store)
382 rename_store_ego(store, handle->name, name);
383}
384
385void
386set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
387{
388 GNUNET_assert(handle);
389
390 if (!name)
331 { 391 {
332 if (handle->operation) 392 if (handle->ego)
333 { 393 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is required!\n");
334 GNUNET_IDENTITY_cancel (handle->operation); 394 else
395 change_handle_name (handle, name);
335 396
336 handle->operation = operation; 397 return;
337 }
338 } 398 }
339 399
340 GNUNET_free(old_dir); 400 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
341 GNUNET_free(new_dir);
342 401
343 return (result == 0 ? GNUNET_OK : GNUNET_NO); 402 lookup_store_ego (store, name, callback_set_handle_name, handle);
344} 403}
345 404
346int 405int
347open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) 406open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
348{ 407{
408 GNUNET_assert((handle) && (key));
409
349 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key))) 410 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
350 return GNUNET_NO; 411 return GNUNET_NO;
351 412
@@ -356,6 +417,8 @@ int
356entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door, 417entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door,
357 const struct GNUNET_HashCode *key) 418 const struct GNUNET_HashCode *key)
358{ 419{
420 GNUNET_assert((handle) && (door) && (key));
421
359 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key))) 422 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
360 return GNUNET_NO; 423 return GNUNET_NO;
361 424
@@ -365,6 +428,8 @@ entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNE
365int 428int
366close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) 429close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
367{ 430{
431 GNUNET_assert((handle) && (key));
432
368 if (!get_handle_member_id (handle, key)) 433 if (!get_handle_member_id (handle, key))
369 return GNUNET_NO; 434 return GNUNET_NO;
370 435
@@ -373,8 +438,10 @@ close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNE
373 438
374int 439int
375send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, 440send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
376 struct GNUNET_MESSENGER_Message *message) 441 const struct GNUNET_MESSENGER_Message *message)
377{ 442{
443 GNUNET_assert((handle) && (key) && (message));
444
378 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key); 445 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
379 446
380 if (!id) 447 if (!id)
@@ -391,45 +458,120 @@ send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNU
391 return GNUNET_NO; 458 return GNUNET_NO;
392 } 459 }
393 460
394 struct GNUNET_HashCode hash; 461 struct GNUNET_MESSENGER_Message *msg = copy_message(message);
395 462
396 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(*id)); 463 GNUNET_memcpy(&(msg->header.sender_id), id, sizeof(*id));
397 464
398 send_room_message (room, handle, message, &hash); 465 return send_room_message (room, handle, msg);
399 return GNUNET_YES; 466}
467
468static const struct GNUNET_HashCode*
469get_next_member_session_contect(const struct GNUNET_MESSENGER_MemberSession *session)
470{
471 if (session->next)
472 return get_next_member_session_contect (session->next);
473 else
474 return get_member_session_context(session);
475}
476
477void
478notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
479 const struct GNUNET_MESSENGER_MemberSession *session,
480 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
481{
482 GNUNET_assert((handle) && (key) && (session) && (message) && (hash));
483
484 if ((!handle->mq) || (!get_handle_member_id (handle, key)))
485 {
486 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notifying client about message requires membership!\n");
487 return;
488 }
489
490 const struct GNUNET_IDENTITY_PublicKey *pubkey = get_contact_key(session->contact);
491
492 struct GNUNET_HashCode sender;
493 GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
494
495 const struct GNUNET_HashCode *context = get_next_member_session_contect (session);
496
497 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying client about message: %s\n", GNUNET_h2s (hash));
498
499 struct GNUNET_MESSENGER_Message *private_message = NULL;
500
501 if (GNUNET_MESSENGER_KIND_PRIVATE == message->header.kind)
502 {
503 private_message = copy_message(message);
504
505 if (GNUNET_YES != decrypt_message(private_message, &(get_handle_ego(handle)->priv)))
506 {
507 destroy_message(private_message);
508 private_message = NULL;
509 }
510 else
511 message = private_message;
512 }
513
514 struct GNUNET_MESSENGER_RecvMessage *msg;
515 struct GNUNET_MQ_Envelope *env;
516
517 uint16_t length = get_message_size (message, GNUNET_YES);
518
519 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
520
521 GNUNET_memcpy(&(msg->key), key, sizeof(msg->key));
522 GNUNET_memcpy(&(msg->sender), &sender, sizeof(msg->sender));
523 GNUNET_memcpy(&(msg->context), context, sizeof(msg->context));
524 GNUNET_memcpy(&(msg->hash), hash, sizeof(msg->hash));
525
526 msg->flags = (uint32_t) (
527 private_message? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
528 );
529
530 char *buffer = ((char*) msg) + sizeof(*msg);
531 encode_message (message, length, buffer, GNUNET_YES);
532
533 if (private_message)
534 destroy_message(private_message);
535
536 GNUNET_MQ_send (handle->mq, env);
400} 537}
401 538
402static int callback_scan_for_rooms(void* cls, const char *filename) { 539static int
403 struct GNUNET_MESSENGER_SrvHandle* handle = cls; 540callback_scan_for_rooms (void *cls, const char *filename)
541{
542 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
404 543
405 struct GNUNET_CONFIGURATION_Handle* cfg = GNUNET_CONFIGURATION_create(); 544 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
406 545
407 if ((GNUNET_YES == GNUNET_DISK_file_test(filename)) && 546 if ((GNUNET_YES == GNUNET_DISK_file_test (filename)) && (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename)))
408 (GNUNET_OK == GNUNET_CONFIGURATION_parse(cfg, filename)))
409 { 547 {
410 struct GNUNET_HashCode key; 548 struct GNUNET_HashCode key;
411 struct GNUNET_ShortHashCode member_id; 549 struct GNUNET_ShortHashCode member_id;
412 550
413 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data(cfg, "room", "key", &key, sizeof(key))) && 551 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "key", &key, sizeof(key))) &&
414 (GNUNET_OK == GNUNET_CONFIGURATION_get_data(cfg, "room", "member_id", &member_id, sizeof(member_id)))) 552 (GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "member_id", &member_id, sizeof(member_id))))
415 change_handle_member_id(handle, &key, &member_id); 553 change_handle_member_id (handle, &key, &member_id);
416 } 554 }
417 555
418 GNUNET_CONFIGURATION_destroy(cfg); 556 GNUNET_CONFIGURATION_destroy (cfg);
419 return GNUNET_OK; 557 return GNUNET_OK;
420} 558}
421 559
422void load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) { 560void
423 char* id_dir; 561load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
424 get_handle_data_subdir(handle, handle->name, &id_dir); 562{
563 GNUNET_assert(handle);
425 564
426 if (GNUNET_YES == GNUNET_DISK_directory_test(id_dir, GNUNET_YES)) 565 char *id_dir;
566 get_handle_data_subdir (handle, handle->name, &id_dir);
567
568 if (GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_YES))
427 { 569 {
428 char* scan_dir; 570 char *scan_dir;
429 GNUNET_asprintf(&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR); 571 GNUNET_asprintf (&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
430 572
431 if (GNUNET_OK == GNUNET_DISK_directory_test(scan_dir, GNUNET_YES)) 573 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
432 GNUNET_DISK_directory_scan(scan_dir, callback_scan_for_rooms, handle); 574 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_rooms, handle);
433 575
434 GNUNET_free(scan_dir); 576 GNUNET_free(scan_dir);
435 } 577 }
@@ -438,63 +580,64 @@ void load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) {
438} 580}
439 581
440static int 582static int
441iterate_save_rooms(void* cls, const struct GNUNET_HashCode* key, void* value) 583iterate_save_rooms (void *cls, const struct GNUNET_HashCode *key, void *value)
442{ 584{
443 struct GNUNET_MESSENGER_SrvHandle* handle = cls; 585 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
444 struct GNUNET_ShortHashCode* member_id = value; 586 struct GNUNET_ShortHashCode *member_id = value;
445 587
446 char* id_dir; 588 char *id_dir;
447 get_handle_data_subdir(handle, handle->name, &id_dir); 589 get_handle_data_subdir (handle, handle->name, &id_dir);
448 590
449 char* filename; 591 char *filename;
450 GNUNET_asprintf(&filename, "%s%s%c%s.cfg", 592 GNUNET_asprintf (&filename, "%s%s%c%s.cfg", id_dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (key));
451 id_dir, "rooms", DIR_SEPARATOR,
452 GNUNET_h2s(key));
453 593
454 GNUNET_free(id_dir); 594 GNUNET_free(id_dir);
455 595
456 struct GNUNET_CONFIGURATION_Handle* cfg = GNUNET_CONFIGURATION_create(); 596 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
457 597
458 char* key_data = GNUNET_STRINGS_data_to_string_alloc(key, sizeof(*key)); 598 char *key_data = GNUNET_STRINGS_data_to_string_alloc (key, sizeof(*key));
459 599
460 if (key_data) 600 if (key_data)
461 { 601 {
462 GNUNET_CONFIGURATION_set_value_string(cfg, "room", "key", key_data); 602 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "key", key_data);
463 603
464 GNUNET_free(key_data); 604 GNUNET_free(key_data);
465 } 605 }
466 606
467 char* member_id_data = GNUNET_STRINGS_data_to_string_alloc(member_id, sizeof(*member_id)); 607 char *member_id_data = GNUNET_STRINGS_data_to_string_alloc (member_id, sizeof(*member_id));
468 608
469 if (member_id_data) 609 if (member_id_data)
470 { 610 {
471 GNUNET_CONFIGURATION_set_value_string(cfg, "room", "member_id", member_id_data); 611 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "member_id", member_id_data);
472 612
473 GNUNET_free(member_id_data); 613 GNUNET_free(member_id_data);
474 } 614 }
475 615
476 GNUNET_CONFIGURATION_write(cfg, filename); 616 GNUNET_CONFIGURATION_write (cfg, filename);
477 GNUNET_CONFIGURATION_destroy(cfg); 617 GNUNET_CONFIGURATION_destroy (cfg);
478 618
479 GNUNET_free(filename); 619 GNUNET_free(filename);
480 620
481 return GNUNET_YES; 621 return GNUNET_YES;
482} 622}
483 623
484void save_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) 624void
625save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
485{ 626{
486 char* id_dir; 627 GNUNET_assert(handle);
487 get_handle_data_subdir(handle, handle->name, &id_dir); 628
629 char *id_dir;
630 get_handle_data_subdir (handle, handle->name, &id_dir);
488 631
489 if ((GNUNET_YES == GNUNET_DISK_directory_test(id_dir, GNUNET_NO)) || 632 if ((GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_NO)) || (GNUNET_OK
490 (GNUNET_OK == GNUNET_DISK_directory_create(id_dir))) 633 == GNUNET_DISK_directory_create (id_dir)))
491 { 634 {
492 char* save_dir; 635 char *save_dir;
493 GNUNET_asprintf(&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR); 636 GNUNET_asprintf (&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
494 637
495 if ((GNUNET_YES == GNUNET_DISK_directory_test(save_dir, GNUNET_NO)) || 638 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
496 (GNUNET_OK == GNUNET_DISK_directory_create(save_dir))) 639 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
497 GNUNET_CONTAINER_multihashmap_iterate(handle->member_ids, iterate_save_rooms, handle); 640 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_save_rooms, handle);
498 641
499 GNUNET_free(save_dir); 642 GNUNET_free(save_dir);
500 } 643 }
diff --git a/src/messenger/gnunet-service-messenger_handle.h b/src/messenger/gnunet-service-messenger_handle.h
index 81cf377a8..70b2cac6d 100644
--- a/src/messenger/gnunet-service-messenger_handle.h
+++ b/src/messenger/gnunet-service-messenger_handle.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -35,6 +35,7 @@
35#include "gnunet_mq_lib.h" 35#include "gnunet_mq_lib.h"
36 36
37#include "gnunet-service-messenger_service.h" 37#include "gnunet-service-messenger_service.h"
38#include "gnunet-service-messenger_member_session.h"
38 39
39#include "messenger_api_ego.h" 40#include "messenger_api_ego.h"
40#include "messenger_api_message.h" 41#include "messenger_api_message.h"
@@ -46,9 +47,7 @@ struct GNUNET_MESSENGER_SrvHandle
46 47
47 char *name; 48 char *name;
48 49
49 struct GNUNET_IDENTITY_Operation *operation; 50 const struct GNUNET_MESSENGER_Ego *ego;
50
51 struct GNUNET_MESSENGER_Ego *ego;
52 51
53 struct GNUNET_CONTAINER_MultiHashMap *member_ids; 52 struct GNUNET_CONTAINER_MultiHashMap *member_ids;
54}; 53};
@@ -56,8 +55,8 @@ struct GNUNET_MESSENGER_SrvHandle
56/** 55/**
57 * Creates and allocates a new handle related to a <i>service</i> and using a given <i>mq</i> (message queue). 56 * Creates and allocates a new handle related to a <i>service</i> and using a given <i>mq</i> (message queue).
58 * 57 *
59 * @param service MESSENGER Service 58 * @param[in/out] service MESSENGER Service
60 * @param mq Message queue 59 * @param[in/out] mq Message queue
61 * @return New handle 60 * @return New handle
62 */ 61 */
63struct GNUNET_MESSENGER_SrvHandle* 62struct GNUNET_MESSENGER_SrvHandle*
@@ -66,7 +65,7 @@ create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle
66/** 65/**
67 * Destroys a handle and frees its memory fully. 66 * Destroys a handle and frees its memory fully.
68 * 67 *
69 * @param handle Handle 68 * @param[in/out] handle Handle
70 */ 69 */
71void 70void
72destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle); 71destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
@@ -75,52 +74,63 @@ destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
75 * Writes the path of the directory for a given <i>handle</i> using a specific <i>name</i> to the parameter 74 * Writes the path of the directory for a given <i>handle</i> using a specific <i>name</i> to the parameter
76 * <i>dir</i>. This directory will be used to store data regarding the handle and its messages. 75 * <i>dir</i>. This directory will be used to store data regarding the handle and its messages.
77 * 76 *
78 * @param handle Handle 77 * @param[in] handle Handle
79 * @param name Potential name of the handle 78 * @param[in] name Potential name of the handle
80 * @param dir[out] Path to store data 79 * @param[out] dir Path to store data
81 */ 80 */
82void 81void
83get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir); 82get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir);
84 83
85/** 84/**
86 * Returns the member id of a given <i>handle</i> in a specific <i>room</i>. 85 * Returns the member id of a given <i>handle</i> in a specific <i>room</i>.
87 * 86 *
88 * If the handle is not a member of the specific <i>room</i>, NULL gets returned. 87 * If the handle is not a member of the specific <i>room</i>, NULL gets returned.
89 * 88 *
90 * @param handle Handle 89 * @param[in] handle Handle
91 * @param key Key of a room 90 * @param[in] key Key of a room
92 * @return Member id or NULL 91 * @return Member id or NULL
93 */ 92 */
94const struct GNUNET_ShortHashCode* 93const struct GNUNET_ShortHashCode*
95get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); 94get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
96 95
97/** 96/**
98 * Changes the member id of a given <i>handle</i> in a specific <i>room</i> to match a <i>unique_id</i>. 97 * Changes the member id of a given <i>handle</i> in a specific <i>room</i> to match a <i>unique_id</i>
98 * and returns GNUNET_OK on success.
99 * 99 *
100 * The client connected to the <i>handle</i> will be informed afterwards automatically. 100 * The client connected to the <i>handle</i> will be informed afterwards automatically.
101 * 101 *
102 * @param handle Handle 102 * @param[in/out] handle Handle
103 * @param key Key of a room 103 * @param[in] key Key of a room
104 * @param unique_id Unique member id 104 * @param[in] unique_id Unique member id
105 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR
105 */ 106 */
106void 107int
107change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, 108change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
108 const struct GNUNET_ShortHashCode *unique_id); 109 const struct GNUNET_ShortHashCode *unique_id);
109 110
110/** 111/**
112 * Sets the EGO used by a given <i>handle</i>.
113 *
114 * @param[in/out] handle Handle
115 * @param[in] ego EGO keypair
116 */
117void
118set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego);
119
120/**
111 * Returns the EGO used by a given <i>handle</i>. 121 * Returns the EGO used by a given <i>handle</i>.
112 * 122 *
113 * @param handle Handle 123 * @param[in] handle Handle
114 * @return EGO keypair 124 * @return EGO keypair
115 */ 125 */
116struct GNUNET_MESSENGER_Ego* 126const struct GNUNET_MESSENGER_Ego*
117get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle); 127get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle);
118 128
119/** 129/**
120 * Tries to set the name and EGO key of a <i>handle</i> initially by looking up a specific <i>name</i>. 130 * Tries to set the name and EGO key of a <i>handle</i> initially by looking up a specific <i>name</i>.
121 * 131 *
122 * @param handle Handle 132 * @param[in/out] handle Handle
123 * @param name Name (optionally: valid EGO name) 133 * @param[in] name Name (optionally: valid EGO name)
124 */ 134 */
125void 135void
126setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name); 136setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name);
@@ -129,10 +139,9 @@ setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name);
129 * Tries to change the keypair of an EGO of a <i>handle</i> under the same name and informs all rooms 139 * Tries to change the keypair of an EGO of a <i>handle</i> under the same name and informs all rooms
130 * about the change automatically. 140 * about the change automatically.
131 * 141 *
132 * @param handle Handle 142 * @param[in/out] handle Handle
133 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR
134 */ 143 */
135int 144void
136update_handle (struct GNUNET_MESSENGER_SrvHandle *handle); 145update_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
137 146
138/** 147/**
@@ -141,20 +150,19 @@ update_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
141 * 150 *
142 * The client connected to the <i>handle</i> will be informed afterwards automatically. 151 * The client connected to the <i>handle</i> will be informed afterwards automatically.
143 * 152 *
144 * @param handle Handle 153 * @param[in/out] handle Handle
145 * @param name New name 154 * @param[in] name New name
146 * @return GNUNET_OK on success, otherwise GNUNET_NO
147 */ 155 */
148int 156void
149set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name); 157set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name);
150 158
151/** 159/**
152 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and opens the 160 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and opens the
153 * room from the handles service. 161 * room from the handles service.
154 * 162 *
155 * @param handle Handle 163 * @param[in/out] handle Handle
156 * @param key Key of a room 164 * @param[in] key Key of a room
157 * @return GNUNET_YES on success, otherwise GNUNET_NO 165 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
158 */ 166 */
159int 167int
160open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); 168open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
@@ -163,10 +171,10 @@ open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET
163 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and enters the room 171 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and enters the room
164 * through a tunnel to a peer identified by a given <i>door</i> (peer identity). 172 * through a tunnel to a peer identified by a given <i>door</i> (peer identity).
165 * 173 *
166 * @param handle Handle 174 * @param[in/out] handle Handle
167 * @param door Peer identity 175 * @param[in] door Peer identity
168 * @param key Key of a room 176 * @param[in] key Key of a room
169 * @return GNUNET_YES on success, otherwise GNUNET_NO 177 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
170 */ 178 */
171int 179int
172entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door, 180entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door,
@@ -176,9 +184,9 @@ entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNE
176 * Removes the membership of the room using a specific <i>key</i> and closes it if no other handle 184 * Removes the membership of the room using a specific <i>key</i> and closes it if no other handle
177 * from this service is still a member of it. 185 * from this service is still a member of it.
178 * 186 *
179 * @param handle Handle 187 * @param[in/out] handle Handle
180 * @param key Key of a room 188 * @param[in] key Key of a room
181 * @return GNUNET_YES on success, otherwise GNUNET_NO 189 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
182 */ 190 */
183int 191int
184close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); 192close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
@@ -186,31 +194,45 @@ close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNE
186/** 194/**
187 * Sends a <i>message</i> from a given <i>handle</i> to the room using a specific <i>key</i>. 195 * Sends a <i>message</i> from a given <i>handle</i> to the room using a specific <i>key</i>.
188 * 196 *
189 * @param handle Handle 197 * @param[in/out] handle Handle
190 * @param key Key of a room 198 * @param[in] key Key of a room
191 * @param message Message 199 * @param[in] message Message
192 * @return GNUNET_YES on success, otherwise GNUNET_NO 200 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
193 */ 201 */
194int 202int
195send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, 203send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
196 struct GNUNET_MESSENGER_Message *message); 204 const struct GNUNET_MESSENGER_Message *message);
205
206/**
207 * Notifies the handle that a new message was received or sent.
208 *
209 * @param[in/out] handle Handle
210 * @param[in] key Key of room
211 * @param[in] session Member session
212 * @param[in] message Message
213 * @param[in] hash Hash of message
214 */
215void
216notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
217 const struct GNUNET_MESSENGER_MemberSession *session,
218 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
197 219
198/** 220/**
199 * Loads member ids and other potential configuration from a given <i>handle</i> which 221 * Loads member ids and other potential configuration from a given <i>handle</i> which
200 * depends on the given name the <i>handle</i> uses. 222 * depends on the given name the <i>handle</i> uses.
201 * 223 *
202 * @param handle Handle 224 * @param[out] handle Handle
203 */ 225 */
204void 226void
205load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle); 227load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
206 228
207/** 229/**
208 * Saves member ids and other potential configuration from a given <i>handle</i> which 230 * Saves member ids and other potential configuration from a given <i>handle</i> which
209 * depends on the given name the <i>handle</i> uses. 231 * depends on the given name the <i>handle</i> uses.
210 * 232 *
211 * @param handle Handle 233 * @param[in] handle Handle
212 */ 234 */
213void 235void
214save_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle); 236save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
215 237
216#endif //GNUNET_SERVICE_MESSENGER_HANDLE_H 238#endif //GNUNET_SERVICE_MESSENGER_HANDLE_H
diff --git a/src/messenger/gnunet-service-messenger_list_handles.c b/src/messenger/gnunet-service-messenger_list_handles.c
index 16a160dea..adcbf6a42 100644
--- a/src/messenger/gnunet-service-messenger_list_handles.c
+++ b/src/messenger/gnunet-service-messenger_list_handles.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -55,8 +55,10 @@ clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles)
55} 55}
56 56
57void 57void
58add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle) 58add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle)
59{ 59{
60 GNUNET_assert((handles) && (handle));
61
60 struct GNUNET_MESSENGER_ListHandle *element = GNUNET_new(struct GNUNET_MESSENGER_ListHandle); 62 struct GNUNET_MESSENGER_ListHandle *element = GNUNET_new(struct GNUNET_MESSENGER_ListHandle);
61 63
62 element->handle = handle; 64 element->handle = handle;
@@ -65,8 +67,10 @@ add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle)
65} 67}
66 68
67int 69int
68remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle) 70remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle)
69{ 71{
72 GNUNET_assert((handles) && (handle));
73
70 struct GNUNET_MESSENGER_ListHandle *element; 74 struct GNUNET_MESSENGER_ListHandle *element;
71 75
72 for (element = handles->head; element; element = element->next) 76 for (element = handles->head; element; element = element->next)
@@ -82,9 +86,11 @@ remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle)
82 return GNUNET_YES; 86 return GNUNET_YES;
83} 87}
84 88
85void* 89struct GNUNET_MESSENGER_SrvHandle*
86find_list_handle_by_member (struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key) 90find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key)
87{ 91{
92 GNUNET_assert((handles) && (key));
93
88 struct GNUNET_MESSENGER_ListHandle *element; 94 struct GNUNET_MESSENGER_ListHandle *element;
89 95
90 for (element = handles->head; element; element = element->next) 96 for (element = handles->head; element; element = element->next)
diff --git a/src/messenger/gnunet-service-messenger_list_handles.h b/src/messenger/gnunet-service-messenger_list_handles.h
index fe92cc58a..9f7ca725f 100644
--- a/src/messenger/gnunet-service-messenger_list_handles.h
+++ b/src/messenger/gnunet-service-messenger_list_handles.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -30,12 +30,14 @@
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h" 31#include "gnunet_container_lib.h"
32 32
33struct GNUNET_MESSENGER_SrvHandle;
34
33struct GNUNET_MESSENGER_ListHandle 35struct GNUNET_MESSENGER_ListHandle
34{ 36{
35 struct GNUNET_MESSENGER_ListHandle *prev; 37 struct GNUNET_MESSENGER_ListHandle *prev;
36 struct GNUNET_MESSENGER_ListHandle *next; 38 struct GNUNET_MESSENGER_ListHandle *next;
37 39
38 void *handle; 40 struct GNUNET_MESSENGER_SrvHandle *handle;
39}; 41};
40 42
41struct GNUNET_MESSENGER_ListHandles 43struct GNUNET_MESSENGER_ListHandles
@@ -45,17 +47,17 @@ struct GNUNET_MESSENGER_ListHandles
45}; 47};
46 48
47/** 49/**
48 * Initializes list of handles as empty list. 50 * Initializes list of <i>handles</i> as empty list.
49 * 51 *
50 * @param handles List of handles 52 * @param[out] handles List of handles
51 */ 53 */
52void 54void
53init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles); 55init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
54 56
55/** 57/**
56 * Destroys remaining handles and clears the list. 58 * Destroys remaining <i>handles</i> and clears the list.
57 * 59 *
58 * @param handles List of handles 60 * @param[in/out] handles List of handles
59 */ 61 */
60void 62void
61clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles); 63clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
@@ -63,34 +65,34 @@ clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
63/** 65/**
64 * Adds a specific <i>handle</i> to the end of the list. 66 * Adds a specific <i>handle</i> to the end of the list.
65 * 67 *
66 * @param handles List of handles 68 * @param[in/out] handles List of handles
67 * @param handle Handle 69 * @param[in/out] handle Handle
68 */ 70 */
69void 71void
70add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle); 72add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle);
71 73
72/** 74/**
73 * Removes the first entry matching with a specific <i>handle</i> from the list and 75 * Removes the first entry matching with a specific <i>handle</i> from the list of
74 * returns GNUNET_YES on success or GNUNET_NO on failure. 76 * <i>handles</i> and returns #GNUNET_YES on success or #GNUNET_NO on failure.
75 * 77 *
76 * @param handles List of handles 78 * @param[in/out] handles List of handles
77 * @param handle Handle 79 * @param[in/out] handle Handle
78 * @return GNUNET_YES on success, otherwise GNUNET_NO 80 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
79 */ 81 */
80int 82int
81remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle); 83remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle);
82 84
83/** 85/**
84 * Searches linearly through the list of handles for members of a specific room 86 * Searches linearly through the list of <i>handles</i> for members of a specific room
85 * which is identified by a given <i>key</i>. 87 * which is identified by a given <i>key</i>.
86 * 88 *
87 * If no handle is found which is a current member, NULL gets returned. 89 * If no handle is found which is a current member, NULL gets returned.
88 * 90 *
89 * @param handles List of handles 91 * @param[in] handles List of handles
90 * @param key Common key of a room 92 * @param[in] key Common key of a room
91 * @return First handle which is a current member 93 * @return First handle which is a current member
92 */ 94 */
93void* 95struct GNUNET_MESSENGER_SrvHandle*
94find_list_handle_by_member (struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key); 96find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key);
95 97
96#endif //GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H 98#endif //GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H
diff --git a/src/messenger/gnunet-service-messenger_list_messages.c b/src/messenger/gnunet-service-messenger_list_messages.c
index c4f1f7043..bb6086e41 100644
--- a/src/messenger/gnunet-service-messenger_list_messages.c
+++ b/src/messenger/gnunet-service-messenger_list_messages.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -54,6 +54,8 @@ clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages)
54void 54void
55add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash) 55add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash)
56{ 56{
57 GNUNET_assert((messages) && (hash));
58
57 struct GNUNET_MESSENGER_ListMessage *element = GNUNET_new(struct GNUNET_MESSENGER_ListMessage); 59 struct GNUNET_MESSENGER_ListMessage *element = GNUNET_new(struct GNUNET_MESSENGER_ListMessage);
58 60
59 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode)); 61 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode));
@@ -62,8 +64,21 @@ add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const stru
62} 64}
63 65
64void 66void
67copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_MESSENGER_ListMessages *origin)
68{
69 GNUNET_assert((messages) && (origin));
70
71 struct GNUNET_MESSENGER_ListMessage *element;
72
73 for (element = origin->head; element; element = element->next)
74 add_to_list_messages (messages, &(element->hash));
75}
76
77void
65remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash) 78remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash)
66{ 79{
80 GNUNET_assert((messages) && (hash));
81
67 struct GNUNET_MESSENGER_ListMessage *element; 82 struct GNUNET_MESSENGER_ListMessage *element;
68 83
69 for (element = messages->head; element; element = element->next) 84 for (element = messages->head; element; element = element->next)
@@ -74,3 +89,62 @@ remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const
74 break; 89 break;
75 } 90 }
76} 91}
92
93void
94load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path)
95{
96 GNUNET_assert((messages) && (path));
97
98 if (GNUNET_YES != GNUNET_DISK_file_test (path))
99 return;
100
101 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
102
103 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
104 path, GNUNET_DISK_OPEN_READ, permission
105 );
106
107 if (!handle)
108 return;
109
110 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
111
112 struct GNUNET_HashCode hash;
113 ssize_t len;
114
115 do {
116 len = GNUNET_DISK_file_read(handle, &hash, sizeof(hash));
117
118 if (len != sizeof(hash))
119 break;
120
121 add_to_list_messages(messages, &hash);
122 } while (len == sizeof(hash));
123
124 GNUNET_DISK_file_close(handle);
125}
126
127void
128save_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path)
129{
130 GNUNET_assert((messages) && (path));
131
132 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
133
134 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
135 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
136 );
137
138 if (!handle)
139 return;
140
141 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
142
143 struct GNUNET_MESSENGER_ListMessage *element;
144
145 for (element = messages->head; element; element = element->next)
146 GNUNET_DISK_file_write(handle, &(element->hash), sizeof(element->hash));
147
148 GNUNET_DISK_file_sync(handle);
149 GNUNET_DISK_file_close(handle);
150}
diff --git a/src/messenger/gnunet-service-messenger_list_messages.h b/src/messenger/gnunet-service-messenger_list_messages.h
index 266c30ec6..9ace84cbf 100644
--- a/src/messenger/gnunet-service-messenger_list_messages.h
+++ b/src/messenger/gnunet-service-messenger_list_messages.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -29,6 +29,7 @@
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h" 31#include "gnunet_container_lib.h"
32#include "gnunet_disk_lib.h"
32 33
33struct GNUNET_MESSENGER_ListMessage 34struct GNUNET_MESSENGER_ListMessage
34{ 35{
@@ -47,7 +48,7 @@ struct GNUNET_MESSENGER_ListMessages
47/** 48/**
48 * Initializes list of message hashes as empty list. 49 * Initializes list of message hashes as empty list.
49 * 50 *
50 * @param messages List of hashes 51 * @param[out] messages List of hashes
51 */ 52 */
52void 53void
53init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages); 54init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
@@ -55,7 +56,7 @@ init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
55/** 56/**
56 * Clears the list of message hashes. 57 * Clears the list of message hashes.
57 * 58 *
58 * @param messages List of hashes 59 * @param[in/out] messages List of hashes
59 */ 60 */
60void 61void
61clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages); 62clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
@@ -63,19 +64,46 @@ clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
63/** 64/**
64 * Adds a specific <i>hash</i> from a message to the end of the list. 65 * Adds a specific <i>hash</i> from a message to the end of the list.
65 * 66 *
66 * @param messages List of hashes 67 * @param[in/out] messages List of hashes
67 * @param hash Hash of message 68 * @param[in] hash Hash of message
68 */ 69 */
69void 70void
70add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash); 71add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash);
71 72
72/** 73/**
74 * Copies all message hashes from an <i>origin</i> to another list.
75 *
76 * @param[in/out] messages Destination list of hashes
77 * @param[in] origin Source list of hashes
78 */
79void
80copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_MESSENGER_ListMessages *origin);
81
82/**
73 * Removes the first entry with a matching <i>hash</i> from the list. 83 * Removes the first entry with a matching <i>hash</i> from the list.
74 * 84 *
75 * @param messages List of hashes 85 * @param[in/out] messages List of hashes
76 * @param hash Hash of message 86 * @param[in] hash Hash of message
77 */ 87 */
78void 88void
79remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash); 89remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash);
80 90
91/**
92 * Loads the list of message hashes from a file under a given <i>path</i>.
93 *
94 * @param[out] messages List of hashes
95 * @param[in] path Path of file
96 */
97void
98load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path);
99
100/**
101 * Saves the list of message hashes to a file under a given <i>path</i>.
102 *
103 * @param[in] messages List of hashes
104 * @param[in] path Path of file
105 */
106void
107save_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path);
108
81#endif //GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H 109#endif //GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H
diff --git a/src/messenger/gnunet-service-messenger_member.c b/src/messenger/gnunet-service-messenger_member.c
new file mode 100755
index 000000000..7f00e8438
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member.c
@@ -0,0 +1,385 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_member.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member.h"
27
28#include "gnunet-service-messenger_member_session.h"
29
30struct GNUNET_MESSENGER_Member*
31create_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
32{
33 GNUNET_assert (store);
34
35 struct GNUNET_MESSENGER_Member *member = GNUNET_new(struct GNUNET_MESSENGER_Member);
36
37 member->store = store;
38
39 if (id)
40 GNUNET_memcpy(&(member->id), id, sizeof(member->id));
41 else if (GNUNET_YES != generate_free_member_id(&(member->id), store->members))
42 {
43 GNUNET_free (member);
44 return NULL;
45 }
46
47 member->sessions = GNUNET_CONTAINER_multihashmap_create(2, GNUNET_NO);
48
49 return member;
50}
51
52static int
53iterate_destroy_session (void *cls, const struct GNUNET_HashCode *key, void *value)
54{
55 struct GNUNET_MESSENGER_MemberSession *session = value;
56 destroy_member_session(session);
57 return GNUNET_YES;
58}
59
60void
61destroy_member (struct GNUNET_MESSENGER_Member *member)
62{
63 GNUNET_assert((member) && (member->sessions));
64
65 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_destroy_session, NULL);
66 GNUNET_CONTAINER_multihashmap_destroy (member->sessions);
67
68 GNUNET_free (member);
69}
70
71const struct GNUNET_ShortHashCode*
72get_member_id (const struct GNUNET_MESSENGER_Member *member)
73{
74 GNUNET_assert (member);
75
76 return &(member->id);
77}
78
79static int
80callback_scan_for_sessions (void *cls, const char *filename)
81{
82 struct GNUNET_MESSENGER_Member *member = cls;
83
84 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
85 {
86 char *directory;
87
88 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
89
90 load_member_session(member, directory);
91 }
92
93 return GNUNET_OK;
94}
95
96void
97load_member (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
98{
99 GNUNET_assert ((store) && (directory));
100
101 char *config_file;
102 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
103
104 struct GNUNET_MESSENGER_Member *member = NULL;
105
106 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
107 goto free_config;
108
109 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
110
111 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
112 {
113 struct GNUNET_ShortHashCode id;
114
115 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "member", "id", &id, sizeof(id)))
116 goto destroy_config;
117
118 member = add_store_member(store, &id);
119 }
120
121destroy_config:
122
123 GNUNET_CONFIGURATION_destroy (cfg);
124
125free_config:
126 GNUNET_free(config_file);
127
128 if (!member)
129 return;
130
131 char *scan_dir;
132 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
133
134 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
135 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_sessions, member);
136
137 GNUNET_free(scan_dir);
138}
139
140static int
141iterate_load_next_session (void *cls, const struct GNUNET_HashCode *key, void *value)
142{
143 const char* sessions_directory = cls;
144
145 char* load_dir;
146 GNUNET_asprintf (&load_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
147
148 struct GNUNET_MESSENGER_MemberSession *session = value;
149
150 if (GNUNET_YES == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
151 load_member_session_next (session, load_dir);
152
153 GNUNET_free (load_dir);
154 return GNUNET_YES;
155}
156
157void
158load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member, const char *directory)
159{
160 GNUNET_assert ((member) && (directory));
161
162 char* load_dir;
163 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
164
165 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_load_next_session, load_dir);
166
167 GNUNET_free(load_dir);
168}
169
170static int
171iterate_save_session (void *cls, const struct GNUNET_HashCode *key, void *value)
172{
173 const char* sessions_directory = cls;
174
175 char* save_dir;
176 GNUNET_asprintf (&save_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
177
178 struct GNUNET_MESSENGER_MemberSession *session = value;
179
180 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
181 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
182 save_member_session (session, save_dir);
183
184 GNUNET_free (save_dir);
185 return GNUNET_YES;
186}
187
188void
189save_member (struct GNUNET_MESSENGER_Member *member, const char *directory)
190{
191 GNUNET_assert ((member) && (directory));
192
193 char *config_file;
194 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
195
196 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
197
198 char *id_data = GNUNET_STRINGS_data_to_string_alloc (&(member->id), sizeof(member->id));
199
200 if (id_data)
201 {
202 GNUNET_CONFIGURATION_set_value_string (cfg, "member", "id", id_data);
203
204 GNUNET_free(id_data);
205 }
206
207 GNUNET_CONFIGURATION_write (cfg, config_file);
208 GNUNET_CONFIGURATION_destroy (cfg);
209
210 GNUNET_free(config_file);
211
212 char* save_dir;
213 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
214
215 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
216 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
217 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_save_session, save_dir);
218
219 GNUNET_free(save_dir);
220}
221
222static void
223sync_session_contact_from_next (struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
224{
225 GNUNET_assert((session) && (next));
226
227 if (session == next)
228 return;
229
230 if (next->next)
231 sync_session_contact_from_next (session, next->next);
232 else
233 session->contact = next->contact;
234}
235
236static int
237iterate_sync_session_contact (void *cls, const struct GNUNET_HashCode *key, void *value)
238{
239 struct GNUNET_MESSENGER_MemberSession *session = value;
240
241 if (session->next)
242 sync_session_contact_from_next (session, session->next);
243
244 return GNUNET_YES;
245}
246
247void
248sync_member_contacts (struct GNUNET_MESSENGER_Member *member)
249{
250 GNUNET_assert ((member) && (member->sessions));
251
252 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_sync_session_contact, NULL);
253}
254
255struct GNUNET_MESSENGER_MemberSession*
256get_member_session (const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
257{
258 GNUNET_assert ((member) && (public_key));
259
260 struct GNUNET_HashCode hash;
261 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
262
263 return GNUNET_CONTAINER_multihashmap_get(member->sessions, &hash);
264}
265
266struct GNUNET_MESSENGER_ClosureSearchSession {
267 const struct GNUNET_MESSENGER_Message *message;
268 const struct GNUNET_HashCode *hash;
269
270 struct GNUNET_MESSENGER_MemberSession *match;
271};
272
273static int
274iterate_search_session (void *cls, const struct GNUNET_HashCode *key, void *value)
275{
276 struct GNUNET_MESSENGER_ClosureSearchSession* search = cls;
277 struct GNUNET_MESSENGER_MemberSession *session = value;
278
279 if (GNUNET_OK != verify_member_session_as_sender(session, search->message, search->hash))
280 return GNUNET_YES;
281
282 search->match = session;
283 return GNUNET_NO;
284}
285
286static struct GNUNET_MESSENGER_MemberSession*
287try_member_session (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
288{
289 struct GNUNET_MESSENGER_MemberSession* session = get_member_session(member, public_key);
290
291 if (session)
292 return session;
293
294 session = create_member_session(member, public_key);
295
296 if (session)
297 add_member_session(member, session);
298
299 return session;
300}
301
302struct GNUNET_MESSENGER_MemberSession*
303get_member_session_of (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message,
304 const struct GNUNET_HashCode *hash)
305{
306 GNUNET_assert ((member) && (message) && (hash) &&
307 (0 == GNUNET_memcmp(&(member->id), &(message->header.sender_id))));
308
309 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
310 return try_member_session(member, &(message->body.info.host_key));
311 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
312 return try_member_session(member, &(message->body.join.key));
313
314 struct GNUNET_MESSENGER_ClosureSearchSession search;
315
316 search.message = message;
317 search.hash = hash;
318
319 search.match = NULL;
320 GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_search_session, &search);
321
322 return search.match;
323}
324
325void
326add_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
327{
328 if (!session)
329 return;
330
331 GNUNET_assert((member) && (session->member == member));
332
333 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
334
335 struct GNUNET_HashCode hash;
336 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
337
338 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
339 member->sessions, &hash, session,
340 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
341 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Adding a member session failed: %s\n",
342 GNUNET_h2s(&hash));
343}
344
345void
346remove_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
347{
348 GNUNET_assert ((member) && (session) && (session->member == member));
349
350 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
351
352 struct GNUNET_HashCode hash;
353 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
354
355 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(member->sessions, &hash, session))
356 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a member session failed: %s\n",
357 GNUNET_h2s(&hash));
358}
359
360struct GNUNET_MESSENGER_ClosureIterateSessions {
361 GNUNET_MESSENGER_MemberIteratorCallback it;
362 void *cls;
363};
364
365static int
366iterate_member_sessions_it (void *cls, const struct GNUNET_HashCode *key, void *value)
367{
368 struct GNUNET_MESSENGER_ClosureIterateSessions *iterate = cls;
369 struct GNUNET_MESSENGER_MemberSession *session = value;
370
371 return iterate->it (iterate->cls, get_member_session_public_key(session), session);
372}
373
374int
375iterate_member_sessions (struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void *cls)
376{
377 GNUNET_assert ((member) && (member->sessions) && (it));
378
379 struct GNUNET_MESSENGER_ClosureIterateSessions iterate;
380
381 iterate.it = it;
382 iterate.cls = cls;
383
384 return GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_member_sessions_it, &iterate);
385}
diff --git a/src/messenger/gnunet-service-messenger_member.h b/src/messenger/gnunet-service-messenger_member.h
new file mode 100644
index 000000000..fb2e57cfb
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member.h
@@ -0,0 +1,170 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_member.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_H
28
29#include "messenger_api_contact.h"
30
31#include "gnunet-service-messenger_list_messages.h"
32#include "gnunet-service-messenger_member_store.h"
33#include "messenger_api_message.h"
34#include "messenger_api_util.h"
35
36struct GNUNET_MESSENGER_Member
37{
38 struct GNUNET_MESSENGER_MemberStore *store;
39 struct GNUNET_ShortHashCode id;
40
41 struct GNUNET_CONTAINER_MultiHashMap *sessions;
42};
43
44/**
45 * Creates and allocates a new member of a <i>room</i> with an optionally defined or
46 * random <i>id</i>.
47 *
48 * If the creation fails, NULL gets returned.
49 *
50 * @param[in/out] store Member store
51 * @param[in] id Member id or NULL
52 * @return New member or NULL
53 */
54struct GNUNET_MESSENGER_Member*
55create_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
56
57/**
58 * Destroys a member and frees its memory fully.
59 *
60 * @param[in/out] member Member
61 */
62void
63destroy_member (struct GNUNET_MESSENGER_Member *member);
64
65/**
66 * Returns the current id of a given <i>member</i>.
67 *
68 * @param[in] member Member
69 * @return Member id
70 */
71const struct GNUNET_ShortHashCode*
72get_member_id (const struct GNUNET_MESSENGER_Member *member);
73
74/**
75 * Loads data from a <i>directory</i> into a new allocated and created member
76 * of a <i>store</i> if the required information can be read from the content
77 * of the given directory.
78 *
79 * @param[out] store Member store
80 * @param[in] directory Path to a directory
81 */
82void
83load_member (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
84
85/**
86 * Loads data about next sessions from a <i>directory</i> into an empty loaded
87 * <i>member</i> which does not contain a fully built session graph yet.
88 *
89 * @param[in/out] member Member
90 * @param[in] directory Path to a directory
91 */
92void
93load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member, const char *directory);
94
95/**
96 * Saves data from a <i>member</i> into a directory which
97 * can be load to restore the member completely.
98 *
99 * @param[in] member Member
100 * @param[in] directory Path to a directory
101 */
102void
103save_member (struct GNUNET_MESSENGER_Member *member, const char *directory);
104
105/**
106 * Synchronizes contacts between all sessions from a given <i>member</i>
107 * and other sessions which are linked to them.
108 *
109 * @param[in/out] member Member
110 */
111void
112sync_member_contacts (struct GNUNET_MESSENGER_Member *member);
113
114/**
115 * Returns the member session of a <i>member</i> identified by a given public key.
116 * If the member does not provide a session with the given key, NULL gets returned.
117 *
118 * @param[in] member Member
119 * @param[in] public_key Public key of EGO
120 * @return Member session
121 */
122struct GNUNET_MESSENGER_MemberSession*
123get_member_session (const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key);
124
125/**
126 * Returns the member session of a <i>member</i> using a public key which can verify
127 * the signature of a given <i>message</i> and its <i>hash</i>. If the member does
128 * not provide a matching session, NULL gets returned.
129 *
130 * @param[in] member Member
131 * @param[in] message Message
132 * @param[in] hash Hash of message
133 * @return Member session
134 */
135struct GNUNET_MESSENGER_MemberSession*
136get_member_session_of (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message,
137 const struct GNUNET_HashCode *hash);
138
139/**
140 * Adds a given member <i>session</i> to its <i>member</i>.
141 *
142 * @param[in/out] member Member
143 * @param[in/out] session Member session
144 */
145void
146add_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session);
147
148/**
149 * Removes a given member <i>session</i> from its <i>member</i>.
150 *
151 * @param[in/out] member Member
152 * @param[in/out] session Member session
153 */
154void
155remove_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session);
156
157/**
158 * Iterate through all member sessions currently connected to a given <i>member</i>
159 * and call the provided iterator callback with a selected closure. The function
160 * will return the amount of member sessions it iterated through.
161 *
162 * @param[in/out] member Member
163 * @param[in] it Iterator callback
164 * @param[in/out] cls Closure
165 * @return Amount of sessions iterated through
166 */
167int
168iterate_member_sessions (struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void* cls);
169
170#endif //GNUNET_SERVICE_MESSENGER_MEMBER_H
diff --git a/src/messenger/gnunet-service-messenger_member_session.c b/src/messenger/gnunet-service-messenger_member_session.c
new file mode 100644
index 000000000..690c703b2
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_session.c
@@ -0,0 +1,743 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_member_session.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member_session.h"
27
28#include "gnunet-service-messenger_room.h"
29#include "gnunet-service-messenger_message_store.h"
30
31#include "messenger_api_contact_store.h"
32
33struct GNUNET_MESSENGER_MemberSession*
34create_member_session (struct GNUNET_MESSENGER_Member *member,
35 const struct GNUNET_IDENTITY_PublicKey *pubkey)
36{
37 if ((!member) || (!pubkey) || (!(member->store)))
38 return NULL;
39
40 struct GNUNET_MESSENGER_MemberSession *session = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
41 session->member = member;
42
43 GNUNET_memcpy(&(session->public_key), pubkey, sizeof(session->public_key));
44
45 get_context_from_member (
46 get_member_session_key (session),
47 get_member_session_id (session),
48 &(session->context)
49 );
50
51 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
52
53 session->contact = get_store_contact(
54 store,
55 get_member_session_context (session),
56 get_member_session_public_key (session)
57 );
58
59 if (!(session->contact))
60 {
61 GNUNET_free(session);
62 return NULL;
63 }
64
65 increase_contact_rc (session->contact);
66
67 session->history = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
68
69 init_list_messages(&(session->messages));
70
71 session->prev = NULL;
72 session->next = NULL;
73
74 session->start = GNUNET_TIME_absolute_get();
75
76 session->closed = GNUNET_NO;
77 session->completed = GNUNET_NO;
78
79 return session;
80}
81
82static void
83check_member_session_completion (struct GNUNET_MESSENGER_MemberSession *session)
84{
85 GNUNET_assert (session);
86
87 if (!session->messages.tail)
88 {
89 session->completed = GNUNET_YES;
90 goto completion;
91 }
92
93 const struct GNUNET_HashCode* start = &(session->messages.head->hash);
94 const struct GNUNET_HashCode* end = &(session->messages.tail->hash);
95
96 struct GNUNET_MESSENGER_ListMessages level;
97 init_list_messages(&level);
98
99 add_to_list_messages(&level, end);
100
101 struct GNUNET_MESSENGER_MessageStore *store = get_room_message_store(session->member->store->room);
102
103 struct GNUNET_MESSENGER_ListMessages list;
104 init_list_messages(&list);
105
106 while (level.head)
107 {
108 struct GNUNET_MESSENGER_ListMessage *element;
109
110 for (element = level.head; element; element = element->next)
111 {
112 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
113 store, &(element->hash), GNUNET_NO
114 );
115
116 if (!link)
117 continue;
118
119 add_to_list_messages(&list, &(link->first));
120
121 if (GNUNET_YES == link->multiple)
122 add_to_list_messages(&list, &(link->second));
123 }
124
125 clear_list_messages(&level);
126
127 for (element = list.head; element; element = element->next)
128 if (GNUNET_YES == check_member_session_history(session, &(element->hash), GNUNET_YES))
129 break;
130
131 if (element)
132 if (0 != GNUNET_CRYPTO_hash_cmp(&(element->hash), start))
133 add_to_list_messages(&level, &(element->hash));
134 else
135 session->completed = GNUNET_YES;
136 else
137 copy_list_messages(&level, &list);
138
139 clear_list_messages(&list);
140 }
141
142completion:
143 if (GNUNET_YES == is_member_session_completed(session))
144 {
145 GNUNET_CONTAINER_multihashmap_destroy (session->history);
146
147 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
148
149 if ((session->contact) && (GNUNET_YES == decrease_contact_rc (session->contact)))
150 remove_store_contact (
151 store,
152 session->contact,
153 get_member_session_context(session)
154 );
155
156 session->contact = NULL;
157 }
158}
159
160static int
161iterate_copy_history (void *cls, const struct GNUNET_HashCode *key, void *value)
162{
163 struct GNUNET_MESSENGER_MemberSession *next = cls;
164
165 GNUNET_CONTAINER_multihashmap_put(next->history, key, (value? next : NULL),
166 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
167
168 return GNUNET_YES;
169}
170
171struct GNUNET_MESSENGER_MemberSession*
172switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
173 const struct GNUNET_MESSENGER_Message *message,
174 const struct GNUNET_HashCode *hash)
175{
176 if ((!session) || (!message) || (!hash))
177 return NULL;
178
179 GNUNET_assert((GNUNET_MESSENGER_KIND_ID == message->header.kind) ||
180 (GNUNET_MESSENGER_KIND_KEY == message->header.kind));
181
182 struct GNUNET_MESSENGER_MemberSession *next = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
183
184 if (GNUNET_MESSENGER_KIND_ID == message->header.kind)
185 next->member = add_store_member(session->member->store, &(message->body.id.id));
186 else
187 next->member = session->member;
188
189 if (GNUNET_MESSENGER_KIND_KEY == message->header.kind)
190 GNUNET_memcpy(&(next->public_key), &(message->body.key.key), sizeof(next->public_key));
191 else
192 GNUNET_memcpy(&(next->public_key), get_member_session_public_key(session), sizeof(next->public_key));
193
194 get_context_from_member (
195 get_member_session_key (next),
196 get_member_session_id (next),
197 &(next->context)
198 );
199
200 update_store_contact(
201 get_member_contact_store(next->member->store),
202 get_member_session_contact(session),
203 get_member_session_context(session),
204 get_member_session_context(next),
205 get_member_session_public_key(next)
206 );
207
208 next->contact = get_member_session_contact(session);
209
210 if (!(next->contact))
211 {
212 GNUNET_free(next);
213 return NULL;
214 }
215
216 increase_contact_rc (next->contact);
217
218 next->history = GNUNET_CONTAINER_multihashmap_create(
219 GNUNET_CONTAINER_multihashmap_size(session->history), GNUNET_NO
220 );
221
222 GNUNET_CONTAINER_multihashmap_iterate(session->history, iterate_copy_history, next);
223
224 init_list_messages(&(next->messages));
225 copy_list_messages(&(next->messages), &(session->messages));
226
227 session->next = next;
228 next->prev = session;
229 next->next = NULL;
230
231 next->start = GNUNET_TIME_absolute_get();
232
233 session->closed = GNUNET_YES;
234 next->closed = GNUNET_NO;
235 next->completed = GNUNET_NO;
236
237 check_member_session_completion (session);
238
239 return next;
240}
241
242void
243destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session)
244{
245 GNUNET_assert (session);
246
247 GNUNET_CONTAINER_multihashmap_destroy (session->history);
248
249 clear_list_messages (&(session->messages));
250
251 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact (session);
252
253 if ((contact) && (GNUNET_YES == decrease_contact_rc (contact)))
254 remove_store_contact (
255 get_member_contact_store(session->member->store),
256 contact,
257 get_member_session_context(session)
258 );
259
260 GNUNET_free(session);
261}
262
263int
264reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
265 const struct GNUNET_HashCode *hash)
266{
267 GNUNET_assert ((session) && (hash));
268
269 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
270 struct GNUNET_MESSENGER_Contact *contact = get_store_contact(
271 store,
272 get_member_session_context (session),
273 get_member_session_public_key (session)
274 );
275
276 if (!contact)
277 return GNUNET_SYSERR;
278
279 if (contact == session->contact)
280 goto clear_messages;
281
282 session->contact = contact;
283 increase_contact_rc (session->contact);
284
285clear_messages:
286 clear_list_messages(&(session->messages));
287 add_to_list_messages(&(session->messages), hash);
288
289 session->next = NULL;
290 session->closed = GNUNET_NO;
291 session->completed = GNUNET_NO;
292
293 return GNUNET_OK;
294}
295
296void
297close_member_session (struct GNUNET_MESSENGER_MemberSession* session)
298{
299 GNUNET_assert (session);
300
301 session->closed = GNUNET_YES;
302 check_member_session_completion (session);
303}
304
305int
306is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session)
307{
308 GNUNET_assert(session);
309
310 return session->closed;
311}
312
313int
314is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session)
315{
316 GNUNET_assert(session);
317
318 return session->completed;
319}
320
321struct GNUNET_TIME_Absolute
322get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session)
323{
324 GNUNET_assert(session);
325
326 if (session->prev)
327 return get_member_session_start(session->prev);
328
329 return session->start;
330}
331
332const struct GNUNET_HashCode*
333get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session)
334{
335 GNUNET_assert((session) && (session->member));
336
337 return get_member_store_key(session->member->store);
338}
339
340const struct GNUNET_ShortHashCode*
341get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session)
342{
343 GNUNET_assert(session);
344
345 return get_member_id(session->member);
346}
347
348const struct GNUNET_IDENTITY_PublicKey*
349get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session)
350{
351 GNUNET_assert(session);
352
353 return &(session->public_key);
354}
355
356const struct GNUNET_HashCode*
357get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session)
358{
359 GNUNET_assert(session);
360
361 return &(session->context);
362}
363
364struct GNUNET_MESSENGER_Contact*
365get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session)
366{
367 GNUNET_assert (session);
368
369 return session->contact;
370}
371
372int verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
373 const struct GNUNET_MESSENGER_Message *message,
374 const struct GNUNET_HashCode *hash)
375{
376 GNUNET_assert((session) && (message) && (hash));
377
378 if (GNUNET_YES == is_member_session_completed(session))
379 return GNUNET_SYSERR;
380
381 if (0 != GNUNET_memcmp(get_member_session_id(session), &(message->header.sender_id)))
382 return GNUNET_SYSERR;
383
384 return verify_message(message, hash, get_member_session_public_key(session));
385}
386
387int
388check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
389 const struct GNUNET_HashCode *hash, int ownership)
390{
391 GNUNET_assert((session) && (hash));
392
393 if (GNUNET_YES == ownership)
394 return (NULL != GNUNET_CONTAINER_multihashmap_get(session->history, hash)? GNUNET_YES : GNUNET_NO);
395 else
396 return GNUNET_CONTAINER_multihashmap_contains(session->history, hash);
397}
398
399static void
400update_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
401 const struct GNUNET_HashCode *hash, int ownership)
402{
403 GNUNET_assert ((session) && (hash));
404
405 if ((GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(session->history, hash, (GNUNET_YES == ownership? session : NULL),
406 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) && (session->next))
407 update_member_chain_history (session->next, hash, ownership);
408}
409
410void
411update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
412 const struct GNUNET_MESSENGER_Message *message,
413 const struct GNUNET_HashCode *hash)
414{
415 GNUNET_assert((session) && (message) && (hash));
416
417 if (GNUNET_YES == is_member_session_completed(session))
418 return;
419
420 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating sessions history (%s) += (%s)\n",
421 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
422
423 if (GNUNET_OK == verify_member_session_as_sender (session, message, hash))
424 {
425 if (GNUNET_YES == is_message_session_bound (message))
426 add_to_list_messages(&(session->messages), hash);
427
428 update_member_chain_history (session, hash, GNUNET_YES);
429 }
430 else
431 update_member_chain_history (session, hash, GNUNET_NO);
432
433 if (GNUNET_YES == session->closed)
434 check_member_session_completion(session);
435}
436
437static void
438clear_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
439 const struct GNUNET_HashCode *hash)
440{
441 GNUNET_assert ((session) && (hash));
442
443 if ((0 < GNUNET_CONTAINER_multihashmap_remove_all(session->history, hash)) && (session->next))
444 clear_member_session_history(session->next, hash);
445}
446
447void
448clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
449 const struct GNUNET_HashCode *hash)
450{
451 GNUNET_assert((session) && (hash));
452
453 clear_member_chain_history (session, hash);
454}
455
456struct GNUNET_MESSENGER_MemberSessionHistoryEntry
457{
458 struct GNUNET_HashCode hash;
459 unsigned char ownership;
460};
461
462static void
463load_member_session_history (struct GNUNET_MESSENGER_MemberSession *session, const char *path)
464{
465 GNUNET_assert((session) && (path));
466
467 if (GNUNET_YES != GNUNET_DISK_file_test (path))
468 return;
469
470 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
471
472 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
473 path, GNUNET_DISK_OPEN_READ, permission
474 );
475
476 if (!handle)
477 return;
478
479 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
480
481 struct GNUNET_MESSENGER_MemberSessionHistoryEntry entry;
482 ssize_t len;
483
484 int status;
485
486 do {
487 len = GNUNET_DISK_file_read(handle, &(entry.hash), sizeof(entry.hash));
488
489 if (len != sizeof(entry.hash))
490 break;
491
492 len = GNUNET_DISK_file_read(handle, &(entry.ownership), sizeof(entry.ownership));
493
494 if (len != sizeof(entry.ownership))
495 break;
496
497 status = GNUNET_CONTAINER_multihashmap_put(session->history, &(entry.hash), (entry.ownership? session : NULL),
498 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
499 } while (status == GNUNET_OK);
500
501 GNUNET_DISK_file_close(handle);
502}
503
504void
505load_member_session (struct GNUNET_MESSENGER_Member *member, const char *directory)
506{
507 GNUNET_assert ((member) && (directory));
508
509 char *config_file;
510 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
511
512 struct GNUNET_MESSENGER_MemberSession *session = NULL;
513
514 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
515 goto free_config;
516
517 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
518
519 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
520 {
521 char *key_data;
522
523 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "key", &key_data))
524 goto destroy_config;
525
526 struct GNUNET_IDENTITY_PublicKey key;
527
528 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &key);
529
530 GNUNET_free(key_data);
531
532 if (GNUNET_OK != key_return)
533 goto destroy_config;
534
535 session = create_member_session(member, &key);
536
537 unsigned long long numeric_value;
538
539 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "start", &numeric_value))
540 session->start.abs_value_us = numeric_value;
541
542 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "closed", &numeric_value))
543 session->closed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
544
545 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "completed", &numeric_value))
546 session->completed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
547 }
548
549destroy_config:
550 GNUNET_CONFIGURATION_destroy (cfg);
551
552free_config:
553 GNUNET_free(config_file);
554
555 if (!session)
556 return;
557
558 char *history_file;
559 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
560
561 load_member_session_history (session, history_file);
562 GNUNET_free(history_file);
563
564 char *messages_file;
565 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
566
567 load_list_messages(&(session->messages), messages_file);
568 GNUNET_free(messages_file);
569
570 add_member_session(member, session);
571}
572
573static struct GNUNET_MESSENGER_MemberSession*
574get_cycle_safe_next_session (struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
575{
576 if (!next)
577 return NULL;
578
579 struct GNUNET_MESSENGER_MemberSession *check = next;
580
581 do {
582 if (check == session)
583 return NULL;
584
585 check = check->next;
586 } while (check);
587
588 return next;
589}
590
591void
592load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session, const char *directory)
593{
594 GNUNET_assert ((session) && (directory));
595
596 char *config_file;
597 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
598
599 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
600 goto free_config;
601
602 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
603
604 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
605 {
606 char *key_data;
607
608 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "next_key", &key_data))
609 goto destroy_config;
610
611 struct GNUNET_IDENTITY_PublicKey next_key;
612
613 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &next_key);
614
615 GNUNET_free(key_data);
616
617 if (GNUNET_OK != key_return)
618 goto destroy_config;
619
620 struct GNUNET_ShortHashCode next_id;
621
622 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "session", "next_id", &next_id, sizeof(next_id)))
623 goto destroy_config;
624
625 struct GNUNET_MESSENGER_Member *member = get_store_member(session->member->store, &next_id);
626
627 session->next = get_cycle_safe_next_session(
628 session, member? get_member_session (member, &next_key) : NULL
629 );
630
631 if (session->next)
632 session->next->prev = session;
633 }
634
635destroy_config:
636 GNUNET_CONFIGURATION_destroy (cfg);
637
638free_config:
639 GNUNET_free(config_file);
640}
641
642static int
643iterate_save_member_session_history_hentries (void *cls, const struct GNUNET_HashCode *key, void *value)
644{
645 struct GNUNET_DISK_FileHandle *handle = cls;
646 unsigned char ownership = value? GNUNET_YES : GNUNET_NO;
647
648 GNUNET_DISK_file_write(handle, key, sizeof(*key));
649 GNUNET_DISK_file_write(handle, &ownership, sizeof(ownership));
650
651 return GNUNET_YES;
652}
653
654static void
655save_member_session_history (struct GNUNET_MESSENGER_MemberSession *session, const char *path)
656{
657 GNUNET_assert((session) && (path));
658
659 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
660
661 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
662 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
663 );
664
665 if (!handle)
666 return;
667
668 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
669
670 GNUNET_CONTAINER_multihashmap_iterate(
671 session->history,
672 iterate_save_member_session_history_hentries,
673 handle
674 );
675
676 GNUNET_DISK_file_sync(handle);
677 GNUNET_DISK_file_close(handle);
678}
679
680void
681save_member_session (struct GNUNET_MESSENGER_MemberSession *session, const char *directory)
682{
683 GNUNET_assert ((session) && (directory));
684
685 char *config_file;
686 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
687
688 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
689
690 char *key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session));
691
692 if (key_data)
693 {
694 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "key", key_data);
695
696 GNUNET_free(key_data);
697 }
698
699 if (session->next)
700 {
701 const struct GNUNET_ShortHashCode *next_id = get_member_session_id(session->next);
702
703 char *next_id_data = GNUNET_STRINGS_data_to_string_alloc (next_id, sizeof(*next_id));
704
705 if (next_id_data)
706 {
707 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_id", next_id_data);
708
709 GNUNET_free(next_id_data);
710 }
711
712 key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session->next));
713
714 if (key_data)
715 {
716 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_key", key_data);
717
718 GNUNET_free(key_data);
719 }
720 }
721
722 GNUNET_CONFIGURATION_set_value_number(cfg, "session", "start", session->start.abs_value_us);
723
724 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "closed", session->closed);
725 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "completed", session->completed);
726
727 GNUNET_CONFIGURATION_write (cfg, config_file);
728 GNUNET_CONFIGURATION_destroy (cfg);
729
730 GNUNET_free(config_file);
731
732 char *history_file;
733 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
734
735 save_member_session_history (session, history_file);
736 GNUNET_free(history_file);
737
738 char *messages_file;
739 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
740
741 save_list_messages(&(session->messages), messages_file);
742 GNUNET_free(messages_file);
743}
diff --git a/src/messenger/gnunet-service-messenger_member_session.h b/src/messenger/gnunet-service-messenger_member_session.h
new file mode 100644
index 000000000..fa9c6b829
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_session.h
@@ -0,0 +1,288 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_member_session.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_identity_service.h"
33#include "gnunet_time_lib.h"
34
35#include "gnunet-service-messenger_member.h"
36
37#include "messenger_api_contact.h"
38
39struct GNUNET_MESSENGER_MemberSession {
40 struct GNUNET_MESSENGER_Member *member;
41
42 struct GNUNET_IDENTITY_PublicKey public_key;
43 struct GNUNET_HashCode context;
44
45 struct GNUNET_MESSENGER_Contact *contact;
46
47 struct GNUNET_CONTAINER_MultiHashMap *history;
48 struct GNUNET_MESSENGER_ListMessages messages;
49
50 struct GNUNET_MESSENGER_MemberSession* prev;
51 struct GNUNET_MESSENGER_MemberSession* next;
52
53 struct GNUNET_TIME_Absolute start;
54
55 int closed;
56 int completed;
57};
58
59/**
60 * Creates and allocates a new member session of a <i>member</i> with a given
61 * public key.
62 *
63 * If the creation fails, NULL gets returned.
64 *
65 * @param[in/out] member Member
66 * @param[in] pubkey Public key of EGO
67 * @return New member session
68 */
69struct GNUNET_MESSENGER_MemberSession*
70create_member_session (struct GNUNET_MESSENGER_Member *member,
71 const struct GNUNET_IDENTITY_PublicKey *pubkey);
72
73/**
74 * Creates and allocates a new member session closing and replacing a given
75 * other <i>session</i> of the same member. The new session could have significant
76 * changes to the members public key or its member id depending on the used
77 * <i>message</i> to switch session. The new session will be linked to the old
78 * one.
79 *
80 * @param[in/out] session Old member session
81 * @param[in] message Message
82 * @param[in] hash Hash of message
83 * @return New member session
84 */
85struct GNUNET_MESSENGER_MemberSession*
86switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
87 const struct GNUNET_MESSENGER_Message *message,
88 const struct GNUNET_HashCode *hash);
89
90/**
91 * Destroys a member session and frees its memory fully.
92 *
93 * @param[in/out] session Member session
94 */
95void
96destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session);
97
98/**
99 * Resets a given member <i>session</i> which re-opens a member
100 * session for new usage. Every connection to other sessions will be
101 * be dropped. The member sessions messages will be cleared but old
102 * history from uncompleted sessions however can be reused!
103 *
104 * @param[in/out] session Member session
105 * @param[in] hash Hash of initial message (JOIN message!)
106 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
107 */
108int
109reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
110 const struct GNUNET_HashCode *hash);
111
112/**
113 * Closes a given member <i>session</i> which opens the request
114 * for completion of the given member session.
115 *
116 * Closing a session may complete a session and can't be used without
117 * a reset! ( @see #reset_member_session() )
118 *
119 * @param[in/out] session Member session
120 */
121void
122close_member_session (struct GNUNET_MESSENGER_MemberSession* session);
123
124/**
125 * Returns if the given member <i>session</i> has been closed.
126 *
127 * @param[in] session Member session
128 * @return #GNUNET_YES or #GNUNET_NO
129 */
130int
131is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session);
132
133/**
134 * Returns if the given member <i>session</i> has been completed.
135 *
136 * A completed member session can't verify any message as its own and
137 * it won't add any message to its history.
138 *
139 * @param[in] session Member session
140 * @return #GNUNET_YES or #GNUNET_NO
141 */
142int
143is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session);
144
145/**
146 * Returns the timestamp of the member <i>session</i>'s start.
147 *
148 * @param[in] session Member session
149 * @return Absolute timestamp
150 */
151struct GNUNET_TIME_Absolute
152get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session);
153
154/**
155 * Returns the key of the room a given member <i>session</i> belongs to.
156 *
157 * @param[in] session Member session
158 * @return Key of room
159 */
160const struct GNUNET_HashCode*
161get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session);
162
163/**
164 * Returns the member id of a given member <i>session</i>.
165 *
166 * @param[in] session Member session
167 * @return Member id
168 */
169const struct GNUNET_ShortHashCode*
170get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session);
171
172/**
173 * Returns the public key from an EGO of a given member <i>session</i>.
174 *
175 * @param[in] session Member session
176 * @return Public key of EGO
177 */
178const struct GNUNET_IDENTITY_PublicKey*
179get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session);
180
181/**
182 * Returns the member context of a given member <i>session</i>.
183 *
184 * @param[in] session Member session
185 * @return Member context as hash
186 */
187const struct GNUNET_HashCode*
188get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session);
189
190/**
191 * Retruns the contact which is connected to a given member <i>session</i>.
192 *
193 * @param[in] session Member session
194 * @return Contact
195 */
196struct GNUNET_MESSENGER_Contact*
197get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session);
198
199/**
200 * Verifies a given member <i>session</i> as sender of a selected <i>message</i> and
201 * its <i>hash</i>. The function returns #GNUNET_OK if the message session is verified
202 * as sender, otherwise #GNUNET_SYSERR.
203 *
204 * @see #is_member_session_completed() for verification.
205 *
206 * @param[in] session Member session
207 * @param[in] message Message
208 * @param[in] hash Hash of message
209 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
210 */
211int
212verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
213 const struct GNUNET_MESSENGER_Message *message,
214 const struct GNUNET_HashCode *hash);
215
216/**
217 * Checks the history of a <i>session</i> for a specific message which is identified
218 * by its <i>hash</i> and if the <i>ownership</i> flag is set, if the message is
219 * owned by the sessions contact.
220 *
221 * @param[in] session Member session
222 * @param[in] hash Hash of message
223 * @param[in] ownership Ownership flag
224 * @return #GNUNET_YES if found, otherwise #GNUNET_NO
225 */
226int
227check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
228 const struct GNUNET_HashCode *hash, int ownership);
229
230/**
231 * Adds a given <i>message</i> to the history of a <i>session</i> using the messages
232 * <i>hash</i>. The ownership will be set automatically.
233 *
234 * @see #is_member_session_completed() for updating a history.
235 *
236 * @param[in/out] session Member session
237 * @param[in] message Message
238 * @param[in] hash Hash of message
239 */
240void
241update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
242 const struct GNUNET_MESSENGER_Message *message,
243 const struct GNUNET_HashCode *hash);
244
245/**
246 * Removes a message from the history of a <i>session</i> using the messages
247 * <i>hash</i>.
248 *
249 * @param[in/out] session Member session
250 * @param[in] hash Hash of message
251 */
252void
253clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
254 const struct GNUNET_HashCode *hash);
255
256/**
257 * Loads data from a <i>directory</i> into a new allocated and created member
258 * session of a <i>member</i> if the required information can be read from the
259 * content of the given directory.
260 *
261 * @param[out] member Member
262 * @param[in] directory Path to a directory
263 */
264void
265load_member_session (struct GNUNET_MESSENGER_Member *member, const char *directory);
266
267/**
268 * Loads the connection from one <i>session</i> to another through the
269 * next attribute. Necessary information will be loaded from a configuration
270 * file inside of a given <i>directory</i>.
271 *
272 * @param[in/out] session Member session
273 * @param[in] directory Path to a directory
274 */
275void
276load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session, const char *directory);
277
278/**
279 * Saves data from a member <i>session</i> into a <i>directory</i> which can be
280 * load to restore the member session completely.
281 *
282 * @param[in] session Member session
283 * @param[in] directory Path to a directory
284 */
285void
286save_member_session (struct GNUNET_MESSENGER_MemberSession *session, const char *directory);
287
288#endif //GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
diff --git a/src/messenger/gnunet-service-messenger_member_store.c b/src/messenger/gnunet-service-messenger_member_store.c
new file mode 100644
index 000000000..2925965d4
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_store.c
@@ -0,0 +1,250 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_member_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member_store.h"
27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_service.h"
30#include "gnunet-service-messenger_room.h"
31
32void
33init_member_store (struct GNUNET_MESSENGER_MemberStore *store, struct GNUNET_MESSENGER_SrvRoom *room)
34{
35 GNUNET_assert ((store) && (room));
36
37 store->room = room;
38 store->members = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
39}
40
41static int
42iterate_destroy_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
43{
44 struct GNUNET_MESSENGER_Member *member = value;
45 destroy_member(member);
46 return GNUNET_YES;
47}
48
49void
50clear_member_store (struct GNUNET_MESSENGER_MemberStore *store)
51{
52 GNUNET_assert ((store) && (store->members));
53
54 GNUNET_CONTAINER_multishortmap_iterate (store->members, iterate_destroy_members, NULL);
55 GNUNET_CONTAINER_multishortmap_destroy (store->members);
56}
57
58
59struct GNUNET_MESSENGER_ContactStore*
60get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store)
61{
62 GNUNET_assert ((store) && (store->room));
63
64 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
65
66 return get_service_contact_store(room->service);
67}
68
69const struct GNUNET_HashCode*
70get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store)
71{
72 GNUNET_assert (store);
73
74 return get_room_key((const struct GNUNET_MESSENGER_SrvRoom*) store->room);
75}
76
77static int
78callback_scan_for_members (void *cls, const char *filename)
79{
80 struct GNUNET_MESSENGER_MemberStore *store = cls;
81
82 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
83 {
84 char *directory;
85
86 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
87
88 load_member(store, directory);
89
90 GNUNET_free(directory);
91 }
92
93 return GNUNET_OK;
94}
95
96static int
97iterate_load_next_member_sessions (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
98{
99 const char *sync_dir = cls;
100
101 struct GNUNET_MESSENGER_Member *member = value;
102
103 if (!member)
104 return GNUNET_YES;
105
106 char *member_dir;
107 GNUNET_asprintf (&member_dir, "%s%s%c", sync_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
108
109 if (GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_YES))
110 load_member_next_sessions (member, member_dir);
111
112 GNUNET_free(member_dir);
113 return GNUNET_YES;
114}
115
116static int
117iterate_sync_member_contacts (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
118{
119 struct GNUNET_MESSENGER_Member *member = value;
120
121 if (!member)
122 return GNUNET_YES;
123
124 sync_member_contacts (member);
125 return GNUNET_YES;
126}
127
128void
129load_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
130{
131 GNUNET_assert ((store) && (directory));
132
133 char *scan_dir;
134 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
135
136 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
137 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_members, store);
138
139 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_load_next_member_sessions, scan_dir);
140 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_sync_member_contacts, NULL);
141
142 GNUNET_free(scan_dir);
143}
144
145static int
146iterate_save_members (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
147{
148 const char *save_dir = cls;
149
150 struct GNUNET_MESSENGER_Member *member = value;
151
152 if (!member)
153 return GNUNET_YES;
154
155 char *member_dir;
156 GNUNET_asprintf (&member_dir, "%s%s%c", save_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
157
158 if ((GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_NO)) ||
159 (GNUNET_OK == GNUNET_DISK_directory_create (member_dir)))
160 save_member(member, member_dir);
161
162 GNUNET_free(member_dir);
163 return GNUNET_YES;
164}
165
166void
167save_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
168{
169 GNUNET_assert ((store) && (directory));
170
171 char* save_dir;
172 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
173
174 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
175 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
176 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_save_members, save_dir);
177
178 GNUNET_free(save_dir);
179}
180
181struct GNUNET_MESSENGER_Member*
182get_store_member (const struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
183{
184 GNUNET_assert ((store) && (store->members) && (id));
185
186 return GNUNET_CONTAINER_multishortmap_get (store->members, id);
187}
188
189struct GNUNET_MESSENGER_Member*
190get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_MESSENGER_Message *message)
191{
192 if ((GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
193 (GNUNET_MESSENGER_KIND_JOIN == message->header.kind))
194 return add_store_member(store, &(message->header.sender_id));
195 else
196 return get_store_member(store, &(message->header.sender_id));
197}
198
199struct GNUNET_MESSENGER_Member*
200add_store_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
201{
202 GNUNET_assert ((store) && (store->members));
203
204 struct GNUNET_MESSENGER_Member *member = id? get_store_member(store, id) : NULL;
205
206 if (member)
207 return member;
208
209 member = create_member(store, id);
210
211 if (!member)
212 return NULL;
213
214 if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (store->members, get_member_id(member), member,
215 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
216 {
217 destroy_member(member);
218 return NULL;
219 }
220
221 return member;
222}
223
224struct GNUNET_MESSENGER_ClosureIterateMembers {
225 GNUNET_MESSENGER_MemberIteratorCallback it;
226 void *cls;
227};
228
229static int
230iterate_store_members_it (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
231{
232 struct GNUNET_MESSENGER_ClosureIterateMembers *iterate = cls;
233 struct GNUNET_MESSENGER_Member *member = value;
234
235 return iterate_member_sessions(member, iterate->it, iterate->cls);
236}
237
238int
239iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store, GNUNET_MESSENGER_MemberIteratorCallback it,
240 void* cls)
241{
242 GNUNET_assert ((store) && (store->members) && (it));
243
244 struct GNUNET_MESSENGER_ClosureIterateMembers iterate;
245
246 iterate.it = it;
247 iterate.cls = cls;
248
249 return GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_store_members_it, &iterate);
250}
diff --git a/src/messenger/gnunet-service-messenger_member_store.h b/src/messenger/gnunet-service-messenger_member_store.h
new file mode 100644
index 000000000..859e4683d
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_store.h
@@ -0,0 +1,151 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_member_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_identity_service.h"
33#include "messenger_api_message.h"
34
35struct GNUNET_MESSENGER_SrvRoom;
36
37struct GNUNET_MESSENGER_Member;
38struct GNUNET_MESSENGER_MemberSession;
39
40struct GNUNET_MESSENGER_MemberStore
41{
42 struct GNUNET_MESSENGER_SrvRoom *room;
43
44 struct GNUNET_CONTAINER_MultiShortmap *members;
45};
46
47typedef int (*GNUNET_MESSENGER_MemberIteratorCallback) (
48 void *cls,
49 const struct GNUNET_IDENTITY_PublicKey *public_key,
50 struct GNUNET_MESSENGER_MemberSession *session);
51
52/**
53 * Initializes a member <i>store</i> as fully empty connected to a <i>room</i>.
54 *
55 * @param[out] store Member store
56 * @param room Room
57 */
58void
59init_member_store (struct GNUNET_MESSENGER_MemberStore *store, struct GNUNET_MESSENGER_SrvRoom *room);
60
61/**
62 * Clears a member <i>store</i>, wipes its content and deallocates its memory.
63 *
64 * @param[in/out] store Member store
65 */
66void
67clear_member_store (struct GNUNET_MESSENGER_MemberStore *store);
68
69/**
70 * Returns the used contact store of a given member <i>store</i>.
71 *
72 * @param[in/out] store Member store
73 * @return Contact store
74 */
75struct GNUNET_MESSENGER_ContactStore*
76get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store);
77
78/**
79 * Returns the shared secret you need to access a room of the <i>store</i>.
80 *
81 * @param[in] store Member store
82 * @return Shared secret
83 */
84const struct GNUNET_HashCode*
85get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store);
86
87/**
88 * Loads members from a directory into a member <i>store</i>.
89 *
90 * @param[out] store Member store
91 * @param[in] directory Path to a directory
92 */
93void
94load_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
95
96/**
97 * Saves members from a member <i>store</i> into a directory.
98 *
99 * @param[in] store Member store
100 * @param[in] directory Path to a directory
101 */
102void
103save_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
104
105/**
106 * Returns the member in a <i>store</i> identified by a given <i>id</i>. If the <i>store</i>
107 * does not contain a member with the given <i>id</i>, NULL gets returned.
108 *
109 * @param[in] store Member store
110 * @param[in] id Member id
111 * @return Member or NULL
112 */
113struct GNUNET_MESSENGER_Member*
114get_store_member (const struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
115
116/**
117 * Returns the member of a <i>store</i> using a sender id of a given <i>message</i>.
118 * If the member does not provide a matching session, NULL gets returned.
119 *
120 * @param[in/out] store Member store
121 * @param[in] message Message
122 * @return Member or NULL
123 */
124struct GNUNET_MESSENGER_Member*
125get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_MESSENGER_Message *message);
126
127/**
128 * Adds a member to a <i>store</i> under a specific <i>id</i> and returns it on success.
129 *
130 * @param[in/out] store Member store
131 * @param[in] id Member id
132 * @return Member or NULL
133 */
134struct GNUNET_MESSENGER_Member*
135add_store_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
136
137/**
138 * Iterate through all member sessions currently connected to the members of the given
139 * member <i>store</i> and call the provided iterator callback with a selected closure.
140 * The function will return the amount of members it iterated through.
141 *
142 * @param[in/out] store Member store
143 * @param[in] it Iterator callback
144 * @param[in/out] cls Closure
145 * @return Amount of members iterated through
146 */
147int
148iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store, GNUNET_MESSENGER_MemberIteratorCallback it,
149 void* cls);
150
151#endif //GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_message_handle.c b/src/messenger/gnunet-service-messenger_message_handle.c
index 1652435c8..1d489310c 100644
--- a/src/messenger/gnunet-service-messenger_message_handle.c
+++ b/src/messenger/gnunet-service-messenger_message_handle.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -25,75 +25,66 @@
25 25
26#include "gnunet-service-messenger_message_handle.h" 26#include "gnunet-service-messenger_message_handle.h"
27 27
28void 28static void
29handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 29handle_session_switch (struct GNUNET_MESSENGER_MemberSession *session,
30 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 30 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
31{ 31{
32 struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); 32 struct GNUNET_MESSENGER_MemberSession *next = switch_member_session(session, message, hash);
33
34 if (!contact)
35 add_room_contact (room, &(message->header.sender_id), &(message->body.join.key));
36
37 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id));
38
39 if (!info)
40 {
41 info = GNUNET_new(struct GNUNET_MESSENGER_MemberInfo);
42
43 info->access = GNUNET_MESSENGER_MEMBER_UNKNOWN;
44 init_list_messages (&(info->session_messages));
45 }
46 else
47 clear_list_messages (&(info->session_messages));
48 33
49 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_put (room->member_infos, &(message->header.sender_id), info, 34 if (next != session)
50 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 35 add_member_session(next->member, next);
51 add_to_list_messages (&(info->session_messages), hash);
52} 36}
53 37
54void 38void
55handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 39handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
56 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 40 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
57{ 41{
58 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); 42 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) joins room (%s).\n",
59 43 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_room_key(room)));
60 if (info) 44
61 clear_list_messages (&(info->session_messages)); 45 if (GNUNET_OK != reset_member_session(session, hash))
46 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Resetting member session failed!\n");
47
48 solve_room_member_collisions (
49 room,
50 &(message->body.join.key),
51 &(message->header.sender_id),
52 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
53 );
62} 54}
63 55
64void 56void
65handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 57handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
66 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 58 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
67{ 59{
68 struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); 60 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) leaves room (%s).\n",
69 61 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_room_key(room)));
70 if (contact)
71 set_contact_name (contact, message->body.name.name);
72
73 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id));
74 62
75 if (info) 63 close_member_session(session);
76 add_to_list_messages (&(info->session_messages), hash);
77} 64}
78 65
79void 66void
80handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 67handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
81 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 68 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
82{ 69{
83 struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); 70 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact(session);
84 71
85 if (contact) 72 if (!contact)
86 swap_service_contact_by_pubkey (room->service, contact, &(message->body.key.key)); 73 return;
87 74
88 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); 75 set_contact_name (contact, message->body.name.name);
76}
89 77
90 if (info) 78void
91 add_to_list_messages (&(info->session_messages), hash); 79handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
80 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
81{
82 handle_session_switch (session, message, hash);
92} 83}
93 84
94void 85void
95handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 86handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
96 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 87 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
97{ 88{
98 if (GNUNET_NO == contains_list_tunnels (&(room->basement), &(message->body.peer.peer))) 89 if (GNUNET_NO == contains_list_tunnels (&(room->basement), &(message->body.peer.peer)))
99 add_to_list_tunnels (&(room->basement), &(message->body.peer.peer)); 90 add_to_list_tunnels (&(room->basement), &(message->body.peer.peer));
@@ -103,20 +94,22 @@ handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSEN
103} 94}
104 95
105void 96void
106handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 97handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
107 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 98 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
108{ 99{
109 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); 100 handle_session_switch (session, message, hash);
110 101
111 if (info) 102 solve_room_member_collisions (
112 add_to_list_messages (&(info->session_messages), hash); 103 room,
113 104 get_member_session_public_key(session),
114 switch_room_member_id (room, &(message->header.sender_id), &(message->body.id.id), hash); 105 &(message->body.id.id),
106 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
107 );
115} 108}
116 109
117void 110void
118handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 111handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
119 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 112 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
120{ 113{
121 struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels (&(room->basement), &(message->body.peer.peer), NULL); 114 struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels (&(room->basement), &(message->body.peer.peer), NULL);
122 115
@@ -128,3 +121,16 @@ handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSEN
128 if (room->peer_message) 121 if (room->peer_message)
129 rebuild_room_basement_structure (room); 122 rebuild_room_basement_structure (room);
130} 123}
124
125void
126handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
127 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
128{
129 struct GNUNET_TIME_Relative delay = GNUNET_TIME_relative_ntoh (message->body.delete.delay);
130 struct GNUNET_TIME_Absolute action = GNUNET_TIME_absolute_ntoh (message->header.timestamp);
131
132 action = GNUNET_TIME_absolute_add (action, delay);
133 delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (), action);
134
135 delete_room_message (room, session, &(message->body.delete.hash), delay);
136}
diff --git a/src/messenger/gnunet-service-messenger_message_handle.h b/src/messenger/gnunet-service-messenger_message_handle.h
index d091e1d11..844142b77 100644
--- a/src/messenger/gnunet-service-messenger_message_handle.h
+++ b/src/messenger/gnunet-service-messenger_message_handle.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -31,6 +31,7 @@
31 31
32#include "gnunet-service-messenger_message_kind.h" 32#include "gnunet-service-messenger_message_kind.h"
33 33
34#include "gnunet-service-messenger_member_session.h"
34#include "gnunet-service-messenger_tunnel.h" 35#include "gnunet-service-messenger_tunnel.h"
35#include "messenger_api_message.h" 36#include "messenger_api_message.h"
36 37
@@ -38,91 +39,104 @@
38 * Handles a received or sent join message to make changes of current member information. 39 * Handles a received or sent join message to make changes of current member information.
39 * (add matching member and clear member info) 40 * (add matching member and clear member info)
40 * 41 *
41 * @param room Room of the message 42 * @param[in/out] room Room of the message
42 * @param tunnel Receiving/sending connection (may be NULL) 43 * @param[in/out] session Member session
43 * @param message JOIN-Message 44 * @param[in] message JOIN-Message
44 * @param hash Hash of the message 45 * @param[in] hash Hash of the message
45 */ 46 */
46void 47void
47handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 48handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
48 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 49 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
49 50
50/** 51/**
51 * Handles a received or sent leave message to make changes of current member information. 52 * Handles a received or sent leave message to make changes of current member information.
52 * (remove matching member and clear member info) 53 * (remove matching member and clear member info)
53 * 54 *
54 * @param room Room of the message 55 * @param[in/out] room Room of the message
55 * @param tunnel Receiving/sending connection (may be NULL) 56 * @param[in/out] session Member session
56 * @param message LEAVE-Message 57 * @param[in] message LEAVE-Message
57 * @param hash Hash of the message 58 * @param[in] hash Hash of the message
58 */ 59 */
59void 60void
60handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 61handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
61 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 62 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
62 63
63/** 64/**
64 * Handles a received or sent name message to rename a current member. 65 * Handles a received or sent name message to rename a current member.
65 * (change name of matching member) 66 * (change name of matching member)
66 * 67 *
67 * @param room Room of the message 68 * @param[in/out] room Room of the message
68 * @param tunnel Receiving/sending connection (may be NULL) 69 * @param[in/out] session Member session
69 * @param message NAME-Message 70 * @param[in] message NAME-Message
70 * @param hash Hash of the message 71 * @param[in] hash Hash of the message
71 */ 72 */
72void 73void
73handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 74handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
74 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 75 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
75 76
76/** 77/**
77 * Handles a received or sent key message to change the key of a member and rearrange the contacts accordingly. 78 * Handles a received or sent key message to change the key of a member and rearrange the contacts accordingly.
78 * (move the member in the contacts and change its key) 79 * (move the member in the contacts and change its key)
79 * 80 *
80 * @param room Room of the message 81 * @param[in/out] room Room of the message
81 * @param tunnel Receiving/sending connection (may be NULL) 82 * @param[in/out] session Member session
82 * @param message KEY-Message 83 * @param[in] message KEY-Message
83 * @param hash Hash of the message 84 * @param[in] hash Hash of the message
84 */ 85 */
85void 86void
86handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 87handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
87 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 88 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
88 89
89/** 90/**
90 * Handles a received or sent peer message to make changes of the basement in the room. 91 * Handles a received or sent peer message to make changes of the basement in the room.
91 * (add a new peer to the basement and restructure connections based on updated list of peers) 92 * (add a new peer to the basement and restructure connections based on updated list of peers)
92 * 93 *
93 * @param room Room of the message 94 * @param[in/out] room Room of the message
94 * @param tunnel Receiving/sending connection (may be NULL) 95 * @param[in/out] session Member session
95 * @param message PEER-Message 96 * @param[in] message PEER-Message
96 * @param hash Hash of the message 97 * @param[in] hash Hash of the message
97 */ 98 */
98void 99void
99handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 100handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
100 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 101 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
101 102
102/** 103/**
103 * Handles a received or sent id message to change a members id. 104 * Handles a received or sent id message to change a members id.
104 * (change id of matching member) 105 * (change id of matching member)
105 * 106 *
106 * @param room Room of the message 107 * @param[in/out] room Room of the message
107 * @param tunnel Receiving/sending connection (may be NULL) 108 * @param[in/out] session Member session
108 * @param message ID-Message 109 * @param[in] message ID-Message
109 * @param hash Hash of the message 110 * @param[in] hash Hash of the message
110 */ 111 */
111void 112void
112handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 113handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
113 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 114 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
114 115
115/** 116/**
116 * Handles a received or sent miss message to drop a peer from the basement in the room. 117 * Handles a received or sent miss message to drop a peer from the basement in the room.
117 * (remove a peer from the basement and restructure connections based on updated list of peers) 118 * (remove a peer from the basement and restructure connections based on updated list of peers)
118 * 119 *
119 * @param room Room of the message 120 * @param[in/out] room Room of the message
120 * @param tunnel Receiving/sending connection (may be NULL) 121 * @param[in/out] session Member session
121 * @param message MISS-Message 122 * @param[in] message MISS-Message
122 * @param hash Hash of the message 123 * @param[in] hash Hash of the message
123 */ 124 */
124void 125void
125handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 126handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
126 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 127 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
128
129/**
130 * Handles a received or sent delete message to delete a specific message from the store.
131 * (remove a message from the store of a room under a given delay)
132 *
133 * @param[in/out] room Room of the message
134 * @param[in/out] session Member session
135 * @param[in] message DELETE-Message
136 * @param[in] hash Hash of the message
137 */
138void
139handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
140 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
127 141
128#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H 142#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H
diff --git a/src/messenger/gnunet-service-messenger_message_kind.c b/src/messenger/gnunet-service-messenger_message_kind.c
index 9c829fe09..ef9bbfd2e 100644
--- a/src/messenger/gnunet-service-messenger_message_kind.c
+++ b/src/messenger/gnunet-service-messenger_message_kind.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -24,11 +24,15 @@
24 */ 24 */
25 25
26#include "gnunet-service-messenger_message_kind.h" 26#include "gnunet-service-messenger_message_kind.h"
27#include "gnunet-service-messenger_util.h" 27
28#include "messenger_api_util.h"
28 29
29struct GNUNET_MESSENGER_Message* 30struct GNUNET_MESSENGER_Message*
30create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_MultiShortmap *members) 31create_message_info (const struct GNUNET_MESSENGER_Ego *ego)
31{ 32{
33 if (!ego)
34 return NULL;
35
32 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INFO); 36 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INFO);
33 37
34 if (!message) 38 if (!message)
@@ -36,18 +40,17 @@ create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_M
36 40
37 GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub)); 41 GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub));
38 42
39 if (GNUNET_YES == generate_free_member_id (&(message->body.info.unique_id), members)) 43 message->body.info.messenger_version = GNUNET_MESSENGER_VERSION;
40 return message; 44
41 else 45 return message;
42 {
43 destroy_message (message);
44 return NULL;
45 }
46} 46}
47 47
48struct GNUNET_MESSENGER_Message* 48struct GNUNET_MESSENGER_Message*
49create_message_join (struct GNUNET_MESSENGER_Ego *ego) 49create_message_join (const struct GNUNET_MESSENGER_Ego *ego)
50{ 50{
51 if (!ego)
52 return NULL;
53
51 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_JOIN); 54 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_JOIN);
52 55
53 if (!message) 56 if (!message)
@@ -67,6 +70,9 @@ create_message_leave ()
67struct GNUNET_MESSENGER_Message* 70struct GNUNET_MESSENGER_Message*
68create_message_name (const char *name) 71create_message_name (const char *name)
69{ 72{
73 if (!name)
74 return NULL;
75
70 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_NAME); 76 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_NAME);
71 77
72 if (!message) 78 if (!message)
@@ -79,6 +85,9 @@ create_message_name (const char *name)
79struct GNUNET_MESSENGER_Message* 85struct GNUNET_MESSENGER_Message*
80create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key) 86create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key)
81{ 87{
88 if (!key)
89 return NULL;
90
82 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_KEY); 91 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_KEY);
83 92
84 if (!message) 93 if (!message)
@@ -91,6 +100,9 @@ create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key)
91struct GNUNET_MESSENGER_Message* 100struct GNUNET_MESSENGER_Message*
92create_message_peer (const struct GNUNET_MESSENGER_Service *service) 101create_message_peer (const struct GNUNET_MESSENGER_Service *service)
93{ 102{
103 if (!service)
104 return NULL;
105
94 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_PEER); 106 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_PEER);
95 107
96 if (!message) 108 if (!message)
@@ -108,6 +120,9 @@ create_message_peer (const struct GNUNET_MESSENGER_Service *service)
108struct GNUNET_MESSENGER_Message* 120struct GNUNET_MESSENGER_Message*
109create_message_id (const struct GNUNET_ShortHashCode *unique_id) 121create_message_id (const struct GNUNET_ShortHashCode *unique_id)
110{ 122{
123 if (!unique_id)
124 return NULL;
125
111 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_ID); 126 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_ID);
112 127
113 if (!message) 128 if (!message)
@@ -121,6 +136,9 @@ create_message_id (const struct GNUNET_ShortHashCode *unique_id)
121struct GNUNET_MESSENGER_Message* 136struct GNUNET_MESSENGER_Message*
122create_message_miss (const struct GNUNET_PeerIdentity *peer) 137create_message_miss (const struct GNUNET_PeerIdentity *peer)
123{ 138{
139 if (!peer)
140 return NULL;
141
124 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MISS); 142 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MISS);
125 143
126 if (!message) 144 if (!message)
@@ -136,6 +154,9 @@ create_message_miss (const struct GNUNET_PeerIdentity *peer)
136struct GNUNET_MESSENGER_Message* 154struct GNUNET_MESSENGER_Message*
137create_message_merge (const struct GNUNET_HashCode *previous) 155create_message_merge (const struct GNUNET_HashCode *previous)
138{ 156{
157 if (!previous)
158 return NULL;
159
139 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MERGE); 160 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MERGE);
140 161
141 if (!message) 162 if (!message)
@@ -149,6 +170,9 @@ create_message_merge (const struct GNUNET_HashCode *previous)
149struct GNUNET_MESSENGER_Message* 170struct GNUNET_MESSENGER_Message*
150create_message_request (const struct GNUNET_HashCode *hash) 171create_message_request (const struct GNUNET_HashCode *hash)
151{ 172{
173 if (!hash)
174 return NULL;
175
152 struct GNUNET_HashCode zero; 176 struct GNUNET_HashCode zero;
153 memset (&zero, 0, sizeof(zero)); 177 memset (&zero, 0, sizeof(zero));
154 178
@@ -168,6 +192,9 @@ create_message_request (const struct GNUNET_HashCode *hash)
168struct GNUNET_MESSENGER_Message* 192struct GNUNET_MESSENGER_Message*
169create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key) 193create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key)
170{ 194{
195 if ((!door) || (!key))
196 return NULL;
197
171 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INVITE); 198 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INVITE);
172 199
173 if (!message) 200 if (!message)
@@ -182,6 +209,9 @@ create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUN
182struct GNUNET_MESSENGER_Message* 209struct GNUNET_MESSENGER_Message*
183create_message_text (const char *text) 210create_message_text (const char *text)
184{ 211{
212 if (!text)
213 return NULL;
214
185 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_TEXT); 215 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_TEXT);
186 216
187 if (!message) 217 if (!message)
@@ -190,3 +220,20 @@ create_message_text (const char *text)
190 message->body.text.text = GNUNET_strdup(text); 220 message->body.text.text = GNUNET_strdup(text);
191 return message; 221 return message;
192} 222}
223
224struct GNUNET_MESSENGER_Message*
225create_message_delete (const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay)
226{
227 if (!hash)
228 return NULL;
229
230 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_DELETE);
231
232 if (!message)
233 return NULL;
234
235 GNUNET_memcpy(&(message->body.delete.hash), hash, sizeof(struct GNUNET_HashCode));
236 message->body.delete.delay = GNUNET_TIME_relative_hton (delay);
237
238 return message;
239}
diff --git a/src/messenger/gnunet-service-messenger_message_kind.h b/src/messenger/gnunet-service-messenger_message_kind.h
index dd89d0b2f..c098868c0 100644
--- a/src/messenger/gnunet-service-messenger_message_kind.h
+++ b/src/messenger/gnunet-service-messenger_message_kind.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -30,31 +30,32 @@
30#include "gnunet_container_lib.h" 30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h" 31#include "gnunet_crypto_lib.h"
32#include "gnunet_identity_service.h" 32#include "gnunet_identity_service.h"
33#include "gnunet_time_lib.h"
33 34
34#include "messenger_api_message.h" 35#include "messenger_api_message.h"
35#include "gnunet-service-messenger_service.h" 36#include "gnunet-service-messenger_service.h"
36#include "messenger_api_ego.h" 37#include "messenger_api_ego.h"
37 38
38/** 39/**
39 * Creates and allocates a new info message containing the hosts public key and a newly generated unique member id. 40 * Creates and allocates a new info message containing the hosts EGO public key and a newly generated unique member id.
40 * (all values are stored as copy) 41 * (all values are stored as copy)
41 * 42 *
42 * @param ego EGO of the host 43 * @param[in] ego EGO of the host
43 * @param members Map of all assigned member ids 44 * @param[in] members Map of all assigned member ids
44 * @return New message 45 * @return New message
45 */ 46 */
46struct GNUNET_MESSENGER_Message* 47struct GNUNET_MESSENGER_Message*
47create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_MultiShortmap *members); 48create_message_info (const struct GNUNET_MESSENGER_Ego *ego);
48 49
49/** 50/**
50 * Creates and allocates a new join message containing the clients public key. 51 * Creates and allocates a new join message containing the clients EGO public key.
51 * (all values are stored as copy) 52 * (all values are stored as copy)
52 * 53 *
53 * @param ego EGO of the client 54 * @param[in] ego EGO of the client
54 * @return New message 55 * @return New message
55 */ 56 */
56struct GNUNET_MESSENGER_Message* 57struct GNUNET_MESSENGER_Message*
57create_message_join (struct GNUNET_MESSENGER_Ego *ego); 58create_message_join (const struct GNUNET_MESSENGER_Ego *ego);
58 59
59/** 60/**
60 * Creates and allocates a new leave message. 61 * Creates and allocates a new leave message.
@@ -68,17 +69,17 @@ create_message_leave ();
68 * Creates and allocates a new name message containing the <i>name</i> to change to. 69 * Creates and allocates a new name message containing the <i>name</i> to change to.
69 * (all values are stored as copy) 70 * (all values are stored as copy)
70 * 71 *
71 * @param name New name 72 * @param[in] name New name
72 * @return New message 73 * @return New message
73 */ 74 */
74struct GNUNET_MESSENGER_Message* 75struct GNUNET_MESSENGER_Message*
75create_message_name (const char *name); 76create_message_name (const char *name);
76 77
77/** 78/**
78 * Creates and allocates a new key message containing the public key to change to derived 79 * Creates and allocates a new key message containing the public <i>key</i> to change to derived
79 * from its private counterpart. (all values are stored as copy) 80 * from its private counterpart. (all values are stored as copy)
80 * 81 *
81 * @param key Private key of EGO 82 * @param[in] key Private key of EGO
82 * @return New message 83 * @return New message
83 */ 84 */
84struct GNUNET_MESSENGER_Message* 85struct GNUNET_MESSENGER_Message*
@@ -88,7 +89,7 @@ create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key);
88 * Creates and allocates a new peer message containing a services peer identity. 89 * Creates and allocates a new peer message containing a services peer identity.
89 * (all values are stored as copy) 90 * (all values are stored as copy)
90 * 91 *
91 * @param service Service 92 * @param[in] service Service
92 * @return New message 93 * @return New message
93 */ 94 */
94struct GNUNET_MESSENGER_Message* 95struct GNUNET_MESSENGER_Message*
@@ -98,38 +99,38 @@ create_message_peer (const struct GNUNET_MESSENGER_Service *service);
98 * Creates and allocates a new id message containing the unique member id to change to. 99 * Creates and allocates a new id message containing the unique member id to change to.
99 * (all values are stored as copy) 100 * (all values are stored as copy)
100 * 101 *
101 * @param unique_id Unique member id 102 * @param[in] unique_id Unique member id
102 * @return New message 103 * @return New message
103 */ 104 */
104struct GNUNET_MESSENGER_Message* 105struct GNUNET_MESSENGER_Message*
105create_message_id (const struct GNUNET_ShortHashCode *unique_id); 106create_message_id (const struct GNUNET_ShortHashCode *unique_id);
106 107
107/** 108/**
108 * Creates and allocates a new miss message containing the missing peer identity. 109 * Creates and allocates a new miss message containing the missing <i>peer</i> identity.
109 * (all values are stored as copy) 110 * (all values are stored as copy)
110 * 111 *
111 * @param peer Missing peer identity 112 * @param[in] peer Missing peer identity
112 * @return New message 113 * @return New message
113 */ 114 */
114struct GNUNET_MESSENGER_Message* 115struct GNUNET_MESSENGER_Message*
115create_message_miss (const struct GNUNET_PeerIdentity *peer); 116create_message_miss (const struct GNUNET_PeerIdentity *peer);
116 117
117/** 118/**
118 * Creates and allocates a new merge message containing the hash of a second previous message 119 * Creates and allocates a new merge message containing the hash of a second <i>previous</i> message
119 * besides the regular previous message mentioned in a messages header. 120 * besides the regular previous message mentioned in a messages header.
120 * (all values are stored as copy) 121 * (all values are stored as copy)
121 * 122 *
122 * @param previous Hash of message 123 * @param[in] previous Hash of message
123 * @return New message 124 * @return New message
124 */ 125 */
125struct GNUNET_MESSENGER_Message* 126struct GNUNET_MESSENGER_Message*
126create_message_merge (const struct GNUNET_HashCode *previous); 127create_message_merge (const struct GNUNET_HashCode *previous);
127 128
128/** 129/**
129 * Creates and allocates a new request message containing the hash of a missing message. 130 * Creates and allocates a new request message containing the <i>hash</i> of a missing message.
130 * (all values are stored as copy) 131 * (all values are stored as copy)
131 * 132 *
132 * @param hash Hash of message 133 * @param[in] hash Hash of message
133 * @return New message 134 * @return New message
134 */ 135 */
135struct GNUNET_MESSENGER_Message* 136struct GNUNET_MESSENGER_Message*
@@ -140,21 +141,32 @@ create_message_request (const struct GNUNET_HashCode *hash);
140 * to a room using a given <i>key</i> as shared secret for communication. 141 * to a room using a given <i>key</i> as shared secret for communication.
141 * (all values are stored as copy) 142 * (all values are stored as copy)
142 * 143 *
143 * @param door Peer identity 144 * @param[in] door Peer identity
144 * @param key Shared secret of a room 145 * @param[in] key Shared secret of a room
145 * @return New message 146 * @return New message
146 */ 147 */
147struct GNUNET_MESSENGER_Message* 148struct GNUNET_MESSENGER_Message*
148create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key); 149create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key);
149 150
150/** 151/**
151 * Creates and allocates a new text message containing a string representing text. 152 * Creates and allocates a new <i>text message containing a string representing text.
152 * (all values are stored as copy) 153 * (all values are stored as copy)
153 * 154 *
154 * @param text Text 155 * @param[in] text Text
155 * @return New message 156 * @return New message
156 */ 157 */
157struct GNUNET_MESSENGER_Message* 158struct GNUNET_MESSENGER_Message*
158create_message_text (const char *text); 159create_message_text (const char *text);
159 160
161/**
162 * Creates and allocates a new delete message containing the <i>hash</i> of a message to delete after a specific <i>delay</i>.
163 * (all values are stored as copy)
164 *
165 * @param[in] hash Hash of message
166 * @param[in] delay Delay of deletion
167 * @return New message
168 */
169struct GNUNET_MESSENGER_Message*
170create_message_delete (const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay);
171
160#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H 172#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H
diff --git a/src/messenger/gnunet-service-messenger_message_recv.c b/src/messenger/gnunet-service-messenger_message_recv.c
index aa28a36ea..b2a5052d2 100644
--- a/src/messenger/gnunet-service-messenger_message_recv.c
+++ b/src/messenger/gnunet-service-messenger_message_recv.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -24,137 +24,92 @@
24 */ 24 */
25 25
26#include "gnunet-service-messenger_message_recv.h" 26#include "gnunet-service-messenger_message_recv.h"
27#include "gnunet-service-messenger_message_handle.h"
28 27
29void 28#include "gnunet-service-messenger_operation.h"
30recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
31 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
32{
33 int conflict = GNUNET_CONTAINER_multishortmap_contains (room->members, &(message->body.info.unique_id));
34
35 if (GNUNET_NO == conflict)
36 {
37 struct GNUNET_MESSENGER_Message *sync_message = create_message_id (&(message->body.info.unique_id));
38 struct GNUNET_HashCode sync_hash;
39 29
40 send_room_message_ext (room, room->host, sync_message, &sync_hash, tunnel); 30static void
41 destroy_message (sync_message); 31forward_about_members (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
42 32 struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_CONTAINER_MultiHashMap *map)
43 switch_room_member_id (room, get_room_host_id (room), &(message->body.info.unique_id), NULL); 33{
44 34 if (session->prev)
45 change_room_host_id (room, &(message->body.info.unique_id)); 35 forward_about_members (room, tunnel, session->prev, map);
46 }
47
48 if (!tunnel->contact_id)
49 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
50
51 GNUNET_memcpy(tunnel->contact_id, &(message->header.sender_id), sizeof(struct GNUNET_ShortHashCode));
52
53 struct GNUNET_ShortHashCode original_id;
54
55 if (GNUNET_YES == conflict)
56 {
57 GNUNET_memcpy(&original_id, get_room_host_id (room), sizeof(struct GNUNET_ShortHashCode));
58 36
59 change_room_host_id (room, &(message->body.info.unique_id)); 37 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
60 } 38 struct GNUNET_MESSENGER_ListMessage *element;
61 39
40 for (element = session->messages.head; element; element = element->next)
62 { 41 {
63 struct GNUNET_MESSENGER_Message *join_message = create_message_join (room->host->ego); 42 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
64 struct GNUNET_HashCode join_hash; 43 continue;
65 44
66 send_tunnel_message (tunnel, room->host, join_message, &join_hash); 45 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
67 destroy_message (join_message); 46 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
68 } 47 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Forwarding of session message could be duplicated!\n");
69 48
70 if ((GNUNET_YES == conflict) && (0 != GNUNET_memcmp(&original_id, get_room_host_id (room)))) 49 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
71 {
72 struct GNUNET_MESSENGER_Message *sync_message = create_message_id (&original_id);
73 struct GNUNET_HashCode sync_hash;
74 50
75 send_tunnel_message (tunnel, room->host, sync_message, &sync_hash); 51 if (message)
76 destroy_message (sync_message); 52 forward_tunnel_message(tunnel, message, &(element->hash));
77 } 53 }
78} 54}
79 55
80struct GNUNET_MESSENGER_MemberInfoSpread
81{
82 struct GNUNET_MESSENGER_SrvRoom *room;
83 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
84};
85
86static int 56static int
87iterate_send_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value) 57iterate_forward_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
58 struct GNUNET_MESSENGER_MemberSession *session)
88{ 59{
89 struct GNUNET_MESSENGER_MemberInfo *info = value; 60 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
90 struct GNUNET_MESSENGER_MemberInfoSpread *spread = cls;
91 61
92 struct GNUNET_MESSENGER_ListMessage *element = info->session_messages.head; 62 if (GNUNET_YES == is_member_session_completed(session))
63 return GNUNET_YES;
93 64
94 while (element) 65 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
95 {
96 const struct GNUNET_MESSENGER_Message *message = get_room_message (spread->room, spread->room->host,
97 &(element->hash), GNUNET_NO);
98 66
99 if (message) 67 forward_about_members (tunnel->room, tunnel, session, map);
100 forward_tunnel_message (spread->tunnel, message, &(element->hash));
101
102 element = element->next;
103 }
104 68
69 GNUNET_CONTAINER_multihashmap_destroy(map);
105 return GNUNET_YES; 70 return GNUNET_YES;
106} 71}
107 72
108void 73int
109recv_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 74recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
110 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 75 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
111{ 76{
112 const struct GNUNET_MESSENGER_Message *info_msg = get_room_message (room, room->host, &(message->header.previous), 77 const uint32_t version = get_tunnel_messenger_version(tunnel);
113 GNUNET_NO);
114 78
115 if ((info_msg) && (0 == GNUNET_memcmp(&(info_msg->header.sender_id), get_room_host_id (room))) 79 if (GNUNET_OK != update_tunnel_messenger_version(tunnel, message->body.info.messenger_version))
116 && (GNUNET_MESSENGER_KIND_INFO == info_msg->header.kind))
117 { 80 {
118 struct GNUNET_MESSENGER_MemberInfoSpread spread; 81 disconnect_tunnel(tunnel);
82 return GNUNET_NO;
83 }
119 84
120 spread.room = room; 85 if (version == get_tunnel_messenger_version(tunnel))
86 return GNUNET_NO;
121 87
122 if ((tunnel) && (tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, &(message->header.sender_id)))) 88 if (room->host)
123 spread.tunnel = tunnel; 89 {
124 else 90 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(room->host);
125 spread.tunnel = find_room_tunnel_to (room, &(message->header.sender_id));
126 91
127 if (spread.tunnel) 92 send_tunnel_message (tunnel, room->host, create_message_info(ego));
128 GNUNET_CONTAINER_multishortmap_iterate (room->member_infos, iterate_send_member_infos, &spread);
129 } 93 }
130 94
131 handle_message_join (room, tunnel, message, hash); 95 struct GNUNET_PeerIdentity peer;
132} 96 get_tunnel_peer_identity(tunnel, &peer);
133 97
134void 98 if (GNUNET_YES != contains_list_tunnels(&(room->basement), &peer))
135recv_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 99 {
136 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 100 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
137{
138 handle_message_leave (room, tunnel, message, hash);
139}
140 101
141void 102 iterate_store_members(member_store, iterate_forward_members, tunnel);
142recv_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 103 }
143 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
144{
145 handle_message_name (room, tunnel, message, hash);
146}
147 104
148void 105 check_room_peer_status(room, tunnel);
149recv_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 106
150 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 107 return GNUNET_NO;
151{
152 handle_message_key (room, tunnel, message, hash);
153} 108}
154 109
155void 110int
156recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 111recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
157 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 112 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
158{ 113{
159 struct GNUNET_PeerIdentity peer; 114 struct GNUNET_PeerIdentity peer;
160 GNUNET_PEER_resolve (tunnel->peer, &peer); 115 GNUNET_PEER_resolve (tunnel->peer, &peer);
@@ -164,41 +119,57 @@ recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
164 if (!tunnel->peer_message) 119 if (!tunnel->peer_message)
165 tunnel->peer_message = GNUNET_new(struct GNUNET_HashCode); 120 tunnel->peer_message = GNUNET_new(struct GNUNET_HashCode);
166 121
167 GNUNET_memcpy(tunnel->peer_message, hash, sizeof(struct GNUNET_HashCode)); 122 GNUNET_memcpy(tunnel->peer_message, &hash, sizeof(hash));
168
169 if (!tunnel->contact_id)
170 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
171
172 GNUNET_memcpy(tunnel->contact_id, &(message->header.sender_id), sizeof(struct GNUNET_ShortHashCode));
173 } 123 }
174 124
175 handle_message_peer (room, tunnel, message, hash); 125 return GNUNET_YES;
176} 126}
177 127
178void 128static void
179recv_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 129callback_found_message (void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
180 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 130 const struct GNUNET_MESSENGER_Message *message,
131 const struct GNUNET_HashCode *hash)
181{ 132{
182 if ((tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, &(message->header.sender_id)))) 133 struct GNUNET_MESSENGER_SrvTunnel *tunnel = tunnel;
183 GNUNET_memcpy(tunnel->contact_id, &(message->body.id.id), sizeof(struct GNUNET_ShortHashCode));
184 134
185 handle_message_id (room, tunnel, message, hash); 135 if (!message)
186} 136 {
187 137 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
188void 138
189recv_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 139 use_store_operation(
190 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 140 operation_store,
191{ 141 hash,
192 handle_message_miss (room, tunnel, message, hash); 142 GNUNET_MESSENGER_OP_REQUEST,
143 GNUNET_MESSENGER_REQUEST_DELAY
144 );
145 }
146 else
147 forward_tunnel_message (tunnel, message, hash);
193} 148}
194 149
195void 150/*
151 * Function returns GNUNET_NO to drop forwarding the request.
152 * It will only be forwarded if it can't be answered!
153 */
154int
196recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 155recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
197 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 156 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
198{ 157{
199 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(message->body.request.hash), 158 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
200 GNUNET_NO); 159 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
160
161 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Request for message (%s)\n", GNUNET_h2s (hash));
162
163 if (!member)
164 return GNUNET_NO;
165
166 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
167
168 if ((!session) || (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO)))
169 return GNUNET_NO;
170
171 if (GNUNET_NO == request_room_message(room, &(message->body.request.hash), session, callback_found_message, tunnel))
172 return GNUNET_YES;
201 173
202 if (msg) 174 return GNUNET_NO;
203 forward_tunnel_message (tunnel, msg, &(message->body.request.hash));
204} 175}
diff --git a/src/messenger/gnunet-service-messenger_message_recv.h b/src/messenger/gnunet-service-messenger_message_recv.h
index 245612cb0..9cb36c466 100644
--- a/src/messenger/gnunet-service-messenger_message_recv.h
+++ b/src/messenger/gnunet-service-messenger_message_recv.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -29,6 +29,9 @@
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31 31
32#include "gnunet-service-messenger_message_kind.h"
33
34#include "gnunet-service-messenger_member_session.h"
32#include "gnunet-service-messenger_tunnel.h" 35#include "gnunet-service-messenger_tunnel.h"
33#include "messenger_api_message.h" 36#include "messenger_api_message.h"
34 37
@@ -36,124 +39,43 @@
36 * Handles a received info message to change the current member id to the one generated by 39 * Handles a received info message to change the current member id to the one generated by
37 * the host connected to. (all current tunnels will be informed about the id change) 40 * the host connected to. (all current tunnels will be informed about the id change)
38 * 41 *
39 * @param room Room of the message 42 * @param[in/out] room Room of the message
40 * @param tunnel Receiving connection 43 * @param[in/out] tunnel Receiving connection
41 * @param message INFO-Message 44 * @param[in] message INFO-Message
42 * @param hash Hash of the message 45 * @param[in] hash Hash of the message
46 * @return #GNUNET_NO to not forward the message
43 */ 47 */
44void 48int
45recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 49recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
46 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 50 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
47
48/**
49 * Handles a received join message to forward all member information to the new member if the message was
50 * the direct reaction to a previous info message from this peer.
51 *
52 * @param room Room of the message
53 * @param tunnel Receiving connection
54 * @param message JOIN-Message
55 * @param hash Hash of the message
56 */
57void
58recv_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
59 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
60
61/**
62 * Handles a received leave message.
63 * @see handle_message_leave()
64 *
65 * @param room Room of the message
66 * @param tunnel Receiving connection
67 * @param message LEAVE-Message
68 * @param hash Hash of the message
69 */
70void
71recv_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
72 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
73
74/**
75 * Handles a received name message.
76 * @see handle_message_name()
77 *
78 * @param room Room of the message
79 * @param tunnel Receiving connection
80 * @param message NAME-Message
81 * @param hash Hash of the message
82 */
83void
84recv_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
85 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
86
87/**
88 * Handles a received key message.
89 * @see handle_message_key()
90 *
91 * @param room Room of the message
92 * @param tunnel Receiving connection
93 * @param message KEY-Message
94 * @param hash Hash of the message
95 */
96void
97recv_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
98 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
99 51
100/** 52/**
101 * Handles a received peer message to link it to its origin tunnel if the peer identity matches. 53 * Handles a received peer message to link it to its origin tunnel if the peer identity matches.
102 * (the peer message and the member id can potentially be linked to the tunnel) 54 * (the peer message and the member id can potentially be linked to the tunnel)
103 * 55 *
104 * TODO: This handling will only check the one given tunnel! 56 * @param[in/out] room Room of the message
105 * 57 * @param[in/out] tunnel Receiving connection
106 * @param room Room of the message 58 * @param[in] message PEER-Message
107 * @param tunnel Receiving connection 59 * @param[in] hash Hash of the message
108 * @param message PEER-Message 60 * @return #GNUNET_YES to forward the message
109 * @param hash Hash of the message
110 */ 61 */
111void 62int
112recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 63recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
113 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 64 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
114
115/**
116 * Handles a received id message to change the tunnels linked member id if necessary.
117 * (the tunnels linked member id will be changed if the sender id is matching)
118 *
119 * TODO: This handling will only check the one given tunnel!
120 *
121 * @param room Room of the message
122 * @param tunnel Receiving connection
123 * @param message ID-Message
124 * @param hash Hash of the message
125 */
126void
127recv_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
128 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
129
130/**
131 * Handles a received miss message.
132 * @see handle_message_miss()
133 *
134 * @param room Room of the message
135 * @param tunnel Receiving connection
136 * @param message MISS-Message
137 * @param hash Hash of the message
138 */
139void
140recv_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
141 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
142 65
143/** 66/**
144 * Handles a received request message by checking for the requested message and forwarding it back 67 * Handles a received request message by checking for the requested message and forwarding it back
145 * if the message was found. 68 * if the message was found.
146 * (this can also cause this peer to send a new request instead of only forwarding the received one) 69 * (this can also cause this peer to send a new request instead of only forwarding the received one)
147 * 70 *
148 * TODO: Requests can cause exponentially more requests! 71 * @param[in/out] room Room of the message
149 * 72 * @param[in/out] tunnel Receiving connection
150 * @param room Room of the message 73 * @param[in] message REQUEST-Message
151 * @param tunnel Receiving connection 74 * @param[in] hash Hash of the message
152 * @param message REQUEST-Message 75 * @return #GNUNET_YES or #GNUNET_NO depending on required forwarding
153 * @param hash Hash of the message
154 */ 76 */
155void 77int
156recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 78recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
157 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 79 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
158 80
159#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H 81#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H
diff --git a/src/messenger/gnunet-service-messenger_message_send.c b/src/messenger/gnunet-service-messenger_message_send.c
index 86cf9b888..a59a178cc 100644
--- a/src/messenger/gnunet-service-messenger_message_send.c
+++ b/src/messenger/gnunet-service-messenger_message_send.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -24,95 +24,45 @@
24 */ 24 */
25 25
26#include "gnunet-service-messenger_message_send.h" 26#include "gnunet-service-messenger_message_send.h"
27#include "gnunet-service-messenger_message_handle.h"
28 27
29void 28#include "gnunet-service-messenger_member.h"
30send_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 29#include "gnunet-service-messenger_member_session.h"
31 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 30#include "gnunet-service-messenger_operation.h"
32 const struct GNUNET_HashCode *hash)
33{
34 if (!tunnel->contact_id)
35 {
36 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
37
38 GNUNET_memcpy(tunnel->contact_id, &(message->body.info.unique_id), sizeof(struct GNUNET_ShortHashCode));
39 }
40 else
41 {
42 disconnect_tunnel (tunnel);
43 }
44}
45 31
46void 32void
47send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 33send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
48 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 34 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
49 const struct GNUNET_HashCode *hash)
50{
51 handle_message_join (room, tunnel, message, hash);
52
53 if (room->peer_message)
54 {
55 const struct GNUNET_MESSENGER_Message *peer_message = get_room_message (room, handle, room->peer_message,
56 GNUNET_NO);
57
58 if ((peer_message) && (tunnel))
59 {
60 forward_tunnel_message (tunnel, peer_message, room->peer_message);
61 }
62 }
63}
64
65void
66send_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
67 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
68 const struct GNUNET_HashCode *hash)
69{ 35{
70 handle_message_leave (room, tunnel, message, hash); 36 check_room_peer_status(room, NULL);
71}
72
73void
74send_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
75 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
76 const struct GNUNET_HashCode *hash)
77{
78 handle_message_name (room, tunnel, message, hash);
79}
80
81void
82send_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
83 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
84 const struct GNUNET_HashCode *hash)
85{
86 handle_message_key (room, tunnel, message, hash);
87} 37}
88 38
89void 39void
90send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 40send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
91 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 41 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
92 const struct GNUNET_HashCode *hash)
93{ 42{
94 if (!room->peer_message) 43 if (!room->peer_message)
95 {
96 room->peer_message = GNUNET_new(struct GNUNET_HashCode); 44 room->peer_message = GNUNET_new(struct GNUNET_HashCode);
97 }
98 45
99 GNUNET_memcpy(room->peer_message, hash, sizeof(struct GNUNET_HashCode)); 46 GNUNET_memcpy(room->peer_message, hash, sizeof(struct GNUNET_HashCode));
100
101 handle_message_peer (room, tunnel, message, hash);
102} 47}
103 48
104void 49void
105send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 50send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
106 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 51 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
107 const struct GNUNET_HashCode *hash)
108{ 52{
109 handle_message_id (room, tunnel, message, hash); 53 change_handle_member_id (handle, get_room_key(room), &(message->body.id.id));
110} 54}
111 55
112void 56void
113send_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 57send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
114 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 58 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
115 const struct GNUNET_HashCode *hash)
116{ 59{
117 handle_message_miss (room, tunnel, message, hash); 60 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
61
62 use_store_operation(
63 operation_store,
64 &(message->body.request.hash),
65 GNUNET_MESSENGER_OP_REQUEST,
66 GNUNET_MESSENGER_REQUEST_DELAY
67 );
118} 68}
diff --git a/src/messenger/gnunet-service-messenger_message_send.h b/src/messenger/gnunet-service-messenger_message_send.h
index c1096205a..63320ab17 100644
--- a/src/messenger/gnunet-service-messenger_message_send.h
+++ b/src/messenger/gnunet-service-messenger_message_send.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -29,127 +29,61 @@
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31 31
32#include "gnunet-service-messenger_message_kind.h"
33
32#include "gnunet-service-messenger_tunnel.h" 34#include "gnunet-service-messenger_tunnel.h"
33#include "messenger_api_message.h" 35#include "messenger_api_message.h"
34 36
35/** 37/**
36 * Handles a sent info message to setup a tunnels linked member id.
37 * (if a tunnel has already got a member id linked to it, the connection will be closed)
38 *
39 * @param room Room of the message
40 * @param handle Sending handle
41 * @param tunnel Sending connection (may be NULL)
42 * @param message INFO-Message
43 * @param hash Hash of the message
44 */
45void
46send_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
47 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
48 const struct GNUNET_HashCode *hash);
49
50/**
51 * Handles a sent join message to ensure growth of the decentralized room structure. 38 * Handles a sent join message to ensure growth of the decentralized room structure.
52 * (if the service provides a peer message for this room currently, it will be forwarded) 39 * (if the service provides a peer message for this room currently, it will be forwarded)
53 * 40 *
54 * @param room Room of the message 41 * @param[in/out] room Room of the message
55 * @param handle Sending handle 42 * @param[in/out] handle Sending handle
56 * @param tunnel Sending connection (may be NULL) 43 * @param[in] message JOIN-Message
57 * @param message JOIN-Message 44 * @param[in] hash Hash of the message
58 * @param hash Hash of the message
59 */ 45 */
60void 46void
61send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 47send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
62 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 48 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
63 const struct GNUNET_HashCode *hash);
64
65/**
66 * Handles a sent leave message.
67 * @see handle_message_leave()
68 *
69 * @param room Room of the message
70 * @param handle Sending handle
71 * @param tunnel Sending connection (may be NULL)
72 * @param message LEAVE-Message
73 * @param hash Hash of the message
74 */
75void
76send_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
77 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
78 const struct GNUNET_HashCode *hash);
79
80/**
81 * Handles a sent name message.
82 * @see handle_message_name()
83 *
84 * @param room Room of the message
85 * @param handle Sending handle
86 * @param tunnel Sending connection (may be NULL)
87 * @param message NAME-Message
88 * @param hash Hash of the message
89 */
90void
91send_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
92 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
93 const struct GNUNET_HashCode *hash);
94
95/**
96 * Handles a sent key message.
97 * @see handle_message_key()
98 *
99 * @param room Room of the message
100 * @param handle Sending handle
101 * @param tunnel Sending connection (may be NULL)
102 * @param message KEY-Message
103 * @param hash Hash of the message
104 */
105void
106send_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
107 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
108 const struct GNUNET_HashCode *hash);
109 49
110/** 50/**
111 * Handles a sent peer message to update the rooms peer message of this service. 51 * Handles a sent peer message to update the rooms peer message of this service.
112 * (a set peer message indicates this service being a part of the decentralized room structure) 52 * (a set peer message indicates this service being a part of the decentralized room structure)
113 * 53 *
114 * @param room Room of the message 54 * @param[in/out] room Room of the message
115 * @param handle Sending handle 55 * @param[in/out] handle Sending handle
116 * @param tunnel Sending connection (may be NULL) 56 * @param[in] message PEER-Message
117 * @param message PEER-Message 57 * @param[in] hash Hash of the message
118 * @param hash Hash of the message
119 */ 58 */
120void 59void
121send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 60send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
122 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 61 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
123 const struct GNUNET_HashCode *hash);
124 62
125/** 63/**
126 * Handles a sent id message. 64 * Handles a sent id message to update the handles member id in the room.
127 * @see handle_message_id() 65 * (changing member id is useful to prevent collisions)
128 * 66 *
129 * @param room Room of the message 67 * @param[in/out] room Room of the message
130 * @param handle Sending handle 68 * @param[in/out] handle Sending handle
131 * @param tunnel Sending connection (may be NULL) 69 * @param[in] message ID-Message
132 * @param message ID-Message 70 * @param[in] hash Hash of the message
133 * @param hash Hash of the message
134 */ 71 */
135void 72void
136send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 73send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
137 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 74 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
138 const struct GNUNET_HashCode *hash);
139 75
140/** 76/**
141 * Handles a sent miss message. 77 * Handles a sent request message to trigger the request operation for this service.
142 * @see handle_message_miss() 78 * (the request operation will deactivate the possibility of spamming requests)
143 * 79 *
144 * @param room Room of the message 80 * @param[in/out] room Room of the message
145 * @param handle Sending handle 81 * @param[in/out] handle Sending handle
146 * @param tunnel Sending connection (may be NULL) 82 * @param[in] message PEER-Message
147 * @param message MISS-Message 83 * @param[in] hash Hash of the message
148 * @param hash Hash of the message
149 */ 84 */
150void 85void
151send_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 86send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
152 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 87 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
153 const struct GNUNET_HashCode *hash);
154 88
155#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H 89#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H
diff --git a/src/messenger/gnunet-service-messenger_message_state.c b/src/messenger/gnunet-service-messenger_message_state.c
new file mode 100644
index 000000000..cdd2d9712
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_message_state.c
@@ -0,0 +1,109 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_message_state.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_message_state.h"
27
28void
29init_message_state (struct GNUNET_MESSENGER_MessageState *state)
30{
31 GNUNET_assert(state);
32
33 init_list_messages (&(state->last_messages));
34}
35
36void
37clear_message_state (struct GNUNET_MESSENGER_MessageState *state)
38{
39 GNUNET_assert(state);
40
41 clear_list_messages (&(state->last_messages));
42}
43
44void
45get_message_state_chain_hash (const struct GNUNET_MESSENGER_MessageState *state,
46 struct GNUNET_HashCode *hash)
47{
48 GNUNET_assert((state) && (hash));
49
50 if (state->last_messages.head)
51 GNUNET_memcpy(hash, &(state->last_messages.head->hash), sizeof(*hash));
52 else
53 memset (hash, 0, sizeof(*hash));
54}
55
56const struct GNUNET_HashCode*
57get_message_state_merge_hash (const struct GNUNET_MESSENGER_MessageState *state)
58{
59 GNUNET_assert(state);
60
61 if (state->last_messages.head == state->last_messages.tail)
62 return NULL;
63
64 return &(state->last_messages.tail->hash);
65}
66
67void
68update_message_state (struct GNUNET_MESSENGER_MessageState *state, int requested,
69 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
70{
71 GNUNET_assert((state) && (message) && (hash));
72
73 if ((GNUNET_YES == requested) ||
74 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
75 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
76 return;
77
78 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
79 remove_from_list_messages(&(state->last_messages), &(message->body.merge.previous));
80 remove_from_list_messages(&(state->last_messages), &(message->header.previous));
81
82 add_to_list_messages (&(state->last_messages), hash);
83}
84
85void
86load_message_state (struct GNUNET_MESSENGER_MessageState *state, const char *path)
87{
88 GNUNET_assert((state) && (path));
89
90 char *last_messages_file;
91 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
92
93 load_list_messages(&(state->last_messages), last_messages_file);
94 GNUNET_free(last_messages_file);
95}
96
97void
98save_message_state (const struct GNUNET_MESSENGER_MessageState *state, const char *path)
99{
100 GNUNET_assert((state) && (path));
101
102 char *last_messages_file;
103 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
104
105 save_list_messages(&(state->last_messages), last_messages_file);
106 GNUNET_free(last_messages_file);
107}
108
109
diff --git a/src/messenger/gnunet-service-messenger_message_state.h b/src/messenger/gnunet-service-messenger_message_state.h
new file mode 100644
index 000000000..dc8671df4
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_message_state.h
@@ -0,0 +1,63 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_message_state.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
27#define GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31
32#include "messenger_api_message.h"
33#include "gnunet-service-messenger_list_messages.h"
34
35struct GNUNET_MESSENGER_MessageState
36{
37 struct GNUNET_MESSENGER_ListMessages last_messages;
38};
39
40void
41init_message_state (struct GNUNET_MESSENGER_MessageState *state);
42
43void
44clear_message_state (struct GNUNET_MESSENGER_MessageState *state);
45
46void
47get_message_state_chain_hash (const struct GNUNET_MESSENGER_MessageState *state,
48 struct GNUNET_HashCode *hash);
49
50const struct GNUNET_HashCode*
51get_message_state_merge_hash (const struct GNUNET_MESSENGER_MessageState *state);
52
53void
54update_message_state (struct GNUNET_MESSENGER_MessageState *state, int requested,
55 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
56
57void
58load_message_state (struct GNUNET_MESSENGER_MessageState *state, const char *path);
59
60void
61save_message_state (const struct GNUNET_MESSENGER_MessageState *state, const char *path);
62
63#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
diff --git a/src/messenger/gnunet-service-messenger_message_store.c b/src/messenger/gnunet-service-messenger_message_store.c
index 5933d6390..1984eba21 100644..100755
--- a/src/messenger/gnunet-service-messenger_message_store.c
+++ b/src/messenger/gnunet-service-messenger_message_store.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -29,10 +29,16 @@
29void 29void
30init_message_store (struct GNUNET_MESSENGER_MessageStore *store) 30init_message_store (struct GNUNET_MESSENGER_MessageStore *store)
31{ 31{
32 GNUNET_assert(store);
33
32 store->storage_messages = NULL; 34 store->storage_messages = NULL;
33 35
34 store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 36 store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
35 store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 37 store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38 store->links = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
39
40 store->rewrite_entries = GNUNET_NO;
41 store->write_links = GNUNET_NO;
36} 42}
37 43
38static int 44static int
@@ -55,9 +61,21 @@ iterate_destroy_messages (void *cls, const struct GNUNET_HashCode *key, void *va
55 return GNUNET_YES; 61 return GNUNET_YES;
56} 62}
57 63
64static int
65iterate_destroy_links (void *cls, const struct GNUNET_HashCode *key, void *value)
66{
67 struct GNUNET_HashCode *previous = value;
68
69 GNUNET_free(previous);
70
71 return GNUNET_YES;
72}
73
58void 74void
59clear_message_store (struct GNUNET_MESSENGER_MessageStore *store) 75clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
60{ 76{
77 GNUNET_assert(store);
78
61 if (store->storage_messages) 79 if (store->storage_messages)
62 { 80 {
63 GNUNET_DISK_file_close (store->storage_messages); 81 GNUNET_DISK_file_close (store->storage_messages);
@@ -67,9 +85,11 @@ clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
67 85
68 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL); 86 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL);
69 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL); 87 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL);
88 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_destroy_links, NULL);
70 89
71 GNUNET_CONTAINER_multihashmap_destroy (store->entries); 90 GNUNET_CONTAINER_multihashmap_destroy (store->entries);
72 GNUNET_CONTAINER_multihashmap_destroy (store->messages); 91 GNUNET_CONTAINER_multihashmap_destroy (store->messages);
92 GNUNET_CONTAINER_multihashmap_destroy (store->links);
73} 93}
74 94
75struct GNUNET_MESSENGER_MessageEntryStorage 95struct GNUNET_MESSENGER_MessageEntryStorage
@@ -78,36 +98,15 @@ struct GNUNET_MESSENGER_MessageEntryStorage
78 struct GNUNET_MESSENGER_MessageEntry entry; 98 struct GNUNET_MESSENGER_MessageEntry entry;
79}; 99};
80 100
81void 101static void
82load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) 102load_message_store_entries (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
83{ 103{
84 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); 104 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
85
86 if (store->storage_messages)
87 GNUNET_DISK_file_close (store->storage_messages);
88
89 char *filename;
90 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
91
92 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
93 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
94 else
95 store->storage_messages = NULL;
96
97 GNUNET_free(filename);
98
99 if (!store->storage_messages)
100 return;
101
102 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
103
104 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
105 goto free_filename;
106 105
107 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission); 106 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
108 107
109 if (!entries) 108 if (!entries)
110 goto free_filename; 109 return;
111 110
112 struct GNUNET_MESSENGER_MessageEntryStorage storage; 111 struct GNUNET_MESSENGER_MessageEntryStorage storage;
113 struct GNUNET_MESSENGER_MessageEntry *entry; 112 struct GNUNET_MESSENGER_MessageEntry *entry;
@@ -120,9 +119,13 @@ load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
120 { 119 {
121 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry)); 120 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry));
122 121
123 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry, 122 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->entries, &(storage.hash))) ||
124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 123 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry,
124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
125 {
126 store->rewrite_entries = GNUNET_YES;
125 GNUNET_free(entry); 127 GNUNET_free(entry);
128 }
126 } 129 }
127 else 130 else
128 { 131 {
@@ -134,22 +137,120 @@ load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
134 while (entry); 137 while (entry);
135 138
136 GNUNET_DISK_file_close (entries); 139 GNUNET_DISK_file_close (entries);
140}
141
142struct GNUNET_MESSENGER_MessageLinkStorage
143{
144 struct GNUNET_HashCode hash;
145 struct GNUNET_MESSENGER_MessageLink link;
146};
147
148static void
149load_message_store_links (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
150{
151 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
152
153 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
154
155 if (!entries)
156 return;
157
158 struct GNUNET_MESSENGER_MessageLinkStorage storage;
159 struct GNUNET_MESSENGER_MessageLink *link = NULL;
160
161 memset(&storage, 0, sizeof(storage));
162
163 do
164 {
165 if ((sizeof(storage.hash) != GNUNET_DISK_file_read (entries, &(storage.hash), sizeof(storage.hash))) ||
166 (sizeof(storage.link.multiple) != GNUNET_DISK_file_read (entries, &(storage.link.multiple), sizeof(storage.link.multiple))) ||
167 (sizeof(storage.link.first) != GNUNET_DISK_file_read (entries, &(storage.link.first), sizeof(storage.link.first))) ||
168 ((GNUNET_YES == storage.link.multiple) &&
169 (sizeof(storage.link.second) != GNUNET_DISK_file_read (entries, &(storage.link.second), sizeof(storage.link.second)))))
170 break;
171
172 link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
173
174 GNUNET_memcpy(link, &(storage.link), sizeof(*link));
175
176 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->links, &(storage.hash))) ||
177 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->links, &(storage.hash), link,
178 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
179 break;
180 }
181 while (link);
182
183 if (link)
184 GNUNET_free(link);
185
186 GNUNET_DISK_file_close (entries);
187}
188
189void
190load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
191{
192 GNUNET_assert((store) && (directory));
193
194 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
195
196 if (store->storage_messages)
197 GNUNET_DISK_file_close (store->storage_messages);
198
199 char *filename;
200 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
201
202 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
203 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, permission);
204 else
205 store->storage_messages = NULL;
206
207 GNUNET_free(filename);
208
209 if (!store->storage_messages)
210 return;
211
212 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
213
214 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
215 load_message_store_entries(store, filename);
216
217 GNUNET_free(filename);
218
219 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
220
221 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
222 load_message_store_links(store, filename);
137 223
138free_filename:
139 GNUNET_free(filename); 224 GNUNET_free(filename);
140} 225}
141 226
142struct GNUNET_MESSENGER_MessageSave 227struct GNUNET_MESSENGER_ClosureMessageSave
143{ 228{
144 struct GNUNET_MESSENGER_MessageStore *store; 229 struct GNUNET_MESSENGER_MessageStore *store;
145 230
146 struct GNUNET_DISK_FileHandle *storage_entries; 231 struct GNUNET_DISK_FileHandle *storage;
147}; 232};
148 233
149static int 234static int
235iterate_save_entries (void *cls, const struct GNUNET_HashCode *key, void *value)
236{
237 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
238 struct GNUNET_MESSENGER_MessageEntry *entry = value;
239
240 struct GNUNET_MESSENGER_MessageEntryStorage storage;
241
242 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
243 GNUNET_memcpy(&(storage.entry), entry, sizeof(*entry));
244
245 GNUNET_DISK_file_write (save->storage, &storage, sizeof(storage));
246
247 return GNUNET_YES;
248}
249
250static int
150iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value) 251iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
151{ 252{
152 struct GNUNET_MESSENGER_MessageSave *save = cls; 253 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
153 254
154 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key)) 255 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key))
155 return GNUNET_YES; 256 return GNUNET_YES;
@@ -159,16 +260,16 @@ iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value
159 260
160 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash)); 261 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
161 262
162 storage.entry.length = get_message_size (message); 263 storage.entry.length = get_message_size (message, GNUNET_YES);
163 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END); 264 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
164 265
165 if ((GNUNET_SYSERR == storage.entry.offset) || 266 if ((GNUNET_SYSERR == storage.entry.offset) || (sizeof(storage)
166 (sizeof(storage) != GNUNET_DISK_file_write (save->storage_entries, &storage, sizeof(storage)))) 267 != GNUNET_DISK_file_write (save->storage, &storage, sizeof(storage))))
167 return GNUNET_YES; 268 return GNUNET_YES;
168 269
169 char *buffer = GNUNET_malloc(storage.entry.length); 270 char *buffer = GNUNET_malloc(storage.entry.length);
170 271
171 encode_message (message, storage.entry.length, buffer); 272 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
172 273
173 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length); 274 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length);
174 275
@@ -177,25 +278,75 @@ iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value
177 return GNUNET_YES; 278 return GNUNET_YES;
178} 279}
179 280
281static int
282iterate_save_links (void *cls, const struct GNUNET_HashCode *key, void *value)
283{
284 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
285 struct GNUNET_MESSENGER_MessageLink *link = value;
286
287 GNUNET_DISK_file_write (save->storage, key, sizeof(*key));
288 GNUNET_DISK_file_write (save->storage, &(link->multiple), sizeof(link->multiple));
289 GNUNET_DISK_file_write (save->storage, &(link->first), sizeof(link->first));
290
291 if (GNUNET_YES == link->multiple)
292 GNUNET_DISK_file_write (save->storage, &(link->second), sizeof(link->second));
293
294 return GNUNET_YES;
295}
296
180void 297void
181save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) 298save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
182{ 299{
183 struct GNUNET_MESSENGER_MessageSave save; 300 GNUNET_assert((store) && (directory));
301
302 struct GNUNET_MESSENGER_ClosureMessageSave save;
184 303
185 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); 304 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
186 305
187 char *filename; 306 char *filename;
307
308 if (GNUNET_YES != store->write_links)
309 goto save_entries;
310
311 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
312
313 save.store = store;
314 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
315
316 GNUNET_free(filename);
317
318 if (!save.storage)
319 goto save_entries;
320
321 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
322 goto close_links;
323
324 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_save_links, &save);
325 store->write_links = GNUNET_NO;
326
327close_links:
328 GNUNET_DISK_file_close (save.storage);
329
330save_entries:
188 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store"); 331 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
189 332
190 save.store = store; 333 save.store = store;
191 save.storage_entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission); 334 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
192 335
193 GNUNET_free(filename); 336 GNUNET_free(filename);
194 337
195 if (!save.storage_entries) 338 if (!save.storage)
196 return; 339 return;
197 340
198 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage_entries, 0, GNUNET_DISK_SEEK_END)) 341 if (GNUNET_YES == store->rewrite_entries)
342 {
343 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
344 goto close_entries;
345
346 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_save_entries, &save);
347 store->rewrite_entries = GNUNET_NO;
348 }
349 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_END))
199 goto close_entries; 350 goto close_entries;
200 351
201 if (store->storage_messages) 352 if (store->storage_messages)
@@ -213,16 +364,18 @@ save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
213 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save); 364 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save);
214 365
215 GNUNET_DISK_file_sync (store->storage_messages); 366 GNUNET_DISK_file_sync (store->storage_messages);
216 GNUNET_DISK_file_sync (save.storage_entries); 367 GNUNET_DISK_file_sync (save.storage);
217 } 368 }
218 369
219close_entries: 370close_entries:
220 GNUNET_DISK_file_close (save.storage_entries); 371 GNUNET_DISK_file_close (save.storage);
221} 372}
222 373
223int 374int
224contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) 375contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
225{ 376{
377 GNUNET_assert((store) && (hash));
378
226 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash)) 379 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash))
227 return GNUNET_YES; 380 return GNUNET_YES;
228 381
@@ -232,6 +385,8 @@ contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struc
232const struct GNUNET_MESSENGER_Message* 385const struct GNUNET_MESSENGER_Message*
233get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) 386get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
234{ 387{
388 GNUNET_assert((store) && (hash));
389
235 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash); 390 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
236 391
237 if (message) 392 if (message)
@@ -250,33 +405,145 @@ get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNU
250 405
251 char *buffer = GNUNET_malloc(entry->length); 406 char *buffer = GNUNET_malloc(entry->length);
252 407
253 if (GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) 408 if (!buffer)
254 goto free_buffer; 409 return NULL;
255 410
411 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) ||
412 (entry->length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN)))
413 goto free_buffer;
256 414
257 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN); 415 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN);
258 416
259 if ((GNUNET_YES != decode_message (message, entry->length, buffer)) || (GNUNET_OK 417 const int decoding = decode_message (message, entry->length, buffer, GNUNET_YES, NULL);
260 != GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message, 418
261 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) 419 struct GNUNET_HashCode check;
420 hash_message (message, entry->length, buffer, &check);
421
422 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
262 { 423 {
263 destroy_message (message); 424 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
425 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Corrupted entry could not be removed from store: %s\n",
426 GNUNET_h2s(hash));
264 427
265 message = NULL; 428 store->rewrite_entries = GNUNET_YES;
266 429
267 GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry); 430 goto free_message;
268 } 431 }
269 432
433 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
434 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
435 goto free_buffer;
436
437free_message: destroy_message (message);
438 message = NULL;
439
270free_buffer: 440free_buffer:
271 GNUNET_free(buffer); 441 GNUNET_free(buffer);
272 442
273 return message; 443 return message;
274} 444}
275 445
446const struct GNUNET_MESSENGER_MessageLink*
447get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
448 int deleted_only)
449{
450 if (deleted_only)
451 goto get_link;
452
453 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
454
455 if (!message)
456 goto get_link;
457
458 static struct GNUNET_MESSENGER_MessageLink link;
459
460 GNUNET_memcpy(&(link.first), &(message->header.previous), sizeof(link.first));
461
462 link.multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
463
464 if (GNUNET_YES == link.multiple)
465 GNUNET_memcpy(&(link.second), &(message->body.merge.previous), sizeof(link.second));
466 else
467 GNUNET_memcpy(&(link.second), &(message->header.previous), sizeof(link.second));
468
469 return &link;
470
471get_link:
472 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
473}
474
276int 475int
277put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, 476put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
278 struct GNUNET_MESSENGER_Message *message) 477 struct GNUNET_MESSENGER_Message *message)
279{ 478{
479 GNUNET_assert((store) && (hash) && (message));
480
280 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message, 481 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
281 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 482 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
282} 483}
484
485static void
486add_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
487 const struct GNUNET_MESSENGER_Message *message)
488{
489 struct GNUNET_MESSENGER_MessageLink *link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
490
491 GNUNET_memcpy(&(link->first), &(message->header.previous), sizeof(link->first));
492
493 link->multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
494
495 if (GNUNET_YES == link->multiple)
496 GNUNET_memcpy(&(link->second), &(message->body.merge.previous), sizeof(link->second));
497 else
498 GNUNET_memcpy(&(link->second), &(message->header.previous), sizeof(link->second));
499
500 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->links, hash, link,
501 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
502 GNUNET_free(link);
503}
504
505int
506delete_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
507{
508 GNUNET_assert((store) && (hash));
509
510 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
511
512 if (!entry)
513 goto clear_memory;
514
515 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
516
517 if (message)
518 add_link (store, hash, message);
519
520 if (!store->storage_messages)
521 goto clear_entry;
522
523 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
524 return GNUNET_SYSERR;
525
526 char *clear_buffer = GNUNET_malloc(entry->length);
527
528 if (!clear_buffer)
529 return GNUNET_SYSERR;
530
531 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
532
533 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages, clear_buffer, entry->length)) || (GNUNET_OK
534 != GNUNET_DISK_file_sync (store->storage_messages)))
535 {
536 GNUNET_free(clear_buffer);
537 return GNUNET_SYSERR;
538 }
539
540 GNUNET_free(clear_buffer);
541
542clear_entry:
543 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
544 store->rewrite_entries = GNUNET_YES;
545
546clear_memory:
547 GNUNET_CONTAINER_multihashmap_remove_all (store->messages, hash);
548 return GNUNET_OK;
549}
diff --git a/src/messenger/gnunet-service-messenger_message_store.h b/src/messenger/gnunet-service-messenger_message_store.h
index e58459b21..87305826a 100644
--- a/src/messenger/gnunet-service-messenger_message_store.h
+++ b/src/messenger/gnunet-service-messenger_message_store.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -36,85 +36,127 @@ struct GNUNET_MESSENGER_MessageEntry
36 uint16_t length; 36 uint16_t length;
37}; 37};
38 38
39struct GNUNET_MESSENGER_Message;
40
41struct GNUNET_MESSENGER_MessageLink
42{
43 uint8_t multiple;
44
45 struct GNUNET_HashCode first;
46 struct GNUNET_HashCode second;
47};
48
39struct GNUNET_MESSENGER_MessageStore 49struct GNUNET_MESSENGER_MessageStore
40{ 50{
41 struct GNUNET_DISK_FileHandle *storage_messages; 51 struct GNUNET_DISK_FileHandle *storage_messages;
42 52
43 struct GNUNET_CONTAINER_MultiHashMap *entries; 53 struct GNUNET_CONTAINER_MultiHashMap *entries;
44 struct GNUNET_CONTAINER_MultiHashMap *messages; 54 struct GNUNET_CONTAINER_MultiHashMap *messages;
55 struct GNUNET_CONTAINER_MultiHashMap *links;
56
57 int rewrite_entries;
58 int write_links;
45}; 59};
46 60
47/** 61/**
48 * Initializes a message store as fully empty. 62 * Initializes a message <i>store</i> as fully empty.
49 * 63 *
50 * @param store Message store 64 * @param[out] store Message store
51 */ 65 */
52void 66void
53init_message_store (struct GNUNET_MESSENGER_MessageStore *store); 67init_message_store (struct GNUNET_MESSENGER_MessageStore *store);
54 68
55/** 69/**
56 * Clears a message store, wipes its content and deallocates its memory. 70 * Clears a message <i>store</i>, wipes its content and deallocates its memory.
57 * 71 *
58 * @param store Message store 72 * @param[in/out] store Message store
59 */ 73 */
60void 74void
61clear_message_store (struct GNUNET_MESSENGER_MessageStore *store); 75clear_message_store (struct GNUNET_MESSENGER_MessageStore *store);
62 76
63/** 77/**
64 * Loads messages from a directory into a message store. 78 * Loads messages from a <i>directory</i> into a message <i>store</i>.
65 * 79 *
66 * @param store Message store 80 * @param[out] store Message store
67 * @param directory Path to a directory 81 * @param[in] directory Path to a directory
68 */ 82 */
69void 83void
70load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory); 84load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory);
71 85
72/** 86/**
73 * Saves messages from a message store into a directory. 87 * Saves messages from a message <i>store</i> into a <i>directory</i>.
74 * 88 *
75 * @param store Message store 89 * @param[in] store Message store
76 * @param directory Path to a directory 90 * @param[in] directory Path to a directory
77 */ 91 */
78void 92void
79save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory); 93save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory);
80 94
81/** 95/**
82 * Checks if a message matching a given <i>hash</i> is stored in a message store. The function returns 96 * Checks if a message matching a given <i>hash</i> is stored in a message <i>store</i>.
83 * GNUNET_YES if a match is found, GNUNET_NO otherwise. 97 * The function returns #GNUNET_YES if a match is found, #GNUNET_NO otherwise.
84 * 98 *
85 * The message has not to be loaded from disk into memory for this check! 99 * The message has not to be loaded from disk into memory for this check!
86 * 100 *
87 * @param store Message store 101 * @param[in] store Message store
88 * @param hash Hash of message 102 * @param[in] hash Hash of message
89 * @return GNUNET_YES on match, otherwise GNUNET_NO 103 * @return #GNUNET_YES on match, otherwise #GNUNET_NO
90 */ 104 */
91int 105int
92contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash); 106contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
93 107
94/** 108/**
95 * Returns the message from a message store matching a given <i>hash</i>. If no matching message is found, 109 * Returns the message from a message <i>store</i> matching a given <i>hash</i>. If no matching
96 * NULL gets returned. 110 * message is found, NULL gets returned.
97 * 111 *
98 * This function requires the message to be loaded into memory! 112 * This function requires the message to be loaded into memory!
99 * @see contains_store_message() 113 * @see contains_store_message()
100 * 114 *
101 * @param store Message store 115 * @param[in/out] store Message store
102 * @param hash Hash of message 116 * @param[in] hash Hash of message
103 * @return Message or NULL 117 * @return Message or NULL
104 */ 118 */
105const struct GNUNET_MESSENGER_Message* 119const struct GNUNET_MESSENGER_Message*
106get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash); 120get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
107 121
108/** 122/**
123 * Returns the message link from a message <i>store</i> matching a given <i>hash</i>. If the
124 * flag is set to #GNUNET_YES, only links from deleted messages will be returned or NULL.
125 *
126 * Otherwise message links will also returned for messages found in the store under the given
127 * hash. The link which will be returned copies link information from the message for
128 * temporary usage.
129 *
130 * @param[in/out] store Message store
131 * @param[in] hash Hash of message
132 * @param[in] deleted_only Flag
133 * @return Message link or NULL
134 */
135const struct GNUNET_MESSENGER_MessageLink*
136get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
137 int deleted_only);
138
139/**
109 * Stores a message into the message store. The result indicates if the operation was successful. 140 * Stores a message into the message store. The result indicates if the operation was successful.
110 * 141 *
111 * @param store Message store 142 * @param[in/out] store Message store
112 * @param hash Hash of message 143 * @param[in] hash Hash of message
113 * @param message Message 144 * @param[in/out] message Message
114 * @return GNUNET_OK on success, otherwise GNUNET_NO 145 * @return #GNUNET_OK on success, otherwise #GNUNET_NO
115 */ 146 */
116int 147int
117put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, 148put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
118 struct GNUNET_MESSENGER_Message *message); 149 struct GNUNET_MESSENGER_Message *message);
119 150
151/**
152 * Deletes a message in the message store. It will be removed from disk space and memory. The result
153 * indicates if the operation was successful.
154 *
155 * @param[in/out] store Message store
156 * @param[in] hash Hash of message
157 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
158 */
159int
160delete_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
161
120#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H 162#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_operation.c b/src/messenger/gnunet-service-messenger_operation.c
new file mode 100644
index 000000000..d0c378699
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_operation.c
@@ -0,0 +1,214 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_operation.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_operation.h"
27
28#include "gnunet-service-messenger_operation_store.h"
29
30struct GNUNET_MESSENGER_Operation*
31create_operation (const struct GNUNET_HashCode *hash)
32{
33 GNUNET_assert(hash);
34
35 struct GNUNET_MESSENGER_Operation *op = GNUNET_new(struct GNUNET_MESSENGER_Operation);
36
37 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
38 GNUNET_memcpy(&(op->hash), hash, sizeof(*hash));
39 op->timestamp = GNUNET_TIME_absolute_get_zero_();
40 op->store = NULL;
41 op->task = NULL;
42
43 return op;
44}
45
46void
47destroy_operation (struct GNUNET_MESSENGER_Operation *op)
48{
49 GNUNET_assert(op);
50
51 if (op->task)
52 GNUNET_SCHEDULER_cancel(op->task);
53
54 GNUNET_free(op);
55}
56
57static void
58callback_operation (void *cls);
59
60struct GNUNET_MESSENGER_Operation*
61load_operation (struct GNUNET_MESSENGER_OperationStore *store, const char *path)
62{
63 GNUNET_assert((store) && (path));
64
65 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
66 struct GNUNET_MESSENGER_Operation* op = NULL;
67
68 if (GNUNET_OK != GNUNET_CONFIGURATION_parse(cfg, path))
69 goto destroy_config;
70
71 struct GNUNET_HashCode hash;
72
73 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "hash", &hash, sizeof(hash)))
74 goto destroy_config;
75
76 op = create_operation(&hash);
77
78 unsigned long long type_number;
79 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number(cfg, "operation", "type", &type_number))
80 switch (type_number)
81 {
82 case GNUNET_MESSENGER_OP_REQUEST:
83 op->type = GNUNET_MESSENGER_OP_REQUEST;
84 break;
85 case GNUNET_MESSENGER_OP_DELETE:
86 op->type = GNUNET_MESSENGER_OP_DELETE;
87 break;
88 case GNUNET_MESSENGER_OP_MERGE:
89 op->type = GNUNET_MESSENGER_OP_MERGE;
90 break;
91 default:
92 break;
93 }
94
95 if ((GNUNET_MESSENGER_OP_UNKNOWN == op->type) ||
96 (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "timestamp", &(op->timestamp), sizeof(op->timestamp))))
97 {
98 destroy_operation(op);
99 op = NULL;
100 goto destroy_config;
101 }
102
103 const struct GNUNET_TIME_Relative delay = GNUNET_TIME_absolute_get_remaining(op->timestamp);
104
105 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
106 delay,
107 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
108 callback_operation,
109 op
110 );
111
112 op->store = store;
113
114destroy_config:
115 GNUNET_CONFIGURATION_destroy (cfg);
116
117 return op;
118}
119
120void
121save_operation (const struct GNUNET_MESSENGER_Operation *op, const char *path)
122{
123 GNUNET_assert((path) && (op));
124
125 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
126
127 char *hash_data;
128 hash_data = GNUNET_STRINGS_data_to_string_alloc (&(op->hash), sizeof(op->hash));
129
130 if (hash_data)
131 {
132 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "hash", hash_data);
133
134 GNUNET_free(hash_data);
135 }
136
137 GNUNET_CONFIGURATION_set_value_number(cfg, "operation", "type", op->type);
138
139 char *timestamp_data;
140 timestamp_data = GNUNET_STRINGS_data_to_string_alloc (&(op->timestamp), sizeof(op->timestamp));
141
142 if (timestamp_data)
143 {
144 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "timestamp", timestamp_data);
145
146 GNUNET_free(timestamp_data);
147 }
148
149 GNUNET_CONFIGURATION_write (cfg, path);
150 GNUNET_CONFIGURATION_destroy (cfg);
151}
152
153extern void
154callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
155 enum GNUNET_MESSENGER_OperationType type,
156 const struct GNUNET_HashCode *hash);
157
158static void
159callback_operation (void *cls)
160{
161 struct GNUNET_MESSENGER_Operation *op = cls;
162
163 op->task = NULL;
164
165 callback_store_operation (op->store, op->type, &(op->hash));
166}
167
168int
169start_operation (struct GNUNET_MESSENGER_Operation *op,
170 enum GNUNET_MESSENGER_OperationType type,
171 struct GNUNET_MESSENGER_OperationStore *store,
172 struct GNUNET_TIME_Relative delay)
173{
174 GNUNET_assert((op) && (store));
175
176 if (op->task)
177 return GNUNET_SYSERR;
178
179 const struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_add(
180 GNUNET_TIME_absolute_get(),
181 delay
182 );
183
184 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
185 delay,
186 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
187 callback_operation,
188 op
189 );
190
191 op->type = type;
192 op->timestamp = timestamp;
193 op->store = store;
194
195 return GNUNET_OK;
196}
197
198int
199stop_operation (struct GNUNET_MESSENGER_Operation *op)
200{
201 GNUNET_assert(op);
202
203 if (!op->task)
204 return GNUNET_SYSERR;
205
206 GNUNET_SCHEDULER_cancel(op->task);
207 op->task = NULL;
208
209 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
210 op->timestamp = GNUNET_TIME_absolute_get_zero_();
211 op->store = NULL;
212
213 return GNUNET_OK;
214}
diff --git a/src/messenger/gnunet-service-messenger_operation.h b/src/messenger/gnunet-service-messenger_operation.h
new file mode 100644
index 000000000..7757b8e88
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_operation.h
@@ -0,0 +1,129 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_operation.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_OPERATION_H
27#define GNUNET_SERVICE_MESSENGER_OPERATION_H
28
29#include "platform.h"
30#include "gnunet_configuration_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_scheduler_lib.h"
33#include "gnunet_strings_lib.h"
34#include "gnunet_time_lib.h"
35
36enum GNUNET_MESSENGER_OperationType
37{
38 GNUNET_MESSENGER_OP_REQUEST = 1,
39 GNUNET_MESSENGER_OP_DELETE = 2,
40 GNUNET_MESSENGER_OP_MERGE = 3,
41
42 GNUNET_MESSENGER_OP_UNKNOWN = 0
43};
44
45struct GNUNET_MESSENGER_OperationStore;
46
47struct GNUNET_MESSENGER_Operation
48{
49 enum GNUNET_MESSENGER_OperationType type;
50
51 struct GNUNET_HashCode hash;
52 struct GNUNET_TIME_Absolute timestamp;
53
54 struct GNUNET_MESSENGER_OperationStore *store;
55 struct GNUNET_SCHEDULER_Task* task;
56};
57
58/**
59 * Creates and allocates a new operation under a given <i>hash</i>.
60 *
61 * @param[in] hash Hash of message
62 */
63struct GNUNET_MESSENGER_Operation*
64create_operation (const struct GNUNET_HashCode *hash);
65
66/**
67 * Destroys an operation and frees its memory fully.
68 *
69 * @param[in/out] op Operation
70 */
71void
72destroy_operation (struct GNUNET_MESSENGER_Operation *op);
73
74/**
75 * Loads data from a configuration file at a selected <i>path</i> into
76 * a new allocated and created operation for a specific operation
77 * <i>store</i> if the required information could be read successfully.
78 *
79 * The method will return the new operation and it will be started
80 * automatically to match its timestamp of execution.
81 *
82 * If the method fails to restore any valid operation from the file,
83 * NULL gets returned instead.
84 *
85 * @param[in/out] store Operation store
86 * @param[in] path Path of a configuration file
87 */
88struct GNUNET_MESSENGER_Operation*
89load_operation (struct GNUNET_MESSENGER_OperationStore *store, const char *path);
90
91/**
92 * Saves data from an <i>operation</i> into a configuration file at a
93 * selected <i>path</i> which can be load to restore the operation
94 * completely and continue its process.
95 *
96 * @param[in] op Operation
97 * @param[in] path Path of a configuration file
98 */
99void
100save_operation (const struct GNUNET_MESSENGER_Operation *op, const char *path);
101
102/**
103 * Starts an inactive operation with a given <i>delay</i> in a
104 * specific operation <i>store</i>. The method will replace the
105 * operations type to process it correctly. An opeation can't be
106 * started twice, it has to be stopped or fully processed first.
107 *
108 * @param[in/out] op Operation
109 * @param[in] type Type of operation
110 * @param[in/out] store Operation store
111 * @param[in] delay Delay
112 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
113 */
114int
115start_operation (struct GNUNET_MESSENGER_Operation *op,
116 enum GNUNET_MESSENGER_OperationType type,
117 struct GNUNET_MESSENGER_OperationStore *store,
118 struct GNUNET_TIME_Relative delay);
119
120/**
121 * Stops an active operation and resets its type to be
122 * #GNUNET_MESSENGER_OP_UNKNOWN.
123 *
124 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
125 */
126int
127stop_operation (struct GNUNET_MESSENGER_Operation *op);
128
129#endif //GNUNET_SERVICE_MESSENGER_OPERATION_H
diff --git a/src/messenger/gnunet-service-messenger_operation_store.c b/src/messenger/gnunet-service-messenger_operation_store.c
new file mode 100755
index 000000000..a32fbad2c
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_operation_store.c
@@ -0,0 +1,226 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_operation_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_operation_store.h"
27
28#include "gnunet-service-messenger_operation.h"
29#include "gnunet-service-messenger_room.h"
30
31void
32init_operation_store (struct GNUNET_MESSENGER_OperationStore *store, struct GNUNET_MESSENGER_SrvRoom *room)
33{
34 GNUNET_assert((store) && (room));
35
36 store->room = room;
37 store->operations = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
38}
39
40static int
41iterate_destroy_operations (void *cls, const struct GNUNET_HashCode *key, void *value)
42{
43 struct GNUNET_MESSENGER_Operation *op = value;
44
45 destroy_operation(op);
46
47 return GNUNET_YES;
48}
49
50void
51clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store)
52{
53 GNUNET_assert(store);
54
55 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_destroy_operations, NULL);
56 GNUNET_CONTAINER_multihashmap_destroy(store->operations);
57}
58
59static int
60callback_scan_for_operations (void *cls, const char *filename)
61{
62 struct GNUNET_MESSENGER_OperationStore *store = cls;
63
64 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
65 {
66 char *path;
67
68 GNUNET_asprintf (&path, "%s%c", filename, DIR_SEPARATOR);
69
70 struct GNUNET_MESSENGER_Operation *op = load_operation(store, path);
71
72 if ((op) && (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
73 store->operations,
74 &(op->hash), op,
75 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
76 {
77 destroy_operation(op);
78 }
79
80 GNUNET_free(path);
81 }
82
83 return GNUNET_OK;
84}
85
86void
87load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
88 const char *directory)
89{
90 GNUNET_assert ((store) && (directory));
91
92 if (GNUNET_OK == GNUNET_DISK_directory_test (directory, GNUNET_YES))
93 GNUNET_DISK_directory_scan (directory, callback_scan_for_operations, store);
94}
95
96static int
97iterate_save_operations (void *cls, const struct GNUNET_HashCode *key, void *value)
98{
99 const char *save_dir = cls;
100
101 struct GNUNET_MESSENGER_Operation *op = value;
102
103 if (!op)
104 return GNUNET_YES;
105
106 char *op_dir;
107 GNUNET_asprintf (&op_dir, "%s%s.cfg", save_dir, GNUNET_h2s(key));
108 save_operation(op, op_dir);
109
110 GNUNET_free(op_dir);
111 return GNUNET_YES;
112}
113
114void
115save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
116 const char *directory)
117{
118 GNUNET_assert ((store) && (directory));
119
120 char* save_dir;
121 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
122
123 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
124 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
125 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_save_operations, save_dir);
126
127 GNUNET_free(save_dir);
128}
129
130enum GNUNET_MESSENGER_OperationType
131get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
132 const struct GNUNET_HashCode *hash)
133{
134 GNUNET_assert((store) && (hash));
135
136 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
137
138 if (!op)
139 return GNUNET_MESSENGER_OP_UNKNOWN;
140
141 return op->type;
142}
143
144int
145use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
146 const struct GNUNET_HashCode *hash,
147 enum GNUNET_MESSENGER_OperationType type,
148 struct GNUNET_TIME_Relative delay)
149{
150 GNUNET_assert((store) && (hash));
151
152 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
153
154 if (op)
155 goto use_op;
156
157 op = create_operation(hash);
158
159 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->operations, hash, op, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
160 {
161 destroy_operation(op);
162
163 return GNUNET_SYSERR;
164 }
165
166use_op:
167 if ((op->type != GNUNET_MESSENGER_OP_UNKNOWN) &&
168 (type == GNUNET_MESSENGER_OP_DELETE))
169 stop_operation (op);
170
171 return start_operation(op, type, store, delay);
172}
173
174void
175cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
176 const struct GNUNET_HashCode *hash)
177{
178 GNUNET_assert((store) && (hash));
179
180 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
181
182 if (!op)
183 return;
184
185 stop_operation(op);
186
187 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(store->operations, hash, op))
188 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Canceled operation could not be removed: %s\n",
189 GNUNET_h2s(hash));
190
191 destroy_operation(op);
192}
193
194extern void
195callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash);
196
197extern void
198callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash);
199
200void
201callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
202 enum GNUNET_MESSENGER_OperationType type,
203 const struct GNUNET_HashCode *hash)
204{
205 GNUNET_assert((store) && (hash));
206
207 struct GNUNET_HashCode op_hash;
208 GNUNET_memcpy(&op_hash, hash, sizeof(op_hash));
209 cancel_store_operation (store, &op_hash);
210
211 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
212
213 switch (type)
214 {
215 case GNUNET_MESSENGER_OP_REQUEST:
216 break;
217 case GNUNET_MESSENGER_OP_DELETE:
218 callback_room_deletion (room, &op_hash);
219 break;
220 case GNUNET_MESSENGER_OP_MERGE:
221 callback_room_merge (room, &op_hash);
222 break;
223 default:
224 break;
225 }
226}
diff --git a/src/messenger/gnunet-service-messenger_operation_store.h b/src/messenger/gnunet-service-messenger_operation_store.h
new file mode 100644
index 000000000..2fd604340
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_operation_store.h
@@ -0,0 +1,131 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_operation_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
27#define GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_scheduler_lib.h"
33#include "gnunet_time_lib.h"
34
35struct GNUNET_MESSENGER_SrvRoom;
36
37struct GNUNET_MESSENGER_OperationStore
38{
39 struct GNUNET_MESSENGER_SrvRoom *room;
40
41 struct GNUNET_CONTAINER_MultiHashMap *operations;
42};
43
44/**
45 * Initializes an operation <i>store</i> as fully empty with a given <i>room</i>.
46 *
47 * @param[out] store Operation store
48 * @param[in/out] room Room
49 */
50void
51init_operation_store (struct GNUNET_MESSENGER_OperationStore *store, struct GNUNET_MESSENGER_SrvRoom *room);
52
53/**
54 * Clears an operation <i>store</i>, stops all operations and deallocates its memory.
55 *
56 * @param[in/out] store Operation store
57 */
58void
59clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store);
60
61/**
62 * Loads operations from a <i>directory</i> into an operation <i>store</i>.
63 *
64 * @param[out] store Operation store
65 * @param[in] directory Path to a directory
66 */
67void
68load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
69 const char *directory);
70
71/**
72 * Saves operations from an operation <i>store</i> into a <i>directory</i>.
73 *
74 * @param[in] store Operation store
75 * @param[in] directory Path to a directory
76 */
77void
78save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
79 const char *directory);
80
81/**
82 * Retruns the type of the active operation under a given <i>hash</i> in
83 * a specific operation <i>store</i>. If there is no active operation under
84 * the given <i>hash</i>, #GNUNET_MESSENGER_OP_UNKNOWN gets returned instead.
85 *
86 * @param[in] store Operation store
87 * @param[in] hash Hash of message
88 * @return Type of operation or #GNUNET_MESSENGER_OP_UNKNOWN
89 */
90enum GNUNET_MESSENGER_OperationType
91get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
92 const struct GNUNET_HashCode *hash);
93
94/**
95 * Tries to use an operation under a given <i>hash</i> in a specific
96 * operation <i>store</i>. The operation will use the selected <i>type</i>
97 * if successful. The operation will be delayed by a given <i>delay</i>.
98 *
99 * If the selected type is #GNUNET_MESSENGER_OP_DELETE any active operation
100 * under the given hash will be stopped and replaced.
101 *
102 * If the new operation could be started successfully the method returns
103 * #GNUNET_OK, otherwise #GNUNET_SYSERR.
104 *
105 * @param[in/out] store Operation store
106 * @param[in] hash Hash of message
107 * @param[in] type Operation type
108 * @param[in] delay Delay
109 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
110 */
111int
112use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
113 const struct GNUNET_HashCode *hash,
114 enum GNUNET_MESSENGER_OperationType type,
115 struct GNUNET_TIME_Relative delay);
116
117/**
118 * Stops any active operation under a given <i>hash</i> in a specific
119 * operation <i>store</i>.
120 *
121 * Beware that calling this method will also implicitly free the memory
122 * of any active operation under the given hash!
123 *
124 * @param[in/out] store Operation store
125 * @param[in] hash Hash of message
126 */
127void
128cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
129 const struct GNUNET_HashCode *hash);
130
131#endif //GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c
index 7383e1d20..e8fe5b1f3 100644
--- a/src/messenger/gnunet-service-messenger_room.c
+++ b/src/messenger/gnunet-service-messenger_room.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -25,10 +25,19 @@
25 25
26#include "gnunet-service-messenger_room.h" 26#include "gnunet-service-messenger_room.h"
27 27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_member_session.h"
30
28#include "gnunet-service-messenger_message_kind.h" 31#include "gnunet-service-messenger_message_kind.h"
32#include "gnunet-service-messenger_message_handle.h"
33#include "gnunet-service-messenger_message_send.h"
29 34
35#include "gnunet-service-messenger_operation.h"
36
37#include "gnunet-service-messenger.h"
30#include "gnunet-service-messenger_service.h" 38#include "gnunet-service-messenger_service.h"
31#include "gnunet-service-messenger_util.h" 39#include "gnunet-service-messenger_tunnel.h"
40#include "messenger_api_util.h"
32 41
33static void 42static void
34idle_request_room_messages (void *cls); 43idle_request_room_messages (void *cls);
@@ -47,24 +56,21 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_Hash
47 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode)); 56 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode));
48 57
49 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO); 58 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
50 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
51 room->member_infos = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
52 59
53 init_message_store (&(room->store)); 60 init_member_store(get_room_member_store(room), room);
54 room->requested = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 61 init_message_store (get_room_message_store(room));
62 init_operation_store(get_room_operation_store(room), room);
55 63
56 init_list_tunnels (&(room->basement)); 64 init_list_tunnels (&(room->basement));
57 init_list_messages (&(room->last_messages)); 65 init_message_state(&(room->state));
58 66
59 room->peer_message = NULL; 67 room->peer_message = NULL;
60 68
61 init_list_messages (&(room->handling)); 69 init_list_messages (&(room->handling));
62 room->idle = NULL; 70 room->idle = NULL;
63 71
64 room->strict_access = GNUNET_NO;
65
66 if (room->service->dir) 72 if (room->service->dir)
67 load_service_room_and_messages (room->service, room); 73 load_room (room);
68 74
69 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room); 75 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room);
70 76
@@ -79,34 +85,8 @@ iterate_destroy_tunnels (void *cls, const struct GNUNET_PeerIdentity *key, void
79 return GNUNET_YES; 85 return GNUNET_YES;
80} 86}
81 87
82static int 88static void
83iterate_clear_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value) 89handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room);
84{
85 struct GNUNET_MESSENGER_SrvContact *contact = value;
86
87 if (GNUNET_YES == decrease_contact_rc (contact))
88 {
89 struct GNUNET_MESSENGER_SrvRoom *room = cls;
90
91 const struct GNUNET_HashCode *id = get_contact_id_from_key (contact);
92
93 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->service->contacts, id, contact))
94 destroy_contact (contact);
95 }
96
97 return GNUNET_YES;
98}
99
100static int
101iterate_destroy_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
102{
103 struct GNUNET_MESSENGER_MemberInfo *info = value;
104
105 clear_list_messages (&(info->session_messages));
106
107 GNUNET_free(info);
108 return GNUNET_YES;
109}
110 90
111void 91void
112destroy_room (struct GNUNET_MESSENGER_SrvRoom *room) 92destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
@@ -123,29 +103,21 @@ destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
123 if (room->port) 103 if (room->port)
124 GNUNET_CADET_close_port (room->port); 104 GNUNET_CADET_close_port (room->port);
125 105
126 merge_room_last_messages (room, room->host); 106 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, NULL);
127
128 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels,
129 NULL);
130 107
131 handle_room_messages (room); 108 handle_room_messages (room);
132 109
133 if (room->service->dir) 110 if (room->service->dir)
134 save_service_room_and_messages (room->service, room); 111 save_room (room);
135
136 GNUNET_CONTAINER_multishortmap_iterate (room->members, iterate_clear_members, room);
137 GNUNET_CONTAINER_multishortmap_iterate (room->member_infos, iterate_destroy_member_infos, NULL);
138 112
139 clear_message_store (&(room->store)); 113 clear_member_store (get_room_member_store(room));
140 114 clear_message_store (get_room_message_store(room));
141 GNUNET_CONTAINER_multihashmap_destroy (room->requested); 115 clear_operation_store(get_room_operation_store(room));
142 116
143 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels); 117 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
144 GNUNET_CONTAINER_multishortmap_destroy (room->members);
145 GNUNET_CONTAINER_multishortmap_destroy (room->member_infos);
146 118
147 clear_list_tunnels (&(room->basement)); 119 clear_list_tunnels (&(room->basement));
148 clear_list_messages (&(room->last_messages)); 120 clear_message_state(&(room->state));
149 121
150 if (room->peer_message) 122 if (room->peer_message)
151 GNUNET_free(room->peer_message); 123 GNUNET_free(room->peer_message);
@@ -153,103 +125,38 @@ destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
153 GNUNET_free(room); 125 GNUNET_free(room);
154} 126}
155 127
156struct GNUNET_MESSENGER_SrvContact* 128struct GNUNET_MESSENGER_MemberStore*
157get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) 129get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room)
158{ 130{
159 GNUNET_assert((room) && (room->members));
160
161 return GNUNET_CONTAINER_multishortmap_get (room->members, id);
162}
163
164void
165add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id,
166 const struct GNUNET_IDENTITY_PublicKey *pubkey)
167{
168 struct GNUNET_MESSENGER_SrvContact *contact = get_service_contact_by_pubkey (room->service, pubkey);
169
170 if (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put (room->members, id, contact,
171 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
172 increase_contact_rc (contact);
173}
174
175struct GNUNET_MESSENGER_MemberInfo*
176get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id)
177{
178 GNUNET_assert((room) && (room->member_infos));
179
180 return GNUNET_CONTAINER_multishortmap_get (room->member_infos, id);
181}
182
183struct GNUNET_ShortHashCode*
184generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room)
185{
186 struct GNUNET_ShortHashCode *unique_id = GNUNET_new(struct GNUNET_ShortHashCode);
187
188 GNUNET_assert(room); 131 GNUNET_assert(room);
189 132
190 if (GNUNET_YES == generate_free_member_id (unique_id, room->members)) 133 return &(room->member_store);
191 return unique_id;
192 else
193 {
194 GNUNET_free(unique_id);
195 return NULL;
196 }
197} 134}
198 135
199const struct GNUNET_ShortHashCode* 136struct GNUNET_MESSENGER_MessageStore*
200get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room) 137get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room)
201{ 138{
202 GNUNET_assert(room); 139 GNUNET_assert(room);
203 140
204 return get_handle_member_id (room->host, &(room->key)); 141 return &(room->message_store);
205} 142}
206 143
207void 144struct GNUNET_MESSENGER_OperationStore*
208change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id) 145get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room)
209{ 146{
210 GNUNET_assert(room); 147 GNUNET_assert(room);
211 148
212 change_handle_member_id (room->host, &(room->key), unique_id); 149 return &(room->operation_store);
213} 150}
214 151
215static int 152static int
216send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 153send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
217 struct GNUNET_MESSENGER_SrvTunnel *tunnel) 154 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
218{ 155{
219 if (!handle) 156 if ((!handle) || (!is_tunnel_connected (tunnel)))
220 return GNUNET_NO; 157 return GNUNET_NO;
221 158
222 merge_room_last_messages (room, handle); 159 return send_tunnel_message (tunnel, handle, create_message_info (get_handle_ego (handle)));
223
224 if (!is_tunnel_connected (tunnel))
225 return GNUNET_NO;
226
227 struct GNUNET_MESSENGER_Message *message = create_message_info (get_handle_ego(handle), room->members);
228
229 if (!message)
230 return GNUNET_NO;
231
232 if ((tunnel->peer_message) && (tunnel->contact_id))
233 {
234 GNUNET_memcpy(&(message->body.info.unique_id), &(tunnel->contact_id), sizeof(struct GNUNET_ShortHashCode));
235 GNUNET_free(tunnel->contact_id);
236
237 tunnel->contact_id = NULL;
238 }
239
240 struct GNUNET_HashCode hash;
241
242 send_tunnel_message (tunnel, handle, message, &hash);
243 destroy_message (message);
244
245 if (tunnel->contact_id)
246 {
247 GNUNET_free(tunnel->contact_id);
248
249 tunnel->contact_id = NULL;
250 }
251
252 return GNUNET_YES;
253} 160}
254 161
255static void* 162static void*
@@ -257,63 +164,51 @@ callback_room_connect (void *cls, struct GNUNET_CADET_Channel *channel, const st
257{ 164{
258 struct GNUNET_MESSENGER_SrvRoom *room = cls; 165 struct GNUNET_MESSENGER_SrvRoom *room = cls;
259 166
260 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, source); 167 struct GNUNET_MESSENGER_SrvTunnel *tunnel = create_tunnel (room, source);
261 168
262 if (tunnel) 169 if ((tunnel) &&
170 (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
171 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
263 { 172 {
264 if (GNUNET_YES == bind_tunnel (tunnel, channel)) 173 destroy_tunnel (tunnel);
265 { 174 tunnel = NULL;
266 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
267 return tunnel;
268 else
269 {
270 disconnect_tunnel (tunnel);
271 return NULL;
272 }
273 }
274 else
275 {
276 delayed_disconnect_channel (channel);
277 return NULL;
278 }
279 } 175 }
280 else 176
177 if (!tunnel)
281 { 178 {
282 tunnel = create_tunnel (room, source); 179 delayed_disconnect_channel (channel);
180 return NULL;
181 }
283 182
284 if ((GNUNET_YES == bind_tunnel (tunnel, channel)) && (GNUNET_OK 183 bind_tunnel(tunnel, channel);
285 == GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
286 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
287 {
288 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
289 return tunnel;
290 else
291 {
292 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel);
293 184
294 disconnect_tunnel (tunnel); 185 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "New tunnel in room (%s) established to peer: %s\n",
295 destroy_tunnel (tunnel); 186 GNUNET_h2s(get_room_key(room)), GNUNET_i2s (source));
296 return NULL;
297 }
298 }
299 else
300 {
301 tunnel->channel = NULL;
302 destroy_tunnel (tunnel);
303 187
304 delayed_disconnect_channel (channel); 188 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
305 return NULL; 189 return tunnel;
306 } 190
307 } 191 disconnect_tunnel (tunnel);
192
193 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel))
194 destroy_tunnel (tunnel);
195
196 return NULL;
308} 197}
309 198
310static int 199static int
311join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 200join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
312 const struct GNUNET_ShortHashCode *member_id) 201 struct GNUNET_MESSENGER_Member *member)
313{ 202{
314 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s(get_room_key(room)), GNUNET_sh2s(member_id)); 203 GNUNET_assert((room) && (handle) && (member));
315 204
316 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego(handle)); 205 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s (get_room_key (room)),
206 GNUNET_sh2s (get_member_id(member)));
207
208 if (GNUNET_OK != change_handle_member_id (handle, get_room_key(room), get_member_id(member)))
209 return GNUNET_NO;
210
211 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego (handle));
317 212
318 if (!message) 213 if (!message)
319 { 214 {
@@ -322,48 +217,97 @@ join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHan
322 return GNUNET_NO; 217 return GNUNET_NO;
323 } 218 }
324 219
325 struct GNUNET_HashCode hash; 220 return send_room_message (room, handle, message);
221}
326 222
327 send_room_message (room, handle, message, &hash); 223struct GNUNET_MESSENGER_MemberNotify
328 destroy_message (message); 224{
225 struct GNUNET_MESSENGER_SrvRoom *room;
226 struct GNUNET_MESSENGER_SrvHandle *handle;
227 struct GNUNET_MESSENGER_MemberSession *session;
228};
329 229
330 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_new(struct GNUNET_MESSENGER_MemberInfo); 230static void
231notify_about_members (struct GNUNET_MESSENGER_MemberNotify *notify, struct GNUNET_MESSENGER_MemberSession *session,
232 struct GNUNET_CONTAINER_MultiHashMap *map, int check_permission)
233{
234 if (session->prev)
235 notify_about_members (notify, session->prev, map, GNUNET_YES);
331 236
332 info->access = GNUNET_MESSENGER_MEMBER_ALLOWED; 237 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(notify->room);
333 init_list_messages (&(info->session_messages)); 238 struct GNUNET_MESSENGER_ListMessage *element;
334 239
335 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_put (room->member_infos, member_id, info, 240 for (element = session->messages.head; element; element = element->next)
336 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
337 { 241 {
338 change_handle_member_id (handle, &(room->key), member_id); 242 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
243 continue;
339 244
340 add_to_list_messages (&(info->session_messages), &hash); 245 if ((GNUNET_YES == check_permission) &&
341 return GNUNET_YES; 246 (GNUNET_YES != check_member_session_history(notify->session, &(element->hash), GNUNET_NO)))
342 } 247 continue;
343 else
344 {
345 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Your member information could not be registered!\n");
346 248
347 GNUNET_free(info); 249 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
348 return GNUNET_NO; 250 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
251 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notification of session message could be duplicated!\n");
252
253 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
254
255 if (message)
256 notify_handle_message (notify->handle, get_room_key(notify->room), session, message, &(element->hash));
349 } 257 }
350} 258}
351 259
352static int 260static int
261iterate_notify_about_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
262 struct GNUNET_MESSENGER_MemberSession *session)
263{
264 struct GNUNET_MESSENGER_MemberNotify *notify = cls;
265
266 if ((notify->session == session) || (GNUNET_YES == is_member_session_completed(session)))
267 return GNUNET_YES;
268
269 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
270
271 notify_about_members (notify, session, map, GNUNET_NO);
272
273 GNUNET_CONTAINER_multihashmap_destroy(map);
274 return GNUNET_YES;
275}
276
277static int
353join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 278join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
354{ 279{
355 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key)); 280 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
281
282 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
283 struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, member_id);
284
285 if (GNUNET_NO == join_room (room, handle, member))
286 return GNUNET_NO;
356 287
357 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id); 288 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
289 struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member, &(ego->pub));
358 290
359 if ((!info) && (GNUNET_NO == join_room (room, handle, member_id))) 291 if (!session)
292 {
293 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "A valid session is required to join a room!\n");
360 return GNUNET_NO; 294 return GNUNET_NO;
295 }
296
297 struct GNUNET_MESSENGER_MemberNotify notify;
298
299 notify.room = room;
300 notify.handle = handle;
301 notify.session = session;
302
303 iterate_store_members(get_room_member_store(room), iterate_notify_about_members, &notify);
361 304
362 return GNUNET_YES; 305 return GNUNET_YES;
363} 306}
364 307
365extern int 308extern int
366check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); 309check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
310
367extern void 311extern void
368handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); 312handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
369 313
@@ -373,24 +317,39 @@ callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channe
373int 317int
374open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 318open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
375{ 319{
320 GNUNET_assert((room) && (handle));
321
376 if (room->port) 322 if (room->port)
377 return join_room_locally (room, handle); 323 return join_room_locally (room, handle);
378 324
379 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room); 325 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room);
380 struct GNUNET_HashCode *key = get_room_key (room); 326 const struct GNUNET_HashCode *key = get_room_key (room);
381 327
382 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI, 328 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
383 struct GNUNET_MessageHeader, NULL), 329 struct GNUNET_MessageHeader, NULL),
384 GNUNET_MQ_handler_end() }; 330 GNUNET_MQ_handler_end() };
385 331
386 room->port = GNUNET_CADET_open_port (cadet, key, callback_room_connect, room, NULL, 332 room->port = GNUNET_CADET_open_port (cadet, key, callback_room_connect, room, NULL, callback_tunnel_disconnect,
387 callback_tunnel_disconnect, handlers); 333 handlers);
334
335 if (room->port)
336 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Port of room (%s) was opened!\n",
337 GNUNET_h2s(get_room_key(room)));
338 else
339 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Port of room (%s) could not be opened!\n",
340 GNUNET_h2s(get_room_key(room)));
341
342 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
343
344 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
345 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
388 346
389 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key)); 347 if (member)
348 goto exit_open_room;
390 349
391 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id); 350 member = add_store_member(member_store, member_id);
392 351
393 if ((!info) && (GNUNET_NO == join_room (room, handle, member_id)) && (room->port)) 352 if ((GNUNET_NO == join_room (room, handle, member)) && (room->port))
394 { 353 {
395 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n"); 354 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n");
396 355
@@ -400,111 +359,62 @@ open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHan
400 return GNUNET_NO; 359 return GNUNET_NO;
401 } 360 }
402 361
403 struct GNUNET_MESSENGER_Message *message = create_message_peer (room->service); 362exit_open_room:
404 363 return (room->port ? send_room_message (room, handle, create_message_peer (room->service)) : GNUNET_NO);
405 if (message)
406 {
407 struct GNUNET_HashCode hash;
408
409 send_room_message (room, handle, message, &hash);
410 destroy_message (message);
411 }
412
413 return (room->port ? GNUNET_YES : GNUNET_NO);
414} 364}
415 365
416int 366int
417entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 367enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
418 const struct GNUNET_PeerIdentity *door) 368 const struct GNUNET_PeerIdentity *door)
419{ 369{
420 if (room->peer_message) 370 GNUNET_assert((room) && (handle) && (door));
421 {
422 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, handle, room->peer_message, GNUNET_NO);
423 371
424 if (0 == GNUNET_memcmp(&(msg->body.peer.peer), door)) 372 struct GNUNET_PeerIdentity peer;
425 return join_room_locally (room, handle); 373
426 } 374 if ((GNUNET_OK == get_service_peer_identity (room->service, &peer)) &&
375 (0 == GNUNET_memcmp(&peer, door)))
376 return join_room_locally (room, handle);
427 377
428 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door); 378 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door);
429 379
430 if (tunnel) 380 if (!tunnel)
431 { 381 {
432 switch (connect_tunnel (tunnel)) 382 tunnel = create_tunnel (room, door);
383
384 if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
385 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
433 { 386 {
434 case GNUNET_YES: 387 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n");
435 return GNUNET_YES; 388 destroy_tunnel (tunnel);
436 case GNUNET_NO:
437 return join_room_locally (room, handle);
438 default:
439 return GNUNET_NO; 389 return GNUNET_NO;
440 } 390 }
441 } 391 }
442 392
443 tunnel = create_tunnel (room, door); 393 if (GNUNET_SYSERR == connect_tunnel (tunnel))
444
445 if ((GNUNET_YES == connect_tunnel (tunnel)) &&
446 (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
447 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
448 return GNUNET_YES;
449 else
450 { 394 {
451 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n"); 395 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connection failure during entrance!\n");
452 396 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, door, tunnel);
453 destroy_tunnel (tunnel); 397 destroy_tunnel (tunnel);
454 return GNUNET_NO; 398 return GNUNET_NO;
455 } 399 }
456}
457
458struct GNUNET_MESSENGER_SrvTunnelFinder
459{
460 const struct GNUNET_ShortHashCode *needle;
461 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
462};
463
464static int
465iterate_find_tunnel (void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
466{
467 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
468 struct GNUNET_MESSENGER_SrvTunnelFinder *finder = cls;
469
470 if ((tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, finder->needle)))
471 {
472 finder->tunnel = tunnel;
473 return GNUNET_NO;
474 }
475
476 return GNUNET_YES;
477}
478
479struct GNUNET_MESSENGER_SrvTunnel*
480find_room_tunnel_to (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *contact_id)
481{
482 struct GNUNET_MESSENGER_SrvTunnelFinder finder;
483
484 finder.needle = contact_id;
485 finder.tunnel = NULL;
486
487 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_find_tunnel, &finder);
488 400
489 return finder.tunnel; 401 return join_room_locally (room, handle);
490} 402}
491 403
492struct GNUNET_MQ_Envelope* 404struct GNUNET_MQ_Envelope*
493pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 405pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_SrvHandle *handle,
494 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode) 406 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode)
495{ 407{
408 GNUNET_assert((room) && (handle) && (message) && (hash));
409
496 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); 410 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
497 411
498 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, &(room->key)); 412 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, get_room_key(room));
499 413
500 GNUNET_assert(id); 414 GNUNET_assert(id);
501 415
502 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode)); 416 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode));
503 417 get_message_state_chain_hash (&(room->state), &(message->header.previous));
504 if (room->last_messages.head)
505 GNUNET_memcpy(&(message->header.previous), &(room->last_messages.head->hash), sizeof(struct GNUNET_HashCode));
506 else
507 memset (&(message->header.previous), 0, sizeof(struct GNUNET_HashCode));
508 418
509 return pack_message (message, hash, get_handle_ego (handle), mode); 419 return pack_message (message, hash, get_handle_ego (handle), mode);
510} 420}
@@ -524,7 +434,8 @@ iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, voi
524{ 434{
525 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value; 435 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
526 436
527 if ((!is_tunnel_connected (tunnel)) || (!tunnel->contact_id)) 437 if ((!is_tunnel_connected (tunnel)) ||
438 (get_tunnel_messenger_version(tunnel) < GNUNET_MESSENGER_VERSION))
528 return GNUNET_YES; 439 return GNUNET_YES;
529 440
530 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls; 441 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls;
@@ -540,80 +451,91 @@ iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, voi
540 GNUNET_MESSENGER_PACK_MODE_ENVELOPE); 451 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
541 452
542 if (env) 453 if (env)
543 {
544 closure->message = copy_message (closure->message);
545 closure->packed = GNUNET_YES; 454 closure->packed = GNUNET_YES;
546 }
547 } 455 }
548 else 456 else
549 { 457 env = pack_message (closure->message, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
550 env = pack_message (closure->message, NULL, NULL,
551 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
552 }
553 458
554 if (env) 459 if (env)
555 send_tunnel_envelope (tunnel, closure->handle, env, closure->message, closure->hash); 460 send_tunnel_envelope (tunnel, env, closure->hash);
556 461
557 return GNUNET_YES; 462 return GNUNET_YES;
558} 463}
559 464
560void 465int
561callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, 466update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
562 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 467 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
563 468
564void 469void
470callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
471 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
472
473int
565send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 474send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
566 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash) 475 struct GNUNET_MESSENGER_Message *message)
567{ 476{
568 struct GNUNET_MESSENGER_ClosureSendRoom closure; 477 GNUNET_assert((room) && (handle));
569 478
570 closure.room = room; 479 if (!message)
571 closure.handle = handle; 480 return GNUNET_NO;
572 closure.exclude = NULL;
573 closure.message = message;
574 closure.hash = hash;
575 closure.packed = GNUNET_NO;
576
577 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
578 481
579 if ((GNUNET_NO == closure.packed) && (closure.message == message)) 482 if (GNUNET_YES == is_message_session_bound(message))
580 { 483 merge_room_last_messages(room, handle);
581 pack_room_message (room, handle, message, hash,
582 GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
583 484
584 callback_room_sent (room, handle, NULL, copy_message (message), hash); 485 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending message from handle with member id: %s\n",
585 } 486 GNUNET_sh2s(get_handle_member_id(handle, get_room_key(room))));
586}
587 487
588void 488 struct GNUNET_HashCode hash;
589send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
590 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
591 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
592{
593 struct GNUNET_MESSENGER_ClosureSendRoom closure; 489 struct GNUNET_MESSENGER_ClosureSendRoom closure;
594 490
595 closure.room = room; 491 closure.room = room;
596 closure.handle = handle; 492 closure.handle = handle;
597 closure.exclude = tunnel; 493 closure.exclude = NULL;
598 closure.message = message; 494 closure.message = message;
599 closure.hash = hash; 495 closure.hash = &hash;
600 closure.packed = GNUNET_NO; 496 closure.packed = GNUNET_NO;
601 497
602 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure); 498 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
603 499
604 if ((GNUNET_NO == closure.packed) && (closure.message == message)) 500 if (GNUNET_NO == closure.packed)
605 { 501 pack_room_message (room, handle, message, &hash, GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
606 pack_room_message (room, handle, message, hash, 502
607 GNUNET_MESSENGER_PACK_MODE_UNKNOWN); 503 const int new_message = update_room_message (room, message, &hash);
504
505 if (GNUNET_YES != new_message)
506 return GNUNET_SYSERR;
608 507
609 callback_room_sent (room, handle, NULL, copy_message (message), hash); 508 switch (message->header.kind)
509 {
510 case GNUNET_MESSENGER_KIND_JOIN:
511 send_message_join (room, handle, message, &hash);
512 break;
513 case GNUNET_MESSENGER_KIND_PEER:
514 send_message_peer (room, handle, message, &hash);
515 break;
516 case GNUNET_MESSENGER_KIND_ID:
517 send_message_id (room, handle, message, &hash);
518 break;
519 case GNUNET_MESSENGER_KIND_REQUEST:
520 send_message_request (room, handle, message, &hash);
521 break;
522 default:
523 break;
610 } 524 }
525
526 callback_room_handle_message (room, handle, message, &hash);
527 return GNUNET_YES;
611} 528}
612 529
613void 530void
614forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 531forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
615 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 532 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
616{ 533{
534 GNUNET_assert((room) && (tunnel));
535
536 if (!message)
537 return;
538
617 struct GNUNET_MESSENGER_ClosureSendRoom closure; 539 struct GNUNET_MESSENGER_ClosureSendRoom closure;
618 struct GNUNET_HashCode message_hash; 540 struct GNUNET_HashCode message_hash;
619 541
@@ -622,7 +544,7 @@ forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSE
622 closure.room = room; 544 closure.room = room;
623 closure.handle = NULL; 545 closure.handle = NULL;
624 closure.exclude = tunnel; 546 closure.exclude = tunnel;
625 closure.message = copy_message (message); 547 closure.message = message;
626 closure.hash = &message_hash; 548 closure.hash = &message_hash;
627 closure.packed = GNUNET_YES; 549 closure.packed = GNUNET_YES;
628 550
@@ -630,76 +552,196 @@ forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSE
630} 552}
631 553
632void 554void
555check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel)
556{
557 if (!room->peer_message)
558 return;
559
560 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
561
562 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, room->peer_message);
563
564 if (!message)
565 {
566 GNUNET_free(room->peer_message);
567 room->peer_message = NULL;
568 return;
569 }
570
571 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
572 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
573
574 if (!member)
575 goto resend_peer_message;
576
577 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, room->peer_message);
578
579 if (GNUNET_YES == is_member_session_closed(session))
580 goto resend_peer_message;
581
582 if (tunnel)
583 forward_tunnel_message(tunnel, message, room->peer_message);
584
585 return;
586
587resend_peer_message:
588 if (room->host)
589 send_room_message (room, room->host, create_message_peer (room->service));
590}
591
592void
633merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 593merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
634{ 594{
595 GNUNET_assert(room);
596
635 if (!handle) 597 if (!handle)
636 return; 598 return;
637 599
638 if (!room->last_messages.head) 600 const struct GNUNET_HashCode *hash;
601
602merge_next:
603 hash = get_message_state_merge_hash (&(room->state));
604
605 if (!hash)
639 return; 606 return;
640 607
641 while (room->last_messages.head != room->last_messages.tail) 608 send_room_message (room, handle, create_message_merge (hash));
609 goto merge_next;
610}
611
612void
613callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
614{
615 if (GNUNET_OK != delete_store_message (get_room_message_store(room), hash))
642 { 616 {
643 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.tail; 617 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n", GNUNET_h2s(hash));
618 return;
619 }
620}
644 621
645 struct GNUNET_MESSENGER_Message *message = create_message_merge (&(element->hash)); 622void
623callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
624{
625 if (!room->host)
626 return;
646 627
647 if (message) 628 send_room_message (room, room->host, create_message_merge (hash));
648 { 629}
649 struct GNUNET_HashCode hash;
650 630
651 send_room_message (room, handle, message, &hash); 631int
652 destroy_message (message); 632delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
653 } 633 const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay)
634{
635 GNUNET_assert((room) && (session) && (hash));
654 636
655 if (element->prev) 637 const struct GNUNET_TIME_Relative forever = GNUNET_TIME_relative_get_forever_ ();
656 GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, element); 638
639 if (0 == GNUNET_memcmp(&forever, &delay))
640 {
641 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deletion is delayed forever: operation is impossible!\n");
642 return GNUNET_SYSERR;
657 } 643 }
644
645 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
646
647 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
648
649 if (!message)
650 return GNUNET_YES;
651
652 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_YES))
653 {
654 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unpermitted request for deletion by member (%s) of message (%s)!\n",
655 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
656
657 return GNUNET_NO;
658 }
659
660 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
661
662 if (GNUNET_OK != use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_DELETE, delay))
663 {
664 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Deletion has failed: operation denied!\n");
665 return GNUNET_SYSERR;
666 }
667
668 return GNUNET_YES;
658} 669}
659 670
660struct GNUNET_CADET_Handle* 671struct GNUNET_CADET_Handle*
661get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room) 672get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room)
662{ 673{
674 GNUNET_assert(room);
675
663 return room->service->cadet; 676 return room->service->cadet;
664} 677}
665 678
666struct GNUNET_HashCode* 679const struct GNUNET_HashCode*
667get_room_key (struct GNUNET_MESSENGER_SrvRoom *room) 680get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room)
668{ 681{
682 GNUNET_assert(room);
683
669 return &(room->key); 684 return &(room->key);
670} 685}
671 686
672const struct GNUNET_MESSENGER_SrvTunnel* 687const struct GNUNET_MESSENGER_SrvTunnel*
673get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer) 688get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer)
674{ 689{
690 GNUNET_assert((room) && (peer));
691
675 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer); 692 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
676} 693}
677 694
678const struct GNUNET_MESSENGER_Message* 695static int
679get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 696request_room_message_step (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
680 const struct GNUNET_HashCode *hash, int request) 697 const struct GNUNET_MESSENGER_MemberSession *session,
698 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls)
681{ 699{
682 const struct GNUNET_MESSENGER_Message *message = get_store_message (&(room->store), hash); 700 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
683 701
684 if ((message) || (!handle) || (GNUNET_YES != request) 702 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
685 || (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->requested, hash))) 703 message_store, hash, GNUNET_YES
686 return message; 704 );
687 705
688 struct GNUNET_MESSENGER_Message *request_msg = create_message_request (hash); 706 if (!link)
707 goto forward;
689 708
690 if (request_msg) 709 int result = request_room_message_step(room, &(link->first), session, callback, cls);
691 {
692 if (GNUNET_CONTAINER_multihashmap_put (room->requested, hash, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST) == GNUNET_OK)
693 {
694 struct GNUNET_HashCode request_hash;
695 710
696 send_room_message (room, handle, request_msg, &request_hash); 711 if ((GNUNET_YES == link->multiple) &&
697 } 712 (GNUNET_YES == request_room_message_step(room, &(link->second), session, callback, cls)))
713 return GNUNET_YES;
714 else
715 return result;
698 716
699 destroy_message (request_msg); 717forward:
700 } 718 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO))
719 return GNUNET_YES;
701 720
702 return message; 721 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
722
723 if (!message)
724 return GNUNET_NO;
725
726 if (callback)
727 callback (cls, room, message, hash);
728
729 return GNUNET_YES;
730}
731
732int
733request_room_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
734 const struct GNUNET_MESSENGER_MemberSession *session,
735 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls)
736{
737 GNUNET_assert((room) && (hash));
738
739 int result = request_room_message_step (room, hash, session, callback, cls);
740
741 if ((GNUNET_NO == result) && (callback))
742 callback (cls, room, NULL, hash);
743
744 return result;
703} 745}
704 746
705void 747void
@@ -711,21 +753,14 @@ callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls)
711 return; 753 return;
712 754
713 struct GNUNET_PeerIdentity identity; 755 struct GNUNET_PeerIdentity identity;
756 get_tunnel_peer_identity(tunnel, &identity);
714 757
715 GNUNET_PEER_resolve (tunnel->peer, &identity); 758 if ((GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (room->tunnels, &identity, tunnel)) ||
759 (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(room->tunnels, &identity)))
760 return;
716 761
717 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity)) 762 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
718 { 763 send_room_message (room, room->host, create_message_miss (&identity));
719 struct GNUNET_MESSENGER_Message *message = create_message_miss (&identity);
720
721 if (message)
722 {
723 struct GNUNET_HashCode hash;
724
725 send_room_message (room, room->host, message, &hash);
726 destroy_message (message);
727 }
728 }
729} 764}
730 765
731int 766int
@@ -733,49 +768,32 @@ callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls,
733 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash) 768 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash)
734{ 769{
735 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind) 770 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind)
736 return GNUNET_SYSERR;
737
738 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members,
739 &(message->header.sender_id));
740
741 if (!contact)
742 { 771 {
743 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind) 772 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Kind is unknown! (%d)\n", message->header.kind);
744 contact = get_service_contact_by_pubkey (room->service, &(message->body.info.host_key));
745 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
746 contact = get_service_contact_by_pubkey (room->service, &(message->body.join.key));
747 }
748
749 if ((!contact) || (GNUNET_SYSERR == verify_message (message, hash, get_contact_key (contact))))
750 return GNUNET_SYSERR; 773 return GNUNET_SYSERR;
751
752 if (GNUNET_YES == room->strict_access)
753 {
754 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos,
755 &(message->header.sender_id));
756
757 if ((info) && (GNUNET_MESSENGER_MEMBER_BLOCKED == info->access))
758 return GNUNET_SYSERR;
759 } 774 }
760 775
761 if (GNUNET_YES == contains_store_message (&(room->store), hash)) 776 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
762 return GNUNET_NO;
763 777
764 return GNUNET_YES; 778 const struct GNUNET_MESSENGER_Message *previous = get_store_message(message_store, &(message->header.previous));
765}
766 779
767static void 780 if (!previous)
768search_room_for_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash) 781 goto skip_time_comparison;
769{
770 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, room->host, hash, GNUNET_YES);
771 782
772 if (!message) 783 struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_ntoh(message->header.timestamp);
773 return; 784 struct GNUNET_TIME_Absolute last = GNUNET_TIME_absolute_ntoh(previous->header.timestamp);
774 785
775 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind) 786 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(timestamp, last).rel_value_us)
776 search_room_for_message (room, &(message->body.merge.previous)); 787 {
788 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Timestamp does not check out!\n");
789 return GNUNET_SYSERR;
790 }
791
792skip_time_comparison:
793 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n",
794 GNUNET_MESSENGER_name_of_kind(message->header.kind));
777 795
778 search_room_for_message (room, &(message->header.previous)); 796 return GNUNET_OK;
779} 797}
780 798
781static void 799static void
@@ -785,102 +803,76 @@ idle_request_room_messages (void *cls)
785 803
786 room->idle = NULL; 804 room->idle = NULL;
787 805
788 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head; 806 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
789 807 const struct GNUNET_HashCode *hash = get_message_state_merge_hash(&(room->state));
790 while (element) 808
791 { 809 if ((hash) &&
792 search_room_for_message (room, &(element->hash)); 810 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type(operation_store, hash)))
793 811 use_store_operation(
794 element = element->next; 812 operation_store,
795 } 813 hash,
796 814 GNUNET_MESSENGER_OP_MERGE,
797 merge_room_last_messages (room, room->host); 815 GNUNET_MESSENGER_MERGE_DELAY
798 816 );
799 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_second_ (), 817
800 GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, 818 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (
801 cls); 819 GNUNET_MESSENGER_IDLE_DELAY,
820 GNUNET_SCHEDULER_PRIORITY_IDLE,
821 idle_request_room_messages,
822 cls
823 );
802} 824}
803 825
804void 826void
805update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message, 827solve_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_IDENTITY_PublicKey *public_key,
806 const struct GNUNET_HashCode *hash) 828 const struct GNUNET_ShortHashCode *member_id, struct GNUNET_TIME_Absolute timestamp)
807{ 829{
808 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head; 830 GNUNET_assert ((room) && (public_key) && (member_id));
809 struct GNUNET_MESSENGER_ListMessage *merging = NULL;
810
811 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
812 {
813 merging = room->last_messages.head;
814
815 while (merging)
816 {
817 if (0 == GNUNET_CRYPTO_hash_cmp (&(merging->hash), &(message->body.merge.previous)))
818 break;
819 831
820 merging = merging->next; 832 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
821 } 833 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
822 834
823 if (merging) 835 if ((!member) || (1 >= GNUNET_CONTAINER_multihashmap_size(member->sessions)))
824 element = merging->next; 836 return;
825 }
826
827 while (element)
828 {
829 if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), &(message->header.previous)))
830 break;
831
832 element = element->next;
833 }
834 837
835 if ((merging) && (!element)) 838 struct GNUNET_MESSENGER_ListHandles *handles = &(room->service->handles);
836 { 839 struct GNUNET_MESSENGER_ListHandle* element;
837 element = merging;
838 merging = NULL;
839 }
840 840
841 if (element) 841 for (element = handles->head; element; element = element->next)
842 { 842 {
843 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode)); 843 if (0 != GNUNET_memcmp(member_id, get_handle_member_id(element->handle, get_room_key(room))))
844 continue;
844 845
845 if (merging) 846 if (0 == GNUNET_memcmp(public_key, &(get_handle_ego(element->handle)->pub)))
846 GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, merging); 847 continue;
847 }
848 else
849 add_to_list_messages (&(room->last_messages), hash);
850 848
851 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (room->requested, hash)) 849 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_handle_ego(element->handle)->pub));
852 GNUNET_CONTAINER_multihashmap_remove_all (room->requested, hash);
853}
854 850
855void 851 if (!session)
856switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, 852 continue;
857 const struct GNUNET_ShortHashCode *new_id, const struct GNUNET_HashCode *hash)
858{
859 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, old_id);
860 853
861 if ((contact) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (room->members, old_id, contact))) 854 struct GNUNET_TIME_Absolute start = get_member_session_start(session);
862 GNUNET_CONTAINER_multishortmap_put (room->members, new_id, contact,
863 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
864 855
865 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, old_id); 856 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(start, timestamp).rel_value_us)
857 continue;
866 858
867 if ((!info) || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->member_infos, old_id, contact)) 859 struct GNUNET_ShortHashCode random_id;
868 || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_put (room->member_infos, new_id, contact, 860 generate_free_member_id (&random_id, member_store->members);
869 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
870 return;
871 861
872 if (hash) 862 send_room_message(room, element->handle, create_message_id(&random_id));
873 add_to_list_messages (&(info->session_messages), hash); 863 }
874} 864}
875 865
876void 866void
877rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room) 867rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
878{ 868{
869 GNUNET_assert(room);
870
879 struct GNUNET_PeerIdentity peer; 871 struct GNUNET_PeerIdentity peer;
880 size_t src; 872 size_t src;
881 873
882 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) || (!find_list_tunnels (&(room->basement), &peer, 874 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) ||
883 &src))) 875 (!find_list_tunnels (&(room->basement), &peer, &src)))
884 return; 876 return;
885 877
886 size_t count = count_of_tunnels (&(room->basement)); 878 size_t count = count_of_tunnels (&(room->basement));
@@ -918,38 +910,167 @@ rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
918 } 910 }
919} 911}
920 912
921void 913static void
922handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room) 914handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
923{ 915{
916 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
917 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
918
924 while (room->handling.head) 919 while (room->handling.head)
925 { 920 {
926 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head; 921 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head;
927 922
928 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(element->hash), GNUNET_NO); 923 const struct GNUNET_MESSENGER_Message *message = get_store_message (message_store, &(element->hash));
924
925 if (!message)
926 goto finish_handling;
929 927
930 if (msg) 928 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
931 handle_service_message (room->service, room, msg, &(element->hash));
932 929
930 if (!member)
931 goto finish_handling;
932
933 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, &(element->hash));
934
935 if (session)
936 handle_service_message (room->service, room, session, message, &(element->hash));
937
938finish_handling:
933 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element); 939 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element);
934 GNUNET_free(element); 940 GNUNET_free(element);
935 } 941 }
936} 942}
937 943
938#include "gnunet-service-messenger_message_recv.h" 944int
945update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
946 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
947{
948 GNUNET_assert((room) && (message) && (hash));
949
950 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
951
952 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
953 GNUNET_YES : GNUNET_NO
954 );
955
956 if (GNUNET_YES == requested)
957 cancel_store_operation(operation_store, hash);
958
959 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
960
961 const struct GNUNET_MESSENGER_Message *old_message = get_store_message (message_store, hash);
962
963 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n", GNUNET_h2s (get_room_key(room)));
964
965 if ((old_message) || (GNUNET_OK != put_store_message (message_store, hash, message)))
966 {
967 if (old_message != message)
968 destroy_message(message);
969
970 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Duplicate message got dropped!\n");
971 return GNUNET_NO;
972 }
973
974 update_message_state(&(room->state), requested, message, hash);
975
976 if ((GNUNET_YES == requested) ||
977 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
978 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
979 return GNUNET_YES;
980
981 if ((GNUNET_MESSENGER_KIND_MERGE == message->header.kind) &&
982 (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->body.merge.previous))))
983 cancel_store_operation(operation_store, &(message->body.merge.previous));
984
985 if (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->header.previous)))
986 cancel_store_operation(operation_store, &(message->header.previous));
987
988 return GNUNET_YES;
989}
990
991struct GNUNET_MESSENGER_MemberSessionCompletion
992{
993 struct GNUNET_MESSENGER_MemberSessionCompletion *prev;
994 struct GNUNET_MESSENGER_MemberSessionCompletion *next;
995
996 struct GNUNET_MESSENGER_MemberSession *session;
997};
998
999struct GNUNET_MESSENGER_MemberUpdate
1000{
1001 const struct GNUNET_MESSENGER_Message *message;
1002 const struct GNUNET_HashCode *hash;
1003
1004 struct GNUNET_MESSENGER_MemberSessionCompletion *head;
1005 struct GNUNET_MESSENGER_MemberSessionCompletion *tail;
1006};
1007
1008static int
1009iterate_update_member_sessions (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
1010 struct GNUNET_MESSENGER_MemberSession *session)
1011{
1012 struct GNUNET_MESSENGER_MemberUpdate *update = cls;
1013
1014 update_member_session_history(session, update->message, update->hash);
1015
1016 if (GNUNET_YES == is_member_session_completed(session))
1017 {
1018 struct GNUNET_MESSENGER_MemberSessionCompletion *element = GNUNET_new(
1019 struct GNUNET_MESSENGER_MemberSessionCompletion
1020 );
1021
1022 element->session = session;
1023
1024 GNUNET_CONTAINER_DLL_insert_tail(update->head, update->tail, element);
1025 }
1026
1027 return GNUNET_YES;
1028}
1029
1030static void
1031remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session);
939 1032
940void 1033void
941callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, 1034callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
942 const struct GNUNET_HashCode *hash) 1035 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
943{ 1036{
944 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; 1037 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
1038 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
1039
1040 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", GNUNET_h2s (hash));
945 1041
946 if (GNUNET_OK != put_store_message (&(room->store), hash, message)) 1042 if (!member)
1043 {
1044 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Member is missing!\n");
947 return; 1045 return;
1046 }
1047
1048 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
1049
1050 if (!session)
1051 {
1052 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Session is missing!\n");
1053 return;
1054 }
948 1055
949 update_room_last_messages (room, message, hash); 1056 struct GNUNET_MESSENGER_MemberUpdate update;
1057 update.message = message;
1058 update.hash = hash;
950 1059
951 if (GNUNET_MESSENGER_KIND_INFO != message->header.kind) 1060 update.head = NULL;
952 forward_room_message (room, tunnel, message, hash); 1061 update.tail = NULL;
1062
1063 iterate_store_members(member_store, iterate_update_member_sessions, &update);
1064
1065 while (update.head)
1066 {
1067 struct GNUNET_MESSENGER_MemberSessionCompletion *element = update.head;
1068
1069 remove_room_member_session (room, element->session);
1070
1071 GNUNET_CONTAINER_DLL_remove(update.head, update.tail, element);
1072 GNUNET_free (element);
1073 }
953 1074
954 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES; 1075 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
955 1076
@@ -957,32 +1078,29 @@ callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNU
957 1078
958 switch (message->header.kind) 1079 switch (message->header.kind)
959 { 1080 {
960 case GNUNET_MESSENGER_KIND_INFO:
961 recv_message_info (room, tunnel, message, hash);
962 break;
963 case GNUNET_MESSENGER_KIND_JOIN: 1081 case GNUNET_MESSENGER_KIND_JOIN:
964 recv_message_join (room, tunnel, message, hash); 1082 handle_message_join (room, session, message, hash);
965 break; 1083 break;
966 case GNUNET_MESSENGER_KIND_LEAVE: 1084 case GNUNET_MESSENGER_KIND_LEAVE:
967 recv_message_leave (room, tunnel, message, hash); 1085 handle_message_leave (room, session, message, hash);
968 break; 1086 break;
969 case GNUNET_MESSENGER_KIND_NAME: 1087 case GNUNET_MESSENGER_KIND_NAME:
970 recv_message_name (room, tunnel, message, hash); 1088 handle_message_name (room, session, message, hash);
971 break; 1089 break;
972 case GNUNET_MESSENGER_KIND_KEY: 1090 case GNUNET_MESSENGER_KIND_KEY:
973 recv_message_key (room, tunnel, message, hash); 1091 handle_message_key (room, session, message, hash);
974 break; 1092 break;
975 case GNUNET_MESSENGER_KIND_PEER: 1093 case GNUNET_MESSENGER_KIND_PEER:
976 recv_message_peer (room, tunnel, message, hash); 1094 handle_message_peer (room, session, message, hash);
977 break; 1095 break;
978 case GNUNET_MESSENGER_KIND_ID: 1096 case GNUNET_MESSENGER_KIND_ID:
979 recv_message_id (room, tunnel, message, hash); 1097 handle_message_id (room, session, message, hash);
980 break; 1098 break;
981 case GNUNET_MESSENGER_KIND_MISS: 1099 case GNUNET_MESSENGER_KIND_MISS:
982 recv_message_miss (room, tunnel, message, hash); 1100 handle_message_miss (room, session, message, hash);
983 break; 1101 break;
984 case GNUNET_MESSENGER_KIND_REQUEST: 1102 case GNUNET_MESSENGER_KIND_DELETE:
985 recv_message_request (room, tunnel, message, hash); 1103 handle_message_delete (room, session, message, hash);
986 break; 1104 break;
987 default: 1105 default:
988 break; 1106 break;
@@ -992,60 +1110,98 @@ callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNU
992 handle_room_messages (room); 1110 handle_room_messages (room);
993} 1111}
994 1112
995#include "gnunet-service-messenger_message_send.h" 1113static void
1114get_room_data_subdir (struct GNUNET_MESSENGER_SrvRoom *room, char **dir)
1115{
1116 GNUNET_assert((room) && (dir));
1117
1118 GNUNET_asprintf (dir, "%s%s%c%s%c", room->service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (get_room_key(room)), DIR_SEPARATOR);
1119}
996 1120
997void 1121void
998callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, 1122load_room (struct GNUNET_MESSENGER_SrvRoom *room)
999 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
1000{ 1123{
1001 const struct GNUNET_MESSENGER_Message *old_message = get_room_message (room, handle, hash, GNUNET_NO); 1124 GNUNET_assert(room);
1125
1126 char *room_dir;
1127 get_room_data_subdir (room, &room_dir);
1002 1128
1003 if ((old_message) || (GNUNET_OK != put_store_message (&(room->store), hash, message))) 1129 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1004 { 1130 {
1005 if (old_message != message) 1131 load_member_store (get_room_member_store(room), room_dir);
1006 GNUNET_free(message); 1132 load_message_store (get_room_message_store(room), room_dir);
1133 load_operation_store(get_room_operation_store(room), room_dir);
1134
1135 char *basement_file;
1136 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1137
1138 load_list_tunnels(&(room->basement), basement_file);
1139 GNUNET_free(basement_file);
1140
1141 char *last_messages_file;
1142 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list");
1143
1144 load_message_state(&(room->state), room_dir);
1007 } 1145 }
1008 else
1009 {
1010 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; // may be NULL
1011 1146
1012 update_room_last_messages (room, message, hash); 1147 GNUNET_free(room_dir);
1148}
1013 1149
1014 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES; 1150void
1151save_room (struct GNUNET_MESSENGER_SrvRoom *room)
1152{
1153 GNUNET_assert(room);
1015 1154
1016 add_to_list_messages (&(room->handling), hash); 1155 char *room_dir;
1156 get_room_data_subdir (room, &room_dir);
1017 1157
1018 switch (message->header.kind) 1158 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) ||
1019 { 1159 (GNUNET_OK == GNUNET_DISK_directory_create (room_dir)))
1020 case GNUNET_MESSENGER_KIND_INFO: 1160 {
1021 send_message_info (room, handle, tunnel, message, hash); 1161 save_member_store(get_room_member_store(room), room_dir);
1022 break; 1162 save_message_store (get_room_message_store(room), room_dir);
1023 case GNUNET_MESSENGER_KIND_JOIN: 1163 save_operation_store(get_room_operation_store(room), room_dir);
1024 send_message_join (room, handle, tunnel, message, hash); 1164
1025 break; 1165 char *basement_file;
1026 case GNUNET_MESSENGER_KIND_LEAVE: 1166 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1027 send_message_leave (room, handle, tunnel, message, hash);
1028 break;
1029 case GNUNET_MESSENGER_KIND_NAME:
1030 send_message_name (room, handle, tunnel, message, hash);
1031 break;
1032 case GNUNET_MESSENGER_KIND_KEY:
1033 send_message_key (room, handle, tunnel, message, hash);
1034 break;
1035 case GNUNET_MESSENGER_KIND_PEER:
1036 send_message_peer (room, handle, tunnel, message, hash);
1037 break;
1038 case GNUNET_MESSENGER_KIND_ID:
1039 send_message_id (room, handle, tunnel, message, hash);
1040 break;
1041 case GNUNET_MESSENGER_KIND_MISS:
1042 send_message_miss (room, handle, tunnel, message, hash);
1043 break;
1044 default:
1045 break;
1046 }
1047 1167
1048 if (GNUNET_YES == start_handle) 1168 save_list_tunnels(&(room->basement), basement_file);
1049 handle_room_messages (room); 1169 GNUNET_free(basement_file);
1170
1171 save_message_state(&(room->state), room_dir);
1050 } 1172 }
1173
1174 GNUNET_free(room_dir);
1175}
1176
1177static void
1178remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session)
1179{
1180 GNUNET_assert ((room) && (session));
1181
1182 remove_member_session (session->member, session);
1183
1184 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
1185
1186 struct GNUNET_HashCode hash;
1187 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
1188
1189 char *room_dir;
1190 get_room_data_subdir (room, &room_dir);
1191
1192 char* session_dir;
1193 GNUNET_asprintf (
1194 &session_dir, "%s%s%c%s%c%s%c%s%c", room_dir,
1195 "members", DIR_SEPARATOR,
1196 GNUNET_sh2s(get_member_session_id(session)), DIR_SEPARATOR,
1197 "sessions", DIR_SEPARATOR,
1198 GNUNET_h2s(&hash), DIR_SEPARATOR
1199 );
1200
1201 GNUNET_free (room_dir);
1202
1203 GNUNET_DISK_directory_remove(session_dir);
1204 GNUNET_free (session_dir);
1205
1206 destroy_member_session(session);
1051} 1207}
diff --git a/src/messenger/gnunet-service-messenger_room.h b/src/messenger/gnunet-service-messenger_room.h
index 36c9e8cf5..b6a0f1064 100644
--- a/src/messenger/gnunet-service-messenger_room.h
+++ b/src/messenger/gnunet-service-messenger_room.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -33,33 +33,30 @@
33#include "gnunet_identity_service.h" 33#include "gnunet_identity_service.h"
34#include "gnunet_mq_lib.h" 34#include "gnunet_mq_lib.h"
35 35
36#include "gnunet-service-messenger_contact.h"
37
38#include "gnunet_messenger_service.h" 36#include "gnunet_messenger_service.h"
39#include "gnunet-service-messenger_basement.h" 37#include "gnunet-service-messenger_basement.h"
40#include "gnunet-service-messenger_handle.h" 38#include "gnunet-service-messenger_handle.h"
41#include "gnunet-service-messenger_tunnel.h" 39#include "gnunet-service-messenger_message_state.h"
42
43#include "gnunet-service-messenger_list_messages.h" 40#include "gnunet-service-messenger_list_messages.h"
41
44#include "messenger_api_list_tunnels.h" 42#include "messenger_api_list_tunnels.h"
45 43
44#include "gnunet-service-messenger_member_store.h"
46#include "gnunet-service-messenger_message_store.h" 45#include "gnunet-service-messenger_message_store.h"
46#include "gnunet-service-messenger_operation_store.h"
47#include "messenger_api_ego.h" 47#include "messenger_api_ego.h"
48 48
49enum GNUNET_MESSENGER_MemberAccess 49#define GNUNET_MESSENGER_IDLE_DELAY GNUNET_TIME_relative_multiply \
50{ 50 (GNUNET_TIME_relative_get_second_ (), 5)
51 GNUNET_MESSENGER_MEMBER_ALLOWED = 1,
52 GNUNET_MESSENGER_MEMBER_BLOCKED = 1,
53 51
54 GNUNET_MESSENGER_MEMBER_UNKNOWN = 0 52#define GNUNET_MESSENGER_REQUEST_DELAY GNUNET_TIME_relative_multiply \
55}; 53 (GNUNET_TIME_relative_get_minute_ (), 5)
56 54
57struct GNUNET_MESSENGER_MemberInfo 55#define GNUNET_MESSENGER_MERGE_DELAY GNUNET_TIME_relative_multiply \
58{ 56 (GNUNET_TIME_relative_get_second_ (), 30)
59 enum GNUNET_MESSENGER_MemberAccess access;
60 57
61 struct GNUNET_MESSENGER_ListMessages session_messages; 58struct GNUNET_MESSENGER_SrvTunnel;
62}; 59struct GNUNET_MESSENGER_MemberSession;
63 60
64struct GNUNET_MESSENGER_SrvRoom 61struct GNUNET_MESSENGER_SrvRoom
65{ 62{
@@ -70,28 +67,25 @@ struct GNUNET_MESSENGER_SrvRoom
70 struct GNUNET_HashCode key; 67 struct GNUNET_HashCode key;
71 68
72 struct GNUNET_CONTAINER_MultiPeerMap *tunnels; 69 struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
73 struct GNUNET_CONTAINER_MultiShortmap *members;
74 struct GNUNET_CONTAINER_MultiShortmap *member_infos;
75 70
76 struct GNUNET_MESSENGER_MessageStore store; 71 struct GNUNET_MESSENGER_MemberStore member_store;
77 struct GNUNET_CONTAINER_MultiHashMap *requested; 72 struct GNUNET_MESSENGER_MessageStore message_store;
73 struct GNUNET_MESSENGER_OperationStore operation_store;
78 74
79 struct GNUNET_MESSENGER_ListTunnels basement; 75 struct GNUNET_MESSENGER_ListTunnels basement;
80 struct GNUNET_MESSENGER_ListMessages last_messages; 76 struct GNUNET_MESSENGER_MessageState state;
81 77
82 struct GNUNET_HashCode *peer_message; 78 struct GNUNET_HashCode *peer_message;
83 79
84 struct GNUNET_MESSENGER_ListMessages handling; 80 struct GNUNET_MESSENGER_ListMessages handling;
85 struct GNUNET_SCHEDULER_Task *idle; 81 struct GNUNET_SCHEDULER_Task *idle;
86
87 int strict_access;
88}; 82};
89 83
90/** 84/**
91 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i>. 85 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i>.
92 * 86 *
93 * @param handle Handle 87 * @param[in/out] handle Handle
94 * @param key Key of room 88 * @param[in] key Key of room
95 * @return New room 89 * @return New room
96 */ 90 */
97struct GNUNET_MESSENGER_SrvRoom* 91struct GNUNET_MESSENGER_SrvRoom*
@@ -100,71 +94,37 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_Hash
100/** 94/**
101 * Destroys a room and frees its memory fully. 95 * Destroys a room and frees its memory fully.
102 * 96 *
103 * @param room Room 97 * @param[in/out] room Room
104 */ 98 */
105void 99void
106destroy_room (struct GNUNET_MESSENGER_SrvRoom *room); 100destroy_room (struct GNUNET_MESSENGER_SrvRoom *room);
107 101
108/** 102/**
109 * Returns the contact of a member in a <i>room</i> identified by a given <i>id</i>. If the <i>room</i> 103 * Returns the used member store of a given <i>room</i>.
110 * does not contain a member with the given <i>id</i>, NULL gets returned.
111 *
112 * @param room Room
113 * @param id Member id
114 * @return Contact or NULL
115 */
116struct GNUNET_MESSENGER_SrvContact*
117get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id);
118
119/**
120 * Adds a contact from the service to a <i>room</i> under a specific <i>id</i> with a given public key.
121 *
122 * @param room Room
123 * @param id Member id
124 * @param pubkey Public key of EGO
125 */
126void
127add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id,
128 const struct GNUNET_IDENTITY_PublicKey *pubkey);
129
130/**
131 * Returns the member information of a member in a <i>room</i> identified by a given <i>id</i>. If the <i>room</i>
132 * does not contain a member with the given <i>id</i>, NULL gets returned.
133 * 104 *
134 * @param room Room 105 * @param[in/out] room Room
135 * @param id Member id 106 * @return Member store
136 * @return Member information or NULL
137 */ 107 */
138struct GNUNET_MESSENGER_MemberInfo* 108struct GNUNET_MESSENGER_MemberStore*
139get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id); 109get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room);
140 110
141/** 111/**
142 * Tries to generate and allocate a new unique member id checking all current members for possible 112 * Returns the used message store of a given <i>room</i>.
143 * duplicates. If the function fails, NULL gets returned.
144 * 113 *
145 * @param room Room 114 * @param[in/out] room Room
146 * @return New member id or NULL 115 * @return Message store
147 */ 116 */
148struct GNUNET_ShortHashCode* 117struct GNUNET_MESSENGER_MessageStore*
149generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room); 118get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room);
150 119
151/** 120/**
152 * Returns the member id of the member representing the handle currently hosting this <i>room</i>. 121 * Returns the used operation store of a given <i>room</i>.
153 * 122 *
154 * @param room Room 123 * @param[in/out] room Room
155 * @return Host member id or NULL 124 * @return Operation store
156 */ 125 */
157const struct GNUNET_ShortHashCode* 126struct GNUNET_MESSENGER_OperationStore*
158get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room); 127get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room);
159
160/**
161 * Changes the member id of the member representing the handle currently hosting this <i>room</i>.
162 *
163 * @param room Room
164 * @param unique_id Unique member id
165 */
166void
167change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id);
168 128
169/** 129/**
170 * Tries to open a <i>room</i> for a given <i>handle</i>. If the room has already been opened, the handle 130 * Tries to open a <i>room</i> for a given <i>handle</i>. If the room has already been opened, the handle
@@ -172,11 +132,11 @@ change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_
172 * 132 *
173 * Calling this method should result in joining a room and sending a peer message as well for this peer. 133 * Calling this method should result in joining a room and sending a peer message as well for this peer.
174 * 134 *
175 * If the function returns GNUNET_YES the port for this room is guranteed to be open for incoming connections. 135 * If the function returns #GNUNET_YES the port for this room is guranteed to be open for incoming connections.
176 * 136 *
177 * @param room Room 137 * @param[in/out] room Room
178 * @param handle Handle 138 * @param[in/out] handle Handle
179 * @return GNUNET_YES on success, GNUNET_NO on failure. 139 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
180 */ 140 */
181int 141int
182open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle); 142open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle);
@@ -186,45 +146,34 @@ open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHan
186 * a peer identity of a hosting peer. During the connection the handle will join the room as a member, waiting for 146 * a peer identity of a hosting peer. During the connection the handle will join the room as a member, waiting for
187 * an info message from the selected host. 147 * an info message from the selected host.
188 * 148 *
189 * @param room Room 149 * @param[in/out] room Room
190 * @param handle Handle 150 * @param[in/out] handle Handle
191 * @param door Peer identity 151 * @param[in] door Peer identity
192 * @return GNUNET_YES on success, GNUNET_NO on failure. 152 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
193 */ 153 */
194int 154int
195entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 155enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
196 const struct GNUNET_PeerIdentity *door); 156 const struct GNUNET_PeerIdentity *door);
197 157
198/** 158/**
199 * Returns a tunnel granting a direct connection to a specific member in a <i>room</i>. The member gets identified
200 * by an <i>id</i>. If no tunnel has been linked to the selected id, NULL gets returned.
201 *
202 * @param room Room
203 * @param contact_id Member id
204 * @return Tunnel to the member or NULL
205 */
206struct GNUNET_MESSENGER_SrvTunnel*
207find_room_tunnel_to (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *contact_id);
208
209/**
210 * Packs a <i>message</i> depending on the selected <i>mode</i> into a newly allocated envelope. It will set the 159 * Packs a <i>message</i> depending on the selected <i>mode</i> into a newly allocated envelope. It will set the
211 * timestamp of the message, the sender id and the previous messages hash automatically before packing. The message 160 * timestamp of the message, the sender id and the previous messages hash automatically before packing. The message
212 * will be signed by the handles EGO. 161 * will be signed by the handles EGO.
213 * 162 *
214 * If the optional <i>hash</i> parameter is a valid pointer, its value will be overriden by the signed messages hash. 163 * If the optional <i>hash</i> parameter is a valid pointer, its value will be overriden by the signed messages hash.
215 * 164 *
216 * If <i>mode</i> is set to GNUNET_MESSENGER_PACK_MODE_ENVELOPE, the function returns a valid envelope to send 165 * If <i>mode</i> is set to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE, the function returns a valid envelope to send
217 * through a message queue, otherwise NULL. 166 * through a message queue, otherwise NULL.
218 * 167 *
219 * @param room Room 168 * @param[in] room Room
220 * @param handle Handle 169 * @param[in] handle Handle
221 * @param message Message 170 * @param[in/out] message Message
222 * @param[out] hash Hash of message 171 * @param[out] hash Hash of message
223 * @param mode Packing mode 172 * @param[in] mode Packing mode
224 * @return New envelope or NULL 173 * @return New envelope or NULL
225 */ 174 */
226struct GNUNET_MQ_Envelope* 175struct GNUNET_MQ_Envelope*
227pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 176pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_SrvHandle *handle,
228 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode); 177 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode);
229 178
230/** 179/**
@@ -234,59 +183,69 @@ pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
234 * The function handles packing the message automatically and will call linked message-events locally even if 183 * The function handles packing the message automatically and will call linked message-events locally even if
235 * the message won't be sent to another peer. 184 * the message won't be sent to another peer.
236 * 185 *
237 * @param room Room 186 * The function returns #GNUNET_YES on success, #GNUNET_NO if message is null and
238 * @param handle Handle 187 * #GNUNET_SYSERR if the message was known already.
239 * @param message Message 188 *
240 * @param[out] hash Hash of message 189 * @param[in/out] room Room
190 * @param[in/out] handle Handle
191 * @param[in/out] message Message
192 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
241 */ 193 */
242void 194int
243send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 195send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
244 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash); 196 struct GNUNET_MESSENGER_Message *message);
245 197
246/** 198/**
247 * Sends a <i>message</i> from a given <i>handle</i> into a <i>room</i> excluding one specific <i>tunnel</i>. 199 * Forwards a <i>message</i> with a given <i>hash</i> to a specific <i>tunnel</i> inside of a <i>room</i>.
248 * The <i>hash</i> parameter will be updated with the hash-value resulting from the sent message.
249 *
250 * The function handles packing the message automatically and will call linked message-events locally even if
251 * the message won't be sent to another peer.
252 * 200 *
253 * @param room Room 201 * @param[in/out] room Room
254 * @param handle Handle 202 * @param[in/out] tunnel Tunnel
255 * @param message Message 203 * @param[in/out] message Message
256 * @param[out] hash Hash of message 204 * @param[in] hash Hash of message
257 * @param tunnel Tunnel
258 */ 205 */
259void 206void
260send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 207forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
261 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, 208 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
262 struct GNUNET_MESSENGER_SrvTunnel *tunnel);
263 209
264/** 210/**
265 * Forwards a <i>message</i> with a given <i>hash</i> to a specific <i>tunnel</i> inside of a <i>room</i>. 211 * Checks the current state of opening a given <i>room</i> from this peer and re-publishes it
212 * if necessary to a selected <i>tunnel</i> or to all connected tunnels if necessary or if the
213 * selected tunnel is NULL.
266 * 214 *
267 * @param room Room 215 * @param[in/out] room Room
268 * @param tunnel Tunnel 216 * @param[in/out] tunnel Tunnel
269 * @param message Message
270 * @param hash Hash of message
271 */ 217 */
272void 218void
273forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 219check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel);
274 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
275 220
276/** 221/**
277 * Reduces all current forks inside of the message history of a <i>room</i> to one remaining last message 222 * Reduces all current forks inside of the message history of a <i>room</i> to one remaining last message
278 * by merging them down. All merge messages will be sent from a given <i>handle</i>. 223 * by merging them down. All merge messages will be sent from a given <i>handle</i>.
279 * 224 *
280 * @param room Room 225 * @param[in/out] room Room
281 * @param handle Handle 226 * @param[in/out] handle Handle
282 */ 227 */
283void 228void
284merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle); 229merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle);
285 230
286/** 231/**
232 * Deletes a message from the <i>room</i> with a given <i>hash</i> in a specific <i>delay</i> if
233 * the provided member by its session is permitted to do so.
234 *
235 * @param[in/out] room Room
236 * @param[in/out] session Member session
237 * @param[in] hash Hash of message
238 * @param[in] delay Delay of deletion
239 * @return #GNUNET_YES on success, #GNUNET_NO if permission gets denied, #GNUNET_SYSERR on operation failure
240 */
241int
242delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
243 const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay);
244
245/**
287 * Returns the CADET handle from a rooms service. 246 * Returns the CADET handle from a rooms service.
288 * 247 *
289 * @param room Room 248 * @param[in/out] room Room
290 * @return CADET handle 249 * @return CADET handle
291 */ 250 */
292struct GNUNET_CADET_Handle* 251struct GNUNET_CADET_Handle*
@@ -295,84 +254,95 @@ get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room);
295/** 254/**
296 * Returns the shared secret you need to access a <i>room</i>. 255 * Returns the shared secret you need to access a <i>room</i>.
297 * 256 *
298 * @param room Room 257 * @param[in] room Room
299 * @return Shared secret 258 * @return Shared secret
300 */ 259 */
301struct GNUNET_HashCode* 260const struct GNUNET_HashCode*
302get_room_key (struct GNUNET_MESSENGER_SrvRoom *room); 261get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room);
303 262
304/** 263/**
305 * Returns a tunnel inside of a <i>room</i> leading towards a given <i>peer</i> if such a tunnel exists, 264 * Returns a tunnel inside of a <i>room</i> leading towards a given <i>peer</i> if such a tunnel exists,
306 * otherwise NULL. 265 * otherwise NULL.
307 * 266 *
308 * @param room Room 267 * @param[in] room Room
309 * @param peer Peer identity 268 * @param[in] peer Peer identity
310 * @return Tunnel or NULL 269 * @return Tunnel or NULL
311 */ 270 */
312const struct GNUNET_MESSENGER_SrvTunnel* 271const struct GNUNET_MESSENGER_SrvTunnel*
313get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer); 272get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer);
314 273
315/** 274/**
316 * Returns a message from a <i>room</i> identified by a given <i>hash</i>. If no matching message is 275 * Method called whenever a <i>message</i> is found during a request in a <i>room</i>.
317 * found and <i>request</i> is set to GNUNET_YES, the <i>handle</i> will request the missing message
318 * automatically.
319 *
320 * The function uses the optimized check for a message via its hash from the message store.
321 * @see contains_store_message()
322 * 276 *
323 * If a message is missing independent of the following request, NULL gets returned instead of the 277 * @param[in/out] cls Closure from #request_room_message
324 * matching message. 278 * @param[in/out] room Room
325 * 279 * @param[in] message Message or NULL
326 * @param room Room 280 * @param[in] hash Hash of message
327 * @param handle Handle
328 * @param hash Hash of message
329 * @param request Flag to request a message
330 * @return Message or NULL
331 */ 281 */
332const struct GNUNET_MESSENGER_Message* 282typedef void (GNUNET_MESSENGER_MessageRequestCallback) (
333get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 283 void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
334 const struct GNUNET_HashCode *hash, int request); 284 const struct GNUNET_MESSENGER_Message *message,
285 const struct GNUNET_HashCode *hash
286);
335 287
336/** 288/**
337 * Updates the last messages of a <i>room</i> by replacing them if the previous hash of a given <i>message</i> 289 * Requests a message from a <i>room</i> identified by a given <i>hash</i>. If the message is found,
338 * matches with one of the latest messages. 290 * the selected <i>callback</i> will be called with it and the provided closure. If no matching message
339 * 291 * is found but it wasn't deleted the selected callback will be called with #NULL as message instead.
340 * @param room Room 292 * In case of deletion the next available previous message will be used to call the callback.
341 * @param message Message 293 *
342 * @param hash Hash of message 294 * It is also possible that the given callback will not be called if the requesting session is not
295 * permitted!
296 *
297 * @param[in/out] room Room
298 * @param[in] hash Hash of message
299 * @param[in] callback Callback to process result
300 * @param[in] cls Closure for the <i>callback</i>
301 * @return #GNUNET_YES if the request could be processed, otherwise #GNUNET_NO
343 */ 302 */
344void 303int
345update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message, 304request_room_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
346 const struct GNUNET_HashCode *hash); 305 const struct GNUNET_MESSENGER_MemberSession *session,
306 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls);
347 307
348/** 308/**
349 * Changes an id of a current member from an old id to a new one and adds optionally the <i>hash</i> of an 309 * Checks for potential collisions with member ids and solves them changing active handles ids if they
350 * id message to the members information. 310 * use an already used member id (comparing public key and timestamp).
351 * 311 *
352 * @param room Room 312 * @param[in/out] room Room
353 * @param old_id Old member id 313 * @param[in] public_key Public key of EGO
354 * @param new_id New member id 314 * @param[in] member_id Member ID
355 * @param hash Hash of id message 315 * @param[in] timestamp Timestamp
356 */ 316 */
357void 317void
358switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, 318solve_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_IDENTITY_PublicKey *public_key,
359 const struct GNUNET_ShortHashCode *new_id, const struct GNUNET_HashCode *hash); 319 const struct GNUNET_ShortHashCode *member_id, struct GNUNET_TIME_Absolute timestamp);
360 320
361/** 321/**
362 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made 322 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made
363 * depending on the amount of peers and this peers index in the list of them. 323 * depending on the amount of peers and this peers index in the list of them.
364 * 324 *
365 * @param room Room 325 * @param[in/out] room Room
366 */ 326 */
367void 327void
368rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room); 328rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room);
369 329
370/** 330/**
371 * Handles all queued up messages of a room to handle in correct order. 331 * Loads the local configuration for a given <i>room</i> of a service which contains the last messages hash
332 * and the ruleset for general access of new members.
333 *
334 * @param[out] room Room
335 */
336void
337load_room (struct GNUNET_MESSENGER_SrvRoom *room);
338
339/**
340 * Saves the configuration for a given <i>room</i> of a service which contains the last messages hash
341 * and the ruleset for general access of new members locally.
372 * 342 *
373 * @param room Room 343 * @param[in] room Room
374 */ 344 */
375void 345void
376handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room); 346save_room (struct GNUNET_MESSENGER_SrvRoom *room);
377 347
378#endif //GNUNET_SERVICE_MESSENGER_ROOM_H 348#endif //GNUNET_SERVICE_MESSENGER_ROOM_H
diff --git a/src/messenger/gnunet-service-messenger_service.c b/src/messenger/gnunet-service-messenger_service.c
index 963314fd8..8c63e9bf4 100644
--- a/src/messenger/gnunet-service-messenger_service.c
+++ b/src/messenger/gnunet-service-messenger_service.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -24,11 +24,8 @@
24 */ 24 */
25 25
26#include "gnunet-service-messenger_service.h" 26#include "gnunet-service-messenger_service.h"
27
28#include "gnunet-service-messenger_message_kind.h" 27#include "gnunet-service-messenger_message_kind.h"
29
30#include "gnunet-service-messenger.h" 28#include "gnunet-service-messenger.h"
31#include "gnunet-service-messenger_util.h"
32 29
33static void 30static void
34callback_shutdown_service (void *cls) 31callback_shutdown_service (void *cls)
@@ -43,23 +40,11 @@ callback_shutdown_service (void *cls)
43 } 40 }
44} 41}
45 42
46static void
47callback_update_ego (void *cls,
48 struct GNUNET_IDENTITY_Ego *ego,
49 void **ctx,
50 const char *identifier)
51{
52 if ((!ego) || (!identifier))
53 return;
54
55 struct GNUNET_MESSENGER_Service *service = cls;
56
57 update_service_ego(service, identifier, GNUNET_IDENTITY_ego_get_private_key(ego));
58}
59
60struct GNUNET_MESSENGER_Service* 43struct GNUNET_MESSENGER_Service*
61create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle) 44create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle)
62{ 45{
46 GNUNET_assert((config) && (service_handle));
47
63 struct GNUNET_MESSENGER_Service *service = GNUNET_new(struct GNUNET_MESSENGER_Service); 48 struct GNUNET_MESSENGER_Service *service = GNUNET_new(struct GNUNET_MESSENGER_Service);
64 49
65 service->config = config; 50 service->config = config;
@@ -90,24 +75,16 @@ create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_
90 } 75 }
91 76
92 service->cadet = GNUNET_CADET_connect (service->config); 77 service->cadet = GNUNET_CADET_connect (service->config);
93 service->identity = GNUNET_IDENTITY_connect (service->config, &callback_update_ego, service);
94 78
95 service->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 79 init_ego_store(get_service_ego_store(service), service->config);
96 80
97 init_list_handles (&(service->handles)); 81 init_list_handles (&(service->handles));
98 82
99 service->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
100 service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 83 service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
101 84
102 return service; 85 init_contact_store(get_service_contact_store(service));
103}
104 86
105static int 87 return service;
106iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value)
107{
108 struct GNUNET_MESSENGER_Ego *ego = value;
109 GNUNET_free(ego);
110 return GNUNET_YES;
111} 88}
112 89
113static int 90static int
@@ -118,17 +95,11 @@ iterate_destroy_rooms (void *cls, const struct GNUNET_HashCode *key, void *value
118 return GNUNET_YES; 95 return GNUNET_YES;
119} 96}
120 97
121static int
122iterate_destroy_contacts (void *cls, const struct GNUNET_HashCode *key, void *value)
123{
124 struct GNUNET_MESSENGER_SrvContact *contact = value;
125 destroy_contact (contact);
126 return GNUNET_YES;
127}
128
129void 98void
130destroy_service (struct GNUNET_MESSENGER_Service *service) 99destroy_service (struct GNUNET_MESSENGER_Service *service)
131{ 100{
101 GNUNET_assert(service);
102
132 if (service->shutdown) 103 if (service->shutdown)
133 { 104 {
134 GNUNET_SCHEDULER_cancel (service->shutdown); 105 GNUNET_SCHEDULER_cancel (service->shutdown);
@@ -136,16 +107,13 @@ destroy_service (struct GNUNET_MESSENGER_Service *service)
136 service->shutdown = NULL; 107 service->shutdown = NULL;
137 } 108 }
138 109
139 GNUNET_CONTAINER_multihashmap_iterate (service->egos, iterate_destroy_egos, NULL); 110 clear_ego_store(get_service_ego_store(service));
140
141 clear_list_handles (&(service->handles)); 111 clear_list_handles (&(service->handles));
142 112
143 GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms, NULL); 113 GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms, NULL);
144 GNUNET_CONTAINER_multihashmap_iterate (service->contacts, iterate_destroy_contacts, NULL);
145
146 GNUNET_CONTAINER_multihashmap_destroy (service->egos);
147 GNUNET_CONTAINER_multihashmap_destroy (service->rooms); 114 GNUNET_CONTAINER_multihashmap_destroy (service->rooms);
148 GNUNET_CONTAINER_multihashmap_destroy (service->contacts); 115
116 clear_contact_store(get_service_contact_store(service));
149 117
150 if (service->cadet) 118 if (service->cadet)
151 { 119 {
@@ -154,13 +122,6 @@ destroy_service (struct GNUNET_MESSENGER_Service *service)
154 service->cadet = NULL; 122 service->cadet = NULL;
155 } 123 }
156 124
157 if (service->identity)
158 {
159 GNUNET_IDENTITY_disconnect (service->identity);
160
161 service->identity = NULL;
162 }
163
164 if (service->dir) 125 if (service->dir)
165 { 126 {
166 GNUNET_free(service->dir); 127 GNUNET_free(service->dir);
@@ -173,44 +134,27 @@ destroy_service (struct GNUNET_MESSENGER_Service *service)
173 GNUNET_free(service); 134 GNUNET_free(service);
174} 135}
175 136
176struct GNUNET_MESSENGER_Ego* 137struct GNUNET_MESSENGER_EgoStore*
177lookup_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier) 138get_service_ego_store (struct GNUNET_MESSENGER_Service *service)
178{ 139{
179 GNUNET_assert(identifier); 140 GNUNET_assert(service);
180 141
181 struct GNUNET_HashCode hash; 142 return &(service->ego_store);
182
183 GNUNET_CRYPTO_hash(identifier, strlen(identifier), &hash);
184 return GNUNET_CONTAINER_multihashmap_get(service->egos, &hash);
185} 143}
186 144
187void 145struct GNUNET_MESSENGER_ContactStore*
188update_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier, 146get_service_contact_store (struct GNUNET_MESSENGER_Service *service)
189 const struct GNUNET_IDENTITY_PrivateKey* key)
190{ 147{
191 GNUNET_assert((identifier) && (key)); 148 GNUNET_assert(service);
192
193 struct GNUNET_HashCode hash;
194
195 GNUNET_CRYPTO_hash(identifier, strlen(identifier), &hash);
196 149
197 struct GNUNET_MESSENGER_Ego* ego = GNUNET_CONTAINER_multihashmap_get(service->egos, &hash); 150 return &(service->contact_store);
198
199 if (!ego)
200 {
201 ego = GNUNET_new(struct GNUNET_MESSENGER_Ego);
202 GNUNET_CONTAINER_multihashmap_put(service->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
203 }
204
205 GNUNET_memcpy(&(ego->priv), key, sizeof(*key));
206
207 if (GNUNET_OK != GNUNET_IDENTITY_key_get_public(key, &(ego->pub)))
208 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n");
209} 151}
210 152
211struct GNUNET_MESSENGER_SrvHandle* 153struct GNUNET_MESSENGER_SrvHandle*
212add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq) 154add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq)
213{ 155{
156 GNUNET_assert((service) && (mq));
157
214 struct GNUNET_MESSENGER_SrvHandle *handle = create_handle (service, mq); 158 struct GNUNET_MESSENGER_SrvHandle *handle = create_handle (service, mq);
215 159
216 if (handle) 160 if (handle)
@@ -224,6 +168,8 @@ add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_H
224void 168void
225remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle) 169remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle)
226{ 170{
171 GNUNET_assert((service) && (handle));
172
227 if (!handle) 173 if (!handle)
228 return; 174 return;
229 175
@@ -234,68 +180,16 @@ remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_M
234int 180int
235get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer) 181get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer)
236{ 182{
237 return GNUNET_CRYPTO_get_peer_identity (service->config, peer); 183 GNUNET_assert((service) && (peer));
238}
239 184
240struct GNUNET_MESSENGER_SrvContact* 185 return GNUNET_CRYPTO_get_peer_identity (service->config, peer);
241get_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_IDENTITY_PublicKey *pubkey)
242{
243 struct GNUNET_HashCode hash;
244
245 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
246
247 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multihashmap_get (service->contacts, &hash);
248
249 if (contact)
250 return contact;
251
252 contact = create_contact (pubkey);
253
254 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->contacts, &hash, contact,
255 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
256 return contact;
257
258 destroy_contact (contact);
259 return NULL;
260}
261
262void
263swap_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvContact *contact,
264 const struct GNUNET_IDENTITY_PublicKey *pubkey)
265{
266 const struct GNUNET_HashCode *hash = get_contact_id_from_key (contact);
267
268 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (service->contacts, hash, contact))
269 {
270 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
271
272 hash = get_contact_id_from_key (contact);
273
274 GNUNET_CONTAINER_multihashmap_put (service->contacts, hash, contact,
275 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
276 }
277}
278
279struct GNUNET_ShortHashCode*
280generate_service_new_member_id (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key)
281{
282 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
283
284 if (room)
285 {
286 return generate_room_member_id (room);
287 }
288 else
289 {
290 struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
291 generate_free_member_id (random_id, NULL);
292 return random_id;
293 }
294} 186}
295 187
296struct GNUNET_MESSENGER_SrvRoom* 188struct GNUNET_MESSENGER_SrvRoom*
297get_service_room (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key) 189get_service_room (const struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key)
298{ 190{
191 GNUNET_assert((service) && (key));
192
299 return GNUNET_CONTAINER_multihashmap_get (service->rooms, key); 193 return GNUNET_CONTAINER_multihashmap_get (service->rooms, key);
300} 194}
301 195
@@ -303,6 +197,8 @@ int
303open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 197open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
304 const struct GNUNET_HashCode *key) 198 const struct GNUNET_HashCode *key)
305{ 199{
200 GNUNET_assert((service) && (handle) && (key));
201
306 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); 202 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
307 203
308 if (room) 204 if (room)
@@ -310,8 +206,10 @@ open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSE
310 206
311 room = create_room (handle, key); 207 room = create_room (handle, key);
312 208
313 if ((GNUNET_YES == open_room (room, handle)) && (GNUNET_OK 209 if ((GNUNET_YES == open_room (room, handle)) &&
314 == GNUNET_CONTAINER_multihashmap_put (service->rooms, key, room, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) 210 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
211 key, room,
212 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
315 return GNUNET_YES; 213 return GNUNET_YES;
316 214
317 destroy_room (room); 215 destroy_room (room);
@@ -322,11 +220,13 @@ int
322entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 220entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
323 const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key) 221 const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key)
324{ 222{
223 GNUNET_assert((service) && (handle) && (door) && (key));
224
325 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); 225 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
326 226
327 if (room) 227 if (room)
328 { 228 {
329 if (GNUNET_YES == entry_room_at (room, handle, door)) 229 if (GNUNET_YES == enter_room_at (room, handle, door))
330 return GNUNET_YES; 230 return GNUNET_YES;
331 else 231 else
332 return GNUNET_NO; 232 return GNUNET_NO;
@@ -334,8 +234,10 @@ entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESS
334 234
335 room = create_room (handle, key); 235 room = create_room (handle, key);
336 236
337 if ((GNUNET_YES == entry_room_at (room, handle, door)) && (GNUNET_OK 237 if ((GNUNET_YES == enter_room_at (room, handle, door)) &&
338 == GNUNET_CONTAINER_multihashmap_put (service->rooms, key, room, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) 238 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
239 key, room,
240 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
339 { 241 {
340 return GNUNET_YES; 242 return GNUNET_YES;
341 } 243 }
@@ -351,20 +253,14 @@ int
351close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 253close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
352 const struct GNUNET_HashCode *key) 254 const struct GNUNET_HashCode *key)
353{ 255{
256 GNUNET_assert((service) && (handle) && (key));
257
354 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); 258 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
355 259
356 if (!room) 260 if (!room)
357 return GNUNET_NO; 261 return GNUNET_NO;
358 262
359 struct GNUNET_MESSENGER_Message *message = create_message_leave (); 263 send_room_message (room, handle, create_message_leave ());
360
361 if (message)
362 {
363 struct GNUNET_HashCode hash;
364
365 send_room_message (room, handle, message, &hash);
366 destroy_message (message);
367 }
368 264
369 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key); 265 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
370 266
@@ -393,124 +289,18 @@ close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESS
393 return GNUNET_YES; 289 return GNUNET_YES;
394} 290}
395 291
396static void
397get_room_data_subdir (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, char **dir)
398{
399 GNUNET_asprintf (dir, "%s%s%c%s%c", service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (&(room->key)), DIR_SEPARATOR);
400}
401
402void
403load_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room)
404{
405 char *room_dir;
406 get_room_data_subdir (service, room, &room_dir);
407
408 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
409 {
410 load_message_store (&room->store, room_dir);
411
412 char *config_file;
413 GNUNET_asprintf (&config_file, "%s%s", room_dir, "room.cfg");
414
415 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
416
417 if ((GNUNET_YES == GNUNET_DISK_file_test (config_file)) && (GNUNET_OK
418 == GNUNET_CONFIGURATION_parse (cfg, config_file)))
419 {
420 unsigned long long access;
421
422 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "room", "access-rule", &access))
423 room->strict_access = (int) (access);
424
425 char *message_string;
426
427 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "room", "last-message", &message_string)) && (message_string))
428 {
429 struct GNUNET_HashCode hash;
430
431 GNUNET_CRYPTO_hash_from_string(message_string, &hash);
432
433 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, room->host, &hash, GNUNET_NO);
434
435 if (message)
436 update_room_last_messages (room, message, &hash);
437
438 GNUNET_free(message_string);
439 }
440 }
441
442 GNUNET_CONFIGURATION_destroy (cfg);
443
444 GNUNET_free(config_file);
445 }
446
447 GNUNET_free(room_dir);
448}
449
450void
451save_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room)
452{
453 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (service->rooms, &(room->key)))
454 {
455 return;
456 }
457
458 char *room_dir;
459 get_room_data_subdir (service, room, &room_dir);
460
461 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) || (GNUNET_OK
462 == GNUNET_DISK_directory_create (room_dir)))
463 {
464 save_message_store (&room->store, room_dir);
465
466 char *config_file;
467 GNUNET_asprintf (&config_file, "%s%s", room_dir, "room.cfg");
468
469 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
470
471 GNUNET_CONFIGURATION_set_value_number (cfg, "room", "access-rule", room->strict_access);
472
473 if (room->last_messages.head)
474 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "last-message",
475 GNUNET_h2s_full (&(room->last_messages.head->hash)));
476
477 GNUNET_CONFIGURATION_write (cfg, config_file);
478 GNUNET_CONFIGURATION_destroy (cfg);
479
480 GNUNET_free(config_file);
481 }
482
483 GNUNET_free(room_dir);
484}
485
486void 292void
487handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, 293handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room,
294 const struct GNUNET_MESSENGER_MemberSession *session,
488 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 295 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
489{ 296{
490 struct GNUNET_MESSENGER_ListHandle *element = service->handles.head; 297 GNUNET_assert((service) && (room) && (session) && (message) && (hash));
491 298
492 const uint16_t length = get_message_size (message); 299 struct GNUNET_MESSENGER_ListHandle *element = service->handles.head;
493 300
494 while (element) 301 while (element)
495 { 302 {
496 struct GNUNET_MESSENGER_SrvHandle *handle = (struct GNUNET_MESSENGER_SrvHandle*) element->handle; 303 notify_handle_message (element->handle, get_room_key(room), session, message, hash);
497
498 if ((handle->mq) && (get_handle_member_id (handle, &(room->key))))
499 {
500 struct GNUNET_MESSENGER_RecvMessage *msg;
501 struct GNUNET_MQ_Envelope *env;
502
503 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
504
505 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key));
506 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
507
508 char *buffer = ((char*) msg) + sizeof(*msg);
509 encode_message (message, length, buffer);
510
511 GNUNET_MQ_send (handle->mq, env);
512 }
513
514 element = element->next; 304 element = element->next;
515 } 305 }
516} 306}
diff --git a/src/messenger/gnunet-service-messenger_service.h b/src/messenger/gnunet-service-messenger_service.h
index 246c74771..aa43fa457 100644
--- a/src/messenger/gnunet-service-messenger_service.h
+++ b/src/messenger/gnunet-service-messenger_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) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -33,13 +33,14 @@
33#include "gnunet_disk_lib.h" 33#include "gnunet_disk_lib.h"
34#include "gnunet_identity_service.h" 34#include "gnunet_identity_service.h"
35 35
36#include "messenger_api_ego.h" 36#include "gnunet-service-messenger_ego_store.h"
37
38#include "gnunet-service-messenger_list_handles.h" 37#include "gnunet-service-messenger_list_handles.h"
39 38
40#include "gnunet-service-messenger_contact.h" 39#include "messenger_api_contact_store.h"
41#include "gnunet-service-messenger_room.h" 40#include "gnunet-service-messenger_room.h"
42 41
42#include "gnunet-service-messenger_member_session.h"
43
43struct GNUNET_MESSENGER_Service 44struct GNUNET_MESSENGER_Service
44{ 45{
45 const struct GNUNET_CONFIGURATION_Handle *config; 46 const struct GNUNET_CONFIGURATION_Handle *config;
@@ -50,21 +51,20 @@ struct GNUNET_MESSENGER_Service
50 char *dir; 51 char *dir;
51 52
52 struct GNUNET_CADET_Handle *cadet; 53 struct GNUNET_CADET_Handle *cadet;
53 struct GNUNET_IDENTITY_Handle *identity;
54 54
55 struct GNUNET_CONTAINER_MultiHashMap *egos; 55 struct GNUNET_MESSENGER_EgoStore ego_store;
56 struct GNUNET_MESSENGER_ContactStore contact_store;
56 57
57 struct GNUNET_MESSENGER_ListHandles handles; 58 struct GNUNET_MESSENGER_ListHandles handles;
58 59
59 struct GNUNET_CONTAINER_MultiHashMap *contacts;
60 struct GNUNET_CONTAINER_MultiHashMap *rooms; 60 struct GNUNET_CONTAINER_MultiHashMap *rooms;
61}; 61};
62 62
63/** 63/**
64 * Creates and allocates a new service using a given <i>config</i> and a GNUnet service handle. 64 * Creates and allocates a new service using a given <i>config</i> and a GNUnet service handle.
65 * 65 *
66 * @param config Configuration 66 * @param[in] config Configuration
67 * @param service_handle GNUnet service handle 67 * @param[in/out] service_handle GNUnet service handle
68 * @return New service 68 * @return New service
69 */ 69 */
70struct GNUNET_MESSENGER_Service* 70struct GNUNET_MESSENGER_Service*
@@ -73,39 +73,34 @@ create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_
73/** 73/**
74 * Destroys a <i>service</i> and frees its memory fully. 74 * Destroys a <i>service</i> and frees its memory fully.
75 * 75 *
76 * @param service Service 76 * @param[in/out] service Service
77 */ 77 */
78void 78void
79destroy_service (struct GNUNET_MESSENGER_Service *service); 79destroy_service (struct GNUNET_MESSENGER_Service *service);
80 80
81/** 81/**
82 * Lookups an EGO which was registered to a <i>service</i> under 82 * Returns the used EGO-store of a given <i>service</i>.
83 * a specific <i>identifier</i>.
84 * 83 *
85 * @param service Service 84 * @param[in/out] service Service
86 * @param identifier Identifier string 85 * @return EGO-store
87 * @return EGO or NULL
88 */ 86 */
89struct GNUNET_MESSENGER_Ego* 87struct GNUNET_MESSENGER_EgoStore*
90lookup_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier); 88get_service_ego_store (struct GNUNET_MESSENGER_Service *service);
91 89
92/** 90/**
93 * Updates the registration of an EGO to a <i>service</i> under 91 * Returns the used contact store of a given <i>service</i>.
94 * a specific <i>identifier</i> with a new <i>key</i>.
95 * 92 *
96 * @param service Service 93 * @param[in/out] service Service
97 * @param identifier Identifier string 94 * @return Contact store
98 * @param key Private EGO key
99 */ 95 */
100void 96struct GNUNET_MESSENGER_ContactStore*
101update_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier, 97get_service_contact_store (struct GNUNET_MESSENGER_Service *service);
102 const struct GNUNET_IDENTITY_PrivateKey* key);
103 98
104/** 99/**
105 * Creates and adds a new handle to a <i>service</i> using a given message queue. 100 * Creates and adds a new handle to a <i>service</i> using a given message queue.
106 * 101 *
107 * @param service Service 102 * @param[in/out] service Service
108 * @param mq Message queue 103 * @param[in/out] mq Message queue
109 * @return New handle 104 * @return New handle
110 */ 105 */
111struct GNUNET_MESSENGER_SrvHandle* 106struct GNUNET_MESSENGER_SrvHandle*
@@ -114,77 +109,42 @@ add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_H
114/** 109/**
115 * Removes a <i>handle</i> from a <i>service</i> and destroys it. 110 * Removes a <i>handle</i> from a <i>service</i> and destroys it.
116 * 111 *
117 * @param service Service 112 * @param[in/out] service Service
118 * @param handle Handle 113 * @param[in/out] handle Handle
119 */ 114 */
120void 115void
121remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle); 116remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle);
122 117
123/** 118/**
124 * Tries to write the peer identity of the peer running a <i>service</i> on to the <i>peer</i> 119 * Tries to write the peer identity of the peer running a <i>service</i> on to the <i>peer</i>
125 * parameter. The functions returns GNUNET_OK on success, otherwise GNUNET_SYSERR. 120 * parameter. The functions returns #GNUNET_OK on success, otherwise #GNUNET_SYSERR.
126 * 121 *
127 * @param service Service 122 * @param[in] service Service
128 * @param[out] peer Peer identity 123 * @param[out] peer Peer identity
129 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR 124 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
130 */ 125 */
131int 126int
132get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer); 127get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer);
133 128
134/** 129/**
135 * Returns a contact of a <i>service</i> identified by a given public key. If no matching contact exists,
136 * it will tried to create one with the specific public key. If the function still fails to do so,
137 * NULL gets returned.
138 *
139 * @param service Service
140 * @param pubkey Public key of EGO
141 * @return Contact
142 */
143struct GNUNET_MESSENGER_SrvContact*
144get_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_IDENTITY_PublicKey *pubkey);
145
146/**
147 * Changes the public key for a <i>contact</i> known to a <i>service</i> to a specific public key and
148 * updates local map entries to access the contact by its updated key.
149 *
150 * @param service Service
151 * @param contact Contact
152 * @param pubkey Public key of EGO
153 */
154void
155swap_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvContact *contact,
156 const struct GNUNET_IDENTITY_PublicKey *pubkey);
157
158/**
159 * Tries to generate and allocate a new unique member id for a given room of a service identified by its <i>key</i>.
160 * If the generation fails caused by too many tries of duplicates, it returns NULL.
161 *
162 * @param service Service
163 * @param key Key of room
164 * @return Newly generated member id or NULL
165 */
166struct GNUNET_ShortHashCode*
167generate_service_new_member_id (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key);
168
169/**
170 * Returns the room identified by a given <i>key</i> for a <i>service</i>. If the service doesn't know any room 130 * Returns the room identified by a given <i>key</i> for a <i>service</i>. If the service doesn't know any room
171 * using the given key, NULL gets returned. 131 * using the given key, NULL gets returned.
172 * 132 *
173 * @param service Service 133 * @param[in] service Service
174 * @param key Key of room 134 * @param[in] key Key of room
175 * @return Room or NULL 135 * @return Room or NULL
176 */ 136 */
177struct GNUNET_MESSENGER_SrvRoom* 137struct GNUNET_MESSENGER_SrvRoom*
178get_service_room (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key); 138get_service_room (const struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key);
179 139
180/** 140/**
181 * Tries to open a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will be 141 * Tries to open a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will be
182 * created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. 142 * created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
183 * 143 *
184 * @param service Service 144 * @param[in/out] service Service
185 * @param handle Handle 145 * @param[in/out] handle Handle
186 * @param key Key of room 146 * @param[in] key Key of room
187 * @return GNUNET_YES on success, otherwise GNUNET_NO 147 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
188 */ 148 */
189int 149int
190open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 150open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
@@ -192,16 +152,16 @@ open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSE
192 152
193/** 153/**
194 * Tries to enter a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will 154 * Tries to enter a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will
195 * be created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. 155 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
196 * 156 *
197 * The room will be entered through the peer identitied by the peer identity provided as <i>door</i> parameter and 157 * The room will be entered through the peer identitied by the peer identity provided as <i>door</i> parameter and
198 * a new connection will be made. 158 * a new connection will be made.
199 * 159 *
200 * @param service Service 160 * @param[in/out] service Service
201 * @param handle Handle 161 * @param[in/out] handle Handle
202 * @param door Peer identity 162 * @param[in] door Peer identity
203 * @param key Key of room 163 * @param[in] key Key of room
204 * @return GNUNET_YES on success, otherwise GNUNET_NO 164 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
205 */ 165 */
206int 166int
207entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 167entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
@@ -209,51 +169,33 @@ entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESS
209 169
210/** 170/**
211 * Tries to close a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will 171 * Tries to close a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will
212 * be created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. 172 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
213 * 173 *
214 * If the specific handle is currently the host of the room for this service, a new handle which is a member will 174 * If the specific handle is currently the host of the room for this service, a new handle which is a member will
215 * take its place. Otherwise the room will be destroyed for this service. 175 * take its place. Otherwise the room will be destroyed for this service.
216 * 176 *
217 * @param service Service 177 * @param[in/out] service Service
218 * @param handle Handle 178 * @param[in/out] handle Handle
219 * @param key Key of room 179 * @param[in] key Key of room
220 * @return GNUNET_YES on success, otherwise GNUNET_NO 180 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
221 */ 181 */
222int 182int
223close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 183close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
224 const struct GNUNET_HashCode *key); 184 const struct GNUNET_HashCode *key);
225 185
226/** 186/**
227 * Loads the local configuration for a given <i>room</i> of a <i>service</i> which contains the last messages hash
228 * and the ruleset for general access of new members.
229 *
230 * @param service Service
231 * @param room Room
232 */
233void
234load_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room);
235
236/**
237 * Saves the configuration for a given <i>room</i> of a <i>service</i> which contains the last messages hash
238 * and the ruleset for general access of new members locally.
239 *
240 * @param service Service
241 * @param room Room
242 */
243void
244save_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room);
245
246/**
247 * Sends a received or sent <i>message</i> with a given <i>hash</i> to each handle of a <i>service</i> which 187 * Sends a received or sent <i>message</i> with a given <i>hash</i> to each handle of a <i>service</i> which
248 * is currently member of a specific <i>room</i> for handling it in the client API. 188 * is currently member of a specific <i>room</i> for handling it in the client API.
249 * 189 *
250 * @param service Service 190 * @param[in/out] service Service
251 * @param room Room 191 * @param[in/out] room Room
252 * @param message Message 192 * @param[in] session Member session
253 * @param hash Hash of message 193 * @param[in] message Message
194 * @param[in] hash Hash of message
254 */ 195 */
255void 196void
256handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, 197handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room,
198 const struct GNUNET_MESSENGER_MemberSession *session,
257 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 199 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
258 200
259#endif //GNUNET_SERVICE_MESSENGER_SERVICE_H 201#endif //GNUNET_SERVICE_MESSENGER_SERVICE_H
diff --git a/src/messenger/gnunet-service-messenger_tunnel.c b/src/messenger/gnunet-service-messenger_tunnel.c
index df9e5c4c7..80d8dfa5e 100644
--- a/src/messenger/gnunet-service-messenger_tunnel.c
+++ b/src/messenger/gnunet-service-messenger_tunnel.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -26,7 +26,11 @@
26#include "gnunet-service-messenger_tunnel.h" 26#include "gnunet-service-messenger_tunnel.h"
27 27
28#include "gnunet-service-messenger_handle.h" 28#include "gnunet-service-messenger_handle.h"
29#include "gnunet-service-messenger_util.h" 29#include "gnunet-service-messenger_message_recv.h"
30#include "gnunet-service-messenger_message_store.h"
31#include "gnunet-service-messenger_operation_store.h"
32#include "gnunet-service-messenger_operation.h"
33#include "messenger_api_util.h"
30 34
31struct GNUNET_MESSENGER_SrvTunnel* 35struct GNUNET_MESSENGER_SrvTunnel*
32create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door) 36create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door)
@@ -39,10 +43,12 @@ create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerId
39 tunnel->channel = NULL; 43 tunnel->channel = NULL;
40 44
41 tunnel->peer = GNUNET_PEER_intern (door); 45 tunnel->peer = GNUNET_PEER_intern (door);
42 tunnel->contact_id = NULL; 46
47 tunnel->messenger_version = 0;
43 48
44 tunnel->peer_message = NULL; 49 tunnel->peer_message = NULL;
45 tunnel->last_message = NULL; 50
51 init_message_state(&(tunnel->state));
46 52
47 return tunnel; 53 return tunnel;
48} 54}
@@ -57,34 +63,23 @@ destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
57 63
58 GNUNET_PEER_change_rc (tunnel->peer, -1); 64 GNUNET_PEER_change_rc (tunnel->peer, -1);
59 65
60 if (tunnel->contact_id)
61 GNUNET_free(tunnel->contact_id);
62
63 if (tunnel->peer_message) 66 if (tunnel->peer_message)
64 GNUNET_free(tunnel->peer_message); 67 GNUNET_free(tunnel->peer_message);
65 68
66 if (tunnel->last_message) 69 clear_message_state(&(tunnel->state));
67 GNUNET_free(tunnel->last_message);
68 70
69 GNUNET_free(tunnel); 71 GNUNET_free(tunnel);
70} 72}
71 73
72int 74void
73bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel) 75bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel)
74{ 76{
75 GNUNET_assert(tunnel); 77 GNUNET_assert(tunnel);
76 78
77 if (tunnel->channel) 79 if (tunnel->channel)
78 {
79 if (tunnel->contact_id)
80 return GNUNET_NO;
81
82 delayed_disconnect_channel (tunnel->channel); 80 delayed_disconnect_channel (tunnel->channel);
83 }
84 81
85 tunnel->channel = channel; 82 tunnel->channel = channel;
86
87 return GNUNET_YES;
88} 83}
89 84
90extern void 85extern void
@@ -113,52 +108,57 @@ check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
113 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; 108 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
114 109
115 if (!tunnel) 110 if (!tunnel)
116 return GNUNET_NO; 111 return GNUNET_SYSERR;
117 112
118 const uint16_t length = ntohs (header->size) - sizeof(*header); 113 const uint16_t length = ntohs (header->size) - sizeof(*header);
119 const char *buffer = (const char*) &header[1]; 114 const char *buffer = (const char*) &header[1];
120 115
121 struct GNUNET_MESSENGER_Message message; 116 struct GNUNET_MESSENGER_Message message;
122 117
123 if (length < sizeof(message.header)) 118 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
124 return GNUNET_NO; 119 {
125 120 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Message too short! (%d)\n", length);
126 if (GNUNET_YES != decode_message (&message, length, buffer)) 121 return GNUNET_SYSERR;
127 return GNUNET_NO; 122 }
128
129 struct GNUNET_HashCode hash;
130 hash_message (length, buffer, &hash);
131 123
132 int result = callback_verify_room_message (tunnel->room, cls, &message, &hash); 124 uint16_t padding = 0;
133 125
134 if (GNUNET_MESSENGER_KIND_PEER == message.header.kind) 126 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, &padding))
135 { 127 {
136 struct GNUNET_PeerIdentity identity; 128 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Decoding failed!\n");
137 129 return GNUNET_SYSERR;
138 GNUNET_PEER_resolve (tunnel->peer, &identity);
139
140 if (0 == GNUNET_memcmp(&(message.body.peer.peer), &(identity)))
141 {
142 if (tunnel->contact_id)
143 {
144 if (0 != GNUNET_memcmp(tunnel->contact_id, &(message.header.sender_id)))
145 result = GNUNET_SYSERR;
146 }
147 else
148 {
149 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
150
151 GNUNET_memcpy(tunnel->contact_id, &(message.header.sender_id), sizeof(struct GNUNET_ShortHashCode));
152 }
153 }
154 } 130 }
155 131
156 return (result == GNUNET_YES ? GNUNET_OK : GNUNET_NO); 132 struct GNUNET_HashCode hash;
133 hash_message (&message, length - padding, buffer, &hash);
134
135 return callback_verify_room_message (tunnel->room, cls, &message, &hash);
157} 136}
158 137
138extern int
139update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
140 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
141
159extern void 142extern void
160callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, 143callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
161 const struct GNUNET_HashCode *hash); 144 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
145
146static void
147update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_HashCode *hash)
148{
149 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(tunnel->room);
150
151 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
152 GNUNET_YES : GNUNET_NO
153 );
154
155 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(tunnel->room);
156
157 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
158
159 if (message)
160 update_message_state(&(tunnel->state), requested, message, hash);
161}
162 162
163void 163void
164handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header) 164handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
@@ -171,19 +171,50 @@ handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
171 struct GNUNET_MESSENGER_Message message; 171 struct GNUNET_MESSENGER_Message message;
172 struct GNUNET_HashCode hash; 172 struct GNUNET_HashCode hash;
173 173
174 decode_message (&message, length, buffer); 174 uint16_t padding = 0;
175 hash_message (length, buffer, &hash);
176 175
177 if (tunnel) 176 decode_message (&message, length, buffer, GNUNET_YES, &padding);
178 { 177 hash_message (&message, length - padding, buffer, &hash);
179 if (!tunnel->last_message) 178
180 tunnel->last_message = GNUNET_new(struct GNUNET_HashCode); 179 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got message of kind: %s!\n",
180 GNUNET_MESSENGER_name_of_kind(message.header.kind));
181
182 if (!tunnel)
183 return;
184
185 const int new_message = update_room_message (
186 tunnel->room, copy_message (&message), &hash
187 );
188
189 if (GNUNET_YES != new_message)
190 goto receive_done;
181 191
182 GNUNET_memcpy(tunnel->last_message, &hash, sizeof(struct GNUNET_HashCode)); 192 update_tunnel_last_message (tunnel, &hash);
183 193
184 callback_room_recv (tunnel->room, cls, copy_message (&message), &hash); 194 int forward_message = GNUNET_YES;
195
196 switch (message.header.kind)
197 {
198 case GNUNET_MESSENGER_KIND_INFO:
199 forward_message = recv_message_info (tunnel->room, tunnel, &message, &hash);
200 break;
201 case GNUNET_MESSENGER_KIND_PEER:
202 forward_message = recv_message_peer (tunnel->room, tunnel, &message, &hash);
203 break;
204 case GNUNET_MESSENGER_KIND_REQUEST:
205 forward_message = recv_message_request (tunnel->room, tunnel, &message, &hash);
206 break;
207 default:
208 break;
185 } 209 }
186 210
211 if (GNUNET_YES == forward_message)
212 {
213 forward_room_message (tunnel->room, tunnel, &message, &hash);
214 callback_room_handle_message (tunnel->room, NULL, &message, &hash);
215 }
216
217receive_done:
187 GNUNET_CADET_receive_done (tunnel->channel); 218 GNUNET_CADET_receive_done (tunnel->channel);
188} 219}
189 220
@@ -198,7 +229,7 @@ connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
198 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer); 229 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer);
199 230
200 struct GNUNET_CADET_Handle *cadet = get_room_cadet (tunnel->room); 231 struct GNUNET_CADET_Handle *cadet = get_room_cadet (tunnel->room);
201 struct GNUNET_HashCode *key = get_room_key (tunnel->room); 232 const struct GNUNET_HashCode *key = get_room_key (tunnel->room);
202 233
203 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI, 234 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
204 struct GNUNET_MessageHeader, NULL), 235 struct GNUNET_MessageHeader, NULL),
@@ -212,6 +243,8 @@ connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
212void 243void
213disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel) 244disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
214{ 245{
246 GNUNET_assert(tunnel);
247
215 if (tunnel->channel) 248 if (tunnel->channel)
216 { 249 {
217 delayed_disconnect_channel (tunnel->channel); 250 delayed_disconnect_channel (tunnel->channel);
@@ -223,6 +256,8 @@ disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
223int 256int
224is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) 257is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
225{ 258{
259 GNUNET_assert(tunnel);
260
226 return (tunnel->channel ? GNUNET_YES : GNUNET_NO); 261 return (tunnel->channel ? GNUNET_YES : GNUNET_NO);
227} 262}
228 263
@@ -232,30 +267,23 @@ struct GNUNET_MESSENGER_MessageSent
232 struct GNUNET_HashCode hash; 267 struct GNUNET_HashCode hash;
233}; 268};
234 269
235extern void
236callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls,
237 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
238
239static void 270static void
240callback_tunnel_sent (void *cls) 271callback_tunnel_sent (void *cls)
241{ 272{
242 struct GNUNET_MESSENGER_MessageSent *sent = cls; 273 struct GNUNET_MESSENGER_MessageSent *sent = cls;
243 274
244 if (sent->tunnel) 275 if (sent->tunnel)
245 { 276 update_tunnel_last_message (sent->tunnel, &(sent->hash));
246 if (!sent->tunnel->last_message)
247 sent->tunnel->last_message = GNUNET_new(struct GNUNET_HashCode);
248
249 GNUNET_memcpy(sent->tunnel->last_message, &(sent->hash), sizeof(struct GNUNET_HashCode));
250 }
251 277
252 GNUNET_free(sent); 278 GNUNET_free(sent);
253} 279}
254 280
255void 281void
256send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env, 282send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MQ_Envelope *env,
257 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 283 const struct GNUNET_HashCode *hash)
258{ 284{
285 GNUNET_assert((tunnel) && (env) && (hash));
286
259 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel); 287 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel);
260 288
261 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent); 289 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent);
@@ -266,35 +294,88 @@ send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, s
266 294
267 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent); 295 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent);
268 GNUNET_MQ_send (mq, env); 296 GNUNET_MQ_send (mq, env);
269
270 callback_room_sent (tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle, tunnel, message, hash);
271} 297}
272 298
273void 299int
274send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message, 300send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message)
275 struct GNUNET_HashCode *hash)
276{ 301{
277 struct GNUNET_MQ_Envelope *env = pack_room_message (tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle, 302 GNUNET_assert((tunnel) && (handle));
278 message, hash, 303
279 GNUNET_MESSENGER_PACK_MODE_ENVELOPE); 304 if (!message)
305 return GNUNET_NO;
306
307 struct GNUNET_HashCode hash;
308 struct GNUNET_MQ_Envelope *env = pack_room_message (
309 tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle,
310 message, &hash, GNUNET_MESSENGER_PACK_MODE_ENVELOPE
311 );
312
313 destroy_message(message);
314
315 if (!env)
316 return GNUNET_NO;
280 317
281 if (env) 318 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending tunnel message: %s\n",
282 send_tunnel_envelope (tunnel, handle, env, copy_message (message), hash); 319 GNUNET_h2s(&hash));
320
321 send_tunnel_envelope (tunnel, env, &hash);
322 return GNUNET_YES;
283} 323}
284 324
285void 325void
286forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, 326forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message,
287 const struct GNUNET_HashCode *hash) 327 const struct GNUNET_HashCode *hash)
288{ 328{
289 struct GNUNET_MESSENGER_Message *clone = copy_message (message); 329 GNUNET_assert((tunnel) && (message) && (hash));
290 struct GNUNET_MQ_Envelope *env = pack_message (clone, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE); 330
331 struct GNUNET_MESSENGER_Message *copy = copy_message(message);
332 struct GNUNET_MQ_Envelope *env = pack_message (copy, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
333
334 destroy_message(copy);
335
336 if (!env)
337 return;
291 338
292 if (env) 339 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Forwarding tunnel message: %s\n",
293 send_tunnel_envelope (tunnel, NULL, env, clone, hash); 340 GNUNET_h2s(hash));
341
342 send_tunnel_envelope (tunnel, env, hash);
294} 343}
295 344
296const struct GNUNET_HashCode* 345const struct GNUNET_HashCode*
297get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) 346get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
298{ 347{
348 GNUNET_assert(tunnel);
349
299 return tunnel->peer_message; 350 return tunnel->peer_message;
300} 351}
352
353void
354get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_PeerIdentity *peer)
355{
356 GNUNET_assert(tunnel);
357
358 GNUNET_PEER_resolve(tunnel->peer, peer);
359}
360
361uint32_t
362get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
363{
364 GNUNET_assert(tunnel);
365
366 return tunnel->messenger_version;
367}
368
369int
370update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel, uint32_t version)
371{
372 GNUNET_assert(tunnel);
373
374 if (version != GNUNET_MESSENGER_VERSION)
375 return GNUNET_SYSERR;
376
377 if (version > tunnel->messenger_version)
378 tunnel->messenger_version = version;
379
380 return GNUNET_OK;
381}
diff --git a/src/messenger/gnunet-service-messenger_tunnel.h b/src/messenger/gnunet-service-messenger_tunnel.h
index e6efb226d..96d98546d 100644
--- a/src/messenger/gnunet-service-messenger_tunnel.h
+++ b/src/messenger/gnunet-service-messenger_tunnel.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -32,6 +32,7 @@
32#include "gnunet_crypto_lib.h" 32#include "gnunet_crypto_lib.h"
33 33
34#include "gnunet-service-messenger_room.h" 34#include "gnunet-service-messenger_room.h"
35#include "gnunet-service-messenger_message_state.h"
35 36
36struct GNUNET_MESSENGER_SrvTunnel 37struct GNUNET_MESSENGER_SrvTunnel
37{ 38{
@@ -39,17 +40,18 @@ struct GNUNET_MESSENGER_SrvTunnel
39 struct GNUNET_CADET_Channel *channel; 40 struct GNUNET_CADET_Channel *channel;
40 41
41 GNUNET_PEER_Id peer; 42 GNUNET_PEER_Id peer;
42 struct GNUNET_ShortHashCode *contact_id; 43
44 uint32_t messenger_version;
43 45
44 struct GNUNET_HashCode *peer_message; 46 struct GNUNET_HashCode *peer_message;
45 struct GNUNET_HashCode *last_message; 47 struct GNUNET_MESSENGER_MessageState state;
46}; 48};
47 49
48/** 50/**
49 * Creates and allocates a tunnel of a <i>room</i> to a specific peer identity. 51 * Creates and allocates a tunnel of a <i>room</i> to a specific peer identity (called <i>door</i>).
50 * 52 *
51 * @param room Room 53 * @param[in/out] room Room
52 * @param door Peer identity 54 * @param[in] door Peer identity
53 * @return New tunnel 55 * @return New tunnel
54 */ 56 */
55struct GNUNET_MESSENGER_SrvTunnel* 57struct GNUNET_MESSENGER_SrvTunnel*
@@ -58,28 +60,27 @@ create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerId
58/** 60/**
59 * Destroys a <i>tunnel</i> and frees its memory fully. 61 * Destroys a <i>tunnel</i> and frees its memory fully.
60 * 62 *
61 * @param tunnel 63 * @param[in/out] tunnel
62 */ 64 */
63void 65void
64destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); 66destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
65 67
66/** 68/**
67 * Binds a CADET <i>channel</i> to a <i>tunnel</i> on returns GNUNET_YES only if 69 * Binds a CADET <i>channel</i> to a <i>tunnel</i> and replaces its channel
68 * the bounds channel was replaced successfully, otherwise GNUNET_NO gets returned. 70 * the tunnel is currently bound to if necessary.
69 * 71 *
70 * @param tunnel Tunnel 72 * @param[in/out] tunnel Tunnel
71 * @param channel CADET channel 73 * @param[in/out] channel CADET channel
72 * @return GNUNET_YES on success, otherwise GNUNET_NO
73 */ 74 */
74int 75void
75bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel); 76bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel);
76 77
77/** 78/**
78 * Tries to connect a <i>tunnel</i> by creating a new CADET channel and binding it. 79 * Tries to connect a <i>tunnel</i> by creating a new CADET channel and binding it.
79 * The function returns GNUNET_YES on success, otherwise GNUNET_NO. 80 * The function returns #GNUNET_YES on success, otherwise #GNUNET_NO.
80 * 81 *
81 * @param tunnel Tunnel 82 * @param[in/out] tunnel Tunnel
82 * @return GNUNET_YES on success, otherwise GNUNET_NO 83 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
83 */ 84 */
84int 85int
85connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); 86connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
@@ -88,7 +89,7 @@ connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
88 * Disconnects and unbinds a channel from a <i>tunnel</i>. The actual disconnection 89 * Disconnects and unbinds a channel from a <i>tunnel</i>. The actual disconnection
89 * will be asynchronous. 90 * will be asynchronous.
90 * 91 *
91 * @param tunnel Tunnel 92 * @param[in/out] tunnel Tunnel
92 */ 93 */
93void 94void
94disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); 95disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
@@ -96,46 +97,43 @@ disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
96/** 97/**
97 * Returns the status of a currently bound channel of a <i>tunnel</i>. 98 * Returns the status of a currently bound channel of a <i>tunnel</i>.
98 * 99 *
99 * @param tunnel Tunnel 100 * @param[in] tunnel Tunnel
100 * @return GNUNET_YES or GNUNET_NO 101 * @return #GNUNET_YES or #GNUNET_NO
101 */ 102 */
102int 103int
103is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel); 104is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
104 105
105/** 106/**
106 * Sends an envelope containing a <i>message</i> with a given <i>hash</i> through 107 * Sends an envelope containing a <i>message</i> with a given <i>hash</i> through
107 * a <i>tunnel</i> by a given <i>handle</i>. 108 * a <i>tunnel</i>.
108 * 109 *
109 * @param tunnel Tunnel 110 * @param[in/out] tunnel Tunnel
110 * @param handle Handle 111 * @param[in/out] env Envelope
111 * @param env Envelope 112 * @param[in] hash Hash of message
112 * @param message Message
113 * @param hash Hash of message
114 */ 113 */
115void 114void
116send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env, 115send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MQ_Envelope *env,
117 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 116 const struct GNUNET_HashCode *hash);
118 117
119/** 118/**
120 * Sends a <i>message</i> by packing it automatically into an envelope and passing it 119 * Sends a <i>message</i> by packing it automatically into an envelope and passing it
121 * through the <i>tunnel</i>. The used <i>handle</i> will sign the message and 120 * through the <i>tunnel</i>. The used <i>handle</i> will sign the message and
122 * the <i>hash</i> will be calculated and stored. 121 * the <i>hash</i> will be calculated and stored.
123 * 122 *
124 * @param tunnel Tunnel 123 * @param[in/out] tunnel Tunnel
125 * @param handle Handle 124 * @param[in/out] handle Handle
126 * @param[out] message Message 125 * @param[in/out] message Message
127 * @param[out] hash Hash of message 126 * @return #GNUNET_YES on success, GNUNET_NO otherwise
128 */ 127 */
129void 128int
130send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message, 129send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message);
131 struct GNUNET_HashCode *hash);
132 130
133/** 131/**
134 * Forwards a given <i>message</i> with a known <i>hash</i> through a <i>tunnel</i>. 132 * Forwards a given <i>message</i> with a known <i>hash</i> through a <i>tunnel</i>.
135 * 133 *
136 * @param tunnel Tunnel 134 * @param[in/out] tunnel Tunnel
137 * @param message Message 135 * @param[in] message Message
138 * @param hash Hash of message 136 * @param[in] hash Hash of message
139 */ 137 */
140void 138void
141forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, 139forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message,
@@ -146,10 +144,43 @@ forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct
146 * and matching the tunnels peer identity. If no peer message has been linked to the tunnel 144 * and matching the tunnels peer identity. If no peer message has been linked to the tunnel
147 * yet, NULL gets returned. 145 * yet, NULL gets returned.
148 * 146 *
149 * @param tunnel Tunnel 147 * @param[in] tunnel Tunnel
150 * @return Hash of peer message or NULL 148 * @return Hash of peer message or NULL
151 */ 149 */
152const struct GNUNET_HashCode* 150const struct GNUNET_HashCode*
153get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel); 151get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
154 152
153/**
154 * Writes the peer identity of the peer connected via <i>tunnel</i> to this peer into
155 * the <i>peer</i> parameter.
156 *
157 * @param[in] tunnel Tunnel
158 * @param[out] peer Peer identity
159 */
160void
161get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_PeerIdentity *peer);
162
163/**
164 * Returns the current messenger version the peer connected via a given <i>tunnel</i>
165 * has reported to be using if it was compatible during updating.
166 *
167 * @see update_tunnel_messenger_version
168 *
169 * @param[in] tunnel Tunnel
170 * @return Version of messenger
171 */
172uint32_t
173get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
174
175/**
176 * Updates the messenger version of the <i>tunnel</i> to a given <i>version</i> if
177 * it is compatible to the running peer of the service. Depending on success it
178 * returns #GNUNET_OK or #GNUNET_SYSERR on failure.
179 *
180 * @param[in/out] tunnel Tunnel
181 * @param[in] version Version of messenger
182 */
183int
184update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel, uint32_t version);
185
155#endif //GNUNET_SERVICE_MESSENGER_TUNNEL_H 186#endif //GNUNET_SERVICE_MESSENGER_TUNNEL_H
diff --git a/src/messenger/messenger_api.c b/src/messenger/messenger_api.c
index 6401b18d7..b42bb40cc 100644
--- a/src/messenger/messenger_api.c
+++ b/src/messenger/messenger_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) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -29,6 +29,7 @@
29 29
30#include "messenger_api_handle.h" 30#include "messenger_api_handle.h"
31#include "messenger_api_message.h" 31#include "messenger_api_message.h"
32#include "messenger_api_util.h"
32 33
33const char* 34const char*
34GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind) 35GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
@@ -61,6 +62,8 @@ GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
61 return "TEXT"; 62 return "TEXT";
62 case GNUNET_MESSENGER_KIND_FILE: 63 case GNUNET_MESSENGER_KIND_FILE:
63 return "FILE"; 64 return "FILE";
65 case GNUNET_MESSENGER_KIND_PRIVATE:
66 return "PRIVATE";
64 default: 67 default:
65 return "UNKNOWN"; 68 return "UNKNOWN";
66 } 69 }
@@ -82,7 +85,25 @@ handle_get_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg)
82 85
83 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name); 86 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name);
84 87
85 set_handle_name (handle, strlen(name) > 0? name : NULL); 88 set_handle_name (handle, strlen (name) > 0 ? name : NULL);
89}
90
91static int
92check_get_key (void *cls, const struct GNUNET_MESSENGER_KeyMessage *msg)
93{
94 const uint16_t full_length = ntohs (msg->header.size);
95
96 if (full_length < sizeof(*msg))
97 return GNUNET_NO;
98
99 const uint16_t length = full_length - sizeof(*msg);
100 const char *buffer = ((const char*) msg) + sizeof(*msg);
101
102 struct GNUNET_IDENTITY_PublicKey pubkey;
103 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
104 return GNUNET_NO;
105
106 return GNUNET_OK;
86} 107}
87 108
88static void 109static void
@@ -90,11 +111,18 @@ handle_get_key (void *cls, const struct GNUNET_MESSENGER_KeyMessage *msg)
90{ 111{
91 struct GNUNET_MESSENGER_Handle *handle = cls; 112 struct GNUNET_MESSENGER_Handle *handle = cls;
92 113
93 const struct GNUNET_IDENTITY_PublicKey *pubkey = &(msg->pubkey); 114 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
115 const char *buffer = ((const char*) msg) + sizeof(*msg);
116
117 struct GNUNET_IDENTITY_PublicKey pubkey;
118 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
119 return;
94 120
95 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", GNUNET_IDENTITY_public_key_to_string (pubkey)); 121 char* str = GNUNET_IDENTITY_public_key_to_string (&pubkey);
122 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", str);
123 GNUNET_free(str);
96 124
97 set_handle_key (handle, pubkey); 125 set_handle_key (handle, &pubkey);
98 126
99 if (handle->identity_callback) 127 if (handle->identity_callback)
100 handle->identity_callback (handle->identity_cls, handle); 128 handle->identity_callback (handle->identity_cls, handle);
@@ -161,20 +189,20 @@ handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
161static int 189static int
162check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) 190check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
163{ 191{
164 const uint16_t full_length = ntohs (msg->header.size) - sizeof(msg->header); 192 const uint16_t full_length = ntohs (msg->header.size);
165 193
166 if (full_length < sizeof(msg->hash)) 194 if (full_length < sizeof(*msg))
167 return GNUNET_NO; 195 return GNUNET_NO;
168 196
169 const uint16_t length = full_length - sizeof(msg->hash); 197 const uint16_t length = full_length - sizeof(*msg);
170 const char *buffer = ((const char*) msg) + sizeof(*msg); 198 const char *buffer = ((const char*) msg) + sizeof(*msg);
171 199
172 struct GNUNET_MESSENGER_Message message; 200 struct GNUNET_MESSENGER_Message message;
173 201
174 if (length < sizeof(message.header)) 202 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
175 return GNUNET_NO; 203 return GNUNET_NO;
176 204
177 if (GNUNET_YES != decode_message (&message, length, buffer)) 205 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
178 return GNUNET_NO; 206 return GNUNET_NO;
179 207
180 return GNUNET_OK; 208 return GNUNET_OK;
@@ -186,14 +214,18 @@ handle_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
186 struct GNUNET_MESSENGER_Handle *handle = cls; 214 struct GNUNET_MESSENGER_Handle *handle = cls;
187 215
188 const struct GNUNET_HashCode *key = &(msg->key); 216 const struct GNUNET_HashCode *key = &(msg->key);
217 const struct GNUNET_HashCode *sender = &(msg->sender);
218 const struct GNUNET_HashCode *context = &(msg->context);
189 const struct GNUNET_HashCode *hash = &(msg->hash); 219 const struct GNUNET_HashCode *hash = &(msg->hash);
190 220 const enum GNUNET_MESSENGER_MessageFlags flags = (
191 const char *buffer = ((const char*) msg) + sizeof(*msg); 221 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
222 );
192 223
193 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg); 224 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
225 const char *buffer = ((const char*) msg) + sizeof(*msg);
194 226
195 struct GNUNET_MESSENGER_Message message; 227 struct GNUNET_MESSENGER_Message message;
196 decode_message (&message, length, buffer); 228 decode_message (&message, length, buffer, GNUNET_YES, NULL);
197 229
198 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind)); 230 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind));
199 231
@@ -201,13 +233,22 @@ handle_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
201 233
202 if (room) 234 if (room)
203 { 235 {
204 handle_room_message (room, &message, hash); 236 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(handle);
237
238 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: (%s : %s)\n",
239 GNUNET_h2s(sender), GNUNET_h2s_full(context));
240
241 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw(
242 store, context, sender
243 );
244
245 handle_room_message (room, contact, &message, hash);
205 246
206 if (handle->msg_callback) 247 if (handle->msg_callback)
207 handle->msg_callback (handle->msg_cls, room, &message, hash); 248 handle->msg_callback (handle->msg_cls, room, contact, &message, hash, flags);
208 } 249 }
209 else 250 else
210 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESSENGER ERROR: Room not found\n"); 251 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found\n");
211} 252}
212 253
213static void 254static void
@@ -220,12 +261,12 @@ send_open_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_
220 struct GNUNET_MQ_Envelope *env; 261 struct GNUNET_MQ_Envelope *env;
221 262
222 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN); 263 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
223 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 264 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
224 GNUNET_MQ_send (handle->mq, env); 265 GNUNET_MQ_send (handle->mq, env);
225} 266}
226 267
227static void 268static void
228send_entry_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room, 269send_enter_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room,
229 const struct GNUNET_PeerIdentity *door) 270 const struct GNUNET_PeerIdentity *door)
230{ 271{
231 struct GNUNET_MESSENGER_RoomMessage *msg; 272 struct GNUNET_MESSENGER_RoomMessage *msg;
@@ -233,7 +274,7 @@ send_entry_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER
233 274
234 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY); 275 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
235 GNUNET_memcpy(&(msg->door), door, sizeof(*door)); 276 GNUNET_memcpy(&(msg->door), door, sizeof(*door));
236 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 277 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
237 GNUNET_MQ_send (handle->mq, env); 278 GNUNET_MQ_send (handle->mq, env);
238} 279}
239 280
@@ -244,7 +285,7 @@ send_close_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER
244 struct GNUNET_MQ_Envelope *env; 285 struct GNUNET_MQ_Envelope *env;
245 286
246 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE); 287 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
247 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 288 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
248 GNUNET_MQ_send (handle->mq, env); 289 GNUNET_MQ_send (handle->mq, env);
249} 290}
250 291
@@ -265,7 +306,7 @@ iterate_reset_room (void *cls, const struct GNUNET_HashCode *key, void *value)
265 { 306 {
266 GNUNET_PEER_resolve (entry->peer, &door); 307 GNUNET_PEER_resolve (entry->peer, &door);
267 308
268 send_entry_room (handle, room, &door); 309 send_enter_room (handle, room, &door);
269 310
270 entry = entry->next; 311 entry = entry->next;
271 } 312 }
@@ -303,7 +344,7 @@ callback_mq_error (void *cls, enum GNUNET_MQ_Error error)
303{ 344{
304 struct GNUNET_MESSENGER_Handle *handle = cls; 345 struct GNUNET_MESSENGER_Handle *handle = cls;
305 346
306 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error); 347 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error);
307 348
308 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle); 349 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle);
309 350
@@ -319,36 +360,45 @@ callback_mq_error (void *cls, enum GNUNET_MQ_Error error)
319static void 360static void
320reconnect (struct GNUNET_MESSENGER_Handle *handle) 361reconnect (struct GNUNET_MESSENGER_Handle *handle)
321{ 362{
322 const struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size( 363 const struct GNUNET_MQ_MessageHandler handlers[] =
323 get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME, struct GNUNET_MESSENGER_NameMessage, handle), 364 {
324 GNUNET_MQ_hd_fixed_size( 365 GNUNET_MQ_hd_var_size(
325 get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY, 366 get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME,
326 struct GNUNET_MESSENGER_KeyMessage, handle), 367 struct GNUNET_MESSENGER_NameMessage, handle
327 GNUNET_MQ_hd_fixed_size( 368 ),
328 member_id, 369 GNUNET_MQ_hd_var_size(
329 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID, 370 get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY,
330 struct GNUNET_MESSENGER_MemberMessage, handle), 371 struct GNUNET_MESSENGER_KeyMessage, handle
331 GNUNET_MQ_hd_fixed_size(room_open, 372 ),
332 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN, 373 GNUNET_MQ_hd_fixed_size(
333 struct GNUNET_MESSENGER_RoomMessage, 374 member_id,
334 handle), 375 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
335 GNUNET_MQ_hd_fixed_size(room_entry, 376 struct GNUNET_MESSENGER_MemberMessage, handle
336 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, 377 ),
337 struct GNUNET_MESSENGER_RoomMessage, 378 GNUNET_MQ_hd_fixed_size(
338 handle), 379 room_open,
339 GNUNET_MQ_hd_fixed_size(room_close, 380 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
340 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, 381 struct GNUNET_MESSENGER_RoomMessage, handle
341 struct GNUNET_MESSENGER_RoomMessage, 382 ),
342 handle), 383 GNUNET_MQ_hd_fixed_size(
343 GNUNET_MQ_hd_var_size( 384 room_entry,
344 recv_message, 385 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
345 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE, 386 struct GNUNET_MESSENGER_RoomMessage, handle
346 struct GNUNET_MESSENGER_RecvMessage, handle), 387 ),
347 GNUNET_MQ_handler_end() }; 388 GNUNET_MQ_hd_fixed_size(
348 389 room_close,
349 handle->mq = GNUNET_CLIENT_connect (handle->cfg, 390 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
350 GNUNET_MESSENGER_SERVICE_NAME, 391 struct GNUNET_MESSENGER_RoomMessage, handle
351 handlers, &callback_mq_error, handle); 392 ),
393 GNUNET_MQ_hd_var_size(
394 recv_message,
395 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
396 struct GNUNET_MESSENGER_RecvMessage, handle
397 ),
398 GNUNET_MQ_handler_end()
399 };
400
401 handle->mq = GNUNET_CLIENT_connect (handle->cfg, GNUNET_MESSENGER_SERVICE_NAME, handlers, &callback_mq_error, handle);
352} 402}
353 403
354struct GNUNET_MESSENGER_Handle* 404struct GNUNET_MESSENGER_Handle*
@@ -389,7 +439,7 @@ GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const c
389int 439int
390GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle) 440GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle)
391{ 441{
392 if ((!handle) || (!get_handle_name(handle))) 442 if ((!handle) || (!get_handle_name (handle)))
393 return GNUNET_SYSERR; 443 return GNUNET_SYSERR;
394 444
395 struct GNUNET_MESSENGER_UpdateMessage *msg; 445 struct GNUNET_MESSENGER_UpdateMessage *msg;
@@ -448,18 +498,30 @@ GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *n
448 return GNUNET_YES; 498 return GNUNET_YES;
449} 499}
450 500
501static const struct GNUNET_IDENTITY_PublicKey*
502get_non_anonymous_key (const struct GNUNET_IDENTITY_PublicKey* public_key)
503{
504 if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key()))
505 return NULL;
506
507 return public_key;
508}
509
451const struct GNUNET_IDENTITY_PublicKey* 510const struct GNUNET_IDENTITY_PublicKey*
452GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle) 511GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle)
453{ 512{
454 if (!handle) 513 if (!handle)
455 return NULL; 514 return NULL;
456 515
457 return get_handle_key (handle); 516 return get_non_anonymous_key (get_handle_key (handle));
458} 517}
459 518
460struct GNUNET_MESSENGER_Room* 519struct GNUNET_MESSENGER_Room*
461GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 520GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
462{ 521{
522 if ((!handle) || (!key))
523 return NULL;
524
463 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 525 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
464 526
465 if (!room) 527 if (!room)
@@ -479,9 +541,12 @@ GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct
479} 541}
480 542
481struct GNUNET_MESSENGER_Room* 543struct GNUNET_MESSENGER_Room*
482GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, 544GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
483 const struct GNUNET_HashCode *key) 545 const struct GNUNET_HashCode *key)
484{ 546{
547 if ((!handle) || (!door) || (!key))
548 return NULL;
549
485 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 550 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
486 551
487 if (!room) 552 if (!room)
@@ -496,20 +561,26 @@ GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struc
496 } 561 }
497 } 562 }
498 563
499 send_entry_room (handle, room, door); 564 send_enter_room (handle, room, door);
500 return room; 565 return room;
501} 566}
502 567
503void 568void
504GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room) 569GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room)
505{ 570{
571 if (!room)
572 return;
573
506 send_close_room (room->handle, room); 574 send_close_room (room->handle, room);
507} 575}
508 576
509struct GNUNET_MESSENGER_Contact* 577struct GNUNET_MESSENGER_Contact*
510GNUNET_MESSENGER_get_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id) 578GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
511{ 579{
512 return GNUNET_CONTAINER_multishortmap_get (room->members, id); 580 if ((!room) || (!hash))
581 return NULL;
582
583 return get_room_sender(room, hash);
513} 584}
514 585
515const char* 586const char*
@@ -527,23 +598,73 @@ GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact
527 if (!contact) 598 if (!contact)
528 return NULL; 599 return NULL;
529 600
530 return get_contact_key (contact); 601 return get_non_anonymous_key (get_contact_key (contact));
531} 602}
532 603
533void 604void
534GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message) 605GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
606 const struct GNUNET_MESSENGER_Contact *contact)
535{ 607{
536 const uint16_t length = get_message_size (message); 608 if ((!room) || (!message))
609 return;
610
611 switch (filter_message_sending (message))
612 {
613 case GNUNET_SYSERR:
614 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message aborted: This kind of message is reserved for the service!\n");
615 return;
616 case GNUNET_NO:
617 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: This kind of message could cause issues!\n");
618 return;
619 default:
620 break;
621 }
622
623 ssize_t key_length = 0;
624
625 if (contact)
626 {
627 const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key (
628 get_contact_key(contact)
629 );
630
631 if (public_key)
632 key_length = GNUNET_IDENTITY_key_get_length(public_key);
633 else
634 key_length = -1;
635 }
636
637 if (key_length < 0)
638 {
639 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid key!\n");
640 return;
641 }
642
643 const uint16_t msg_length = get_message_size (message, GNUNET_NO);
537 644
538 struct GNUNET_MESSENGER_SendMessage *msg; 645 struct GNUNET_MESSENGER_SendMessage *msg;
539 struct GNUNET_MQ_Envelope *env; 646 struct GNUNET_MQ_Envelope *env;
540 647
541 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE); 648 const uint16_t length = (uint16_t) key_length + msg_length;
649
650 env = GNUNET_MQ_msg_extra(
651 msg, length,
652 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
653 );
542 654
543 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 655 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
656
657 msg->flags = (uint32_t) (
658 contact? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
659 );
544 660
545 char *buffer = ((char*) msg) + sizeof(*msg); 661 char *buffer = ((char*) msg) + sizeof(*msg);
546 encode_message (message, length, buffer); 662 char *msg_buffer = buffer + key_length;
663
664 if (key_length > 0)
665 GNUNET_IDENTITY_write_key_to_buffer(get_contact_key(contact), buffer, key_length);
666
667 encode_message (message, msg_length, msg_buffer, GNUNET_NO);
547 668
548 GNUNET_MQ_send (room->handle->mq, env); 669 GNUNET_MQ_send (room->handle->mq, env);
549} 670}
@@ -551,18 +672,31 @@ GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct
551const struct GNUNET_MESSENGER_Message* 672const struct GNUNET_MESSENGER_Message*
552GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) 673GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
553{ 674{
675 if ((!room) || (!hash))
676 return NULL;
677
554 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash); 678 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash);
555 679
556 if (!message) 680 if (!message)
557 { 681 {
558 struct GNUNET_MESSENGER_RecvMessage *msg; 682 struct GNUNET_MESSENGER_GetMessage *msg;
559 struct GNUNET_MQ_Envelope *env; 683 struct GNUNET_MQ_Envelope *env;
560 684
561 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE); 685 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
562 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 686 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
563 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash)); 687 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
564 GNUNET_MQ_send (room->handle->mq, env); 688 GNUNET_MQ_send (room->handle->mq, env);
565 } 689 }
566 690
567 return message; 691 return message;
568} 692}
693
694int
695GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
696 void* cls)
697{
698 if (!room)
699 return GNUNET_SYSERR;
700
701 return iterate_room_members(room, callback, cls);
702}
diff --git a/src/messenger/messenger_api_contact.c b/src/messenger/messenger_api_contact.c
index 9a242aa00..04e1f60c1 100644
--- a/src/messenger/messenger_api_contact.c
+++ b/src/messenger/messenger_api_contact.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -28,9 +28,12 @@
28struct GNUNET_MESSENGER_Contact* 28struct GNUNET_MESSENGER_Contact*
29create_contact (const struct GNUNET_IDENTITY_PublicKey *key) 29create_contact (const struct GNUNET_IDENTITY_PublicKey *key)
30{ 30{
31 GNUNET_assert(key);
32
31 struct GNUNET_MESSENGER_Contact *contact = GNUNET_new(struct GNUNET_MESSENGER_Contact); 33 struct GNUNET_MESSENGER_Contact *contact = GNUNET_new(struct GNUNET_MESSENGER_Contact);
32 34
33 contact->name = NULL; 35 contact->name = NULL;
36 contact->rc = 0;
34 37
35 GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key)); 38 GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key));
36 39
@@ -40,6 +43,8 @@ create_contact (const struct GNUNET_IDENTITY_PublicKey *key)
40void 43void
41destroy_contact (struct GNUNET_MESSENGER_Contact *contact) 44destroy_contact (struct GNUNET_MESSENGER_Contact *contact)
42{ 45{
46 GNUNET_assert(contact);
47
43 if (contact->name) 48 if (contact->name)
44 GNUNET_free(contact->name); 49 GNUNET_free(contact->name);
45 50
@@ -49,30 +54,55 @@ destroy_contact (struct GNUNET_MESSENGER_Contact *contact)
49const char* 54const char*
50get_contact_name (const struct GNUNET_MESSENGER_Contact *contact) 55get_contact_name (const struct GNUNET_MESSENGER_Contact *contact)
51{ 56{
57 GNUNET_assert(contact);
58
52 return contact->name; 59 return contact->name;
53} 60}
54 61
55void 62void
56set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name) 63set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name)
57{ 64{
65 GNUNET_assert(contact);
66
58 if (contact->name) 67 if (contact->name)
59 GNUNET_free(contact->name); 68 GNUNET_free(contact->name);
60 69
61 contact->name = name? GNUNET_strdup(name) : NULL; 70 contact->name = name ? GNUNET_strdup(name) : NULL;
62} 71}
63 72
64const struct GNUNET_IDENTITY_PublicKey* 73const struct GNUNET_IDENTITY_PublicKey*
65get_contact_key (const struct GNUNET_MESSENGER_Contact *contact) 74get_contact_key (const struct GNUNET_MESSENGER_Contact *contact)
66{ 75{
76 GNUNET_assert(contact);
77
67 return &(contact->public_key); 78 return &(contact->public_key);
68} 79}
69 80
70const struct GNUNET_HashCode* 81void
71get_contact_id_from_key (const struct GNUNET_MESSENGER_Contact *contact) 82increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
72{ 83{
73 static struct GNUNET_HashCode id; 84 GNUNET_assert(contact);
85
86 contact->rc++;
87}
74 88
75 GNUNET_CRYPTO_hash (&(contact->public_key), sizeof(contact->public_key), &id); 89int
90decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
91{
92 GNUNET_assert(contact);
93
94 if (contact->rc > 0)
95 contact->rc--;
96
97 return contact->rc ? GNUNET_NO : GNUNET_YES;
98}
99
100void
101get_context_from_member (const struct GNUNET_HashCode *key, const struct GNUNET_ShortHashCode *id,
102 struct GNUNET_HashCode *context)
103{
104 GNUNET_assert((key) && (id) && (context));
76 105
77 return &id; 106 GNUNET_CRYPTO_hash (id, sizeof(*id), context);
107 GNUNET_CRYPTO_hash_xor (key, context, context);
78} 108}
diff --git a/src/messenger/messenger_api_contact.h b/src/messenger/messenger_api_contact.h
index 0673b9b85..e94d1fcd0 100644
--- a/src/messenger/messenger_api_contact.h
+++ b/src/messenger/messenger_api_contact.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -33,6 +33,7 @@
33struct GNUNET_MESSENGER_Contact 33struct GNUNET_MESSENGER_Contact
34{ 34{
35 char *name; 35 char *name;
36 size_t rc;
36 37
37 struct GNUNET_IDENTITY_PublicKey public_key; 38 struct GNUNET_IDENTITY_PublicKey public_key;
38}; 39};
@@ -40,7 +41,7 @@ struct GNUNET_MESSENGER_Contact
40/** 41/**
41 * Creates and allocates a new contact with a given public <i>key</i> from an EGO. 42 * Creates and allocates a new contact with a given public <i>key</i> from an EGO.
42 * 43 *
43 * @param key Public key 44 * @param[in] key Public key
44 * @return New contact 45 * @return New contact
45 */ 46 */
46struct GNUNET_MESSENGER_Contact* 47struct GNUNET_MESSENGER_Contact*
@@ -49,7 +50,7 @@ create_contact (const struct GNUNET_IDENTITY_PublicKey *key);
49/** 50/**
50 * Destroys a contact and frees its memory fully. 51 * Destroys a contact and frees its memory fully.
51 * 52 *
52 * @param contact Contact 53 * @param[in/out] contact Contact
53 */ 54 */
54void 55void
55destroy_contact (struct GNUNET_MESSENGER_Contact *contact); 56destroy_contact (struct GNUNET_MESSENGER_Contact *contact);
@@ -57,7 +58,7 @@ destroy_contact (struct GNUNET_MESSENGER_Contact *contact);
57/** 58/**
58 * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet. 59 * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet.
59 * 60 *
60 * @param contact Contact 61 * @param[in] contact Contact
61 * @return Name of the contact or NULL 62 * @return Name of the contact or NULL
62 */ 63 */
63const char* 64const char*
@@ -66,8 +67,8 @@ get_contact_name (const struct GNUNET_MESSENGER_Contact *contact);
66/** 67/**
67 * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>. 68 * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>.
68 * 69 *
69 * @param contact Contact 70 * @param[in/out] contact Contact
70 * @param name Valid name (may not be NULL!) 71 * @param[in] name Name
71 */ 72 */
72void 73void
73set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name); 74set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name);
@@ -75,19 +76,39 @@ set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name);
75/** 76/**
76 * Returns the public key of a given <i>contact</i>. 77 * Returns the public key of a given <i>contact</i>.
77 * 78 *
78 * @param contact Contact 79 * @param[in] contact Contact
79 * @return Public key of the contact 80 * @return Public key of the contact
80 */ 81 */
81const struct GNUNET_IDENTITY_PublicKey* 82const struct GNUNET_IDENTITY_PublicKey*
82get_contact_key (const struct GNUNET_MESSENGER_Contact *contact); 83get_contact_key (const struct GNUNET_MESSENGER_Contact *contact);
83 84
84/** 85/**
85 * Returns the resulting hashcode of the public key from a given <i>contact</i>. 86 * Increases the reference counter of a given <i>contact</i> which is zero as default.
86 * 87 *
87 * @param contact Contact 88 * @param[in/out] contact Contact
88 * @return Hash of the contacts public key
89 */ 89 */
90const struct GNUNET_HashCode* 90void
91get_contact_id_from_key (const struct GNUNET_MESSENGER_Contact *contact); 91increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact);
92
93/**
94 * Decreases the reference counter if possible (can not underflow!) of a given <i>contact</i>
95 * and returns #GNUNET_YES if the counter is equal to zero, otherwise #GNUNET_NO.
96 *
97 * @param[in/out] contact Contact
98 * @return #GNUNET_YES or #GNUNET_NO depending on the reference counter
99 */
100int
101decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact);
102
103/**
104 * Calculates the context <i>hash</i> of a member in a room and returns it.
105 *
106 * @param[in] key Key of room
107 * @param[in] id Member id
108 * @param[out] hash Member context
109 */
110void
111get_context_from_member (const struct GNUNET_HashCode *key, const struct GNUNET_ShortHashCode *id,
112 struct GNUNET_HashCode *context);
92 113
93#endif //GNUNET_MESSENGER_API_CONTACT_H 114#endif //GNUNET_MESSENGER_API_CONTACT_H
diff --git a/src/messenger/messenger_api_contact_store.c b/src/messenger/messenger_api_contact_store.c
new file mode 100755
index 000000000..6a517c2e0
--- /dev/null
+++ b/src/messenger/messenger_api_contact_store.c
@@ -0,0 +1,185 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/messenger_api_contact_store.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_contact_store.h"
27
28#include "messenger_api_contact.h"
29#include "messenger_api_util.h"
30
31void
32init_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
33{
34 GNUNET_assert (store);
35
36 store->anonymous = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
37 store->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38}
39
40static int
41iterate_destroy_contacts (void *cls, const struct GNUNET_HashCode *key, void *value)
42{
43 struct GNUNET_MESSENGER_Contact *contact = value;
44 destroy_contact (contact);
45 return GNUNET_YES;
46}
47
48void
49clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
50{
51 GNUNET_assert ((store) && (store->contacts));
52
53 GNUNET_CONTAINER_multihashmap_iterate (store->anonymous, iterate_destroy_contacts, NULL);
54 GNUNET_CONTAINER_multihashmap_iterate (store->contacts, iterate_destroy_contacts, NULL);
55
56 GNUNET_CONTAINER_multihashmap_destroy (store->anonymous);
57 GNUNET_CONTAINER_multihashmap_destroy (store->contacts);
58}
59
60static struct GNUNET_CONTAINER_MultiHashMap*
61select_store_contact_map (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
62 struct GNUNET_HashCode *hash)
63{
64 const struct GNUNET_IDENTITY_PublicKey *anonymous = get_anonymous_public_key ();
65
66 struct GNUNET_HashCode anonHash;
67 GNUNET_CRYPTO_hash (anonymous, sizeof(*anonymous), &anonHash);
68
69 if ((context) && (0 == GNUNET_CRYPTO_hash_cmp(hash, &anonHash)))
70 {
71 GNUNET_memcpy(hash, context, sizeof(*context));
72 return store->anonymous;
73 }
74 else
75 return store->contacts;
76}
77
78struct GNUNET_MESSENGER_Contact*
79get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
80 const struct GNUNET_HashCode *key_hash)
81{
82 GNUNET_assert ((store) && (store->contacts) && (context) && (key_hash));
83
84 struct GNUNET_HashCode hash;
85 GNUNET_memcpy(&hash, key_hash, sizeof(*key_hash));
86
87 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
88 store, context, &hash
89 );
90
91 return GNUNET_CONTAINER_multihashmap_get (map, &hash);
92}
93
94struct GNUNET_MESSENGER_Contact*
95get_store_contact (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
96 const struct GNUNET_IDENTITY_PublicKey *pubkey)
97{
98 GNUNET_assert ((store) && (store->contacts) && (context) && (pubkey));
99
100 struct GNUNET_HashCode hash;
101 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
102
103 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
104 store, context, &hash
105 );
106
107 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (map, &hash);
108
109 if (contact)
110 {
111 if (0 != GNUNET_memcmp(pubkey, get_contact_key(contact)))
112 {
113 char* str = GNUNET_IDENTITY_public_key_to_string (get_contact_key(contact));
114 GNUNET_log (GNUNET_ERROR_TYPE_INVALID, "Contact in store uses wrong key: %s\n", str);
115 GNUNET_free (str);
116 return NULL;
117 }
118
119 return contact;
120 }
121
122 contact = create_contact (pubkey);
123
124 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
126 return contact;
127
128 destroy_contact (contact);
129 return NULL;
130}
131
132void
133update_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
134 const struct GNUNET_HashCode *context, const struct GNUNET_HashCode *next_context,
135 const struct GNUNET_IDENTITY_PublicKey *pubkey)
136{
137 GNUNET_assert ((store) && (store->contacts) && (contact) && (pubkey));
138
139 const struct GNUNET_IDENTITY_PublicKey* oldkey = get_contact_key (contact);
140
141 struct GNUNET_HashCode hash;
142 GNUNET_CRYPTO_hash (oldkey, sizeof(*oldkey), &hash);
143
144 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
145 store, context, &hash
146 );
147
148 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
149 {
150 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
151
152 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
153
154 map = select_store_contact_map (
155 store, next_context, &hash
156 );
157
158 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
159 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
160 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating a contact failed: %s\n",
161 GNUNET_h2s(&hash));
162 }
163}
164
165void
166remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
167 const struct GNUNET_HashCode *context)
168{
169 GNUNET_assert ((store) && (store->contacts) && (contact));
170
171 const struct GNUNET_IDENTITY_PublicKey* pubkey = get_contact_key(contact);
172
173 struct GNUNET_HashCode hash;
174 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
175
176 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
177 store, context, &hash
178 );
179
180 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
181 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a contact failed: %s\n",
182 GNUNET_h2s(&hash));
183
184 destroy_contact (contact);
185}
diff --git a/src/messenger/messenger_api_contact_store.h b/src/messenger/messenger_api_contact_store.h
new file mode 100644
index 000000000..966f6d962
--- /dev/null
+++ b/src/messenger/messenger_api_contact_store.h
@@ -0,0 +1,122 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/messenger_api_contact_store.h
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_CONTACT_STORE_H
27#define GNUNET_MESSENGER_API_CONTACT_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_identity_service.h"
33
34struct GNUNET_MESSENGER_Contact;
35
36struct GNUNET_MESSENGER_ContactStore
37{
38 struct GNUNET_CONTAINER_MultiHashMap *anonymous;
39 struct GNUNET_CONTAINER_MultiHashMap *contacts;
40};
41
42/**
43 * Initializes a contact store as fully empty.
44 *
45 * @param[out] store Contact store
46 */
47void
48init_contact_store (struct GNUNET_MESSENGER_ContactStore *store);
49
50/**
51 * Clears a contact store, wipes its content and deallocates its memory.
52 *
53 * @param[in/out] store Contact store
54 */
55void
56clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store);
57
58/**
59 * Returns a contact using the hash of a specific public key. In case the anonymous
60 * key gets used by the requested contact, it will use its provided member
61 * <i>context</i> to select the matching contact from the <i>store</i>.
62 *
63 * In case there is no contact stored which uses the given key or context,
64 * NULL gets returned.
65 *
66 * @param[in/out] store Contact store
67 * @param[in] context Member context
68 * @param[in] key_hash Hash of public key
69 */
70struct GNUNET_MESSENGER_Contact*
71get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
72 const struct GNUNET_HashCode *key_hash);
73
74/**
75 * Returns a contact using a specific public key. In case the anonymous
76 * key gets used by the requested contact, it will use its provided member
77 * <i>context</i> to select the matching contact from the <i>store</i>.
78 *
79 * In case there is no contact stored which uses the given key or context,
80 * a new contact will be created automatically.
81 *
82 * The function returns NULL if an error occures during allocation
83 * or validation of the contacts key.
84 *
85 * @param[in/out] store Contact store
86 * @param[in] context Member context
87 * @param[in] pubkey Public key of EGO
88 */
89struct GNUNET_MESSENGER_Contact*
90get_store_contact (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
91 const struct GNUNET_IDENTITY_PublicKey *pubkey);
92
93/**
94 * Moves a <i>contact</i> from the <i>store</i> to another location
95 * matching a given public key and member <i>context</i>.
96 *
97 * This function allows changes of keys or changes of member contexts!
98 *
99 * @param[in/out] store Contact store
100 * @param[in/out] contact Contact
101 * @param[in] context Member context
102 * @param[in] next_context Member context
103 * @param[in] pubkey Public key of EGO
104 */
105void
106update_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
107 const struct GNUNET_HashCode *context, const struct GNUNET_HashCode *next_context,
108 const struct GNUNET_IDENTITY_PublicKey *pubkey);
109
110/**
111 * Removes a <i>contact</i> from the <i>store</i> which uses
112 * a given member <i>context</i>.
113 *
114 * @param[in/out] store Contact store
115 * @param[in/out] contact Contact
116 * @param[in] context Member context
117 */
118void
119remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
120 const struct GNUNET_HashCode *context);
121
122#endif //GNUNET_MESSENGER_API_CONTACT_STORE_H
diff --git a/src/messenger/messenger_api_ego.h b/src/messenger/messenger_api_ego.h
index c60eeac50..b52b895f2 100644
--- a/src/messenger/messenger_api_ego.h
+++ b/src/messenger/messenger_api_ego.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
diff --git a/src/messenger/messenger_api_handle.c b/src/messenger/messenger_api_handle.c
index 20ef77254..ab57f82cc 100644
--- a/src/messenger/messenger_api_handle.c
+++ b/src/messenger/messenger_api_handle.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -25,10 +25,14 @@
25 25
26#include "messenger_api_handle.h" 26#include "messenger_api_handle.h"
27 27
28#include "messenger_api_util.h"
29
28struct GNUNET_MESSENGER_Handle* 30struct GNUNET_MESSENGER_Handle*
29create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback, 31create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback,
30 void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls) 32 void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls)
31{ 33{
34 GNUNET_assert(cfg);
35
32 struct GNUNET_MESSENGER_Handle *handle = GNUNET_new(struct GNUNET_MESSENGER_Handle); 36 struct GNUNET_MESSENGER_Handle *handle = GNUNET_new(struct GNUNET_MESSENGER_Handle);
33 37
34 handle->cfg = cfg; 38 handle->cfg = cfg;
@@ -47,7 +51,8 @@ create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_I
47 handle->reconnect_task = NULL; 51 handle->reconnect_task = NULL;
48 52
49 handle->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 53 handle->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
50 handle->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 54
55 init_contact_store(get_handle_contact_store(handle));
51 56
52 return handle; 57 return handle;
53} 58}
@@ -62,19 +67,11 @@ iterate_destroy_room (void *cls, const struct GNUNET_HashCode *key, void *value)
62 return GNUNET_YES; 67 return GNUNET_YES;
63} 68}
64 69
65static int
66iterate_destroy_contact (void *cls, const struct GNUNET_HashCode *key, void *value)
67{
68 struct GNUNET_MESSENGER_Contact *contact = value;
69
70 destroy_contact (contact);
71
72 return GNUNET_YES;
73}
74
75void 70void
76destroy_handle (struct GNUNET_MESSENGER_Handle *handle) 71destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
77{ 72{
73 GNUNET_assert(handle);
74
78 if (handle->reconnect_task) 75 if (handle->reconnect_task)
79 GNUNET_SCHEDULER_cancel (handle->reconnect_task); 76 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
80 77
@@ -94,12 +91,7 @@ destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
94 GNUNET_CONTAINER_multihashmap_destroy (handle->rooms); 91 GNUNET_CONTAINER_multihashmap_destroy (handle->rooms);
95 } 92 }
96 93
97 if (handle->contacts) 94 clear_contact_store(get_handle_contact_store(handle));
98 {
99 GNUNET_CONTAINER_multihashmap_iterate (handle->contacts, iterate_destroy_contact, NULL);
100
101 GNUNET_CONTAINER_multihashmap_destroy (handle->contacts);
102 }
103 95
104 GNUNET_free(handle->name); 96 GNUNET_free(handle->name);
105} 97}
@@ -107,21 +99,27 @@ destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
107void 99void
108set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name) 100set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name)
109{ 101{
102 GNUNET_assert(handle);
103
110 if (handle->name) 104 if (handle->name)
111 GNUNET_free(handle->name); 105 GNUNET_free(handle->name);
112 106
113 handle->name = name? GNUNET_strdup(name) : NULL; 107 handle->name = name ? GNUNET_strdup(name) : NULL;
114} 108}
115 109
116const char* 110const char*
117get_handle_name (const struct GNUNET_MESSENGER_Handle *handle) 111get_handle_name (const struct GNUNET_MESSENGER_Handle *handle)
118{ 112{
113 GNUNET_assert(handle);
114
119 return handle->name; 115 return handle->name;
120} 116}
121 117
122void 118void
123set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey) 119set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey)
124{ 120{
121 GNUNET_assert(handle);
122
125 if (!handle->pubkey) 123 if (!handle->pubkey)
126 handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey); 124 handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey);
127 125
@@ -131,62 +129,43 @@ set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDEN
131const struct GNUNET_IDENTITY_PublicKey* 129const struct GNUNET_IDENTITY_PublicKey*
132get_handle_key (const struct GNUNET_MESSENGER_Handle *handle) 130get_handle_key (const struct GNUNET_MESSENGER_Handle *handle)
133{ 131{
134 if (!handle->pubkey) 132 GNUNET_assert(handle);
135 {
136 struct GNUNET_IDENTITY_Ego *anonymous = GNUNET_IDENTITY_ego_get_anonymous ();
137 static struct GNUNET_IDENTITY_PublicKey pubkey;
138 133
139 GNUNET_IDENTITY_ego_get_public_key (anonymous, &pubkey); 134 if (handle->pubkey)
140 135 return handle->pubkey;
141 return &pubkey;
142 }
143 136
144 return handle->pubkey; 137 return get_anonymous_public_key ();
145} 138}
146 139
147struct GNUNET_MESSENGER_Contact* 140struct GNUNET_MESSENGER_ContactStore*
148get_handle_contact_by_pubkey (const struct GNUNET_MESSENGER_Handle *handle, 141get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle)
149 const struct GNUNET_IDENTITY_PublicKey *pubkey)
150{ 142{
151 struct GNUNET_HashCode hash; 143 GNUNET_assert(handle);
152
153 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
154
155 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (handle->contacts, &hash);
156
157 if (contact)
158 return contact;
159
160 contact = create_contact (pubkey);
161
162 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (handle->contacts, &hash, contact,
163 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
164 return contact;
165 144
166 destroy_contact (contact); 145 return &(handle->contact_store);
167 return NULL;
168} 146}
169 147
170void 148struct GNUNET_MESSENGER_Contact*
171swap_handle_contact_by_pubkey (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Contact *contact, 149get_handle_contact (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
172 const struct GNUNET_IDENTITY_PublicKey *pubkey)
173{ 150{
174 const struct GNUNET_HashCode *hash = get_contact_id_from_key (contact); 151 GNUNET_assert((handle) && (key));
175 152
176 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->contacts, hash, contact)) 153 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
177 {
178 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
179 154
180 hash = get_contact_id_from_key (contact); 155 if ((!room) || (!(room->contact_id)))
156 return NULL;
181 157
182 GNUNET_CONTAINER_multihashmap_put (handle->contacts, hash, contact, 158 struct GNUNET_HashCode context;
183 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 159 get_context_from_member (key, room->contact_id, &context);
184 } 160
161 return get_store_contact(get_handle_contact_store(handle), &context, get_handle_key(handle));
185} 162}
186 163
187void 164void
188open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 165open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
189{ 166{
167 GNUNET_assert((handle) && (key));
168
190 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 169 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
191 170
192 if (room) 171 if (room)
@@ -197,6 +176,8 @@ void
197entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, 176entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
198 const struct GNUNET_HashCode *key) 177 const struct GNUNET_HashCode *key)
199{ 178{
179 GNUNET_assert((handle) && (door) && (key));
180
200 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 181 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
201 182
202 if (room) 183 if (room)
@@ -206,6 +187,8 @@ entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNE
206void 187void
207close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 188close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
208{ 189{
190 GNUNET_assert((handle) && (key));
191
209 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 192 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
210 193
211 if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->rooms, key, room))) 194 if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->rooms, key, room)))
diff --git a/src/messenger/messenger_api_handle.h b/src/messenger/messenger_api_handle.h
index d6cde0106..e6ca474f2 100644
--- a/src/messenger/messenger_api_handle.h
+++ b/src/messenger/messenger_api_handle.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -35,7 +35,7 @@
35 35
36#include "gnunet_messenger_service.h" 36#include "gnunet_messenger_service.h"
37 37
38#include "messenger_api_contact.h" 38#include "messenger_api_contact_store.h"
39#include "messenger_api_room.h" 39#include "messenger_api_room.h"
40 40
41struct GNUNET_MESSENGER_Handle 41struct GNUNET_MESSENGER_Handle
@@ -56,17 +56,18 @@ struct GNUNET_MESSENGER_Handle
56 struct GNUNET_TIME_Relative reconnect_time; 56 struct GNUNET_TIME_Relative reconnect_time;
57 struct GNUNET_SCHEDULER_Task *reconnect_task; 57 struct GNUNET_SCHEDULER_Task *reconnect_task;
58 58
59 struct GNUNET_MESSENGER_ContactStore contact_store;
60
59 struct GNUNET_CONTAINER_MultiHashMap *rooms; 61 struct GNUNET_CONTAINER_MultiHashMap *rooms;
60 struct GNUNET_CONTAINER_MultiHashMap *contacts;
61}; 62};
62 63
63/** 64/**
64 * Creates and allocates a new handle using a given configuration and a custom message callback 65 * Creates and allocates a new handle using a given configuration and a custom message callback
65 * with a given closure for the client API. 66 * with a given closure for the client API.
66 * 67 *
67 * @param cfg Configuration 68 * @param[in] cfg Configuration
68 * @param msg_callback Message callback 69 * @param[in] msg_callback Message callback
69 * @param msg_cls Closure 70 * @param[in/out] msg_cls Closure
70 * @return New handle 71 * @return New handle
71 */ 72 */
72struct GNUNET_MESSENGER_Handle* 73struct GNUNET_MESSENGER_Handle*
@@ -76,7 +77,7 @@ create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_I
76/** 77/**
77 * Destroys a <i>handle</i> and frees its memory fully from the client API. 78 * Destroys a <i>handle</i> and frees its memory fully from the client API.
78 * 79 *
79 * @param handle Handle 80 * @param[in/out] handle Handle
80 */ 81 */
81void 82void
82destroy_handle (struct GNUNET_MESSENGER_Handle *handle); 83destroy_handle (struct GNUNET_MESSENGER_Handle *handle);
@@ -84,8 +85,8 @@ destroy_handle (struct GNUNET_MESSENGER_Handle *handle);
84/** 85/**
85 * Sets the name of a <i>handle</i> to a specific <i>name</i>. 86 * Sets the name of a <i>handle</i> to a specific <i>name</i>.
86 * 87 *
87 * @param handle Handle 88 * @param[in/out] handle Handle
88 * @param name New name 89 * @param[in] name New name
89 */ 90 */
90void 91void
91set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name); 92set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name);
@@ -93,7 +94,7 @@ set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name);
93/** 94/**
94 * Returns the current name of a given <i>handle</i> or NULL if no valid name was assigned yet. 95 * Returns the current name of a given <i>handle</i> or NULL if no valid name was assigned yet.
95 * 96 *
96 * @param handle Handle 97 * @param[in] handle Handle
97 * @return Name of the handle or NULL 98 * @return Name of the handle or NULL
98 */ 99 */
99const char* 100const char*
@@ -102,8 +103,8 @@ get_handle_name (const struct GNUNET_MESSENGER_Handle *handle);
102/** 103/**
103 * Sets the public key of a given <i>handle</i> to a specific public key. 104 * Sets the public key of a given <i>handle</i> to a specific public key.
104 * 105 *
105 * @param handle Handle 106 * @param[in/out] handle Handle
106 * @param pubkey Public key 107 * @param[in] pubkey Public key
107 */ 108 */
108void 109void
109set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey); 110set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey);
@@ -111,41 +112,37 @@ set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDEN
111/** 112/**
112 * Returns the public key of a given <i>handle</i>. 113 * Returns the public key of a given <i>handle</i>.
113 * 114 *
114 * @param handle Handle 115 * @param[in] handle Handle
115 * @return Public key of the handle 116 * @return Public key of the handle
116 */ 117 */
117const struct GNUNET_IDENTITY_PublicKey* 118const struct GNUNET_IDENTITY_PublicKey*
118get_handle_key (const struct GNUNET_MESSENGER_Handle *handle); 119get_handle_key (const struct GNUNET_MESSENGER_Handle *handle);
119 120
120/** 121/**
121 * Returns a contact known to a <i>handle</i> identified by a given public key. If not matching 122 * Returns the used contact store of a given <i>handle</i>.
122 * contact is found, NULL gets returned.
123 * 123 *
124 * @param handle Handle 124 * @param[in/out] handle Handle
125 * @param pubkey Public key of EGO 125 * @return Contact store
126 * @return Contact or NULL
127 */ 126 */
128struct GNUNET_MESSENGER_Contact* 127struct GNUNET_MESSENGER_ContactStore*
129get_handle_contact_by_pubkey (const struct GNUNET_MESSENGER_Handle *handle, 128get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle);
130 const struct GNUNET_IDENTITY_PublicKey *pubkey);
131 129
132/** 130/**
133 * Changes the public key for a <i>contact</i> known to a <i>handle</i> to a specific public key and 131 * Returns the contact of a given <i>handle</i> in a room identified by a
134 * updates local map entries to access the contact by its updated key. 132 * given <i>key</i>.
135 * 133 *
136 * @param handle Handle 134 * @param[in/out] handle Handle
137 * @param contact Contact 135 * @param[in] key Key of room
138 * @param pubkey Public key of EGO 136 * @return Contact
139 */ 137 */
140void 138struct GNUNET_MESSENGER_Contact*
141swap_handle_contact_by_pubkey (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Contact *contact, 139get_handle_contact (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
142 const struct GNUNET_IDENTITY_PublicKey *pubkey);
143 140
144/** 141/**
145 * Marks a room known to a <i>handle</i> identified by a given <i>key</i> as open. 142 * Marks a room known to a <i>handle</i> identified by a given <i>key</i> as open.
146 * 143 *
147 * @param handle Handle 144 * @param[in/out] handle Handle
148 * @param key Key of room 145 * @param[in] key Key of room
149 */ 146 */
150void 147void
151open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); 148open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
@@ -154,9 +151,9 @@ open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_Ha
154 * Adds a tunnel for a room known to a <i>handle</i> identified by a given <i>key</i> to a 151 * Adds a tunnel for a room known to a <i>handle</i> identified by a given <i>key</i> to a
155 * list of opened connections. 152 * list of opened connections.
156 * 153 *
157 * @param handle Handle 154 * @param[in/out] handle Handle
158 * @param door Peer identity 155 * @param[in] door Peer identity
159 * @param key Key of room 156 * @param[in] key Key of room
160 */ 157 */
161void 158void
162entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, 159entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
@@ -165,8 +162,8 @@ entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNE
165/** 162/**
166 * Destroys and so implicitly closes a room known to a <i>handle</i> identified by a given <i>key</i>. 163 * Destroys and so implicitly closes a room known to a <i>handle</i> identified by a given <i>key</i>.
167 * 164 *
168 * @param handle Handle 165 * @param[in/out] handle Handle
169 * @param key Key of room 166 * @param[in] key Key of room
170 */ 167 */
171void 168void
172close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); 169close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
diff --git a/src/messenger/messenger_api_list_tunnels.c b/src/messenger/messenger_api_list_tunnels.c
index 13d8c1906..990e36878 100644
--- a/src/messenger/messenger_api_list_tunnels.c
+++ b/src/messenger/messenger_api_list_tunnels.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -62,6 +62,8 @@ compare_list_tunnels (void *cls, struct GNUNET_MESSENGER_ListTunnel *element0,
62void 62void
63add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer) 63add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer)
64{ 64{
65 GNUNET_assert((tunnels) && (peer));
66
65 struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct GNUNET_MESSENGER_ListTunnel); 67 struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct GNUNET_MESSENGER_ListTunnel);
66 68
67 element->peer = GNUNET_PEER_intern (peer); 69 element->peer = GNUNET_PEER_intern (peer);
@@ -73,6 +75,8 @@ add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct
73struct GNUNET_MESSENGER_ListTunnel* 75struct GNUNET_MESSENGER_ListTunnel*
74find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index) 76find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index)
75{ 77{
78 GNUNET_assert((tunnels) && (peer));
79
76 struct GNUNET_MESSENGER_ListTunnel *element; 80 struct GNUNET_MESSENGER_ListTunnel *element;
77 struct GNUNET_PeerIdentity pid; 81 struct GNUNET_PeerIdentity pid;
78 82
@@ -96,12 +100,16 @@ find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GN
96int 100int
97contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer) 101contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer)
98{ 102{
103 GNUNET_assert((tunnels) && (peer));
104
99 return find_list_tunnels (tunnels, peer, NULL) != NULL ? GNUNET_YES : GNUNET_NO; 105 return find_list_tunnels (tunnels, peer, NULL) != NULL ? GNUNET_YES : GNUNET_NO;
100} 106}
101 107
102struct GNUNET_MESSENGER_ListTunnel* 108struct GNUNET_MESSENGER_ListTunnel*
103remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element) 109remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element)
104{ 110{
111 GNUNET_assert((tunnels) && (element));
112
105 struct GNUNET_MESSENGER_ListTunnel *next = element->next; 113 struct GNUNET_MESSENGER_ListTunnel *next = element->next;
106 114
107 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element); 115 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
@@ -110,3 +118,67 @@ remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct G
110 118
111 return next; 119 return next;
112} 120}
121
122void
123load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path)
124{
125 GNUNET_assert((tunnels) && (path));
126
127 if (GNUNET_YES != GNUNET_DISK_file_test (path))
128 return;
129
130 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
131
132 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
133 path, GNUNET_DISK_OPEN_READ, permission
134 );
135
136 if (!handle)
137 return;
138
139 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
140
141 struct GNUNET_PeerIdentity peer;
142 ssize_t len;
143
144 do {
145 len = GNUNET_DISK_file_read(handle, &peer, sizeof(peer));
146
147 if (len != sizeof(peer))
148 break;
149
150 add_to_list_tunnels(tunnels, &peer);
151 } while (len == sizeof(peer));
152
153 GNUNET_DISK_file_close(handle);
154}
155
156void
157save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path)
158{
159 GNUNET_assert((tunnels) && (path));
160
161 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
162
163 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
164 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
165 );
166
167 if (!handle)
168 return;
169
170 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
171
172 struct GNUNET_MESSENGER_ListTunnel *element;
173 struct GNUNET_PeerIdentity pid;
174
175 for (element = tunnels->head; element; element = element->next)
176 {
177 GNUNET_PEER_resolve (element->peer, &pid);
178
179 GNUNET_DISK_file_write(handle, &pid, sizeof(pid));
180 }
181
182 GNUNET_DISK_file_sync(handle);
183 GNUNET_DISK_file_close(handle);
184}
diff --git a/src/messenger/messenger_api_list_tunnels.h b/src/messenger/messenger_api_list_tunnels.h
index 0240fceb8..bd0a42e41 100644
--- a/src/messenger/messenger_api_list_tunnels.h
+++ b/src/messenger/messenger_api_list_tunnels.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -47,7 +47,7 @@ struct GNUNET_MESSENGER_ListTunnels
47/** 47/**
48 * Initializes list of tunnels peer identities as empty list. 48 * Initializes list of tunnels peer identities as empty list.
49 * 49 *
50 * @param tunnels List of peer identities 50 * @param[out] tunnels List of peer identities
51 */ 51 */
52void 52void
53init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels); 53init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
@@ -55,7 +55,7 @@ init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
55/** 55/**
56 * Clears the list of tunnels peer identities. 56 * Clears the list of tunnels peer identities.
57 * 57 *
58 * @param tunnels List of peer identities 58 * @param[in/out] tunnels List of peer identities
59 */ 59 */
60void 60void
61clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels); 61clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
@@ -63,8 +63,8 @@ clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
63/** 63/**
64 * Adds a specific <i>peer</i> from a tunnel to the end of the list. 64 * Adds a specific <i>peer</i> from a tunnel to the end of the list.
65 * 65 *
66 * @param tunnels List of peer identities 66 * @param[in/out] tunnels List of peer identities
67 * @param peer Peer identity of tunnel 67 * @param[in] peer Peer identity of tunnel
68 */ 68 */
69void 69void
70add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer); 70add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer);
@@ -79,8 +79,8 @@ add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct
79 * the found element in the list. If no matching element is found, <i>index</i> will 79 * the found element in the list. If no matching element is found, <i>index</i> will
80 * contain the total amount of elements in the list. 80 * contain the total amount of elements in the list.
81 * 81 *
82 * @param tunnels List of peer identities 82 * @param[in/out] tunnels List of peer identities
83 * @param peer Peer identity of tunnel 83 * @param[in] peer Peer identity of tunnel
84 * @param[out] index Index of found element (optional) 84 * @param[out] index Index of found element (optional)
85 * @return Element in the list with matching peer identity 85 * @return Element in the list with matching peer identity
86 */ 86 */
@@ -89,11 +89,11 @@ find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GN
89 89
90/** 90/**
91 * Tests linearly if the list of tunnels peer identities contains a specific 91 * Tests linearly if the list of tunnels peer identities contains a specific
92 * <i>peer</i> identity and returns GNUNET_YES on success, otherwise GNUNET_NO. 92 * <i>peer</i> identity and returns #GNUNET_YES on success, otherwise #GNUNET_NO.
93 * 93 *
94 * @param tunnels List of peer identities 94 * @param[in/out] tunnels List of peer identities
95 * @param peer Peer identity of tunnel 95 * @param[in] peer Peer identity of tunnel
96 * @return GNUNET_YES on success, otherwise GNUNET_NO 96 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
97 */ 97 */
98int 98int
99contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer); 99contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer);
@@ -102,11 +102,29 @@ contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struc
102 * Removes a specific <i>element</i> from the list of tunnels peer identities and returns 102 * Removes a specific <i>element</i> from the list of tunnels peer identities and returns
103 * the next element in the list. 103 * the next element in the list.
104 * 104 *
105 * @param tunnels List of peer identities 105 * @param[in/out] tunnels List of peer identities
106 * @param element Element of the list 106 * @param[in/out] element Element of the list
107 * @return Next element in the list 107 * @return Next element in the list
108 */ 108 */
109struct GNUNET_MESSENGER_ListTunnel* 109struct GNUNET_MESSENGER_ListTunnel*
110remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element); 110remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element);
111 111
112/**
113 * Loads the list of tunnels peer identities from a file under a given <i>path</i>.
114 *
115 * @param[out] messages List of hashes
116 * @param[in] path Path of file
117 */
118void
119load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path);
120
121/**
122 * Saves the list of tunnels peer identities to a file under a given <i>path</i>.
123 *
124 * @param[in] messages List of hashes
125 * @param[in] path Path of file
126 */
127void
128save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path);
129
112#endif //GNUNET_MESSENGER_API_LIST_TUNNELS_H 130#endif //GNUNET_MESSENGER_API_LIST_TUNNELS_H
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
index fdab60eef..d65b80576 100644..100755
--- a/src/messenger/messenger_api_message.c
+++ b/src/messenger/messenger_api_message.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -69,6 +69,8 @@ create_message (enum GNUNET_MESSENGER_MessageKind kind)
69struct GNUNET_MESSENGER_Message* 69struct GNUNET_MESSENGER_Message*
70copy_message (const struct GNUNET_MESSENGER_Message *message) 70copy_message (const struct GNUNET_MESSENGER_Message *message)
71{ 71{
72 GNUNET_assert(message);
73
72 struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message); 74 struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message);
73 75
74 GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message)); 76 GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message));
@@ -125,11 +127,28 @@ destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind, struct GNUNET_MESS
125void 127void
126destroy_message (struct GNUNET_MESSENGER_Message *message) 128destroy_message (struct GNUNET_MESSENGER_Message *message)
127{ 129{
130 GNUNET_assert(message);
131
128 destroy_message_body (message->header.kind, &(message->body)); 132 destroy_message_body (message->header.kind, &(message->body));
129 133
130 GNUNET_free(message); 134 GNUNET_free(message);
131} 135}
132 136
137int
138is_message_session_bound (const struct GNUNET_MESSENGER_Message *message)
139{
140 GNUNET_assert(message);
141
142 if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) ||
143 (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) ||
144 (GNUNET_MESSENGER_KIND_NAME == message->header.kind) ||
145 (GNUNET_MESSENGER_KIND_KEY == message->header.kind) ||
146 (GNUNET_MESSENGER_KIND_ID == message->header.kind))
147 return GNUNET_YES;
148 else
149 return GNUNET_NO;
150}
151
133static void 152static void
134fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened) 153fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened)
135{ 154{
@@ -158,18 +177,7 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
158 switch (kind) 177 switch (kind)
159 { 178 {
160 case GNUNET_MESSENGER_KIND_INFO: 179 case GNUNET_MESSENGER_KIND_INFO:
161 length += member_size(struct GNUNET_MESSENGER_Message, body.info.host_key); 180 length += member_size(struct GNUNET_MESSENGER_Message, body.info.messenger_version);
162 length += member_size(struct GNUNET_MESSENGER_Message, body.info.unique_id);
163 break;
164 case GNUNET_MESSENGER_KIND_JOIN:
165 length += member_size(struct GNUNET_MESSENGER_Message, body.join.key);
166 break;
167 case GNUNET_MESSENGER_KIND_LEAVE:
168 break;
169 case GNUNET_MESSENGER_KIND_NAME:
170 break;
171 case GNUNET_MESSENGER_KIND_KEY:
172 length += member_size(struct GNUNET_MESSENGER_Message, body.key.key);
173 break; 181 break;
174 case GNUNET_MESSENGER_KIND_PEER: 182 case GNUNET_MESSENGER_KIND_PEER:
175 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer); 183 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer);
@@ -195,7 +203,7 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
195 case GNUNET_MESSENGER_KIND_FILE: 203 case GNUNET_MESSENGER_KIND_FILE:
196 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key); 204 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key);
197 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash); 205 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash);
198 length += NAME_MAX; 206 length += member_size(struct GNUNET_MESSENGER_Message, body.file.name);
199 break; 207 break;
200 case GNUNET_MESSENGER_KIND_PRIVATE: 208 case GNUNET_MESSENGER_KIND_PRIVATE:
201 length += member_size(struct GNUNET_MESSENGER_Message, body.private.key); 209 length += member_size(struct GNUNET_MESSENGER_Message, body.private.key);
@@ -207,16 +215,17 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
207 return length; 215 return length;
208} 216}
209 217
218typedef uint32_t kind_t;
219
210uint16_t 220uint16_t
211get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind) 221get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
212{ 222{
213 uint16_t length = 0; 223 uint16_t length = 0;
214 224
215 length += member_size(struct GNUNET_MESSENGER_Message, header.signature);
216 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp); 225 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
217 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id); 226 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
218 length += member_size(struct GNUNET_MESSENGER_Message, header.previous); 227 length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
219 length += member_size(struct GNUNET_MESSENGER_Message, header.kind); 228 length += sizeof(kind_t);
220 229
221 return length + get_message_body_kind_size (kind); 230 return length + get_message_body_kind_size (kind);
222} 231}
@@ -228,8 +237,17 @@ get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUN
228 237
229 switch (kind) 238 switch (kind)
230 { 239 {
240 case GNUNET_MESSENGER_KIND_INFO:
241 length += GNUNET_IDENTITY_key_get_length(&(body->info.host_key));
242 break;
243 case GNUNET_MESSENGER_KIND_JOIN:
244 length += GNUNET_IDENTITY_key_get_length(&(body->join.key));
245 break;
231 case GNUNET_MESSENGER_KIND_NAME: 246 case GNUNET_MESSENGER_KIND_NAME:
232 length += (body->name.name? strlen (body->name.name) : 0); 247 length += (body->name.name ? strlen (body->name.name) : 0);
248 break;
249 case GNUNET_MESSENGER_KIND_KEY:
250 length += GNUNET_IDENTITY_key_get_length(&(body->key.key));
233 break; 251 break;
234 case GNUNET_MESSENGER_KIND_TEXT: 252 case GNUNET_MESSENGER_KIND_TEXT:
235 length += strlen (body->text.text); 253 length += strlen (body->text.text);
@@ -248,19 +266,76 @@ get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUN
248} 266}
249 267
250uint16_t 268uint16_t
251get_message_size (const struct GNUNET_MESSENGER_Message *message) 269get_message_size (const struct GNUNET_MESSENGER_Message *message,
270 int include_signature)
252{ 271{
253 return get_message_kind_size (message->header.kind) + get_message_body_size (message->header.kind, &(message->body)); 272 GNUNET_assert(message);
273
274 uint16_t length = 0;
275
276 if (GNUNET_YES == include_signature)
277 length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature));
278
279 length += get_message_kind_size (message->header.kind);
280 length += get_message_body_size (message->header.kind, &(message->body));
281
282 return length;
254} 283}
255 284
256static uint16_t 285static uint16_t
257get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message) 286get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message, int include_body)
258{ 287{
288 const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t);
289
259 if (message) 290 if (message)
260 return sizeof(message->kind) + get_message_body_kind_size (message->kind) 291 return minimum_size + get_message_body_kind_size (message->kind)
261 + get_message_body_size (message->kind, &(message->body)); 292 + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0);
262 else 293 else
263 return sizeof(message->kind); 294 return minimum_size;
295}
296
297static uint16_t
298calc_usual_padding ()
299{
300 uint16_t padding = 0;
301 uint16_t kind_size;
302
303 for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) {
304 kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i);
305
306 if (kind_size > padding)
307 padding = kind_size;
308 }
309
310 return padding + GNUNET_MESSENGER_PADDING_MIN;
311}
312
313#define max(x, y) (x > y? x : y)
314
315static uint16_t
316calc_padded_length (uint16_t length)
317{
318 static uint16_t usual_padding = 0;
319
320 if (!usual_padding)
321 usual_padding = calc_usual_padding();
322
323 const uint16_t padded_length = max(
324 length + GNUNET_MESSENGER_PADDING_MIN,
325 usual_padding
326 );
327
328 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
329 return GNUNET_MESSENGER_PADDING_LEVEL0;
330
331 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1)
332 return GNUNET_MESSENGER_PADDING_LEVEL1;
333
334 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2)
335 return GNUNET_MESSENGER_PADDING_LEVEL2;
336
337 return GNUNET_MESSENGER_MAX_MESSAGE_SIZE;
338
264} 339}
265 340
266#define min(x, y) (x < y? x : y) 341#define min(x, y) (x < y? x : y)
@@ -272,7 +347,27 @@ get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message)
272 347
273#define encode_step(dst, offset, src) do { \ 348#define encode_step(dst, offset, src) do { \
274 encode_step_ext(dst, offset, src, sizeof(*src)); \ 349 encode_step_ext(dst, offset, src, sizeof(*src)); \
275} while(0) 350} while (0)
351
352#define encode_step_key(dst, offset, src, length) do { \
353 ssize_t result = GNUNET_IDENTITY_write_key_to_buffer( \
354 src, dst + offset, length - offset \
355 ); \
356 if (result < 0) \
357 GNUNET_break (0); \
358 else \
359 offset += result; \
360} while (0)
361
362#define encode_step_signature(dst, offset, src, length) do { \
363 ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \
364 src, dst + offset, length - offset \
365 ); \
366 if (result < 0) \
367 GNUNET_break (0); \
368 else \
369 offset += result; \
370} while (0)
276 371
277static void 372static void
278encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body, 373encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body,
@@ -281,20 +376,18 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET
281 switch (kind) 376 switch (kind)
282 { 377 {
283 case GNUNET_MESSENGER_KIND_INFO: 378 case GNUNET_MESSENGER_KIND_INFO:
284 encode_step(buffer, offset, &(body->info.host_key)); 379 encode_step_key(buffer, offset, &(body->info.host_key), length);
285 encode_step(buffer, offset, &(body->info.unique_id)); 380 encode_step(buffer, offset, &(body->info.messenger_version));
286 break; 381 break;
287 case GNUNET_MESSENGER_KIND_JOIN: 382 case GNUNET_MESSENGER_KIND_JOIN:
288 encode_step(buffer, offset, &(body->join.key)); 383 encode_step_key(buffer, offset, &(body->join.key), length);
289 break;
290 case GNUNET_MESSENGER_KIND_LEAVE:
291 break; 384 break;
292 case GNUNET_MESSENGER_KIND_NAME: 385 case GNUNET_MESSENGER_KIND_NAME:
293 if (body->name.name) 386 if (body->name.name)
294 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name))); 387 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
295 break; 388 break;
296 case GNUNET_MESSENGER_KIND_KEY: 389 case GNUNET_MESSENGER_KIND_KEY:
297 encode_step(buffer, offset, &(body->key.key)); 390 encode_step_key(buffer, offset, &(body->key.key), length);
298 break; 391 break;
299 case GNUNET_MESSENGER_KIND_PEER: 392 case GNUNET_MESSENGER_KIND_PEER:
300 encode_step(buffer, offset, &(body->peer.peer)); 393 encode_step(buffer, offset, &(body->peer.peer));
@@ -321,7 +414,7 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET
321 case GNUNET_MESSENGER_KIND_FILE: 414 case GNUNET_MESSENGER_KIND_FILE:
322 encode_step(buffer, offset, &(body->file.key)); 415 encode_step(buffer, offset, &(body->file.key));
323 encode_step(buffer, offset, &(body->file.hash)); 416 encode_step(buffer, offset, &(body->file.hash));
324 encode_step_ext(buffer, offset, body->file.name, NAME_MAX); 417 encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
325 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri))); 418 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
326 break; 419 break;
327 case GNUNET_MESSENGER_KIND_PRIVATE: 420 case GNUNET_MESSENGER_KIND_PRIVATE:
@@ -331,18 +424,40 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET
331 default: 424 default:
332 break; 425 break;
333 } 426 }
427
428 if (offset >= length)
429 return;
430
431 const uint16_t padding = length - offset;
432 const uint16_t used_padding = sizeof(padding) + sizeof(char);
433
434 GNUNET_assert(padding >= used_padding);
435
436 buffer[offset++] = '\0';
437
438 if (padding > used_padding)
439 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding);
440
441 GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
334} 442}
335 443
336void 444void
337encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer) 445encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
446 int include_signature)
338{ 447{
448 GNUNET_assert((message) && (buffer));
449
339 uint16_t offset = 0; 450 uint16_t offset = 0;
340 451
341 encode_step(buffer, offset, &(message->header.signature)); 452 if (GNUNET_YES == include_signature)
453 encode_step_signature(buffer, offset, &(message->header.signature), length);
454
455 const kind_t kind = (kind_t) message->header.kind;
456
342 encode_step(buffer, offset, &(message->header.timestamp)); 457 encode_step(buffer, offset, &(message->header.timestamp));
343 encode_step(buffer, offset, &(message->header.sender_id)); 458 encode_step(buffer, offset, &(message->header.sender_id));
344 encode_step(buffer, offset, &(message->header.previous)); 459 encode_step(buffer, offset, &(message->header.previous));
345 encode_step(buffer, offset, &(message->header.kind)); 460 encode_step(buffer, offset, &kind);
346 461
347 encode_message_body (message->header.kind, &(message->body), length, buffer, offset); 462 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
348} 463}
@@ -350,11 +465,22 @@ encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length,
350static void 465static void
351encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer) 466encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer)
352{ 467{
353 uint16_t offset = 0; 468 struct GNUNET_HashCode hash;
469 uint16_t offset = sizeof(hash);
354 470
355 encode_step(buffer, offset, &(message->kind)); 471 const kind_t kind = (kind_t) message->kind;
472
473 encode_step(buffer, offset, &kind);
356 474
357 encode_message_body (message->kind, &(message->body), length, buffer, offset); 475 encode_message_body (message->kind, &(message->body), length, buffer, offset);
476
477 GNUNET_CRYPTO_hash(
478 buffer + sizeof(hash),
479 length - sizeof(hash),
480 &hash
481 );
482
483 GNUNET_memcpy(buffer, &hash, sizeof(hash));
358} 484}
359 485
360#define decode_step_ext(src, offset, dst, size) do { \ 486#define decode_step_ext(src, offset, dst, size) do { \
@@ -372,29 +498,51 @@ encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint1
372 decode_step_ext(src, offset, dst, size); \ 498 decode_step_ext(src, offset, dst, size); \
373} while (0) 499} while (0)
374 500
375static void 501#define decode_step_key(src, offset, dst, length) do { \
502 ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \
503 dst, src + offset, length - offset \
504 ); \
505 if (result < 0) \
506 GNUNET_break(0); \
507 else \
508 offset += result; \
509} while (0)
510
511static uint16_t
376decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body, 512decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body,
377 uint16_t length, const char *buffer, uint16_t offset) 513 uint16_t length, const char *buffer, uint16_t offset)
378{ 514{
515 uint16_t padding = 0;
516
517 GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
518
519 if (padding > length - offset)
520 padding = 0;
521
522 const uint16_t end_zero = length - padding;
523
524 if ((padding) && (buffer[end_zero] != '\0'))
525 padding = 0;
526
527 length -= padding;
528
379 switch (*kind) 529 switch (*kind)
380 { 530 {
381 case GNUNET_MESSENGER_KIND_INFO: 531 case GNUNET_MESSENGER_KIND_INFO: {
382 decode_step(buffer, offset, &(body->info.host_key)); 532 decode_step_key(buffer, offset, &(body->info.host_key), length);
383 decode_step(buffer, offset, &(body->info.unique_id)); 533 decode_step(buffer, offset, &(body->info.messenger_version));
384 break; 534 break;
385 case GNUNET_MESSENGER_KIND_JOIN: 535 } case GNUNET_MESSENGER_KIND_JOIN: {
386 decode_step(buffer, offset, &(body->join.key)); 536 decode_step_key(buffer, offset, &(body->join.key), length);
387 break;
388 case GNUNET_MESSENGER_KIND_LEAVE:
389 break; 537 break;
390 case GNUNET_MESSENGER_KIND_NAME: 538 } case GNUNET_MESSENGER_KIND_NAME:
391 if (length - offset > 0) 539 if (length - offset > 0)
392 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1); 540 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
393 else 541 else
394 body->name.name = NULL; 542 body->name.name = NULL;
395 break; 543 break;
396 case GNUNET_MESSENGER_KIND_KEY: 544 case GNUNET_MESSENGER_KIND_KEY:
397 decode_step(buffer, offset, &(body->key.key)); 545 decode_step_key(buffer, offset, &(body->key.key), length);
398 break; 546 break;
399 case GNUNET_MESSENGER_KIND_PEER: 547 case GNUNET_MESSENGER_KIND_PEER:
400 decode_step(buffer, offset, &(body->peer.peer)); 548 decode_step(buffer, offset, &(body->peer.peer));
@@ -421,7 +569,7 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESS
421 case GNUNET_MESSENGER_KIND_FILE: 569 case GNUNET_MESSENGER_KIND_FILE:
422 decode_step(buffer, offset, &(body->file.key)); 570 decode_step(buffer, offset, &(body->file.key));
423 decode_step(buffer, offset, &(body->file.hash)); 571 decode_step(buffer, offset, &(body->file.hash));
424 decode_step_ext(buffer, offset, body->file.name, NAME_MAX); 572 decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
425 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1); 573 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
426 break; 574 break;
427 case GNUNET_MESSENGER_KIND_PRIVATE: 575 case GNUNET_MESSENGER_KIND_PRIVATE:
@@ -434,26 +582,51 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESS
434 *kind = GNUNET_MESSENGER_KIND_UNKNOWN; 582 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
435 break; 583 break;
436 } 584 }
585
586 return padding;
437} 587}
438 588
439int 589int
440decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer) 590decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
591 int include_signature, uint16_t *padding)
441{ 592{
593 GNUNET_assert((message) && (buffer) && (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN)));
594
442 uint16_t offset = 0; 595 uint16_t offset = 0;
443 596
444 if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN)) 597 if (GNUNET_YES == include_signature)
598 {
599 ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
600 &(message->header.signature), buffer, length - offset
601 );
602
603 if (result < 0)
604 return GNUNET_NO;
605 else
606 offset += result;
607 }
608
609 const uint16_t count = length - offset;
610
611 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN))
445 return GNUNET_NO; 612 return GNUNET_NO;
446 613
447 decode_step(buffer, offset, &(message->header.signature)); 614 kind_t kind;
615
448 decode_step(buffer, offset, &(message->header.timestamp)); 616 decode_step(buffer, offset, &(message->header.timestamp));
449 decode_step(buffer, offset, &(message->header.sender_id)); 617 decode_step(buffer, offset, &(message->header.sender_id));
450 decode_step(buffer, offset, &(message->header.previous)); 618 decode_step(buffer, offset, &(message->header.previous));
451 decode_step(buffer, offset, &(message->header.kind)); 619 decode_step(buffer, offset, &kind);
452 620
453 if (length < get_message_kind_size (message->header.kind)) 621 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) kind;
622
623 if (count < get_message_kind_size (message->header.kind))
454 return GNUNET_NO; 624 return GNUNET_NO;
455 625
456 decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset); 626 const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
627
628 if (padding)
629 *padding = result;
457 630
458 return GNUNET_YES; 631 return GNUNET_YES;
459} 632}
@@ -461,47 +634,80 @@ decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const
461static int 634static int
462decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer) 635decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer)
463{ 636{
464 uint16_t offset = 0; 637 struct GNUNET_HashCode expected, hash;
638 uint16_t offset = sizeof(hash);
639
640 if (length < get_short_message_size (NULL, GNUNET_NO))
641 return GNUNET_NO;
642
643 GNUNET_memcpy(&hash, buffer, sizeof(hash));
644
645 GNUNET_CRYPTO_hash(
646 buffer + sizeof(hash),
647 length - sizeof(hash),
648 &expected
649 );
465 650
466 if (length < get_short_message_size (NULL)) 651 if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
467 return GNUNET_NO; 652 return GNUNET_NO;
468 653
469 decode_step(buffer, offset, &(message->kind)); 654 kind_t kind;
470 655
471 if (length < get_short_message_size (message)) 656 decode_step(buffer, offset, &kind);
657
658 message->kind = (enum GNUNET_MESSENGER_MessageKind) kind;
659
660 if (length < get_short_message_size (message, GNUNET_NO))
472 return GNUNET_NO; 661 return GNUNET_NO;
473 662
474 decode_message_body (&(message->kind), &(message->body), length, buffer, offset); 663 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
475 664
665 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
666 return GNUNET_NO;
667
476 return GNUNET_YES; 668 return GNUNET_YES;
477} 669}
478 670
479void 671void
480hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash) 672hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
673 struct GNUNET_HashCode *hash)
481{ 674{
482 GNUNET_CRYPTO_hash (buffer + sizeof(struct GNUNET_CRYPTO_EcdsaSignature), 675 GNUNET_assert((message) && (buffer) && (hash));
483 length - sizeof(struct GNUNET_CRYPTO_EcdsaSignature), hash); 676
677 const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
678 &(message->header.signature)
679 );
680
681 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
484} 682}
485 683
486void 684void
487sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, 685sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
488 const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego) 686 const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego)
489{ 687{
688 GNUNET_assert((message) && (buffer) && (hash) && (ego));
689
490 struct GNUNET_MESSENGER_MessageSignature signature; 690 struct GNUNET_MESSENGER_MessageSignature signature;
491 691
492 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); 692 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
493 signature.purpose.size = htonl (sizeof(signature)); 693 signature.purpose.size = htonl (sizeof(signature));
494 694
495 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode)); 695 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
496
497 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature)); 696 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
498 GNUNET_memcpy(buffer, &(message->header.signature), sizeof(struct GNUNET_CRYPTO_EcdsaSignature)); 697
698 uint16_t offset = 0;
699 encode_step_signature(buffer, offset, &(message->header.signature), length);
499} 700}
500 701
501int 702int
502verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, 703verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
503 const struct GNUNET_IDENTITY_PublicKey *key) 704 const struct GNUNET_IDENTITY_PublicKey *key)
504{ 705{
706 GNUNET_assert((message) && (hash) && (key));
707
708 if (ntohl (key->type) != ntohl (message->header.signature.type))
709 return GNUNET_SYSERR;
710
505 struct GNUNET_MESSENGER_MessageSignature signature; 711 struct GNUNET_MESSENGER_MessageSignature signature;
506 712
507 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); 713 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
@@ -516,26 +722,32 @@ verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNU
516int 722int
517encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key) 723encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key)
518{ 724{
725 GNUNET_assert((message) && (key));
726
519 struct GNUNET_MESSENGER_ShortMessage shortened; 727 struct GNUNET_MESSENGER_ShortMessage shortened;
520 728
521 fold_short_message (message, &shortened); 729 fold_short_message (message, &shortened);
522 730
523 const uint16_t length = get_short_message_size (&shortened); 731 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
732 const uint16_t padded_length = calc_padded_length(length);
524 733
525 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE; 734 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
526 message->body.private.data = GNUNET_malloc(length); 735 message->body.private.data = GNUNET_malloc(padded_length);
736 message->body.private.length = padded_length;
527 737
528 encode_short_message (&shortened, length, message->body.private.data); 738 encode_short_message (&shortened, padded_length, message->body.private.data);
529 739
530 if (GNUNET_IDENTITY_encrypt (message->body.private.data, length, key, &(message->body.private.key), 740 if (padded_length == GNUNET_IDENTITY_encrypt (message->body.private.data, padded_length, key,
531 message->body.private.data) 741 &(message->body.private.key),
532 == length) 742 message->body.private.data))
533 { 743 {
534 destroy_message_body (shortened.kind, &(shortened.body)); 744 destroy_message_body (shortened.kind, &(shortened.body));
535 return GNUNET_YES; 745 return GNUNET_YES;
536 } 746 }
537 else 747 else
538 { 748 {
749 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
750
539 unfold_short_message (&shortened, message); 751 unfold_short_message (&shortened, message);
540 return GNUNET_NO; 752 return GNUNET_NO;
541 } 753 }
@@ -544,18 +756,28 @@ encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_I
544int 756int
545decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key) 757decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key)
546{ 758{
547 if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data, 759 GNUNET_assert((message) && (key));
548 message->body.private.length, key, 760
549 &(message->body.private.key), 761 if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data, message->body.private.length,
762 key, &(message->body.private.key),
550 message->body.private.data)) 763 message->body.private.data))
764 {
765 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
766
551 return GNUNET_NO; 767 return GNUNET_NO;
768 }
552 769
553 struct GNUNET_MESSENGER_ShortMessage shortened; 770 struct GNUNET_MESSENGER_ShortMessage shortened;
554 771
555 if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data)) 772 if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data))
773 {
774 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n");
775
556 return GNUNET_NO; 776 return GNUNET_NO;
777 }
557 778
558 unfold_short_message (&shortened, message); 779 unfold_short_message (&shortened, message);
780
559 return GNUNET_YES; 781 return GNUNET_YES;
560} 782}
561 783
@@ -563,18 +785,25 @@ struct GNUNET_MQ_Envelope*
563pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, 785pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
564 const struct GNUNET_MESSENGER_Ego *ego, int mode) 786 const struct GNUNET_MESSENGER_Ego *ego, int mode)
565{ 787{
566 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message: %u\n", message->header.kind); 788 GNUNET_assert(message);
789
790 if (ego)
791 message->header.signature.type = ego->priv.type;
792
793 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n",
794 message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
567 795
568 struct GNUNET_MessageHeader *header; 796 struct GNUNET_MessageHeader *header;
569 797
570 uint16_t length = get_message_size (message); 798 const uint16_t length = get_message_size (message, GNUNET_YES);
799 const uint16_t padded_length = calc_padded_length(length);
571 800
572 struct GNUNET_MQ_Envelope *env; 801 struct GNUNET_MQ_Envelope *env;
573 char *buffer; 802 char *buffer;
574 803
575 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode) 804 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
576 { 805 {
577 env = GNUNET_MQ_msg_extra(header, length, GNUNET_MESSAGE_TYPE_CADET_CLI); 806 env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI);
578 807
579 buffer = (char*) &(header[1]); 808 buffer = (char*) &(header[1]);
580 } 809 }
@@ -582,14 +811,14 @@ pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *
582 { 811 {
583 env = NULL; 812 env = NULL;
584 813
585 buffer = GNUNET_malloc(length); 814 buffer = GNUNET_malloc(padded_length);
586 } 815 }
587 816
588 encode_message (message, length, buffer); 817 encode_message (message, padded_length, buffer, GNUNET_YES);
589 818
590 if (hash) 819 if (hash)
591 { 820 {
592 hash_message (length, buffer, hash); 821 hash_message (message, length, buffer, hash);
593 822
594 if (ego) 823 if (ego)
595 sign_message (message, length, buffer, hash, ego); 824 sign_message (message, length, buffer, hash, ego);
@@ -600,3 +829,43 @@ pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *
600 829
601 return env; 830 return env;
602} 831}
832
833int
834filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
835{
836 switch (message->header.kind)
837 {
838 case GNUNET_MESSENGER_KIND_INFO:
839 return GNUNET_SYSERR; // Reserved for connection handling only!
840 case GNUNET_MESSENGER_KIND_JOIN:
841 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
842 case GNUNET_MESSENGER_KIND_LEAVE:
843 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
844 case GNUNET_MESSENGER_KIND_NAME:
845 return GNUNET_YES;
846 case GNUNET_MESSENGER_KIND_KEY:
847 return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
848 case GNUNET_MESSENGER_KIND_PEER:
849 return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
850 case GNUNET_MESSENGER_KIND_ID:
851 return GNUNET_SYSERR; // Reserved for member id handling only!
852 case GNUNET_MESSENGER_KIND_MISS:
853 return GNUNET_SYSERR; // Reserved for connection handling only!
854 case GNUNET_MESSENGER_KIND_MERGE:
855 return GNUNET_YES;
856 case GNUNET_MESSENGER_KIND_REQUEST:
857 return GNUNET_YES;
858 case GNUNET_MESSENGER_KIND_INVITE:
859 return GNUNET_YES;
860 case GNUNET_MESSENGER_KIND_TEXT:
861 return GNUNET_YES;
862 case GNUNET_MESSENGER_KIND_FILE:
863 return GNUNET_YES;
864 case GNUNET_MESSENGER_KIND_PRIVATE:
865 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
866 case GNUNET_MESSENGER_KIND_DELETE:
867 return GNUNET_YES;
868 default:
869 return GNUNET_SYSERR;
870 }
871}
diff --git a/src/messenger/messenger_api_message.h b/src/messenger/messenger_api_message.h
index 0f0a97e9c..7ce30dc92 100644
--- a/src/messenger/messenger_api_message.h
+++ b/src/messenger/messenger_api_message.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -36,10 +36,17 @@
36 36
37#include "messenger_api_ego.h" 37#include "messenger_api_ego.h"
38 38
39#define GNUNET_MESSENGER_MAX_MESSAGE_SIZE (GNUNET_MAX_MESSAGE_SIZE - GNUNET_MIN_MESSAGE_SIZE)
40
41#define GNUNET_MESSENGER_PADDING_MIN (sizeof(uint16_t) + sizeof(char))
42#define GNUNET_MESSENGER_PADDING_LEVEL0 (512)
43#define GNUNET_MESSENGER_PADDING_LEVEL1 (4096)
44#define GNUNET_MESSENGER_PADDING_LEVEL2 (32768)
45
39/** 46/**
40 * Creates and allocates a new message with a specific <i>kind</i>. 47 * Creates and allocates a new message with a specific <i>kind</i>.
41 * 48 *
42 * @param kind Kind of message 49 * @param[in] kind Kind of message
43 * @return New message 50 * @return New message
44 */ 51 */
45struct GNUNET_MESSENGER_Message* 52struct GNUNET_MESSENGER_Message*
@@ -48,7 +55,7 @@ create_message (enum GNUNET_MESSENGER_MessageKind kind);
48/** 55/**
49 * Creates and allocates a copy of a given <i>message</i>. 56 * Creates and allocates a copy of a given <i>message</i>.
50 * 57 *
51 * @param message Message 58 * @param[in] message Message
52 * @return New message 59 * @return New message
53 */ 60 */
54struct GNUNET_MESSENGER_Message* 61struct GNUNET_MESSENGER_Message*
@@ -57,15 +64,24 @@ copy_message (const struct GNUNET_MESSENGER_Message *message);
57/** 64/**
58 * Destroys a message and frees its memory fully. 65 * Destroys a message and frees its memory fully.
59 * 66 *
60 * @param message Message 67 * @param[in/out] message Message
61 */ 68 */
62void 69void
63destroy_message (struct GNUNET_MESSENGER_Message *message); 70destroy_message (struct GNUNET_MESSENGER_Message *message);
64 71
65/** 72/**
73 * Returns if the message should be bound to a member session.
74 *
75 * @param[in] message Message
76 * @return #GNUNET_YES or #GNUNET_NO
77 */
78int
79is_message_session_bound (const struct GNUNET_MESSENGER_Message *message);
80
81/**
66 * Returns the minimal size in bytes to encode a message of a specific <i>kind</i>. 82 * Returns the minimal size in bytes to encode a message of a specific <i>kind</i>.
67 * 83 *
68 * @param kind Kind of message 84 * @param[in] kind Kind of message
69 * @return Minimal size to encode 85 * @return Minimal size to encode
70 */ 86 */
71uint16_t 87uint16_t
@@ -74,57 +90,66 @@ get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind);
74/** 90/**
75 * Returns the exact size in bytes to encode a given <i>message</i>. 91 * Returns the exact size in bytes to encode a given <i>message</i>.
76 * 92 *
77 * @param message Message 93 * @param[in] message Message
94 * @param[in] encode_signature Flag to include signature
78 * @return Size to encode 95 * @return Size to encode
79 */ 96 */
80uint16_t 97uint16_t
81get_message_size (const struct GNUNET_MESSENGER_Message *message); 98get_message_size (const struct GNUNET_MESSENGER_Message *message,
99 int include_signature);
82 100
83/** 101/**
84 * Encodes a given <i>message</i> into a <i>buffer</i> of a maximal <i>length</i> in bytes. 102 * Encodes a given <i>message</i> into a <i>buffer</i> of a maximal <i>length</i> in bytes.
85 * 103 *
86 * @param message Message 104 * @param[in] message Message
87 * @param length Maximal length to encode 105 * @param[in] length Maximal length to encode
88 * @param[out] buffer Buffer 106 * @param[out] buffer Buffer
107 * @param[in] encode_signature Flag to include signature
89 */ 108 */
90void 109void
91encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer); 110encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
111 int include_signature);
92 112
93/** 113/**
94 * Decodes a <i>message</i> from a given <i>buffer</i> of a maximal <i>length</i> in bytes. 114 * Decodes a <i>message</i> from a given <i>buffer</i> of a maximal <i>length</i> in bytes.
95 * 115 *
96 * If the buffer is too small for a message of its decoded kind the function fails with 116 * If the buffer is too small for a message of its decoded kind the function fails with
97 * resulting GNUNET_NO after decoding only the messages header. 117 * resulting #GNUNET_NO after decoding only the messages header.
98 * 118 *
99 * On success the function returns GNUNET_YES. 119 * On success the function returns #GNUNET_YES.
100 * 120 *
101 * @param[out] message Message 121 * @param[out] message Message
102 * @param length Maximal length to decode 122 * @param[in] length Maximal length to decode
103 * @param buffer Buffer 123 * @param[in] buffer Buffer
104 * @return GNUNET_YES on success, otherwise GNUNET_NO 124 * @param[out] padding Padding
125 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
105 */ 126 */
106int 127int
107decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer); 128decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
129 int include_signature, uint16_t *padding);
108 130
109/** 131/**
110 * Calculates a <i>hash</i> of a given <i>buffer</i> of a <i>length</i> in bytes. 132 * Calculates a <i>hash</i> of a given <i>buffer</i> with a <i>length</i> in bytes
133 * from a <i>message</i>.
111 * 134 *
112 * @param length Length of buffer 135 * @param[in] message Message
113 * @param buffer Buffer 136 * @param[in] length Length of buffer
137 * @param[in] buffer Buffer
114 * @param[out] hash Hash 138 * @param[out] hash Hash
115 */ 139 */
116void 140void
117hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash); 141hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
142 struct GNUNET_HashCode *hash);
118 143
119/** 144/**
120 * Signs the <i>hash</i> of a <i>message</i> with a given <i>ego</i> and writes the signature 145 * Signs the <i>hash</i> of a <i>message</i> with a given <i>ego</i> and writes the signature
121 * into the <i>buffer</i> as well. 146 * into the <i>buffer</i> as well.
122 * 147 *
123 * @param[out] message Message 148 * @param[in/out] message Message
124 * @param length Length of buffer 149 * @param[in] length Length of buffer
125 * @param[out] buffer Buffer 150 * @param[out] buffer Buffer
126 * @param hash Hash of message 151 * @param[in] hash Hash of message
127 * @param ego EGO 152 * @param[in] ego EGO
128 */ 153 */
129void 154void
130sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, 155sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
@@ -132,13 +157,13 @@ sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *b
132 157
133/** 158/**
134 * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a specific 159 * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a specific
135 * public key. The function returns GNUNET_OK if the signature was valid, otherwise 160 * public key. The function returns #GNUNET_OK if the signature was valid, otherwise
136 * GNUNET_SYSERR. 161 * #GNUNET_SYSERR.
137 * 162 *
138 * @param message Message 163 * @param[in] message Message
139 * @param hash Hash of message 164 * @param[in] hash Hash of message
140 * @param key Public key of EGO 165 * @param[in] key Public key of EGO
141 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR 166 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
142 */ 167 */
143int 168int
144verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, 169verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
@@ -147,23 +172,23 @@ verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNU
147/** 172/**
148 * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its body 173 * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its body
149 * and kind with the now private encrypted <i>message</i>. The function returns 174 * and kind with the now private encrypted <i>message</i>. The function returns
150 * GNUNET_YES if the operation succeeded, otherwise GNUNET_NO. 175 * #GNUNET_YES if the operation succeeded, otherwise #GNUNET_NO.
151 * 176 *
152 * @param message Message 177 * @param[in/out] message Message
153 * @param key Public key of EGO 178 * @param[in] key Public key of EGO
154 * @return GNUNET_YES on success, otherwise GNUNET_NO 179 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
155 */ 180 */
156int 181int
157encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key); 182encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key);
158 183
159/** 184/**
160 * Decrypts a private <i>message</i> using a given private <i>key</i> and replaces its body 185 * Decrypts a private <i>message</i> using a given private <i>key</i> and replaces its body
161 * and kind with the inner encrypted message. The function returns GNUNET_YES if the 186 * and kind with the inner encrypted message. The function returns #GNUNET_YES if the
162 * operation succeeded, otherwise GNUNET_NO. 187 * operation succeeded, otherwise #GNUNET_NO.
163 * 188 *
164 * @param message Message 189 * @param[in/out] message Message
165 * @param key Private key of EGO 190 * @param[in] key Private key of EGO
166 * @return GNUNET_YES on success, otherwise GNUNET_NO 191 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
167 */ 192 */
168int 193int
169decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key); 194decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key);
@@ -173,18 +198,28 @@ decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_I
173 198
174/** 199/**
175 * Encodes the <i>message</i> to pack it into a newly allocated envelope if <i>mode</i> 200 * Encodes the <i>message</i> to pack it into a newly allocated envelope if <i>mode</i>
176 * is equal to GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message 201 * is equal to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message
177 * will be hashed if <i>hash</i> is not NULL and it will be signed if the <i>ego</i> is 202 * will be hashed if <i>hash</i> is not NULL and it will be signed if the <i>ego</i> is
178 * not NULL. 203 * not NULL.
179 * 204 *
180 * @param[out] message Message 205 * @param[out] message Message
181 * @param[out] hash Hash of message 206 * @param[out] hash Hash of message
182 * @param ego EGO to sign 207 * @param[in] ego EGO to sign
183 * @param mode Mode of packing 208 * @param[in] mode Mode of packing
184 * @return Envelope or NULL 209 * @return Envelope or NULL
185 */ 210 */
186struct GNUNET_MQ_Envelope* 211struct GNUNET_MQ_Envelope*
187pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, 212pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
188 const struct GNUNET_MESSENGER_Ego *ego, int mode); 213 const struct GNUNET_MESSENGER_Ego *ego, int mode);
189 214
215/**
216 * Returns if a specific kind of message should be sent by a client. The function returns
217 * #GNUNET_YES or #GNUNET_NO for recommendations and #GNUNET_SYSERR for specific kinds
218 * of messages which should not be sent manually at all.
219 *
220 * @param[in] message Message
221 */
222int
223filter_message_sending (const struct GNUNET_MESSENGER_Message *message);
224
190#endif //GNUNET_MESSENGER_API_MESSAGE_H 225#endif //GNUNET_MESSENGER_API_MESSAGE_H
diff --git a/src/messenger/messenger_api_room.c b/src/messenger/messenger_api_room.c
index 5fedf1a78..5b7edee60 100644..100755
--- a/src/messenger/messenger_api_room.c
+++ b/src/messenger/messenger_api_room.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -30,6 +30,8 @@
30struct GNUNET_MESSENGER_Room* 30struct GNUNET_MESSENGER_Room*
31create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 31create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
32{ 32{
33 GNUNET_assert((handle) && (key));
34
33 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room); 35 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room);
34 36
35 room->handle = handle; 37 room->handle = handle;
@@ -38,11 +40,10 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCod
38 room->opened = GNUNET_NO; 40 room->opened = GNUNET_NO;
39 room->contact_id = NULL; 41 room->contact_id = NULL;
40 42
41 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
42
43 init_list_tunnels (&(room->entries)); 43 init_list_tunnels (&(room->entries));
44 44
45 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 45 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
46 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
46 47
47 return room; 48 return room;
48} 49}
@@ -50,9 +51,10 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCod
50static int 51static int
51iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value) 52iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value)
52{ 53{
53 struct GNUNET_MESSENGER_Message *message = value; 54 struct GNUNET_MESSENGER_RoomMessageEntry *entry = value;
54 55
55 destroy_message (message); 56 destroy_message (entry->message);
57 GNUNET_free(entry);
56 58
57 return GNUNET_YES; 59 return GNUNET_YES;
58} 60}
@@ -60,8 +62,7 @@ iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *val
60void 62void
61destroy_room (struct GNUNET_MESSENGER_Room *room) 63destroy_room (struct GNUNET_MESSENGER_Room *room)
62{ 64{
63 if (room->members) 65 GNUNET_assert(room);
64 GNUNET_CONTAINER_multishortmap_destroy (room->members);
65 66
66 clear_list_tunnels (&(room->entries)); 67 clear_list_tunnels (&(room->entries));
67 68
@@ -72,6 +73,9 @@ destroy_room (struct GNUNET_MESSENGER_Room *room)
72 GNUNET_CONTAINER_multihashmap_destroy (room->messages); 73 GNUNET_CONTAINER_multihashmap_destroy (room->messages);
73 } 74 }
74 75
76 if (room->members)
77 GNUNET_CONTAINER_multishortmap_destroy (room->members);
78
75 if (room->contact_id) 79 if (room->contact_id)
76 GNUNET_free(room->contact_id); 80 GNUNET_free(room->contact_id);
77 81
@@ -81,65 +85,113 @@ destroy_room (struct GNUNET_MESSENGER_Room *room)
81const struct GNUNET_MESSENGER_Message* 85const struct GNUNET_MESSENGER_Message*
82get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) 86get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
83{ 87{
84 return GNUNET_CONTAINER_multihashmap_get (room->messages, hash); 88 GNUNET_assert((room) && (hash));
89
90 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
91 room->messages, hash
92 );
93
94 return (entry? entry->message : NULL);
85} 95}
86 96
87static void 97struct GNUNET_MESSENGER_Contact*
88handle_join_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 98get_room_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
89 const struct GNUNET_HashCode *hash) 99{
100 GNUNET_assert((room) && (hash));
101
102 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
103 room->messages, hash
104 );
105
106 return (entry? entry->sender : NULL);
107}
108
109static struct GNUNET_MESSENGER_Contact*
110handle_join_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
111 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
90{ 112{
91 struct GNUNET_MESSENGER_Contact *contact = get_handle_contact_by_pubkey (room->handle, &(message->body.join.key)); 113 if (!sender)
114 {
115 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
116 struct GNUNET_HashCode context;
117
118 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
119
120 sender = get_store_contact(store, &context, &(message->body.join.key));
121 }
122
123 if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value(room->members, &(message->header.sender_id), sender)) &&
124 (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put(room->members, &(message->header.sender_id), sender,
125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
126 increase_contact_rc(sender);
92 127
93 if (contact) 128 return sender;
94 GNUNET_CONTAINER_multishortmap_put (room->members, &(message->header.sender_id), contact,
95 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
96} 129}
97 130
98static void 131static void
99handle_leave_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 132handle_leave_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
100 const struct GNUNET_HashCode *hash) 133 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
101{ 134{
102 GNUNET_CONTAINER_multishortmap_remove_all (room->members, &(message->header.sender_id)); 135 if ((!sender) ||
136 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)))
137 return;
138
139 struct GNUNET_HashCode context;
140 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
141
142 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
143
144 if (GNUNET_YES == decrease_contact_rc(sender))
145 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A contact does not share any room with you anymore!\n");
103} 146}
104 147
105static void 148static void
106handle_name_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 149handle_name_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
107 const struct GNUNET_HashCode *hash) 150 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
108{ 151{
109 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, 152 if (!sender)
110 &(message->header.sender_id)); 153 return;
111 154
112 if (contact) 155 set_contact_name (sender, message->body.name.name);
113 set_contact_name (contact, message->body.name.name);
114} 156}
115 157
116static void 158static void
117handle_key_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 159handle_key_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
118 const struct GNUNET_HashCode *hash) 160 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
119{ 161{
120 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, 162 if (!sender)
121 &(message->header.sender_id)); 163 return;
122 164
123 if (contact) 165 struct GNUNET_HashCode context;
124 swap_handle_contact_by_pubkey (room->handle, contact, &(message->body.key.key)); 166 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
167
168 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
169
170 update_store_contact(store, sender, &context, &context, &(message->body.key.key));
125} 171}
126 172
127static void 173static void
128handle_id_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 174handle_id_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
129 const struct GNUNET_HashCode *hash) 175 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
130{ 176{
131 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, 177 if ((!sender) ||
132 &(message->header.sender_id)); 178 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)) ||
179 (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, &(message->body.id.id), sender,
180 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
181 return;
182
183 struct GNUNET_HashCode context, next_context;
184 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
185 get_context_from_member(&(room->key), &(message->body.id.id), &next_context);
133 186
134 if ((contact) && (GNUNET_OK 187 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
135 == GNUNET_CONTAINER_multishortmap_put (room->members, &(message->body.id.id), contact, 188
136 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) 189 update_store_contact(store, sender, &context, &next_context, get_contact_key(sender));
137 GNUNET_CONTAINER_multishortmap_remove (room->members, &(message->header.sender_id), contact);
138} 190}
139 191
140static void 192static void
141handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 193handle_miss_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
142 const struct GNUNET_HashCode *hash) 194 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
143{ 195{
144 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id))) 196 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id)))
145 { 197 {
@@ -150,40 +202,106 @@ handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MES
150 } 202 }
151} 203}
152 204
153void 205static void
154handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 206handle_delete_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
155 const struct GNUNET_HashCode *hash) 207 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
208{
209 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
210 room->messages, &(message->body.delete.hash)
211 );
212
213 if ((entry) && ((entry->sender == sender) || (get_handle_contact (room->handle, &(room->key)) == sender)) &&
214 (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages, &(message->body.delete.hash), entry)))
215 {
216 destroy_message (entry->message);
217 GNUNET_free(entry);
218 }
219}
220
221struct GNUNET_MESSENGER_Contact*
222handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
223 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
156{ 224{
157 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash)) 225 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash))
158 return; 226 return sender;
159 227
160 switch (message->header.kind) 228 switch (message->header.kind)
161 { 229 {
162 case GNUNET_MESSENGER_KIND_JOIN: 230 case GNUNET_MESSENGER_KIND_JOIN:
163 handle_join_message (room, message, hash); 231 sender = handle_join_message (room, sender, message, hash);
164 break; 232 break;
165 case GNUNET_MESSENGER_KIND_LEAVE: 233 case GNUNET_MESSENGER_KIND_LEAVE:
166 handle_leave_message (room, message, hash); 234 handle_leave_message (room, sender, message, hash);
167 break; 235 break;
168 case GNUNET_MESSENGER_KIND_NAME: 236 case GNUNET_MESSENGER_KIND_NAME:
169 handle_name_message (room, message, hash); 237 handle_name_message (room, sender, message, hash);
170 break; 238 break;
171 case GNUNET_MESSENGER_KIND_KEY: 239 case GNUNET_MESSENGER_KIND_KEY:
172 handle_key_message (room, message, hash); 240 handle_key_message (room, sender, message, hash);
173 break; 241 break;
174 case GNUNET_MESSENGER_KIND_ID: 242 case GNUNET_MESSENGER_KIND_ID:
175 handle_id_message (room, message, hash); 243 handle_id_message (room, sender, message, hash);
176 break; 244 break;
177 case GNUNET_MESSENGER_KIND_MISS: 245 case GNUNET_MESSENGER_KIND_MISS:
178 handle_miss_message (room, message, hash); 246 handle_miss_message (room, sender, message, hash);
247 break;
248 case GNUNET_MESSENGER_KIND_DELETE:
249 handle_delete_message (room, sender, message, hash);
179 break; 250 break;
180 default: 251 default:
181 break; 252 break;
182 } 253 }
183 254
184 struct GNUNET_MESSENGER_Message *clone = copy_message (message); 255 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_new(struct GNUNET_MESSENGER_RoomMessageEntry);
256
257 if (!entry)
258 return sender;
185 259
186 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, clone, 260 entry->sender = sender;
261 entry->message = copy_message (message);
262
263 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, entry,
187 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 264 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
188 destroy_message (clone); 265 {
266 destroy_message (entry->message);
267 GNUNET_free(entry);
268 }
269
270 return sender;
271}
272
273struct GNUNET_MESSENGER_MemberCall
274{
275 struct GNUNET_MESSENGER_Room *room;
276 GNUNET_MESSENGER_MemberCallback callback;
277 void *cls;
278};
279
280static int
281iterate_local_members (void* cls, const struct GNUNET_ShortHashCode *key, void *value)
282{
283 struct GNUNET_MESSENGER_MemberCall *call = cls;
284 struct GNUNET_MESSENGER_Contact *contact = value;
285
286 return call->callback(call->cls, call->room, contact);
287}
288
289int
290iterate_room_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
291 void* cls)
292{
293 GNUNET_assert(room);
294
295 if (!callback)
296 return GNUNET_CONTAINER_multishortmap_iterate(room->members, NULL, NULL);
297
298 struct GNUNET_MESSENGER_MemberCall call;
299
300 call.room = room;
301 call.callback = callback;
302 call.cls = cls;
303
304 GNUNET_assert(callback);
305
306 return GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_local_members, &call);
189} 307}
diff --git a/src/messenger/messenger_api_room.h b/src/messenger/messenger_api_room.h
index 0038128d8..eb41cf740 100644..100755
--- a/src/messenger/messenger_api_room.h
+++ b/src/messenger/messenger_api_room.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -36,6 +36,11 @@
36#include "messenger_api_contact.h" 36#include "messenger_api_contact.h"
37#include "messenger_api_message.h" 37#include "messenger_api_message.h"
38 38
39struct GNUNET_MESSENGER_RoomMessageEntry {
40 struct GNUNET_MESSENGER_Contact* sender;
41 struct GNUNET_MESSENGER_Message* message;
42};
43
39struct GNUNET_MESSENGER_Room 44struct GNUNET_MESSENGER_Room
40{ 45{
41 struct GNUNET_MESSENGER_Handle *handle; 46 struct GNUNET_MESSENGER_Handle *handle;
@@ -45,17 +50,17 @@ struct GNUNET_MESSENGER_Room
45 50
46 struct GNUNET_ShortHashCode *contact_id; 51 struct GNUNET_ShortHashCode *contact_id;
47 52
48 struct GNUNET_CONTAINER_MultiShortmap *members;
49 struct GNUNET_MESSENGER_ListTunnels entries; 53 struct GNUNET_MESSENGER_ListTunnels entries;
50 54
51 struct GNUNET_CONTAINER_MultiHashMap *messages; 55 struct GNUNET_CONTAINER_MultiHashMap *messages;
56 struct GNUNET_CONTAINER_MultiShortmap *members;
52}; 57};
53 58
54/** 59/**
55 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i> for the client API. 60 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i> for the client API.
56 * 61 *
57 * @param handle Handle 62 * @param[in/out] handle Handle
58 * @param key Key of room 63 * @param[in] key Key of room
59 * @return New room 64 * @return New room
60 */ 65 */
61struct GNUNET_MESSENGER_Room* 66struct GNUNET_MESSENGER_Room*
@@ -64,7 +69,7 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCod
64/** 69/**
65 * Destroys a room and frees its memory fully from the client API. 70 * Destroys a room and frees its memory fully from the client API.
66 * 71 *
67 * @param room Room 72 * @param[in/out] room Room
68 */ 73 */
69void 74void
70destroy_room (struct GNUNET_MESSENGER_Room *room); 75destroy_room (struct GNUNET_MESSENGER_Room *room);
@@ -73,23 +78,52 @@ destroy_room (struct GNUNET_MESSENGER_Room *room);
73 * Returns a message locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no matching 78 * Returns a message locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no matching
74 * message is found, NULL gets returned. 79 * message is found, NULL gets returned.
75 * 80 *
76 * @param room Room 81 * @param[in] room Room
77 * @param hash Hash of message 82 * @param[in] hash Hash of message
78 * @return Message or NULL 83 * @return Message or NULL
79 */ 84 */
80const struct GNUNET_MESSENGER_Message* 85const struct GNUNET_MESSENGER_Message*
81get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash); 86get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
82 87
83/** 88/**
89 * Returns a messages sender locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no
90 * matching message is found, NULL gets returned.
91 *
92 * @param[in] room Room
93 * @param[in] hash Hash of message
94 * @return Contact of sender or NULL
95 */
96struct GNUNET_MESSENGER_Contact*
97get_room_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
98
99/**
84 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update 100 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update
85 * members and its information. The function also stores the message in map locally for access afterwards. 101 * members and its information. The function also stores the message in map locally for access afterwards.
86 * 102 *
87 * @param room Room 103 * The contact of the message's sender could be updated or even created. It may not be freed or destroyed though!
88 * @param message Message 104 * (The contact may still be in use for old messages...)
89 * @param hash Hash of message 105 *
106 * @param[in/out] room Room
107 * @param[in/out] sender Contact of sender
108 * @param[in] message Message
109 * @param[in] hash Hash of message
110 * @return Contact of sender
90 */ 111 */
91void 112struct GNUNET_MESSENGER_Contact*
92handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 113handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
93 const struct GNUNET_HashCode *hash); 114 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
115
116/**
117 * Iterates through all members of a given <i>room</i> to forward each of them to a selected
118 * <i>callback</i> with a custom closure.
119 *
120 * @param[in/out] room Room
121 * @param[in] callback Function called for each member
122 * @param[in/out] cls Closure
123 * @return Amount of members iterated
124 */
125int
126iterate_room_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
127 void* cls);
94 128
95#endif //GNUNET_MESSENGER_API_ROOM_H 129#endif //GNUNET_MESSENGER_API_ROOM_H
diff --git a/src/messenger/gnunet-service-messenger_util.c b/src/messenger/messenger_api_util.c
index 94fc9469d..68e15d789 100644
--- a/src/messenger/gnunet-service-messenger_util.c
+++ b/src/messenger/messenger_api_util.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -19,11 +19,11 @@
19 */ 19 */
20/** 20/**
21 * @author Tobias Frisch 21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_util.c 22 * @file src/messenger/messenger_api_util.c
23 * @brief GNUnet MESSENGER service 23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */ 24 */
25 25
26#include "gnunet-service-messenger_util.h" 26#include "messenger_api_util.h"
27 27
28static void 28static void
29callback_close_channel (void *cls) 29callback_close_channel (void *cls)
@@ -37,13 +37,18 @@ callback_close_channel (void *cls)
37void 37void
38delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel) 38delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel)
39{ 39{
40 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_URGENT, 40 GNUNET_assert(channel);
41
42 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (),
43 GNUNET_SCHEDULER_PRIORITY_URGENT,
41 callback_close_channel, channel); 44 callback_close_channel, channel);
42} 45}
43 46
44int 47int
45generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members) 48generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members)
46{ 49{
50 GNUNET_assert(id);
51
47 size_t counter = 1 + (members ? GNUNET_CONTAINER_multishortmap_size (members) : 0); 52 size_t counter = 1 + (members ? GNUNET_CONTAINER_multishortmap_size (members) : 0);
48 53
49 do 54 do
@@ -62,3 +67,18 @@ generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CO
62 67
63 return GNUNET_NO; 68 return GNUNET_NO;
64} 69}
70
71const struct GNUNET_IDENTITY_PublicKey*
72get_anonymous_public_key ()
73{
74 static struct GNUNET_IDENTITY_PublicKey public_key;
75 static struct GNUNET_IDENTITY_Ego* ego = NULL;
76
77 if (!ego)
78 {
79 ego = GNUNET_IDENTITY_ego_get_anonymous();
80 GNUNET_IDENTITY_ego_get_public_key(ego, &public_key);
81 }
82
83 return &public_key;
84}
diff --git a/src/messenger/gnunet-service-messenger_util.h b/src/messenger/messenger_api_util.h
index 20f8f0afe..c70a3601f 100644
--- a/src/messenger/gnunet-service-messenger_util.h
+++ b/src/messenger/messenger_api_util.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -19,8 +19,8 @@
19 */ 19 */
20/** 20/**
21 * @author Tobias Frisch 21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_util.h 22 * @file src/messenger/messenger_api_util.h
23 * @brief GNUnet MESSENGER service 23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */ 24 */
25 25
26#ifndef GNUNET_SERVICE_MESSENGER_UTIL_H 26#ifndef GNUNET_SERVICE_MESSENGER_UTIL_H
@@ -30,24 +30,35 @@
30#include "gnunet_cadet_service.h" 30#include "gnunet_cadet_service.h"
31#include "gnunet_container_lib.h" 31#include "gnunet_container_lib.h"
32#include "gnunet_crypto_lib.h" 32#include "gnunet_crypto_lib.h"
33#include "gnunet_disk_lib.h"
34#include "gnunet_identity_service.h"
33 35
34/** 36/**
35 * Starts an urgent task to close a CADET channel asynchronously. 37 * Starts an urgent task to close a CADET channel asynchronously.
36 * 38 *
37 * @param channel Channel 39 * @param[in/out] channel Channel
38 */ 40 */
39void 41void
40delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel); 42delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel);
41 43
42/** 44/**
43 * Tries to generate an unused member id and store it into the <i>id</i> parameter. A map containing all currently 45 * Tries to generate an unused member id and store it into the <i>id</i> parameter.
44 * used member ids is used to check against. 46 * A map containing all currently used member ids is used to check against.
45 * 47 *
46 * @param[out] id New member id 48 * @param[out] id New member id
47 * @param members Map of member ids 49 * @param[in] members Map of member ids
48 * @return GNUNET_YES on success, GNUNET_NO on failure 50 * @return #GNUNET_YES on success, #GNUNET_NO on failure
49 */ 51 */
50int 52int
51generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members); 53generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members);
52 54
55/**
56 * Returns the public identity key of #GNUNET_IDENTITY_ego_get_anonymous() without
57 * recalculating it every time.
58 *
59 * @return anonymous public key
60 */
61const struct GNUNET_IDENTITY_PublicKey*
62get_anonymous_public_key ();
63
53#endif //GNUNET_SERVICE_MESSENGER_UTIL_H 64#endif //GNUNET_SERVICE_MESSENGER_UTIL_H
diff --git a/src/messenger/test_messenger.c b/src/messenger/test_messenger.c
index b42dfe6d9..fb3e3e1bc 100644
--- a/src/messenger/test_messenger.c
+++ b/src/messenger/test_messenger.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -61,14 +61,13 @@ end (void *cls)
61 61
62 if (messenger) 62 if (messenger)
63 { 63 {
64 GNUNET_MESSENGER_disconnect(messenger); 64 GNUNET_MESSENGER_disconnect (messenger);
65 messenger = NULL; 65 messenger = NULL;
66 } 66 }
67 67
68 status = 0; 68 status = 0;
69} 69}
70 70
71
72static void 71static void
73end_badly (void *cls) 72end_badly (void *cls)
74{ 73{
@@ -83,7 +82,7 @@ end_operation (void *cls)
83{ 82{
84 op_task = NULL; 83 op_task = NULL;
85 84
86 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown"); 85 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls ? (const char*) cls : "unknown");
87 86
88 if (die_task) 87 if (die_task)
89 GNUNET_SCHEDULER_cancel (die_task); 88 GNUNET_SCHEDULER_cancel (die_task);
@@ -109,30 +108,25 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
109 op_task = NULL; 108 op_task = NULL;
110 } 109 }
111 110
112 const char* name = GNUNET_MESSENGER_get_name(handle); 111 const char *name = GNUNET_MESSENGER_get_name (handle);
113 112
114 if (0 != strcmp(name, TESTER_NAME)) 113 if (0 != strcmp (name, TESTER_NAME))
115 { 114 {
116 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name"); 115 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name");
117 return; 116 return;
118 } 117 }
119 118
120 struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous(); 119 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key (handle);
121 struct GNUNET_IDENTITY_PublicKey anonymous_key;
122
123 GNUNET_IDENTITY_ego_get_public_key(ego, &anonymous_key);
124 120
125 const struct GNUNET_IDENTITY_PublicKey* key = GNUNET_MESSENGER_get_key(handle); 121 if (((!identity_counter) && (key)) || ((identity_counter) && (!key)))
126
127 if (((!identity_counter) && (0 != GNUNET_memcmp(key, (&anonymous_key)))) ||
128 ((identity_counter) && (0 == GNUNET_memcmp(key, (&anonymous_key)))))
129 { 122 {
130 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key"); 123 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key");
131 return; 124 return;
132 } 125 }
133 126
134 if (identity_counter) { 127 if (identity_counter)
135 GNUNET_MESSENGER_disconnect(handle); 128 {
129 GNUNET_MESSENGER_disconnect (handle);
136 130
137 op_task = NULL; 131 op_task = NULL;
138 messenger = NULL; 132 messenger = NULL;
@@ -144,7 +138,7 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
144 return; 138 return;
145 } 139 }
146 140
147 GNUNET_MESSENGER_update(messenger); 141 GNUNET_MESSENGER_update (messenger);
148 identity_counter++; 142 identity_counter++;
149} 143}
150 144
@@ -156,16 +150,14 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
156 * @param peer Peer for testing 150 * @param peer Peer for testing
157 */ 151 */
158static void 152static void
159run (void *cls, 153run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
160 const struct GNUNET_CONFIGURATION_Handle *cfg,
161 struct GNUNET_TESTING_Peer *peer)
162{ 154{
163 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL); 155 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
164 156
165 identity_counter = 0; 157 identity_counter = 0;
166 158
167 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect"); 159 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect");
168 messenger = GNUNET_MESSENGER_connect(cfg, TESTER_NAME, &on_identity, NULL, NULL, NULL); 160 messenger = GNUNET_MESSENGER_connect (cfg, TESTER_NAME, &on_identity, NULL, NULL, NULL);
169} 161}
170 162
171/** 163/**
@@ -176,11 +168,9 @@ run (void *cls,
176 * @return 0 ok, 1 on error 168 * @return 0 ok, 1 on error
177 */ 169 */
178int 170int
179main(int argc, char **argv) 171main (int argc, char **argv)
180{ 172{
181 if (0 != GNUNET_TESTING_peer_run("test-messenger", 173 if (0 != GNUNET_TESTING_peer_run ("test-messenger", "test_messenger_api.conf", &run, NULL))
182 "test_messenger_api.conf",
183 &run, NULL))
184 return 1; 174 return 1;
185 175
186 return status; 176 return status;
diff --git a/src/messenger/test_messenger_adapt.c b/src/messenger/test_messenger_adapt.c
new file mode 100644
index 000000000..90e8ac28d
--- /dev/null
+++ b/src/messenger/test_messenger_adapt.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_adapt.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 5, 1, 2, 3, 6, 7, 8, 4 };
39 unsigned int stages [] = { 0x21, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_adapt", &cfg);
47}
diff --git a/src/messenger/test_messenger_anonymous.c b/src/messenger/test_messenger_anonymous.c
index e2057acc4..a70121a30 100644
--- a/src/messenger/test_messenger_anonymous.c
+++ b/src/messenger/test_messenger_anonymous.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -59,14 +59,13 @@ end (void *cls)
59 59
60 if (messenger) 60 if (messenger)
61 { 61 {
62 GNUNET_MESSENGER_disconnect(messenger); 62 GNUNET_MESSENGER_disconnect (messenger);
63 messenger = NULL; 63 messenger = NULL;
64 } 64 }
65 65
66 status = 0; 66 status = 0;
67} 67}
68 68
69
70static void 69static void
71end_badly (void *cls) 70end_badly (void *cls)
72{ 71{
@@ -81,7 +80,7 @@ end_operation (void *cls)
81{ 80{
82 op_task = NULL; 81 op_task = NULL;
83 82
84 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown"); 83 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls ? (const char*) cls : "unknown");
85 84
86 if (die_task) 85 if (die_task)
87 GNUNET_SCHEDULER_cancel (die_task); 86 GNUNET_SCHEDULER_cancel (die_task);
@@ -105,7 +104,7 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
105 op_task = NULL; 104 op_task = NULL;
106 } 105 }
107 106
108 const char* name = GNUNET_MESSENGER_get_name(handle); 107 const char *name = GNUNET_MESSENGER_get_name (handle);
109 108
110 if (NULL != name) 109 if (NULL != name)
111 { 110 {
@@ -113,26 +112,21 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
113 return; 112 return;
114 } 113 }
115 114
116 if (GNUNET_SYSERR != GNUNET_MESSENGER_update(handle)) 115 if (GNUNET_SYSERR != GNUNET_MESSENGER_update (handle))
117 { 116 {
118 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "update-fail"); 117 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "update-fail");
119 return; 118 return;
120 } 119 }
121 120
122 struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous(); 121 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key (handle);
123 struct GNUNET_IDENTITY_PublicKey anonymous_key;
124
125 GNUNET_IDENTITY_ego_get_public_key(ego, &anonymous_key);
126
127 const struct GNUNET_IDENTITY_PublicKey* key = GNUNET_MESSENGER_get_key(handle);
128 122
129 if (0 != GNUNET_memcmp(key, (&anonymous_key))) 123 if (key)
130 { 124 {
131 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key-anonymous"); 125 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key-anonymous");
132 return; 126 return;
133 } 127 }
134 128
135 GNUNET_MESSENGER_disconnect(handle); 129 GNUNET_MESSENGER_disconnect (handle);
136 130
137 messenger = NULL; 131 messenger = NULL;
138 132
@@ -150,14 +144,12 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
150 * @param peer Peer for testing 144 * @param peer Peer for testing
151 */ 145 */
152static void 146static void
153run (void *cls, 147run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
154 const struct GNUNET_CONFIGURATION_Handle *cfg,
155 struct GNUNET_TESTING_Peer *peer)
156{ 148{
157 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL); 149 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
158 150
159 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect"); 151 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect");
160 messenger = GNUNET_MESSENGER_connect(cfg, NULL, &on_identity, NULL, NULL, NULL); 152 messenger = GNUNET_MESSENGER_connect (cfg, NULL, &on_identity, NULL, NULL, NULL);
161} 153}
162 154
163/** 155/**
@@ -168,11 +160,9 @@ run (void *cls,
168 * @return 0 ok, 1 on error 160 * @return 0 ok, 1 on error
169 */ 161 */
170int 162int
171main(int argc, char **argv) 163main (int argc, char **argv)
172{ 164{
173 if (0 != GNUNET_TESTING_peer_run("test-messenger", 165 if (0 != GNUNET_TESTING_peer_run ("test-messenger", "test_messenger_api.conf", &run, NULL))
174 "test_messenger_api.conf",
175 &run, NULL))
176 return 1; 166 return 1;
177 167
178 return status; 168 return status;
diff --git a/src/messenger/test_messenger_api.conf b/src/messenger/test_messenger_api.conf
index f5837392e..968f56f6d 100644
--- a/src/messenger/test_messenger_api.conf
+++ b/src/messenger/test_messenger_api.conf
@@ -1,11 +1,39 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf 1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf 2@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf
3 3
4[testbed]
5HOSTNAME = localhost
6OVERLAY_TOPOLOGY = CLIQUE
7
8[arm]
9GLOBAL_POSTFIX = -l $GNUNET_CACHE_HOME/{}-logs -L verbose
10
11[transport]
12IMMEDIATE_START = YES
13
14[core]
15START_ON_DEMAND = YES
16IMMEDIATE_START = YES
17USE_EPHEMERAL_KEYS = NO
18
4[PATHS] 19[PATHS]
5GNUNET_TEST_HOME = $GNUNET_TMP/test-messenger-api/ 20GNUNET_TEST_HOME = $GNUNET_TMP/test-messenger-api/
6 21
22[peerinfo]
23NO_IO = YES
24
7[cadet] 25[cadet]
8START_ON_DEMAND = YES 26START_ON_DEMAND = YES
27REFRESH_CONNECTION_TIME = 1 s
28ID_ANNOUNCE_TIME = 5 s
29CONNECT_TIMEOUT = 30 s
30DEFAULT_TTL = 16
31DHT_REPLICATION_LEVEL = 10
32MAX_TUNNELS = 10
33MAX_CONNECTIONS = 10
34MAX_MSGS_QUEUE = 20
35DISABLE_TRY_CONNECT = YES
36REKEY_PERIOD = 2 s
9 37
10[identity] 38[identity]
11START_ON_DEMAND = YES 39START_ON_DEMAND = YES
@@ -14,4 +42,6 @@ START_ON_DEMAND = YES
14START_ON_DEMAND = YES 42START_ON_DEMAND = YES
15 43
16[nat] 44[nat]
17ENABLE_UPNP = NO \ No newline at end of file 45ENABLE_UPNP = NO
46RETURN_LOCAL_ADDRESSES = YES
47IMMEDIATE_START = NO \ No newline at end of file
diff --git a/src/messenger/test_messenger_async_client.c b/src/messenger/test_messenger_async_client.c
new file mode 100644
index 000000000..1067b9a6d
--- /dev/null
+++ b/src/messenger/test_messenger_async_client.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_async_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x10, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_async_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_async_p2p.c b/src/messenger/test_messenger_async_p2p.c
new file mode 100644
index 000000000..d827aae16
--- /dev/null
+++ b/src/messenger/test_messenger_async_p2p.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_async_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x30, 0x30 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_async_p2p", &cfg);
47}
diff --git a/src/messenger/test_messenger_comm0.c b/src/messenger/test_messenger_comm0.c
deleted file mode 100644
index 631b5b2c9..000000000
--- a/src/messenger/test_messenger_comm0.c
+++ /dev/null
@@ -1,252 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_comm0.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25#include <stdio.h>
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testbed_logger_service.h"
29#include "gnunet_testbed_service.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_messenger_service.h"
32
33/**
34 * How long until we really give up on a particular testcase portion?
35 */
36#define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \
37 60)
38
39/**
40 * How long until we give up on any particular operation (and retry)?
41 */
42#define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
43
44static int status = 1;
45
46static struct GNUNET_SCHEDULER_Task *die_task = NULL;
47static struct GNUNET_SCHEDULER_Task *op_task = NULL;
48
49static void
50end (void *cls)
51{
52 die_task = NULL;
53
54 if (op_task)
55 {
56 GNUNET_SCHEDULER_cancel (op_task);
57 op_task = NULL;
58 }
59
60 GNUNET_SCHEDULER_shutdown ();
61 status = 0;
62}
63
64
65static void
66end_badly (void *cls)
67{
68 fprintf (stderr, "Testcase failed (timeout).\n");
69
70 end (NULL);
71 status = 1;
72}
73
74static void
75end_operation (void *cls)
76{
77 op_task = NULL;
78
79 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown");
80
81 if (die_task)
82 GNUNET_SCHEDULER_cancel (die_task);
83
84 end (NULL);
85 status = 1;
86}
87
88static void
89end_error (void *cls)
90{
91 op_task = NULL;
92
93 fprintf (stderr, "Testcase failed (error: '%s').\n", cls? (const char*) cls : "unknown");
94 GNUNET_free(cls);
95
96 if (die_task)
97 GNUNET_SCHEDULER_cancel (die_task);
98
99 end (NULL);
100 status = 1;
101}
102
103/**
104 * Function called whenever a message is received or sent.
105 *
106 * @param cls Closure
107 * @param room Room
108 * @param message Message
109 * @param hash Hash of message
110 */
111static void
112on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
113 const struct GNUNET_HashCode *hash)
114{
115 // TODO
116}
117
118/**
119 * Function called when an identity is retrieved.
120 *
121 * @param cls Closure
122 * @param handle Handle of messenger service
123 */
124static void
125on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
126{
127 // TODO
128}
129
130static void
131on_peer (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
132 const struct GNUNET_TESTBED_PeerInformation *pinfo,
133 const char *emsg)
134{
135 if (emsg)
136 {
137 op_task = GNUNET_SCHEDULER_add_now (&end_error, GNUNET_strdup(emsg));
138 return;
139 }
140
141 if (pinfo->pit != GNUNET_TESTBED_PIT_CONFIGURATION)
142 {
143 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "config");
144 return;
145 }
146
147 struct GNUNET_MESSENGER_Handle *handle;
148 struct GNUNET_MESSENGER_Room *room;
149
150 fprintf (stderr, "MSG: connect\n");
151
152 handle = GNUNET_MESSENGER_connect(pinfo->result.cfg, "tester", &on_identity, NULL, &on_message, NULL);
153
154 struct GNUNET_HashCode hash;
155 GNUNET_CRYPTO_hash("test", 4, &hash);
156
157 fprintf (stderr, "MSG: open\n");
158
159 room = GNUNET_MESSENGER_open_room(handle, &hash);
160
161 fprintf (stderr, "MSG: close\n");
162
163 GNUNET_MESSENGER_close_room(room);
164
165 fprintf (stderr, "MSG: disconnect\n");
166
167 GNUNET_MESSENGER_disconnect(handle);
168
169 GNUNET_TESTBED_operation_done(op);
170
171}
172
173/**
174 * Main function for a peer of the testcase.
175 *
176 * @param cls Closure
177 * @param event Information about the event
178 */
179static void
180run (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
181{
182 if (GNUNET_TESTBED_ET_PEER_START != event->type)
183 {
184 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "start");
185 return;
186 }
187
188 GNUNET_TESTBED_peer_get_information(event->details.peer_start.peer,
189 GNUNET_TESTBED_PIT_CONFIGURATION,
190 on_peer, event->details.peer_start.peer);
191
192 fprintf (stderr, "MSG: barrier\n");
193
194 GNUNET_TESTBED_barrier_wait("exit", NULL, NULL);
195
196 fprintf (stderr, "MSG: exit\n");
197}
198
199static void
200exit_status (void *cls, const char *name,
201 struct GNUNET_TESTBED_Barrier *barrier,
202 enum GNUNET_TESTBED_BarrierStatus status,
203 const char *emsg)
204{
205 if (emsg)
206 {
207 op_task = GNUNET_SCHEDULER_add_now (&end_error, GNUNET_strdup(emsg));
208 return;
209 }
210
211 if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)
212 {
213 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "exit");
214 return;
215 }
216 else if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status)
217 GNUNET_SCHEDULER_add_now(&end, NULL);
218}
219
220static void
221init (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers,
222 struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded,
223 unsigned int links_failed)
224{
225 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
226
227 struct GNUNET_TESTBED_Controller *controller;
228
229 controller = GNUNET_TESTBED_run_get_controller_handle(h);
230
231 GNUNET_TESTBED_barrier_init(controller, "exit", num_peers, exit_status, NULL);
232}
233
234/**
235 * The main function.
236 *
237 * @param argc number of arguments from the command line
238 * @param argv command line arguments
239 * @return 0 ok, 1 on error
240 */
241int
242main(int argc, char **argv)
243{
244 if (GNUNET_OK != GNUNET_TESTBED_test_run("test-messenger-comm0",
245 "test_messenger_api.conf",
246 2, 0,
247 &run, NULL,
248 &init, NULL))
249 return 1;
250
251 return status;
252}
diff --git a/src/messenger/test_messenger_growth.c b/src/messenger/test_messenger_growth.c
new file mode 100644
index 000000000..3781f3ee5
--- /dev/null
+++ b/src/messenger/test_messenger_growth.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_growth.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
39 unsigned int stages [] = { 0x01, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_growth", &cfg);
47}
diff --git a/src/messenger/test_messenger_ring.c b/src/messenger/test_messenger_ring.c
new file mode 100644
index 000000000..07cfd0c47
--- /dev/null
+++ b/src/messenger/test_messenger_ring.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_ring.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 8, 1, 2, 3, 4, 5, 6, 7 };
39 unsigned int stages [] = { 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_ring", &cfg);
47}
diff --git a/src/messenger/test_messenger_server.c b/src/messenger/test_messenger_server.c
new file mode 100644
index 000000000..1cf2fcc27
--- /dev/null
+++ b/src/messenger/test_messenger_server.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_server.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
39 unsigned int stages [] = { 0x01, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_server", &cfg);
47}
diff --git a/src/messenger/test_messenger_sync_client.c b/src/messenger/test_messenger_sync_client.c
new file mode 100644
index 000000000..99f26b018
--- /dev/null
+++ b/src/messenger/test_messenger_sync_client.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_sync_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x01, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_sync_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_sync_p2p.c b/src/messenger/test_messenger_sync_p2p.c
new file mode 100644
index 000000000..77ce280a1
--- /dev/null
+++ b/src/messenger/test_messenger_sync_p2p.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_sync_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_sync_p2p", &cfg);
47}
diff --git a/src/messenger/test_messenger_worst_client.c b/src/messenger/test_messenger_worst_client.c
new file mode 100644
index 000000000..63826631c
--- /dev/null
+++ b/src/messenger/test_messenger_worst_client.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_worst_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x10, 0x02 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_worst_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_worst_p2p.c b/src/messenger/test_messenger_worst_p2p.c
new file mode 100644
index 000000000..c89288eea
--- /dev/null
+++ b/src/messenger/test_messenger_worst_p2p.c
@@ -0,0 +1,47 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/test_messenger_worst_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x12, 0x12 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_worst_p2p", &cfg);
47}
diff --git a/src/messenger/testing_messenger_barrier.c b/src/messenger/testing_messenger_barrier.c
new file mode 100644
index 000000000..618d255b7
--- /dev/null
+++ b/src/messenger/testing_messenger_barrier.c
@@ -0,0 +1,170 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/testing_messenger_barrier.c
22 * @author Tobias Frisch
23 * @brief Pseudo-barriers for simple event handling
24 */
25
26#include "testing_messenger_barrier.h"
27
28struct GNUNET_BarrierHandle
29{
30 unsigned int requirement;
31 GNUNET_BarrierStatusCallback cb;
32 void *cls;
33
34 struct GNUNET_BarrierWaitHandle *head;
35 struct GNUNET_BarrierWaitHandle *tail;
36
37 struct GNUNET_SCHEDULER_Task* task;
38};
39
40struct GNUNET_BarrierHandle*
41GNUNET_init_barrier (unsigned int requirement,
42 GNUNET_BarrierStatusCallback cb,
43 void *cb_cls)
44{
45 if (0 == requirement)
46 return NULL;
47
48 struct GNUNET_BarrierHandle *barrier = GNUNET_new(struct GNUNET_BarrierHandle);
49
50 if (!barrier)
51 return NULL;
52
53 barrier->requirement = requirement;
54 barrier->cb = cb;
55 barrier->cls = cb_cls;
56 barrier->head = NULL;
57 barrier->tail = NULL;
58 barrier->task = NULL;
59
60 return barrier;
61}
62
63static void
64exit_status (struct GNUNET_BarrierHandle *barrier, int status);
65
66static void
67cancel_barrier (void *cls)
68{
69 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_SYSERR);
70}
71
72static void
73complete_barrier (void *cls)
74{
75 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_OK);
76}
77
78void
79GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier)
80{
81 if ((!barrier) || (barrier->task))
82 return;
83
84 barrier->task = GNUNET_SCHEDULER_add_now(cancel_barrier, barrier);
85}
86
87struct GNUNET_BarrierWaitHandle
88{
89 GNUNET_BarrierWaitStatusCallback cb;
90 void *cls;
91
92 struct GNUNET_BarrierWaitHandle *prev;
93 struct GNUNET_BarrierWaitHandle *next;
94
95 struct GNUNET_BarrierHandle *barrier;
96};
97
98static void
99exit_status (struct GNUNET_BarrierHandle *barrier, int status)
100{
101 struct GNUNET_BarrierWaitHandle *waiting = barrier->head;
102 while (waiting)
103 {
104 struct GNUNET_BarrierWaitHandle *current = waiting;
105
106 if (current->cb)
107 current->cb(current->cls, current, status);
108
109 waiting = waiting->next;
110
111 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, current);
112 GNUNET_free(current);
113 }
114
115 if (barrier->cb)
116 barrier->cb(barrier->cls, barrier, status);
117
118 GNUNET_free(barrier);
119}
120
121struct GNUNET_BarrierWaitHandle*
122GNUNET_wait_barrier (struct GNUNET_BarrierHandle *barrier,
123 GNUNET_BarrierWaitStatusCallback cb,
124 void *cb_cls)
125{
126 if ((!barrier) || (0 == barrier->requirement))
127 return NULL;
128
129 struct GNUNET_BarrierWaitHandle *waiting = GNUNET_new(struct GNUNET_BarrierWaitHandle);
130
131 if (!waiting)
132 return NULL;
133
134 waiting->cb = cb;
135 waiting->cls = cb_cls;
136 waiting->prev = NULL;
137 waiting->next = NULL;
138 waiting->barrier = barrier;
139
140 GNUNET_CONTAINER_DLL_insert_tail(barrier->head, barrier->tail, waiting);
141 barrier->requirement--;
142
143 if ((barrier->requirement == 0) && (!barrier->task))
144 barrier->task = GNUNET_SCHEDULER_add_now(complete_barrier, barrier);
145
146 return waiting;
147}
148
149void
150GNUNET_cancel_wait_barrier (struct GNUNET_BarrierWaitHandle *waiting)
151{
152 if (!waiting)
153 return;
154
155 struct GNUNET_BarrierHandle *barrier = waiting->barrier;
156
157 if (!barrier)
158 return;
159
160 if ((barrier->requirement == 0) && (barrier->task))
161 {
162 GNUNET_SCHEDULER_cancel(barrier->task);
163 barrier->task = NULL;
164 }
165
166 barrier->requirement++;
167 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, waiting);
168
169 GNUNET_free(waiting);
170}
diff --git a/src/messenger/testing_messenger_barrier.h b/src/messenger/testing_messenger_barrier.h
new file mode 100644
index 000000000..3062a393a
--- /dev/null
+++ b/src/messenger/testing_messenger_barrier.h
@@ -0,0 +1,131 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/testing_messenger_barrier.h
22 * @author Tobias Frisch
23 * @brief Pseudo-barriers for simple event handling
24 */
25
26#ifndef GNUNET_TESTING_MESSENGER_BARRIER_H_
27#define GNUNET_TESTING_MESSENGER_BARRIER_H_
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31
32/**
33 * Handle for pseudo-barrier
34 */
35struct GNUNET_BarrierHandle;
36
37
38/**
39 * Functions of this type are to be given as callback argument to
40 * GNUNET_init_barrier(). The callback will be called when status
41 * information is available for the pseudo-barrier.
42 *
43 * @param cls the closure given to GNUNET_init_barrier()
44 * @param barrier the pseudo-barrier handle
45 * @param status status of the pseudo-barrier. The pseudo-barrier is removed
46 * once it has been crossed or an error occurs while processing it.
47 * Therefore it is invalid to call GNUNET_cancel_barrier() on a
48 * crossed or errored pseudo-barrier.
49 */
50typedef void
51(*GNUNET_BarrierStatusCallback) (void *cls,
52 struct GNUNET_BarrierHandle *barrier,
53 int status);
54
55
56/**
57 * Initialise a pseudo-barrier and call the given callback when the required
58 * amount of peers (requirement) reach the pseudo-barrier OR upon error.
59 *
60 * @param requirement the amount of peers that is required to reach the
61 * pseudo-barrier. Peers signal reaching a pseudo-barrier by calling
62 * GNUNET_wait_barrier().
63 * @param cb the callback to call when the pseudo-barrier is reached or upon
64 * error. Can be NULL.
65 * @param cls closure for the above callback
66 * @return pseudo-barrier handle; NULL upon error
67 */
68struct GNUNET_BarrierHandle*
69GNUNET_init_barrier (unsigned int requirement,
70 GNUNET_BarrierStatusCallback cb,
71 void *cb_cls);
72
73
74/**
75 * Cancel a pseudo-barrier.
76 *
77 * @param barrier the pseudo-barrier handle
78 */
79void
80GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier);
81
82
83/**
84 * Handle for pseudo-barrier wait
85 */
86struct GNUNET_BarrierWaitHandle;
87
88
89/**
90 * Functions of this type are to be given as acallback argument to
91 * GNUNET_wait_barrier(). The callback will be called when the pseudo-barrier
92 * corresponding given in GNUNET_wait_barrier() is crossed or cancelled.
93 *
94 * @param cls closure pointer given to GNUNET_wait_barrier()
95 * @param waiting the pseudo-barrier wait handle
96 * @param status #GNUNET_SYSERR in case of error while waiting for the
97 * pseudo-barrier; #GNUNET_OK if the pseudo-barrier is crossed
98 */
99typedef void
100(*GNUNET_BarrierWaitStatusCallback) (void *cls,
101 struct GNUNET_BarrierWaitHandle *waiting,
102 int status);
103
104
105/**
106 * Wait for a pseudo-barrier to be crossed. This function should be called for
107 * the peers which have been started by the testbed.
108 *
109 * @param barrier the pseudo-barrier handle
110 * @param cb the pseudo-barrier wait callback
111 * @param cls the closure for the above callback
112 * @return pseudo-barrier wait handle which can be used to cancel the waiting
113 * at anytime before the callback is called. NULL upon error.
114 */
115struct GNUNET_BarrierWaitHandle*
116GNUNET_wait_barrier (struct GNUNET_BarrierHandle *barrier,
117 GNUNET_BarrierWaitStatusCallback cb,
118 void *cb_cls);
119
120
121/**
122 * Cancel a pseudo-barrier wait handle. Should not be called in or after the
123 * callback given to GNUNET_wait_barrier() has been called.
124 *
125 * @param waiting the pseudo-barrier wait handle
126 */
127void
128GNUNET_cancel_wait_barrier (struct GNUNET_BarrierWaitHandle *waiting);
129
130
131#endif /* GNUNET_TESTING_MESSENGER_BARRIER_H_ */
diff --git a/src/messenger/testing_messenger_setup.c b/src/messenger/testing_messenger_setup.c
new file mode 100644
index 000000000..98241fa08
--- /dev/null
+++ b/src/messenger/testing_messenger_setup.c
@@ -0,0 +1,528 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/testing_messenger_barrier.c
22 * @author Tobias Frisch
23 * @brief A simple test-case setup for the messenger service
24 */
25
26#include "testing_messenger_setup.h"
27
28#include <stdio.h>
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_testbed_logger_service.h"
32#include "gnunet_testbed_service.h"
33#include "gnunet_testing_lib.h"
34#include "gnunet_messenger_service.h"
35#include "testing_messenger_barrier.h"
36
37#define TEST_ROOM "test"
38#define TEST_NAME "tester"
39
40struct test_properties;
41
42struct test_peer {
43 struct test_properties *props;
44 unsigned int num;
45
46 struct GNUNET_SCHEDULER_Task *op_task;
47 struct GNUNET_TESTBED_Operation *op;
48
49 struct GNUNET_TESTBED_Peer *peer;
50 struct GNUNET_PeerIdentity peer_id;
51 struct GNUNET_BarrierWaitHandle *wait;
52
53 struct GNUNET_MESSENGER_Handle *handle;
54 struct GNUNET_MESSENGER_Room *room;
55
56 unsigned int peer_messages;
57
58 const char *message;
59};
60
61struct test_properties {
62 const struct test_configuration *cfg;
63
64 unsigned int num_hosts;
65
66 struct GNUNET_SCHEDULER_Task *die_task;
67 struct GNUNET_SCHEDULER_Task *end_task;
68
69 struct GNUNET_BarrierHandle *barrier;
70
71 struct test_peer *peers;
72 unsigned int num_peer;
73
74 int status;
75};
76
77static void
78shutdown_cb (void *cls)
79{
80 struct test_properties *properties = cls;
81
82
83 for (unsigned int i = 0; i < properties->num_peer; i++)
84 {
85 struct test_peer *peer = &properties->peers[i];
86
87 GNUNET_assert(peer != NULL);
88
89 if (peer->op_task)
90 GNUNET_SCHEDULER_cancel(peer->op_task);
91
92 peer->op_task = NULL;
93
94 if (peer->op)
95 GNUNET_TESTBED_operation_done (peer->op);
96
97 peer->op = NULL;
98
99 if (peer->wait)
100 GNUNET_cancel_wait_barrier(peer->wait);
101
102 peer->wait = NULL;
103
104 if (peer->room)
105 GNUNET_MESSENGER_close_room (peer->room);
106
107 peer->room = NULL;
108
109 if (peer->handle)
110 GNUNET_MESSENGER_disconnect (peer->handle);
111
112 peer->handle = NULL;
113 }
114
115 if (properties->die_task)
116 GNUNET_SCHEDULER_cancel(properties->die_task);
117
118 properties->die_task = NULL;
119 properties->end_task = NULL;
120
121 if (properties->barrier)
122 GNUNET_cancel_barrier(properties->barrier);
123
124 properties->barrier = NULL;
125}
126
127
128
129static void
130end_cb (void *cls)
131{
132 struct test_properties *properties = cls;
133
134 GNUNET_assert(properties != NULL);
135
136 properties->die_task = NULL;
137
138 int status = 0;
139
140 for (unsigned int i = 0; i < properties->num_peer; i++)
141 {
142 struct test_peer *peer = &properties->peers[i];
143
144 GNUNET_assert(peer != NULL);
145
146 const int members = GNUNET_MESSENGER_iterate_members(peer->room, NULL, NULL);
147
148 GNUNET_assert (members >= 0);
149
150 if (peer->props->num_peer != (unsigned int) members)
151 {
152 fprintf (stderr, "Testcase failed (members: %d/%u).\n", members, peer->props->num_peer);
153 status = 1;
154 break;
155 }
156 }
157
158 GNUNET_SCHEDULER_shutdown ();
159
160 properties->status = status;
161}
162
163static void
164end_badly_cb (void *cls)
165{
166 struct test_properties *properties = cls;
167
168 GNUNET_assert(properties != NULL);
169
170 fprintf (stderr, "Testcase failed (timeout).\n");
171
172 end_cb (properties);
173
174 properties->status = 1;
175}
176
177static void
178end_operation_cb (void *cls)
179{
180 struct test_peer *peer = cls;
181
182 GNUNET_assert(peer != NULL);
183
184 peer->op_task = NULL;
185
186 fprintf (stderr, "Testcase failed (operation: '%s').\n", peer->message);
187
188 GNUNET_SCHEDULER_shutdown ();
189}
190
191static void
192end_error_cb (void *cls)
193{
194 struct test_peer *peer = cls;
195
196 GNUNET_assert(peer != NULL);
197
198 peer->op_task = NULL;
199
200 fprintf (stderr, "Testcase failed (error: '%s').\n", peer->message);
201 GNUNET_free (peer);
202
203 GNUNET_SCHEDULER_shutdown ();
204}
205
206static void
207barrier2_wait_cb (void *cls, struct GNUNET_BarrierWaitHandle *waiting, int status)
208{
209 struct test_peer *peer = cls;
210
211 GNUNET_assert(peer != NULL);
212
213 if (peer->wait == waiting)
214 peer->wait = NULL;
215}
216
217static void
218barrier_wait_cb (void *cls, struct GNUNET_BarrierWaitHandle *waiting, int status)
219{
220 struct test_peer *peer = cls;
221
222 GNUNET_assert(peer != NULL);
223
224 if (peer->wait == waiting)
225 peer->wait = NULL;
226
227 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x02))
228 {
229 unsigned int door = peer->props->cfg->doors[peer->num - 1];
230
231 if (door == 0)
232 door = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, peer->props->cfg->count);
233 else
234 door = door - 1;
235
236 struct GNUNET_HashCode hash;
237 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
238
239 struct GNUNET_MESSENGER_Room *room;
240 room = GNUNET_MESSENGER_enter_room(peer->handle, &(peer->props->peers[door].peer_id), &hash);
241
242 if (peer->room)
243 GNUNET_assert(room == peer->room);
244 else
245 GNUNET_assert(room != NULL);
246
247 peer->room = room;
248 }
249}
250
251/**
252 * Function called whenever a message is received or sent.
253 *
254 * @param cls Closure
255 * @param room Room
256 * @param sender Sender
257 * @param message Message
258 * @param hash Hash of message
259 * @param flags Flags of message
260 */
261static void
262on_message (void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *sender,
263 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
264 enum GNUNET_MESSENGER_MessageFlags flags)
265{
266 struct test_peer *peer = cls;
267
268 GNUNET_assert(peer != NULL);
269
270 fprintf (stderr, "Peer: %s; [%s] Message: %s (%s)\n",
271 GNUNET_i2s(&(peer->peer_id)),
272 GNUNET_sh2s(&(message->header.sender_id)),
273 GNUNET_MESSENGER_name_of_kind(message->header.kind),
274 GNUNET_h2s(hash));
275
276 if (GNUNET_MESSENGER_KIND_PEER == message->header.kind)
277 peer->peer_messages++;
278
279 if (peer->props->num_hosts == peer->peer_messages)
280 peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier2_wait_cb, peer);
281 else if (peer->props->num_hosts < peer->peer_messages)
282 {
283 if (peer->wait)
284 GNUNET_cancel_wait_barrier(peer->wait);
285
286 peer->wait = NULL;
287
288 if (peer->op_task)
289 GNUNET_SCHEDULER_cancel(peer->op_task);
290
291 peer->message = "peer";
292 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
293 }
294}
295
296static void
297second_stage (void *cls)
298{
299 struct test_peer *peer = cls;
300
301 GNUNET_assert(peer != NULL);
302
303 peer->op_task = NULL;
304
305 struct GNUNET_HashCode hash;
306 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
307
308 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x10))
309 {
310 struct GNUNET_MESSENGER_Room *room;
311 room = GNUNET_MESSENGER_open_room (peer->handle, &hash);
312
313 if (peer->room)
314 GNUNET_assert(room == peer->room);
315 else
316 GNUNET_assert(room != NULL);
317
318 peer->room = room;
319 }
320
321 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x20))
322 {
323 unsigned int door = peer->props->cfg->doors[peer->num - 1];
324
325 if (door == 0)
326 door = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, peer->props->cfg->count);
327 else
328 door = door - 1;
329
330 struct GNUNET_MESSENGER_Room *room;
331 room = GNUNET_MESSENGER_enter_room(peer->handle, &(peer->props->peers[door].peer_id), &hash);
332
333 if (peer->room)
334 GNUNET_assert(room == peer->room);
335 else
336 GNUNET_assert(room != NULL);
337
338 peer->room = room;
339 }
340}
341
342static void
343on_peer (void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo,
344 const char *emsg)
345{
346 struct test_peer *peer = cb_cls;
347
348 GNUNET_assert(peer != NULL);
349
350 if (emsg)
351 {
352 peer->message = GNUNET_strdup(emsg);
353 peer->op_task = GNUNET_SCHEDULER_add_now (&end_error_cb, peer);
354 return;
355 }
356
357 if (!pinfo)
358 {
359 peer->message = "info";
360 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
361 return;
362 }
363
364 if (pinfo->pit != GNUNET_TESTBED_PIT_CONFIGURATION)
365 {
366 peer->message = "config";
367 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
368 return;
369 }
370
371 peer->handle = GNUNET_MESSENGER_connect (pinfo->result.cfg, TEST_NAME, NULL, NULL, &on_message, peer);
372
373 GNUNET_assert(GNUNET_OK == GNUNET_CRYPTO_get_peer_identity(
374 pinfo->result.cfg, &(peer->peer_id)
375 ));
376
377 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x01))
378 {
379 struct GNUNET_HashCode hash;
380 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
381
382 peer->room = GNUNET_MESSENGER_open_room (peer->handle, &hash);
383
384 GNUNET_assert(peer->room != NULL);
385 }
386 else
387 peer->room = NULL;
388
389 peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier_wait_cb, peer);
390}
391
392/**
393 * Main function for a peer of the testcase.
394 *
395 * @param cls Closure
396 * @param event Information about the event
397 */
398static void
399run (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
400{
401 struct test_properties *properties = cls;
402
403 GNUNET_assert(properties != NULL);
404
405 if (GNUNET_TESTBED_ET_PEER_START != event->type)
406 {
407 fprintf (stderr, "Testcase failed (operation: 'start').\n");
408
409 GNUNET_SCHEDULER_shutdown ();
410 return;
411 }
412
413 struct test_peer *peer = &(properties->peers[properties->num_peer++]);
414
415 peer->props = properties;
416 peer->num = properties->num_peer;
417
418 peer->peer = event->details.peer_start.peer;
419 peer->op = GNUNET_TESTBED_peer_get_information (peer->peer, GNUNET_TESTBED_PIT_CONFIGURATION, on_peer, peer);
420}
421
422static void
423barrier2_cb (void *cls, struct GNUNET_BarrierHandle *barrier, int status)
424{
425 struct test_properties *properties = cls;
426
427 GNUNET_assert(properties != NULL);
428
429 if (properties->barrier == barrier)
430 properties->barrier = NULL;
431
432 if (GNUNET_SYSERR == status)
433 {
434 fprintf (stderr, "Testcase failed (operation: 'barrier2').\n");
435
436 GNUNET_SCHEDULER_shutdown ();
437 return;
438 }
439 else if (GNUNET_OK == status)
440 {
441 if (properties->die_task)
442 GNUNET_SCHEDULER_cancel(properties->die_task);
443
444 properties->die_task = GNUNET_SCHEDULER_add_delayed (
445 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, properties->cfg->count),
446 &end_cb, properties
447 );
448 }
449}
450
451static void
452barrier_cb (void *cls, struct GNUNET_BarrierHandle *barrier, int status)
453{
454 struct test_properties *properties = cls;
455
456 GNUNET_assert(properties != NULL);
457
458 if (properties->barrier == barrier)
459 properties->barrier = NULL;
460 else if (!properties->barrier)
461 return;
462
463 if (properties->num_peer != properties->cfg->count)
464 {
465 fprintf (stderr, "Testcase failed (operation: 'process').\n");
466
467 GNUNET_SCHEDULER_shutdown ();
468 return;
469 }
470
471 if (GNUNET_SYSERR == status)
472 {
473 fprintf (stderr, "Testcase failed (operation: 'barrier').\n");
474
475 GNUNET_SCHEDULER_shutdown ();
476 return;
477 }
478 else if (GNUNET_OK == status)
479 {
480 properties->barrier = GNUNET_init_barrier (properties->num_peer, &barrier2_cb, properties);
481
482 for (unsigned int i = 0; i < properties->num_peer; i++)
483 properties->peers[i].op_task = GNUNET_SCHEDULER_add_now (&second_stage, &(properties->peers[i]));
484 }
485}
486
487static void
488init (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers,
489 unsigned int links_succeeded, unsigned int links_failed)
490{
491 struct test_properties *properties = cls;
492
493 GNUNET_assert(properties != NULL);
494
495 properties->end_task = GNUNET_SCHEDULER_add_shutdown(&shutdown_cb, properties);
496 properties->die_task = GNUNET_SCHEDULER_add_delayed (
497 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, properties->cfg->count * 5),
498 &end_badly_cb, properties
499 );
500}
501
502int
503GNUNET_run_messenger_setup (const char* test_name, const struct test_configuration *cfg)
504{
505 struct test_properties properties;
506 memset(&properties, 0, sizeof(properties));
507
508 properties.cfg = cfg;
509 properties.peers = GNUNET_new_array(cfg->count, struct test_peer);
510
511 for (unsigned int i = 0; i < cfg->count; i++)
512 if (0 != (cfg->stages[i] & 0x11))
513 properties.num_hosts++;
514
515 properties.status = 1;
516 properties.barrier = GNUNET_init_barrier (cfg->count, &barrier_cb, &properties);
517
518 if (GNUNET_OK != GNUNET_TESTBED_test_run (test_name, "test_messenger_api.conf",
519 cfg->count,
520 (1LL << GNUNET_TESTBED_ET_PEER_START),
521 &run, &properties,
522 &init, &properties))
523 return 1;
524
525 GNUNET_free(properties.peers);
526
527 return properties.status;
528}
diff --git a/src/messenger/testing_messenger_setup.h b/src/messenger/testing_messenger_setup.h
new file mode 100644
index 000000000..5e6b5d461
--- /dev/null
+++ b/src/messenger/testing_messenger_setup.h
@@ -0,0 +1,39 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file messenger/testing_messenger_setup.h
22 * @author Tobias Frisch
23 * @brief A simple test-case setup for the messenger service
24 */
25
26#ifndef GNUNET_TESTING_MESSENGER_SETUP_H_
27#define GNUNET_TESTING_MESSENGER_SETUP_H_
28
29struct test_configuration
30{
31 unsigned int count;
32 unsigned int *doors;
33 unsigned int *stages;
34};
35
36int
37GNUNET_run_messenger_setup (const char* test_name, const struct test_configuration *cfg);
38
39#endif /* GNUNET_TESTING_MESSENGER_SETUP_H_ */
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index d6774b37b..79210939f 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -743,13 +743,14 @@ send_lookup_response (struct NamestoreClient *nc,
743 nick->flags = 743 nick->flags =
744 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; 744 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
745 merge_with_nick_records (nick, rd_count, rd, &res_count, &res); 745 merge_with_nick_records (nick, rd_count, rd, &res_count, &res);
746 GNUNET_free (nick);
747 } 746 }
748 else 747 else
749 { 748 {
750 res_count = rd_count; 749 res_count = rd_count;
751 res = (struct GNUNET_GNSRECORD_Data *) rd; 750 res = (struct GNUNET_GNSRECORD_Data *) rd;
752 } 751 }
752 if (NULL != nick)
753 GNUNET_free (nick);
753 754
754 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (res_count, res)); 755 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (res_count, res));
755 756
@@ -758,12 +759,16 @@ send_lookup_response (struct NamestoreClient *nc,
758 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res); 759 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res);
759 if (rd_ser_len < 0) 760 if (rd_ser_len < 0)
760 { 761 {
762 if (rd != res)
763 GNUNET_free (res);
761 GNUNET_break (0); 764 GNUNET_break (0);
762 GNUNET_SERVICE_client_drop (nc->client); 765 GNUNET_SERVICE_client_drop (nc->client);
763 return; 766 return;
764 } 767 }
765 if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg)) 768 if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg))
766 { 769 {
770 if (rd != res)
771 GNUNET_free (res);
767 GNUNET_break (0); 772 GNUNET_break (0);
768 GNUNET_SERVICE_client_drop (nc->client); 773 GNUNET_SERVICE_client_drop (nc->client);
769 return; 774 return;
@@ -920,12 +925,15 @@ refresh_block (struct NamestoreClient *nc,
920 nick->flags = 925 nick->flags =
921 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; 926 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
922 merge_with_nick_records (nick, rd_count, rd, &res_count, &res); 927 merge_with_nick_records (nick, rd_count, rd, &res_count, &res);
923 GNUNET_free (nick);
924 } 928 }
929 if (NULL != nick)
930 GNUNET_free (nick);
925 if (0 == res_count) 931 if (0 == res_count)
926 { 932 {
927 if (NULL != nc) 933 if (NULL != nc)
928 send_store_response (nc, GNUNET_OK, rid); 934 send_store_response (nc, GNUNET_OK, rid);
935 if (rd != res)
936 GNUNET_free (res);
929 return; /* no data, no need to update cache */ 937 return; /* no data, no need to update cache */
930 } 938 }
931 if (GNUNET_YES == disable_namecache) 939 if (GNUNET_YES == disable_namecache)
@@ -936,6 +944,8 @@ refresh_block (struct NamestoreClient *nc,
936 GNUNET_NO); 944 GNUNET_NO);
937 if (NULL != nc) 945 if (NULL != nc)
938 send_store_response (nc, GNUNET_OK, rid); 946 send_store_response (nc, GNUNET_OK, rid);
947 if (rd != res)
948 GNUNET_free (res);
939 return; 949 return;
940 } 950 }
941 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res); 951 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res);
@@ -970,6 +980,8 @@ refresh_block (struct NamestoreClient *nc,
970 &finish_cache_operation, 980 &finish_cache_operation,
971 cop); 981 cop);
972 GNUNET_free (block); 982 GNUNET_free (block);
983 if (rd != res)
984 GNUNET_free (res);
973} 985}
974 986
975 987
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index c845b5019..2d5327e06 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -690,6 +690,12 @@ handle_zone_to_name_response (void *cls,
690 690
691 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME_RESPONSE\n"); 691 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME_RESPONSE\n");
692 qe = find_qe (h, ntohl (msg->gns_header.r_id)); 692 qe = find_qe (h, ntohl (msg->gns_header.r_id));
693 if (NULL == qe)
694 {
695 LOG (GNUNET_ERROR_TYPE_WARNING,
696 "Response queue already gone...\n");
697 return;
698 }
693 res = ntohs (msg->res); 699 res = ntohs (msg->res);
694 switch (res) 700 switch (res)
695 { 701 {
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c
index edcbeb874..ae93e5eff 100644
--- a/src/namestore/plugin_rest_namestore.c
+++ b/src/namestore/plugin_rest_namestore.c
@@ -375,6 +375,8 @@ get_egoentry_namestore (struct RequestHandle *handle, char *name)
375 if (NULL == name) 375 if (NULL == name)
376 return NULL; 376 return NULL;
377 tmp = strtok (copy, "/"); 377 tmp = strtok (copy, "/");
378 if (NULL == tmp)
379 return NULL;
378 for (ego_entry = ego_head; NULL != ego_entry; 380 for (ego_entry = ego_head; NULL != ego_entry;
379 ego_entry = ego_entry->next) 381 ego_entry = ego_entry->next)
380 { 382 {
diff --git a/src/peerinfo-tool/plugin_rest_peerinfo.c b/src/peerinfo-tool/plugin_rest_peerinfo.c
index 4bbc7442e..f969a175b 100644
--- a/src/peerinfo-tool/plugin_rest_peerinfo.c
+++ b/src/peerinfo-tool/plugin_rest_peerinfo.c
@@ -379,7 +379,9 @@ peerinfo_list_finished (void *cls)
379 result_str = json_dumps (handle->response, 0); 379 result_str = json_dumps (handle->response, 0);
380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
381 resp = GNUNET_REST_create_response (result_str); 381 resp = GNUNET_REST_create_response (result_str);
382 MHD_add_response_header (resp, "Content-Type", "application/json"); 382 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
383 "Content-Type",
384 "application/json"));
383 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 385 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
384 GNUNET_free (result_str); 386 GNUNET_free (result_str);
385 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); 387 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
diff --git a/src/peerstore/gnunet-service-peerstore.c b/src/peerstore/gnunet-service-peerstore.c
index c92e4d3f0..959d088f9 100644
--- a/src/peerstore/gnunet-service-peerstore.c
+++ b/src/peerstore/gnunet-service-peerstore.c
@@ -77,6 +77,8 @@ static unsigned int num_clients;
77static void 77static void
78do_shutdown () 78do_shutdown ()
79{ 79{
80 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81 "Shutting down peerstore, bye.\n");
80 if (NULL != db_lib_name) 82 if (NULL != db_lib_name)
81 { 83 {
82 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db)); 84 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db));
@@ -105,6 +107,8 @@ do_shutdown ()
105static void 107static void
106shutdown_task (void *cls) 108shutdown_task (void *cls)
107{ 109{
110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
111 "Priming PEERSTORE for shutdown.\n");
108 in_shutdown = GNUNET_YES; 112 in_shutdown = GNUNET_YES;
109 if (0 == num_clients) /* Only when no connected clients. */ 113 if (0 == num_clients) /* Only when no connected clients. */
110 do_shutdown (); 114 do_shutdown ();
@@ -176,6 +180,8 @@ client_connect_cb (void *cls,
176 struct GNUNET_MQ_Handle *mq) 180 struct GNUNET_MQ_Handle *mq)
177{ 181{
178 num_clients++; 182 num_clients++;
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184 "A client connected (now %u)\n", num_clients);
179 return client; 185 return client;
180} 186}
181 187
@@ -195,7 +201,7 @@ client_disconnect_it (void *cls, const struct GNUNET_HashCode *key, void *value)
195 { 201 {
196 GNUNET_assert (GNUNET_YES == 202 GNUNET_assert (GNUNET_YES ==
197 GNUNET_CONTAINER_multihashmap_remove (watchers, key, value)); 203 GNUNET_CONTAINER_multihashmap_remove (watchers, key, value));
198 num_clients++; 204 num_clients++; /* Watchers do not count */
199 } 205 }
200 return GNUNET_OK; 206 return GNUNET_OK;
201} 207}
@@ -212,12 +218,14 @@ client_disconnect_cb (void *cls,
212 struct GNUNET_SERVICE_Client *client, 218 struct GNUNET_SERVICE_Client *client,
213 void *app_cls) 219 void *app_cls)
214{ 220{
215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "A client disconnected, cleaning up.\n"); 221 num_clients--;
216 if (NULL != watchers) 222 if (NULL != watchers)
217 GNUNET_CONTAINER_multihashmap_iterate (watchers, 223 GNUNET_CONTAINER_multihashmap_iterate (watchers,
218 &client_disconnect_it, 224 &client_disconnect_it,
219 client); 225 client);
220 num_clients--; 226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
227 "A client disconnected (%u remaining).\n",
228 num_clients);
221 if ((0 == num_clients) && in_shutdown) 229 if ((0 == num_clients) && in_shutdown)
222 do_shutdown (); 230 do_shutdown ();
223} 231}
@@ -540,6 +548,7 @@ run (void *cls,
540 char *database; 548 char *database;
541 549
542 in_shutdown = GNUNET_NO; 550 in_shutdown = GNUNET_NO;
551 num_clients = 0;
543 cfg = c; 552 cfg = c;
544 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, 553 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
545 "peerstore", 554 "peerstore",
diff --git a/src/peerstore/peerstore_api.c b/src/peerstore/peerstore_api.c
index db5aee0d5..196d44faa 100644
--- a/src/peerstore/peerstore_api.c
+++ b/src/peerstore/peerstore_api.c
@@ -823,7 +823,12 @@ reconnect (void *cls)
823 &handle_client_error, 823 &handle_client_error,
824 h); 824 h);
825 if (NULL == h->mq) 825 if (NULL == h->mq)
826 {
827 h->reconnect_task =
828 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
829 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
826 return; 830 return;
831 }
827 LOG (GNUNET_ERROR_TYPE_DEBUG, 832 LOG (GNUNET_ERROR_TYPE_DEBUG,
828 "Resending pending requests after reconnect.\n"); 833 "Resending pending requests after reconnect.\n");
829 if (NULL != h->watches) 834 if (NULL != h->watches)
diff --git a/src/peerstore/test_peerstore_api_sync.c b/src/peerstore/test_peerstore_api_sync.c
index 4c826c654..5057c98b5 100644
--- a/src/peerstore/test_peerstore_api_sync.c
+++ b/src/peerstore/test_peerstore_api_sync.c
@@ -67,6 +67,24 @@ static const char *val = "test_peerstore_api_store_val";
67 67
68 68
69/** 69/**
70 * Timeout
71 */
72#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
73
74/**
75 * Timeout task
76 */
77static struct GNUNET_SCHEDULER_Task *to;
78
79/**
80 * Iterate handle
81 */
82static struct GNUNET_PEERSTORE_IterateContext *it;
83
84static void
85test_cont (void *cls);
86
87/**
70 * Function that should be called with the result of the 88 * Function that should be called with the result of the
71 * lookup, and finally once with NULL to signal the end 89 * lookup, and finally once with NULL to signal the end
72 * of the iteration. 90 * of the iteration.
@@ -89,9 +107,24 @@ iterate_cb (void *cls,
89 GNUNET_break (NULL == emsg); 107 GNUNET_break (NULL == emsg);
90 if (NULL == record) 108 if (NULL == record)
91 { 109 {
92 GNUNET_PEERSTORE_disconnect (h, 110 it = NULL;
93 GNUNET_NO); 111 if (0 == ok)
94 GNUNET_SCHEDULER_shutdown (); 112 {
113 GNUNET_PEERSTORE_disconnect (h,
114 GNUNET_NO);
115 if (NULL != to)
116 {
117 GNUNET_SCHEDULER_cancel (to);
118 to = NULL;
119 }
120 GNUNET_SCHEDULER_shutdown ();
121 return;
122 }
123 /**
124 * Try again
125 */
126 GNUNET_SCHEDULER_add_now (&test_cont,
127 NULL);
95 return; 128 return;
96 } 129 }
97 rec_val = record->value; 130 rec_val = record->value;
@@ -100,6 +133,22 @@ iterate_cb (void *cls,
100} 133}
101 134
102 135
136static void
137timeout_task (void *cls)
138{
139 to = NULL;
140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
141 "Timeout reached\n");
142 if (NULL != it)
143 GNUNET_PEERSTORE_iterate_cancel (it);
144 it = NULL;
145 GNUNET_PEERSTORE_disconnect (h,
146 GNUNET_NO);
147 GNUNET_SCHEDULER_shutdown ();
148 return;
149}
150
151
103/** 152/**
104 * Run the 2nd stage of the test where we fetch the 153 * Run the 2nd stage of the test where we fetch the
105 * data that should have been stored. 154 * data that should have been stored.
@@ -109,12 +158,11 @@ iterate_cb (void *cls,
109static void 158static void
110test_cont (void *cls) 159test_cont (void *cls)
111{ 160{
112 h = GNUNET_PEERSTORE_connect (cfg); 161 it = GNUNET_PEERSTORE_iterate (h,
113 GNUNET_PEERSTORE_iterate (h, 162 subsystem,
114 subsystem, 163 &pid, key,
115 &pid, key, 164 &iterate_cb,
116 &iterate_cb, 165 NULL);
117 NULL);
118} 166}
119 167
120 168
@@ -122,10 +170,9 @@ static void
122disc_cont (void *cls) 170disc_cont (void *cls)
123{ 171{
124 GNUNET_PEERSTORE_disconnect (h, GNUNET_YES); 172 GNUNET_PEERSTORE_disconnect (h, GNUNET_YES);
125 h = NULL; 173 h = GNUNET_PEERSTORE_connect (cfg);
126 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, 174 GNUNET_SCHEDULER_add_now (&test_cont,
127 &test_cont, 175 NULL);
128 NULL);
129} 176}
130 177
131 178
@@ -133,12 +180,17 @@ static void
133store_cont (void *cls, int success) 180store_cont (void *cls, int success)
134{ 181{
135 ok = success; 182 ok = success;
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184 "Success: %s\n",
185 (GNUNET_SYSERR == ok) ? "no" : "yes");
136 /* We need to wait a little bit to give the disconnect 186 /* We need to wait a little bit to give the disconnect
137 a chance to actually finish the operation; otherwise, 187 a chance to actually finish the operation; otherwise,
138 the test may fail non-deterministically if the new 188 the test may fail non-deterministically if the new
139 connection is faster than the cleanup routine of the 189 connection is faster than the cleanup routine of the
140 old one. */GNUNET_SCHEDULER_add_now (&disc_cont, 190 old one. */
141 NULL); 191 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
192 &disc_cont,
193 NULL);
142} 194}
143 195
144 196
@@ -174,7 +226,10 @@ run (void *cls,
174{ 226{
175 cfg = c; 227 cfg = c;
176 memset (&pid, 1, sizeof(pid)); 228 memset (&pid, 1, sizeof(pid));
177 test1 (); 229 to = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
230 &timeout_task,
231 NULL);
232 GNUNET_SCHEDULER_add_now (&test1, NULL);
178} 233}
179 234
180 235
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
index 913b667b7..04c12735b 100644
--- a/src/reclaim/gnunet-service-reclaim.c
+++ b/src/reclaim/gnunet-service-reclaim.c
@@ -731,9 +731,12 @@ static int
731check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im) 731check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
732{ 732{
733 uint16_t size; 733 uint16_t size;
734 size_t attrs_len;
734 735
735 size = ntohs (im->header.size); 736 size = ntohs (im->header.size);
736 if (size <= sizeof(struct IssueTicketMessage)) 737 attrs_len = ntohs (im->attr_len);
738
739 if (attrs_len > size - sizeof(struct IssueTicketMessage))
737 { 740 {
738 GNUNET_break (0); 741 GNUNET_break (0);
739 return GNUNET_SYSERR; 742 return GNUNET_SYSERR;
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c b/src/reclaim/gnunet-service-reclaim_tickets.c
index ef2303bd7..48b3fe214 100644
--- a/src/reclaim/gnunet-service-reclaim_tickets.c
+++ b/src/reclaim/gnunet-service-reclaim_tickets.c
@@ -690,7 +690,10 @@ rvk_move_attr_cb (void *cls,
690 return; 690 return;
691 } 691 }
692 GNUNET_RECLAIM_id_generate (&rvk->move_attr->new_id); 692 GNUNET_RECLAIM_id_generate (&rvk->move_attr->new_id);
693 new_label = NULL; 693 new_label =
694 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
695 sizeof (rvk->move_attr->new_id));
696
694 attr_data = NULL; 697 attr_data = NULL;
695 // new_rd = *rd; 698 // new_rd = *rd;
696 for (int i = 0; i < rd_count; i++) 699 for (int i = 0; i < rd_count; i++)
@@ -714,9 +717,6 @@ rvk_move_attr_cb (void *cls,
714 new_rd[i].record_type = rd[i].record_type; 717 new_rd[i].record_type = rd[i].record_type;
715 new_rd[i].flags = rd[i].flags; 718 new_rd[i].flags = rd[i].flags;
716 new_rd[i].expiration_time = rd[i].expiration_time; 719 new_rd[i].expiration_time = rd[i].expiration_time;
717 new_label =
718 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
719 sizeof (rvk->move_attr->new_id));
720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label); 720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
721 GNUNET_free (claim); 721 GNUNET_free (claim);
722 } 722 }
@@ -738,9 +738,6 @@ rvk_move_attr_cb (void *cls,
738 new_rd[i].record_type = rd[i].record_type; 738 new_rd[i].record_type = rd[i].record_type;
739 new_rd[i].flags = rd[i].flags; 739 new_rd[i].flags = rd[i].flags;
740 new_rd[i].expiration_time = rd[i].expiration_time; 740 new_rd[i].expiration_time = rd[i].expiration_time;
741 new_label =
742 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
743 sizeof (rvk->move_attr->new_id));
744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n", 741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n",
745 new_label); 742 new_label);
746 GNUNET_free (credential); 743 GNUNET_free (credential);
@@ -1400,7 +1397,7 @@ issue_ticket (struct TicketIssueHandle *ih)
1400 attrs_record, 1397 attrs_record,
1401 &store_ticket_issue_cont, 1398 &store_ticket_issue_cont,
1402 ih); 1399 ih);
1403 for (j = 0; j > i; j++) 1400 for (j = 0; j < i; j++)
1404 { 1401 {
1405 if (attrs_record[j].record_type 1402 if (attrs_record[j].record_type
1406 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION) 1403 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
@@ -1585,7 +1582,7 @@ filter_tickets_cb (void *cls,
1585 cleanup_issue_handle (tih); 1582 cleanup_issue_handle (tih);
1586 return; 1583 return;
1587 } 1584 }
1588 1585 GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
1589 // ticket not found in current record, checking next record set 1586 // ticket not found in current record, checking next record set
1590 GNUNET_NAMESTORE_zone_iterator_next (tih->ns_it, 1); 1587 GNUNET_NAMESTORE_zone_iterator_next (tih->ns_it, 1);
1591} 1588}
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index bd3a8ee05..7b24ee598 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -839,11 +839,17 @@ int
839OIDC_access_token_parse (const char *token, 839OIDC_access_token_parse (const char *token,
840 struct GNUNET_RECLAIM_Ticket **ticket) 840 struct GNUNET_RECLAIM_Ticket **ticket)
841{ 841{
842 if (sizeof (struct GNUNET_RECLAIM_Ticket) != 842 size_t sret;
843 GNUNET_STRINGS_base64_decode (token, 843 char *decoded;
844 strlen (token), 844 sret = GNUNET_STRINGS_base64_decode (token,
845 (void**) ticket)) 845 strlen (token),
846 (void**) &decoded);
847 if (sizeof (struct GNUNET_RECLAIM_Ticket) != sret)
848 {
849 GNUNET_free (decoded);
846 return GNUNET_SYSERR; 850 return GNUNET_SYSERR;
851 }
852 *ticket = (struct GNUNET_RECLAIM_Ticket *) decoded;
847 return GNUNET_OK; 853 return GNUNET_OK;
848} 854}
849 855
diff --git a/src/reclaim/pabc_helper.c b/src/reclaim/pabc_helper.c
index e76977d03..c435ad5b3 100644
--- a/src/reclaim/pabc_helper.c
+++ b/src/reclaim/pabc_helper.c
@@ -29,7 +29,8 @@ write_file (char const *const filename, const char *buffer)
29 struct GNUNET_DISK_FileHandle *fh; 29 struct GNUNET_DISK_FileHandle *fh;
30 fh = GNUNET_DISK_file_open (filename, 30 fh = GNUNET_DISK_file_open (filename,
31 GNUNET_DISK_OPEN_WRITE 31 GNUNET_DISK_OPEN_WRITE
32 | GNUNET_DISK_OPEN_TRUNCATE, 32 | GNUNET_DISK_OPEN_TRUNCATE
33 | GNUNET_DISK_OPEN_CREATE,
33 GNUNET_DISK_PERM_USER_WRITE); 34 GNUNET_DISK_PERM_USER_WRITE);
34 if (fh == NULL) 35 if (fh == NULL)
35 return GNUNET_SYSERR; 36 return GNUNET_SYSERR;
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c
index 60c49fd6a..9e4f0a5c4 100644
--- a/src/reclaim/plugin_gnsrecord_reclaim.c
+++ b/src/reclaim/plugin_gnsrecord_reclaim.c
@@ -50,7 +50,6 @@ value_to_string (void *cls, uint32_t type, const void *data, size_t data_size)
50 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE: 50 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
51 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF: 51 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
52 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET: 52 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
53 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
54 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL: 53 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
55 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION: 54 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
56 return GNUNET_STRINGS_data_to_string_alloc (data, data_size); 55 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
@@ -87,7 +86,6 @@ string_to_value (void *cls, uint32_t type, const char *s, void **data,
87 return GNUNET_OK; 86 return GNUNET_OK;
88 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE: 87 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE:
89 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF: 88 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
90 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
91 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET: 89 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
92 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL: 90 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
93 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION: 91 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
@@ -112,7 +110,6 @@ static struct
112 { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF }, 110 { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF },
113 { "RECLAIM_CREDENTIAL", GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL }, 111 { "RECLAIM_CREDENTIAL", GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL },
114 { "RECLAIM_PRESENTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION }, 112 { "RECLAIM_PRESENTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION },
115 { "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER },
116 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT }, 113 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
117 { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT }, 114 { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT },
118 { "RECLAIM_TICKET", GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET }, 115 { "RECLAIM_TICKET", GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET },
diff --git a/src/reclaim/plugin_reclaim_credential_pabc.c b/src/reclaim/plugin_reclaim_credential_pabc.c
index 148cfec13..87406e60b 100644
--- a/src/reclaim/plugin_reclaim_credential_pabc.c
+++ b/src/reclaim/plugin_reclaim_credential_pabc.c
@@ -144,6 +144,22 @@ pabc_number_to_typename (void *cls, uint32_t type)
144} 144}
145 145
146 146
147static void
148inspect_attrs (char const *const key,
149 char const *const value,
150 void *ctx)
151{
152 struct GNUNET_RECLAIM_AttributeList *attrs = ctx;
153
154 GNUNET_RECLAIM_attribute_list_add (attrs,
155 key,
156 NULL,
157 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
158 value,
159 strlen (value));
160}
161
162
147/** 163/**
148 * Parse a pabc and return the respective claim value as Attribute 164 * Parse a pabc and return the respective claim value as Attribute
149 * 165 *
@@ -156,14 +172,9 @@ pabc_parse_attributes (void *cls,
156 const char *data, 172 const char *data,
157 size_t data_size) 173 size_t data_size)
158{ 174{
159 const char *key;
160 struct GNUNET_RECLAIM_AttributeList *attrs; 175 struct GNUNET_RECLAIM_AttributeList *attrs;
161 char *val_str = NULL;
162 char *tmp;
163 json_t *value;
164 json_t *attr;
165 json_t *json_attrs;
166 json_t *json_root; 176 json_t *json_root;
177 json_t *json_attrs;
167 json_error_t *json_err = NULL; 178 json_error_t *json_err = NULL;
168 179
169 json_root = json_loads (data, JSON_DECODE_ANY, json_err); 180 json_root = json_loads (data, JSON_DECODE_ANY, json_err);
@@ -177,55 +188,20 @@ pabc_parse_attributes (void *cls,
177 json_decref (json_root); 188 json_decref (json_root);
178 return NULL; 189 return NULL;
179 } 190 }
180 json_attrs = json_object_get (json_root, "attributes"); 191 json_attrs = json_object_get (json_root, PABC_JSON_PLAIN_ATTRS_KEY);
181 if ((NULL == json_attrs) || 192 if ((NULL == json_attrs) ||
182 (! json_is_array (json_attrs))) 193 (! json_is_object (json_attrs)))
183 { 194 {
184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
185 "%s is not a valid pabc credentials (attributes not an array)\n", 196 "%s is not a valid pabc credentials (attributes not an object)\n",
186 data); 197 data);
187 json_decref (json_root); 198 json_decref (json_root);
188 return NULL; 199 return NULL;
189 } 200 }
190 201
191 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); 202 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
192 for (int i = 0; i < json_array_size (json_attrs); i++) 203 char *attr_str = json_dumps (json_attrs, JSON_DECODE_ANY);
193 { 204 pabc_cred_inspect_credential (attr_str, &inspect_attrs, attrs);
194 attr = json_array_get (json_attrs, i);
195 if (! json_is_object (attr))
196 {
197 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
198 "Found json entry is not an object!\n");
199 GNUNET_RECLAIM_attribute_list_destroy (attrs);
200 json_decref (json_root);
201 return NULL;
202 }
203 /**
204 * This *should* only contain a single pair.
205 */
206 json_object_foreach (attr, key, value)
207 {
208 if ((0 == strcmp ("issuer", key)) ||
209 (0 == strcmp ("expiration", key)) ||
210 (0 == strcmp ("subject", key)))
211 continue;
212 val_str = json_dumps (value, JSON_ENCODE_ANY);
213 tmp = val_str;
214 // Remove leading " from jasson conversion
215 if (tmp[0] == '"')
216 tmp++;
217 // Remove trailing " from jansson conversion
218 if (tmp[strlen (tmp) - 1] == '"')
219 tmp[strlen (tmp) - 1] = '\0';
220 GNUNET_RECLAIM_attribute_list_add (attrs,
221 key,
222 NULL,
223 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
224 tmp,
225 strlen (tmp));
226 GNUNET_free (val_str);
227 }
228 }
229 json_decref (json_root); 205 json_decref (json_root);
230 return attrs; 206 return attrs;
231} 207}
@@ -260,6 +236,22 @@ pabc_parse_attributes_p (void *cls,
260 return pabc_parse_attributes (cls, cred->data, cred->data_size); 236 return pabc_parse_attributes (cls, cred->data, cred->data_size);
261} 237}
262 238
239struct Finder
240{
241 const char* target;
242 char *result;
243};
244
245static void
246find_attr (char const *const key,
247 char const *const value,
248 void *ctx)
249{
250 struct Finder *fdr = ctx;
251 if (0 == strcmp (key, fdr->target))
252 fdr->result = GNUNET_strdup (value);
253}
254
263 255
264/** 256/**
265 * Parse a pabc and return an attribute value. 257 * Parse a pabc and return an attribute value.
@@ -267,7 +259,7 @@ pabc_parse_attributes_p (void *cls,
267 * @param cls the plugin 259 * @param cls the plugin
268 * @param data the pabc credential data 260 * @param data the pabc credential data
269 * @param data_size the pabc credential size 261 * @param data_size the pabc credential size
270 * @param key the attribute key to look for. 262 * @param skey the attribute key to look for.
271 * @return a string, containing the isser 263 * @return a string, containing the isser
272 */ 264 */
273char * 265char *
@@ -276,13 +268,8 @@ pabc_get_attribute (void *cls,
276 size_t data_size, 268 size_t data_size,
277 const char *skey) 269 const char *skey)
278{ 270{
279 const char *key;
280 char *val_str = NULL;
281 char *tmp;
282 json_t *json_root; 271 json_t *json_root;
283 json_t *json_attrs; 272 json_t *json_attrs;
284 json_t *value;
285 json_t *attr;
286 json_error_t *json_err = NULL; 273 json_error_t *json_err = NULL;
287 274
288 json_root = json_loads (data, JSON_DECODE_ANY, json_err); 275 json_root = json_loads (data, JSON_DECODE_ANY, json_err);
@@ -290,50 +277,29 @@ pabc_get_attribute (void *cls,
290 (! json_is_object (json_root))) 277 (! json_is_object (json_root)))
291 { 278 {
292 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 279 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
293 "%s is not a valid pabc credentials (not an object)\n", 280 "%s is not a valid pabc credential (not an object)\n",
294 data); 281 data);
295 if (NULL != json_root) 282 if (NULL != json_root)
296 json_decref (json_root); 283 json_decref (json_root);
297 return NULL; 284 return NULL;
298 } 285 }
299 json_attrs = json_object_get (json_root, "attributes"); 286 json_attrs = json_object_get (json_root, PABC_JSON_PLAIN_ATTRS_KEY);
300 if ((NULL == json_attrs) || 287 if ((NULL == json_attrs) ||
301 (! json_is_array (json_attrs))) 288 (! json_is_object (json_attrs)))
302 { 289 {
303 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 290 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
304 "%s is not a valid pabc credentials (attributes not an array)\n", 291 "%s is not a valid pabc credential (attributes not an object)\n",
305 data); 292 data);
306 json_decref (json_root); 293 json_decref (json_root);
307 return NULL; 294 return NULL;
308 } 295 }
309 296 char *attr_str = json_dumps (json_attrs, JSON_DECODE_ANY);
310 for (int i = 0; i < json_array_size (json_attrs); i++)
311 {
312 attr = json_array_get (json_attrs, i);
313 if (! json_is_object (attr))
314 continue;
315 /**
316 * This *should* only contain a single pair.
317 */
318 json_object_foreach (attr, key, value)
319 {
320 if (0 != strcmp (skey, key))
321 continue;
322 val_str = json_dumps (value, JSON_ENCODE_ANY);
323 tmp = val_str;
324 // Remove leading " from jasson conversion
325 if (tmp[0] == '"')
326 tmp++;
327 // Remove trailing " from jansson conversion
328 if (tmp[strlen (tmp) - 1] == '"')
329 tmp[strlen (tmp) - 1] = '\0';
330 GNUNET_free (val_str);
331 json_decref (json_root);
332 return tmp;
333 }
334 }
335 json_decref (json_root); 297 json_decref (json_root);
336 return NULL; 298 struct Finder fdr;
299 memset (&fdr, 0, sizeof (fdr));
300 fdr.target = skey;
301 pabc_cred_inspect_credential (attr_str, &find_attr, &fdr);
302 return fdr.result;
337} 303}
338 304
339 305
@@ -403,9 +369,8 @@ pabc_get_expiration (void *cls,
403 json_t *json_root; 369 json_t *json_root;
404 json_t *json_attrs; 370 json_t *json_attrs;
405 json_t *value; 371 json_t *value;
406 json_t *attr; 372 json_t *exp_j;
407 json_error_t *json_err = NULL; 373 json_error_t *json_err = NULL;
408 const char*key;
409 374
410 json_root = json_loads (data, JSON_DECODE_ANY, json_err); 375 json_root = json_loads (data, JSON_DECODE_ANY, json_err);
411 if ((NULL == json_root) || 376 if ((NULL == json_root) ||
@@ -418,24 +383,23 @@ pabc_get_expiration (void *cls,
418 json_decref (json_root); 383 json_decref (json_root);
419 return GNUNET_SYSERR; 384 return GNUNET_SYSERR;
420 } 385 }
421 for (int i = 0; i < json_array_size (json_attrs); i++) 386 json_attrs = json_object_get (json_root, PABC_JSON_PLAIN_ATTRS_KEY);
387 if ((NULL == json_attrs) ||
388 (! json_is_object (json_attrs)))
422 { 389 {
423 attr = json_array_get (json_attrs, i); 390 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
424 if (! json_is_object (attr)) 391 "%s is not a valid pabc credential (attributes not an object)\n",
425 continue; 392 data);
426 /** 393 json_decref (json_root);
427 * This *should* only contain a single pair. 394 return GNUNET_SYSERR;
428 */ 395 }
429 json_object_foreach (attr, key, value) 396 exp_j = json_object_get (json_attrs, "expiration");
430 { 397 if ((NULL != exp_j) &&
431 if (0 != strcmp ("expiration", key)) 398 json_is_integer (exp_j))
432 continue; 399 {
433 if (! json_is_integer (value)) 400 exp->abs_value_us = json_integer_value (value) * 1000 * 1000;
434 continue; 401 json_decref (json_root);
435 exp->abs_value_us = json_integer_value (value) * 1000 * 1000; 402 return GNUNET_OK;
436 json_decref (json_root);
437 return GNUNET_OK;
438 }
439 } 403 }
440 json_decref (json_root); 404 json_decref (json_root);
441 return GNUNET_SYSERR; 405 return GNUNET_SYSERR;
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
index 0ee61755b..c6259d745 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -686,7 +686,10 @@ do_userinfo_error (void *cls)
686 handle->emsg, 686 handle->emsg,
687 (NULL != handle->edesc) ? handle->edesc : ""); 687 (NULL != handle->edesc) ? handle->edesc : "");
688 resp = GNUNET_REST_create_response (""); 688 resp = GNUNET_REST_create_response ("");
689 MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer"); 689 GNUNET_assert (MHD_NO !=
690 MHD_add_response_header (resp,
691 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
692 "Bearer"));
690 handle->proc (handle->proc_cls, resp, handle->response_code); 693 handle->proc (handle->proc_cls, resp, handle->response_code);
691 cleanup_handle (handle); 694 cleanup_handle (handle);
692 GNUNET_free (error); 695 GNUNET_free (error);
@@ -713,7 +716,8 @@ do_redirect_error (void *cls)
713 (NULL != handle->oidc->state) ? "&state=" : "", 716 (NULL != handle->oidc->state) ? "&state=" : "",
714 (NULL != handle->oidc->state) ? handle->oidc->state : ""); 717 (NULL != handle->oidc->state) ? handle->oidc->state : "");
715 resp = GNUNET_REST_create_response (""); 718 resp = GNUNET_REST_create_response ("");
716 MHD_add_response_header (resp, "Location", redirect); 719 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
720 "Location", redirect));
717 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); 721 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
718 cleanup_handle (handle); 722 cleanup_handle (handle);
719 GNUNET_free (redirect); 723 GNUNET_free (redirect);
@@ -1022,7 +1026,8 @@ oidc_ticket_issue_cb (void *cls,
1022 handle->oidc->state); 1026 handle->oidc->state);
1023 } 1027 }
1024 resp = GNUNET_REST_create_response (""); 1028 resp = GNUNET_REST_create_response ("");
1025 MHD_add_response_header (resp, "Location", redirect_uri); 1029 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1030 "Location", redirect_uri));
1026 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); 1031 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1027 cleanup_handle (handle); 1032 cleanup_handle (handle);
1028 GNUNET_free (redirect_uri); 1033 GNUNET_free (redirect_uri);
@@ -1381,7 +1386,8 @@ build_redirect (void *cls)
1381 handle->oidc->state); 1386 handle->oidc->state);
1382 } 1387 }
1383 resp = GNUNET_REST_create_response (""); 1388 resp = GNUNET_REST_create_response ("");
1384 MHD_add_response_header (resp, "Location", redirect_uri); 1389 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1390 "Location", redirect_uri));
1385 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); 1391 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1386 cleanup_handle (handle); 1392 cleanup_handle (handle);
1387 GNUNET_free (redirect_uri); 1393 GNUNET_free (redirect_uri);
@@ -1764,8 +1770,12 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1764 "%s;Max-Age=%d", 1770 "%s;Max-Age=%d",
1765 cookie, 1771 cookie,
1766 OIDC_COOKIE_EXPIRATION); 1772 OIDC_COOKIE_EXPIRATION);
1767 MHD_add_response_header (resp, "Set-Cookie", header_val); 1773 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1768 MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST"); 1774 "Set-Cookie", header_val));
1775 GNUNET_assert (MHD_NO !=
1776 MHD_add_response_header (resp,
1777 "Access-Control-Allow-Methods",
1778 "POST"));
1769 GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key); 1779 GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1770 1780
1771 if (0 != strcmp (json_string_value (identity), "Denied")) 1781 if (0 != strcmp (json_string_value (identity), "Denied"))
@@ -1880,7 +1890,8 @@ parse_credentials_post_body (struct RequestHandle *handle,
1880 } 1890 }
1881 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, 1891 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1882 &cache_key); 1892 &cache_key);
1883 if (NULL == pass) { 1893 if (NULL == pass)
1894 {
1884 GNUNET_free (*client_id); 1895 GNUNET_free (*client_id);
1885 *client_id = NULL; 1896 *client_id = NULL;
1886 return GNUNET_SYSERR; 1897 return GNUNET_SYSERR;
@@ -2134,6 +2145,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2134 GNUNET_free (code); 2145 GNUNET_free (code);
2135 if (NULL != nonce) 2146 if (NULL != nonce)
2136 GNUNET_free (nonce); 2147 GNUNET_free (nonce);
2148 GNUNET_RECLAIM_attribute_list_destroy (cl);
2149 GNUNET_RECLAIM_presentation_list_destroy (pl);
2137 GNUNET_SCHEDULER_add_now (&do_error, handle); 2150 GNUNET_SCHEDULER_add_now (&do_error, handle);
2138 return; 2151 return;
2139 } 2152 }
@@ -2149,6 +2162,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2149 handle->edesc = GNUNET_strdup ("No signing secret configured!"); 2162 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2150 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; 2163 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2151 GNUNET_free (code); 2164 GNUNET_free (code);
2165 GNUNET_RECLAIM_attribute_list_destroy (cl);
2166 GNUNET_RECLAIM_presentation_list_destroy (pl);
2152 if (NULL != nonce) 2167 if (NULL != nonce)
2153 GNUNET_free (nonce); 2168 GNUNET_free (nonce);
2154 GNUNET_SCHEDULER_add_now (&do_error, handle); 2169 GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -2191,9 +2206,14 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2191 &json_response); 2206 &json_response);
2192 2207
2193 resp = GNUNET_REST_create_response (json_response); 2208 resp = GNUNET_REST_create_response (json_response);
2194 MHD_add_response_header (resp, "Cache-Control", "no-store"); 2209 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2195 MHD_add_response_header (resp, "Pragma", "no-cache"); 2210 "Cache-Control",
2196 MHD_add_response_header (resp, "Content-Type", "application/json"); 2211 "no-store"));
2212 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2213 "Pragma", "no-cache"));
2214 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2215 "Content-Type",
2216 "application/json"));
2197 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 2217 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2198 GNUNET_RECLAIM_attribute_list_destroy (cl); 2218 GNUNET_RECLAIM_attribute_list_destroy (cl);
2199 GNUNET_RECLAIM_presentation_list_destroy (pl); 2219 GNUNET_RECLAIM_presentation_list_destroy (pl);
@@ -2665,8 +2685,14 @@ oidc_config_cors (struct GNUNET_REST_RequestHandle *con_handle,
2665 2685
2666 // For now, independent of path return all options 2686 // For now, independent of path return all options
2667 resp = GNUNET_REST_create_response (NULL); 2687 resp = GNUNET_REST_create_response (NULL);
2668 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); 2688 GNUNET_assert (MHD_NO !=
2669 MHD_add_response_header (resp, "Access-Control-Allow-Origin", "*"); 2689 MHD_add_response_header (resp,
2690 "Access-Control-Allow-Methods",
2691 allow_methods));
2692 GNUNET_assert (MHD_NO !=
2693 MHD_add_response_header (resp,
2694 "Access-Control-Allow-Origin",
2695 "*"));
2670 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 2696 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2671 cleanup_handle (handle); 2697 cleanup_handle (handle);
2672 return; 2698 return;
diff --git a/src/reclaim/plugin_rest_pabc.c b/src/reclaim/plugin_rest_pabc.c
index 1c766a716..9c1ac3c47 100644
--- a/src/reclaim/plugin_rest_pabc.c
+++ b/src/reclaim/plugin_rest_pabc.c
@@ -264,9 +264,8 @@ set_attributes_from_idtoken (const struct pabc_context *ctx,
264 json_string_value (value)); 264 json_string_value (value));
265 if (PABC_OK != status) 265 if (PABC_OK != status)
266 { 266 {
267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 267 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
268 "Failed to set attribute.\n"); 268 "Failed to set attribute `%s'.\n", key);
269 return PABC_FAILURE;
270 } 269 }
271 } 270 }
272 return PABC_OK; 271 return PABC_OK;
@@ -370,7 +369,7 @@ cr_cont (struct GNUNET_REST_RequestHandle *con_handle,
370 GNUNET_SCHEDULER_add_now (&do_error, handle); 369 GNUNET_SCHEDULER_add_now (&do_error, handle);
371 return; 370 return;
372 } 371 }
373 idtoken_json = json_object_get (idtoken_json, "id_token"); 372 idtoken_json = json_object_get (data_json, "id_token");
374 if (NULL == idtoken_json) 373 if (NULL == idtoken_json)
375 { 374 {
376 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 375 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -390,13 +389,18 @@ cr_cont (struct GNUNET_REST_RequestHandle *con_handle,
390 } 389 }
391 390
392 PABC_ASSERT (pabc_new_ctx (&ctx)); 391 PABC_ASSERT (pabc_new_ctx (&ctx));
393 // FIXME jansson does stupid escaping here maybe expect ecoded? 392 char *pp_str = json_dumps (pp_json, JSON_ENCODE_ANY);
394 status = pabc_decode_and_new_public_parameters (ctx, 393 status = pabc_decode_and_new_public_parameters (ctx,
395 &pp, 394 &pp,
396 json_string_value (pp_json)); 395 pp_str);
396 char *ppid;
397 GNUNET_assert (PABC_OK == pabc_cred_get_ppid_from_pp (pp_str, &ppid));
398 GNUNET_free (pp_str);
397 if (status != PABC_OK) 399 if (status != PABC_OK)
398 { 400 {
399 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to read public parameters.\n"); 401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
402 "Failed to read public parameters: %s\n",
403 pp_str);
400 json_decref (data_json); 404 json_decref (data_json);
401 GNUNET_SCHEDULER_add_now (&do_error, handle); 405 GNUNET_SCHEDULER_add_now (&do_error, handle);
402 return; 406 return;
@@ -457,8 +461,8 @@ cr_cont (struct GNUNET_REST_RequestHandle *con_handle,
457 GNUNET_SCHEDULER_add_now (&do_error, handle); 461 GNUNET_SCHEDULER_add_now (&do_error, handle);
458 return; 462 return;
459 } 463 }
460 // FIXME: where does this come from??? 464 char *nonce_str = json_dumps (nonce_json, JSON_ENCODE_ANY);
461 status = pabc_decode_nonce (ctx, nonce, json_string_value (nonce_json)); 465 status = pabc_decode_nonce (ctx, nonce, nonce_str);
462 if (status != PABC_OK) 466 if (status != PABC_OK)
463 { 467 {
464 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to decode nonce.\n"); 468 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to decode nonce.\n");
@@ -496,7 +500,9 @@ cr_cont (struct GNUNET_REST_RequestHandle *con_handle,
496 return; 500 return;
497 } 501 }
498 handle->resp_object = json_object (); 502 handle->resp_object = json_object ();
499 pabc_encode_credential_request (ctx, pp, cr, &response_str); 503 GNUNET_assert (PABC_OK == pabc_cred_encode_cr (ctx, pp, cr,
504 json_string_value (identity_json),
505 ppid, &response_str));
500 if (PABC_OK != status) 506 if (PABC_OK != status)
501 { 507 {
502 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to serialize cr.\n"); 508 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to serialize cr.\n");
@@ -508,9 +514,9 @@ cr_cont (struct GNUNET_REST_RequestHandle *con_handle,
508 GNUNET_SCHEDULER_add_now (&do_error, handle); 514 GNUNET_SCHEDULER_add_now (&do_error, handle);
509 return; 515 return;
510 } 516 }
517 json_decref (handle->resp_object);
518 handle->resp_object = json_loads (response_str, JSON_DECODE_ANY, &err);
511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", response_str); 519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", response_str);
512 json_object_set_new (handle->resp_object, "cr",
513 json_string (response_str));
514 GNUNET_free (response_str); 520 GNUNET_free (response_str);
515 521
516 // clean up 522 // clean up
@@ -593,7 +599,7 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
593 * @return NULL on error, otherwise the plugin context 599 * @return NULL on error, otherwise the plugin context
594 */ 600 */
595void * 601void *
596libgnunet_plugin_rest_reclaim_init (void *cls) 602libgnunet_plugin_rest_pabc_init (void *cls)
597{ 603{
598 static struct Plugin plugin; 604 static struct Plugin plugin;
599 struct GNUNET_REST_Plugin *api; 605 struct GNUNET_REST_Plugin *api;
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
index 84456b386..39d24ea61 100644
--- a/src/reclaim/plugin_rest_reclaim.c
+++ b/src/reclaim/plugin_rest_reclaim.c
@@ -353,14 +353,18 @@ finished_cont (void *cls, int32_t success, const char *emsg)
353 struct MHD_Response *resp; 353 struct MHD_Response *resp;
354 354
355 handle->idp_op = NULL; 355 handle->idp_op = NULL;
356 resp = GNUNET_REST_create_response (emsg);
357 MHD_add_response_header (resp, "Content-Type", "application/json");
358 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
359 if (GNUNET_OK != success) 356 if (GNUNET_OK != success)
360 { 357 {
361 GNUNET_SCHEDULER_add_now (&do_error, handle); 358 GNUNET_SCHEDULER_add_now (&do_error, handle);
362 return; 359 return;
363 } 360 }
361 resp = GNUNET_REST_create_response (emsg);
362 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
363 "Content-Type",
364 "application/json"));
365 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
366 "Access-Control-Allow-Methods",
367 allow_methods));
364 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 368 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
365 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); 369 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
366} 370}
@@ -372,13 +376,15 @@ delete_finished_cb (void *cls, int32_t success, const char *emsg)
372 struct RequestHandle *handle = cls; 376 struct RequestHandle *handle = cls;
373 struct MHD_Response *resp; 377 struct MHD_Response *resp;
374 378
375 resp = GNUNET_REST_create_response (emsg);
376 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
377 if (GNUNET_OK != success) 379 if (GNUNET_OK != success)
378 { 380 {
379 GNUNET_SCHEDULER_add_now (&do_error, handle); 381 GNUNET_SCHEDULER_add_now (&do_error, handle);
380 return; 382 return;
381 } 383 }
384 resp = GNUNET_REST_create_response (emsg);
385 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
386 "Access-Control-Allow-Methods",
387 allow_methods));
382 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 388 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
383 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); 389 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
384} 390}
@@ -399,7 +405,10 @@ return_response (void *cls)
399 result_str = json_dumps (handle->resp_object, 0); 405 result_str = json_dumps (handle->resp_object, 0);
400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
401 resp = GNUNET_REST_create_response (result_str); 407 resp = GNUNET_REST_create_response (result_str);
402 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); 408 GNUNET_assert (MHD_NO !=
409 MHD_add_response_header (resp,
410 "Access-Control-Allow-Methods",
411 allow_methods));
403 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 412 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
404 GNUNET_free (result_str); 413 GNUNET_free (result_str);
405 cleanup_handle (handle); 414 cleanup_handle (handle);
@@ -461,8 +470,8 @@ ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
461 470
462static void 471static void
463add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle, 472add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
464 const char *url, 473 const char *url,
465 void *cls) 474 void *cls)
466{ 475{
467 struct RequestHandle *handle = cls; 476 struct RequestHandle *handle = cls;
468 const struct GNUNET_IDENTITY_PrivateKey *identity_priv; 477 const struct GNUNET_IDENTITY_PrivateKey *identity_priv;
@@ -513,7 +522,15 @@ add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
513 handle->rest_handle->data, 522 handle->rest_handle->data,
514 handle->rest_handle->data_size); 523 handle->rest_handle->data_size);
515 data_json = json_loads (term_data, JSON_DECODE_ANY, &err); 524 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
516 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL); 525 if (GNUNET_OK != GNUNET_JSON_parse (data_json, attrspec, NULL, NULL))
526 {
527 json_decref (data_json);
528 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
529 "Unable to parse JSON from %s\n",
530 term_data);
531 GNUNET_SCHEDULER_add_now (&do_error, handle);
532 return;
533 }
517 json_decref (data_json); 534 json_decref (data_json);
518 if (NULL == attribute) 535 if (NULL == attribute)
519 { 536 {
@@ -530,11 +547,11 @@ add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
530 GNUNET_RECLAIM_id_generate (&attribute->id); 547 GNUNET_RECLAIM_id_generate (&attribute->id);
531 exp = GNUNET_TIME_UNIT_HOURS; 548 exp = GNUNET_TIME_UNIT_HOURS;
532 handle->idp_op = GNUNET_RECLAIM_credential_store (idp, 549 handle->idp_op = GNUNET_RECLAIM_credential_store (idp,
533 identity_priv, 550 identity_priv,
534 attribute, 551 attribute,
535 &exp, 552 &exp,
536 &finished_cont, 553 &finished_cont,
537 handle); 554 handle);
538 GNUNET_JSON_parse_free (attrspec); 555 GNUNET_JSON_parse_free (attrspec);
539} 556}
540 557
@@ -545,8 +562,8 @@ add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
545 */ 562 */
546static void 563static void
547cred_collect (void *cls, 564cred_collect (void *cls,
548 const struct GNUNET_IDENTITY_PublicKey *identity, 565 const struct GNUNET_IDENTITY_PublicKey *identity,
549 const struct GNUNET_RECLAIM_Credential *cred) 566 const struct GNUNET_RECLAIM_Credential *cred)
550{ 567{
551 struct RequestHandle *handle = cls; 568 struct RequestHandle *handle = cls;
552 struct GNUNET_RECLAIM_AttributeList *attrs; 569 struct GNUNET_RECLAIM_AttributeList *attrs;
@@ -565,8 +582,8 @@ cred_collect (void *cls,
565 attrs = GNUNET_RECLAIM_credential_get_attributes (cred); 582 attrs = GNUNET_RECLAIM_credential_get_attributes (cred);
566 issuer = GNUNET_RECLAIM_credential_get_issuer (cred); 583 issuer = GNUNET_RECLAIM_credential_get_issuer (cred);
567 tmp_value = GNUNET_RECLAIM_credential_value_to_string (cred->type, 584 tmp_value = GNUNET_RECLAIM_credential_value_to_string (cred->type,
568 cred->data, 585 cred->data,
569 cred->data_size); 586 cred->data_size);
570 cred_obj = json_object (); 587 cred_obj = json_object ();
571 json_object_set_new (cred_obj, "value", json_string (tmp_value)); 588 json_object_set_new (cred_obj, "value", json_string (tmp_value));
572 json_object_set_new (cred_obj, "name", json_string (cred->name)); 589 json_object_set_new (cred_obj, "name", json_string (cred->name));
@@ -578,7 +595,7 @@ cred_collect (void *cls,
578 GNUNET_free (issuer); 595 GNUNET_free (issuer);
579 } 596 }
580 if (GNUNET_OK == GNUNET_RECLAIM_credential_get_expiration (cred, 597 if (GNUNET_OK == GNUNET_RECLAIM_credential_get_expiration (cred,
581 &exp)) 598 &exp))
582 { 599 {
583 json_object_set_new (cred_obj, "expiration", json_integer ( 600 json_object_set_new (cred_obj, "expiration", json_integer (
584 exp.abs_value_us)); 601 exp.abs_value_us));
@@ -613,7 +630,8 @@ cred_collect (void *cls,
613 json_object_set_new (cred_obj, "attributes", attr_arr); 630 json_object_set_new (cred_obj, "attributes", attr_arr);
614 } 631 }
615 json_array_append_new (handle->resp_object, cred_obj); 632 json_array_append_new (handle->resp_object, cred_obj);
616 GNUNET_RECLAIM_attribute_list_destroy (attrs); 633 if (NULL != attrs)
634 GNUNET_RECLAIM_attribute_list_destroy (attrs);
617 GNUNET_RECLAIM_get_credentials_next (handle->cred_it); 635 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
618} 636}
619 637
@@ -627,8 +645,8 @@ cred_collect (void *cls,
627 */ 645 */
628static void 646static void
629list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle, 647list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
630 const char *url, 648 const char *url,
631 void *cls) 649 void *cls)
632{ 650{
633 struct RequestHandle *handle = cls; 651 struct RequestHandle *handle = cls;
634 const struct GNUNET_IDENTITY_PrivateKey *priv_key; 652 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
@@ -664,14 +682,14 @@ list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
664 } 682 }
665 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); 683 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
666 handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp, 684 handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
667 priv_key, 685 priv_key,
668 &collect_error_cb, 686 &collect_error_cb,
669 handle, 687 handle,
670 &cred_collect, 688 &cred_collect,
671 handle, 689 handle,
672 & 690 &
673 collect_finished_cb, 691 collect_finished_cb,
674 handle); 692 handle);
675} 693}
676 694
677 695
@@ -684,8 +702,8 @@ list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
684 */ 702 */
685static void 703static void
686delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle, 704delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
687 const char *url, 705 const char *url,
688 void *cls) 706 void *cls)
689{ 707{
690 struct RequestHandle *handle = cls; 708 struct RequestHandle *handle = cls;
691 const struct GNUNET_IDENTITY_PrivateKey *priv_key; 709 const struct GNUNET_IDENTITY_PrivateKey *priv_key;
@@ -734,10 +752,10 @@ delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
734 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id)); 752 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
735 attr.name = ""; 753 attr.name = "";
736 handle->idp_op = GNUNET_RECLAIM_credential_delete (idp, 754 handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
737 priv_key, 755 priv_key,
738 &attr, 756 &attr,
739 &delete_finished_cb, 757 &delete_finished_cb,
740 handle); 758 handle);
741 GNUNET_free (identity_id_str); 759 GNUNET_free (identity_id_str);
742} 760}
743 761
@@ -900,8 +918,8 @@ parse_jwt (const struct GNUNET_RECLAIM_Credential *cred,
900 json_error_t *json_err = NULL; 918 json_error_t *json_err = NULL;
901 919
902 jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type, 920 jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type,
903 cred->data, 921 cred->data,
904 cred->data_size); 922 cred->data_size);
905 char *jwt_body = strtok (jwt_string, delim); 923 char *jwt_body = strtok (jwt_string, delim);
906 jwt_body = strtok (NULL, delim); 924 jwt_body = strtok (NULL, delim);
907 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body), 925 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
@@ -1424,25 +1442,24 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1424 static const struct GNUNET_REST_RequestHandler handlers[] = 1442 static const struct GNUNET_REST_RequestHandler handlers[] =
1425 { { MHD_HTTP_METHOD_GET, 1443 { { MHD_HTTP_METHOD_GET,
1426 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont }, 1444 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont },
1427 { MHD_HTTP_METHOD_POST, 1445 { MHD_HTTP_METHOD_POST,
1428 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont }, 1446 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont },
1429 { MHD_HTTP_METHOD_DELETE, 1447 { MHD_HTTP_METHOD_DELETE,
1430 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont }, 1448 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont },
1431 { MHD_HTTP_METHOD_GET, 1449 { MHD_HTTP_METHOD_GET,
1432 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont }, 1450 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
1433 { MHD_HTTP_METHOD_POST, 1451 { MHD_HTTP_METHOD_POST,
1434 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont }, 1452 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
1435 { MHD_HTTP_METHOD_DELETE, 1453 { MHD_HTTP_METHOD_DELETE,
1436 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont }, 1454 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont },
1437 { MHD_HTTP_METHOD_GET, 1455 { MHD_HTTP_METHOD_GET,
1438 GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont }, 1456 GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont },
1439 { MHD_HTTP_METHOD_POST, 1457 { MHD_HTTP_METHOD_POST,
1440 GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont }, 1458 GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont },
1441 { MHD_HTTP_METHOD_POST, 1459 { MHD_HTTP_METHOD_POST,
1442 GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont }, 1460 GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont },
1443 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont }, 1461 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
1444 GNUNET_REST_HANDLER_END 1462 GNUNET_REST_HANDLER_END};
1445 };
1446 1463
1447 handle->response_code = 0; 1464 handle->response_code = 0;
1448 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 1465 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
index f4f2b946a..c08cc868c 100644
--- a/src/reclaim/reclaim_api.c
+++ b/src/reclaim/reclaim_api.c
@@ -651,18 +651,15 @@ handle_consume_ticket_result (void *cls,
651 le->attribute, NULL); 651 le->attribute, NULL);
652 } 652 }
653 } 653 }
654 if (NULL != attrs)
655 GNUNET_RECLAIM_attribute_list_destroy (attrs);
656 if (NULL != pl)
657 GNUNET_RECLAIM_presentation_list_destroy (pl);
658 attrs = NULL;
659 pl = NULL;
660 } 654 }
661 op->atr_cb (op->cls, NULL, NULL, NULL); 655 op->atr_cb (op->cls, NULL, NULL, NULL);
662 } 656 }
657 if (NULL != attrs)
658 GNUNET_RECLAIM_attribute_list_destroy (attrs);
659 if (NULL != pl)
660 GNUNET_RECLAIM_presentation_list_destroy (pl);
663 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); 661 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
664 free_op (op); 662 free_op (op);
665 GNUNET_free (attrs);
666 return; 663 return;
667 } 664 }
668 GNUNET_assert (0); 665 GNUNET_assert (0);
@@ -804,7 +801,7 @@ check_credential_result (void *cls, const struct CredentialResultMessage *msg)
804 */ 801 */
805static void 802static void
806handle_credential_result (void *cls, const struct 803handle_credential_result (void *cls, const struct
807 CredentialResultMessage *msg) 804 CredentialResultMessage *msg)
808{ 805{
809 static struct GNUNET_IDENTITY_PrivateKey identity_dummy; 806 static struct GNUNET_IDENTITY_PrivateKey identity_dummy;
810 struct GNUNET_RECLAIM_Handle *h = cls; 807 struct GNUNET_RECLAIM_Handle *h = cls;
@@ -871,6 +868,7 @@ handle_credential_result (void *cls, const struct
871 GNUNET_assert (0); 868 GNUNET_assert (0);
872} 869}
873 870
871
874/** 872/**
875 * Handle an incoming message of type 873 * Handle an incoming message of type
876 * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT 874 * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
@@ -925,7 +923,7 @@ handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
925 if (NULL != op) 923 if (NULL != op)
926 { 924 {
927 if (0 < pres_len) 925 if (0 < pres_len)
928 pres = GNUNET_RECLAIM_presentation_list_deserialize ((char*)&msg[1], 926 pres = GNUNET_RECLAIM_presentation_list_deserialize ((char*) &msg[1],
929 pres_len); 927 pres_len);
930 GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op); 928 GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
931 if (0 == 929 if (0 ==
@@ -1485,7 +1483,7 @@ GNUNET_RECLAIM_get_credentials_start (
1485 */ 1483 */
1486void 1484void
1487GNUNET_RECLAIM_get_credentials_next (struct 1485GNUNET_RECLAIM_get_credentials_next (struct
1488 GNUNET_RECLAIM_CredentialIterator *ait) 1486 GNUNET_RECLAIM_CredentialIterator *ait)
1489{ 1487{
1490 struct GNUNET_RECLAIM_Handle *h = ait->h; 1488 struct GNUNET_RECLAIM_Handle *h = ait->h;
1491 struct CredentialIterationNextMessage *msg; 1489 struct CredentialIterationNextMessage *msg;
@@ -1507,7 +1505,7 @@ GNUNET_RECLAIM_get_credentials_next (struct
1507 */ 1505 */
1508void 1506void
1509GNUNET_RECLAIM_get_credentials_stop (struct 1507GNUNET_RECLAIM_get_credentials_stop (struct
1510 GNUNET_RECLAIM_CredentialIterator *ait) 1508 GNUNET_RECLAIM_CredentialIterator *ait)
1511{ 1509{
1512 struct GNUNET_RECLAIM_Handle *h = ait->h; 1510 struct GNUNET_RECLAIM_Handle *h = ait->h;
1513 struct GNUNET_MQ_Envelope *env; 1511 struct GNUNET_MQ_Envelope *env;
diff --git a/src/reclaim/reclaim_attribute.c b/src/reclaim/reclaim_attribute.c
index 14690d7c9..21fdd83a2 100644
--- a/src/reclaim/reclaim_attribute.c
+++ b/src/reclaim/reclaim_attribute.c
@@ -96,10 +96,11 @@ init ()
96 if (GNUNET_YES == initialized) 96 if (GNUNET_YES == initialized)
97 return; 97 return;
98 initialized = GNUNET_YES; 98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_", 99 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
100 NULL, 100 "libgnunet_plugin_reclaim_attribute_",
101 &add_plugin, 101 NULL,
102 NULL); 102 &add_plugin,
103 NULL);
103} 104}
104 105
105/** 106/**
diff --git a/src/reclaim/reclaim_credential.c b/src/reclaim/reclaim_credential.c
index 05601c3d3..c8c0d397c 100644
--- a/src/reclaim/reclaim_credential.c
+++ b/src/reclaim/reclaim_credential.c
@@ -96,10 +96,11 @@ init ()
96 if (GNUNET_YES == initialized) 96 if (GNUNET_YES == initialized)
97 return; 97 return;
98 initialized = GNUNET_YES; 98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_credential_", 99 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
100 NULL, 100 "libgnunet_plugin_reclaim_credential_",
101 &add_plugin, 101 NULL,
102 NULL); 102 &add_plugin,
103 NULL);
103} 104}
104 105
105 106
diff --git a/src/rest/gnunet-rest-server.c b/src/rest/gnunet-rest-server.c
index e6e03b16d..ecb3e2ae5 100644
--- a/src/rest/gnunet-rest-server.c
+++ b/src/rest/gnunet-rest-server.c
@@ -1229,10 +1229,11 @@ run (void *cls,
1229 return; 1229 return;
1230 } 1230 }
1231 /* Load plugins */ 1231 /* Load plugins */
1232 GNUNET_PLUGIN_load_all ("libgnunet_plugin_rest", 1232 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
1233 (void *) cfg, 1233 "libgnunet_plugin_rest",
1234 &load_plugin, 1234 (void *) cfg,
1235 NULL); 1235 &load_plugin,
1236 NULL);
1236 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); 1237 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1237} 1238}
1238 1239
diff --git a/src/rest/plugin_rest_copying.c b/src/rest/plugin_rest_copying.c
index 6d074d3d1..52783a81a 100644
--- a/src/rest/plugin_rest_copying.c
+++ b/src/rest/plugin_rest_copying.c
@@ -138,9 +138,9 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
138 struct RequestHandle *handle = cls; 138 struct RequestHandle *handle = cls;
139 139
140 resp = GNUNET_REST_create_response (NULL); 140 resp = GNUNET_REST_create_response (NULL);
141 MHD_add_response_header (resp, 141 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
142 "Access-Control-Allow-Methods", 142 "Access-Control-Allow-Methods",
143 MHD_HTTP_METHOD_GET); 143 MHD_HTTP_METHOD_GET));
144 handle->proc (handle->proc_cls, 144 handle->proc (handle->proc_cls,
145 resp, 145 resp,
146 MHD_HTTP_OK); 146 MHD_HTTP_OK);
diff --git a/src/revocation/gnunet-revocation.c b/src/revocation/gnunet-revocation.c
index b5737158b..99fecdd35 100644
--- a/src/revocation/gnunet-revocation.c
+++ b/src/revocation/gnunet-revocation.c
@@ -307,17 +307,9 @@ calculate_pow (void *cls)
307 return; 307 return;
308 } 308 }
309 pow_passes++; 309 pow_passes++;
310 /** 310 pow_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
311 * Otherwise CTRL-C does not work 311 &calculate_pow,
312 */ 312 ph);
313 if (0 == pow_passes % 128)
314 pow_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
315 &calculate_pow,
316 ph);
317 else
318 pow_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
319 &calculate_pow,
320 ph);
321 313
322} 314}
323 315
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c
index 863289aae..6f70720ba 100644
--- a/src/revocation/gnunet-service-revocation.c
+++ b/src/revocation/gnunet-service-revocation.c
@@ -306,12 +306,19 @@ publicize_rm (const struct RevokeMessage *rm)
306 struct RevokeMessage *cp; 306 struct RevokeMessage *cp;
307 struct GNUNET_HashCode hc; 307 struct GNUNET_HashCode hc;
308 struct GNUNET_SETU_Element e; 308 struct GNUNET_SETU_Element e;
309 ssize_t pklen;
309 const struct GNUNET_IDENTITY_PublicKey *pk; 310 const struct GNUNET_IDENTITY_PublicKey *pk;
310 311
311 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1]; 312 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1];
312 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1]; 313 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
314 pklen = GNUNET_IDENTITY_key_get_length (pk);
315 if (0 > pklen)
316 {
317 GNUNET_break_op (0);
318 return GNUNET_SYSERR;
319 }
313 GNUNET_CRYPTO_hash (pk, 320 GNUNET_CRYPTO_hash (pk,
314 GNUNET_IDENTITY_key_get_length (pk), 321 pklen,
315 &hc); 322 &hc);
316 if (GNUNET_YES == 323 if (GNUNET_YES ==
317 GNUNET_CONTAINER_multihashmap_contains (revocation_map, 324 GNUNET_CONTAINER_multihashmap_contains (revocation_map,
@@ -384,7 +391,8 @@ check_revoke_message (void *cls,
384 uint16_t size; 391 uint16_t size;
385 392
386 size = ntohs (rm->header.size); 393 size = ntohs (rm->header.size);
387 if (size <= sizeof(struct RevokeMessage)) 394 if (size <= sizeof(struct RevokeMessage) ||
395 (size > UINT16_MAX))
388 { 396 {
389 GNUNET_break (0); 397 GNUNET_break (0);
390 return GNUNET_SYSERR; 398 return GNUNET_SYSERR;
diff --git a/src/revocation/plugin_block_revocation.c b/src/revocation/plugin_block_revocation.c
index 3c9344a49..1928d09cd 100644
--- a/src/revocation/plugin_block_revocation.c
+++ b/src/revocation/plugin_block_revocation.c
@@ -134,6 +134,7 @@ block_plugin_revocation_evaluate (void *cls,
134{ 134{
135 struct InternalContext *ic = cls; 135 struct InternalContext *ic = cls;
136 struct GNUNET_HashCode chash; 136 struct GNUNET_HashCode chash;
137 ssize_t pklen;
137 const struct RevokeMessage *rm = reply_block; 138 const struct RevokeMessage *rm = reply_block;
138 139
139 if (NULL == reply_block) 140 if (NULL == reply_block)
@@ -153,8 +154,14 @@ block_plugin_revocation_evaluate (void *cls,
153 GNUNET_break_op (0); 154 GNUNET_break_op (0);
154 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; 155 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
155 } 156 }
157 pklen = GNUNET_IDENTITY_key_get_length (pk);
158 if (0 > pklen)
159 {
160 GNUNET_break_op (0);
161 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
162 }
156 GNUNET_CRYPTO_hash (pk, 163 GNUNET_CRYPTO_hash (pk,
157 GNUNET_IDENTITY_key_get_length (pk), 164 pklen,
158 &chash); 165 &chash);
159 if (GNUNET_YES == 166 if (GNUNET_YES ==
160 GNUNET_BLOCK_GROUP_bf_test_and_set (group, 167 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
index 5cf191847..e2f871c23 100644
--- a/src/revocation/revocation_api.c
+++ b/src/revocation/revocation_api.c
@@ -492,6 +492,7 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
492 unsigned int tmp_score = 0; 492 unsigned int tmp_score = 0;
493 unsigned int epochs; 493 unsigned int epochs;
494 uint64_t pow_val; 494 uint64_t pow_val;
495 ssize_t pklen;
495 const struct GNUNET_IDENTITY_PublicKey *pk; 496 const struct GNUNET_IDENTITY_PublicKey *pk;
496 497
497 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1]; 498 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
@@ -517,9 +518,15 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
517 GNUNET_memcpy (&buf[sizeof(uint64_t)], 518 GNUNET_memcpy (&buf[sizeof(uint64_t)],
518 &pow->timestamp, 519 &pow->timestamp,
519 sizeof (uint64_t)); 520 sizeof (uint64_t));
521 pklen = GNUNET_IDENTITY_key_get_length (pk);
522 if (0 > pklen)
523 {
524 GNUNET_break (0);
525 return GNUNET_NO;
526 }
520 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2], 527 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
521 pk, 528 pk,
522 GNUNET_IDENTITY_key_get_length (pk)); 529 pklen);
523 for (unsigned int i = 0; i < POW_COUNT; i++) 530 for (unsigned int i = 0; i < POW_COUNT; i++)
524 { 531 {
525 pow_val = GNUNET_ntohll (pow->pow[i]); 532 pow_val = GNUNET_ntohll (pow->pow[i]);
diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c
index 82aeffb79..908dcca17 100644
--- a/src/rps/gnunet-rps-profiler.c
+++ b/src/rps/gnunet-rps-profiler.c
@@ -3067,9 +3067,10 @@ run (void *cls,
3067 } 3067 }
3068 else 3068 else
3069 { 3069 {
3070 duration = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3070 duration = GNUNET_TIME_relative_multiply (
3071 (timeout.rel_value_us / 1000000) 3071 GNUNET_TIME_UNIT_SECONDS,
3072 * 0.75); 3072 ( (double) timeout.rel_value_us / (double) 1000000)
3073 * 0.75);
3073 } 3074 }
3074 } 3075 }
3075 else 3076 else
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c
index dc4c5dab7..56eab288e 100644
--- a/src/rps/gnunet-service-rps.c
+++ b/src/rps/gnunet-service-rps.c
@@ -965,8 +965,6 @@ remove_channel_ctx (struct ChannelCtx *channel_ctx)
965 channel_ctx->destruction_task = NULL; 965 channel_ctx->destruction_task = NULL;
966 } 966 }
967 967
968 GNUNET_free (channel_ctx);
969
970 if (NULL == peer_ctx) 968 if (NULL == peer_ctx)
971 return; 969 return;
972 if (channel_ctx == peer_ctx->send_channel_ctx) 970 if (channel_ctx == peer_ctx->send_channel_ctx)
@@ -978,6 +976,7 @@ remove_channel_ctx (struct ChannelCtx *channel_ctx)
978 { 976 {
979 peer_ctx->recv_channel_ctx = NULL; 977 peer_ctx->recv_channel_ctx = NULL;
980 } 978 }
979 GNUNET_free (channel_ctx);
981} 980}
982 981
983 982
@@ -2637,7 +2636,7 @@ insert_in_sampler (void *cls,
2637 } 2636 }
2638#ifdef TO_FILE 2637#ifdef TO_FILE
2639 sub->num_observed_peers++; 2638 sub->num_observed_peers++;
2640 GNUNET_CONTAINER_multipeermap_put 2639 (void) GNUNET_CONTAINER_multipeermap_put
2641 (sub->observed_unique_peers, 2640 (sub->observed_unique_peers,
2642 peer, 2641 peer,
2643 NULL, 2642 NULL,
@@ -2802,7 +2801,7 @@ clean_peer (struct Sub *sub,
2802 peer))) && 2801 peer))) &&
2803 (GNUNET_NO == View_contains_peer (sub->view, peer)) && 2802 (GNUNET_NO == View_contains_peer (sub->view, peer)) &&
2804 (GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) && 2803 (GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) &&
2805 (GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) && 2804 (GNUNET_NO == CustomPeerMap_contains_peer (sub->pull_map, peer)) &&
2806 (0 == RPS_sampler_count_id (sub->sampler, peer)) && 2805 (0 == RPS_sampler_count_id (sub->sampler, peer)) &&
2807 (GNUNET_YES == check_removable (get_peer_ctx (sub->peer_map, peer)))) 2806 (GNUNET_YES == check_removable (get_peer_ctx (sub->peer_map, peer))))
2808 { /* We can safely remove this peer */ 2807 { /* We can safely remove this peer */
@@ -2836,13 +2835,20 @@ cleanup_destroyed_channel (void *cls,
2836 (void) channel; 2835 (void) channel;
2837 2836
2838 channel_ctx->channel = NULL; 2837 channel_ctx->channel = NULL;
2839 remove_channel_ctx (channel_ctx);
2840 if ((NULL != peer_ctx) && 2838 if ((NULL != peer_ctx) &&
2841 (peer_ctx->send_channel_ctx == channel_ctx) && 2839 (peer_ctx->send_channel_ctx == channel_ctx) &&
2842 (GNUNET_YES == check_sending_channel_needed (channel_ctx->peer_ctx)) ) 2840 (GNUNET_YES == check_sending_channel_needed (peer_ctx)) )
2843 { 2841 {
2842 remove_channel_ctx (channel_ctx);
2844 remove_peer (peer_ctx->sub, &peer_ctx->peer_id); 2843 remove_peer (peer_ctx->sub, &peer_ctx->peer_id);
2845 } 2844 }
2845 else
2846 {
2847 /* We need this if-else construct because we need to make sure the channel
2848 * (context) is cleaned up before removing the peer, but still neet to
2849 * compare it while checking the condition */
2850 remove_channel_ctx (channel_ctx);
2851 }
2846} 2852}
2847 2853
2848 2854
diff --git a/src/rps/gnunet-service-rps_custommap.c b/src/rps/gnunet-service-rps_custommap.c
index 54e361d32..392c29397 100644
--- a/src/rps/gnunet-service-rps_custommap.c
+++ b/src/rps/gnunet-service-rps_custommap.c
@@ -206,6 +206,7 @@ CustomPeerMap_remove_peer (const struct CustomPeerMap *c_peer_map,
206 struct GNUNET_PeerIdentity *p; 206 struct GNUNET_PeerIdentity *p;
207 uint32_t *last_index; 207 uint32_t *last_index;
208 struct GNUNET_PeerIdentity *last_p; 208 struct GNUNET_PeerIdentity *last_p;
209 int ret;
209 210
210 if (GNUNET_NO == CustomPeerMap_contains_peer (c_peer_map, 211 if (GNUNET_NO == CustomPeerMap_contains_peer (c_peer_map,
211 peer)) 212 peer))
@@ -234,9 +235,11 @@ CustomPeerMap_remove_peer (const struct CustomPeerMap *c_peer_map,
234 last_p); 235 last_p);
235 GNUNET_assert (NULL != last_index); 236 GNUNET_assert (NULL != last_index);
236 GNUNET_assert (CustomPeerMap_size (c_peer_map) == *last_index); 237 GNUNET_assert (CustomPeerMap_size (c_peer_map) == *last_index);
237 GNUNET_CONTAINER_multihashmap32_put (c_peer_map->hash_map, 238 ret = GNUNET_CONTAINER_multihashmap32_put (c_peer_map->hash_map,
238 *index, last_p, 239 *index,
239 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 240 last_p,
241 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
242 GNUNET_assert (GNUNET_OK == ret);
240 GNUNET_CONTAINER_multihashmap32_remove_all (c_peer_map->hash_map, 243 GNUNET_CONTAINER_multihashmap32_remove_all (c_peer_map->hash_map,
241 *last_index); 244 *last_index);
242 *last_index = *index; 245 *last_index = *index;
diff --git a/src/rps/rps-test_util.c b/src/rps/rps-test_util.c
index 497225973..6dee20c95 100644
--- a/src/rps/rps-test_util.c
+++ b/src/rps/rps-test_util.c
@@ -152,12 +152,16 @@ close_all_files ()
152{ 152{
153 int ret; 153 int ret;
154 154
155 ret = GNUNET_CONTAINER_multihashmap_iterate (open_files, 155 if (NULL != open_files)
156 close_files_iter, 156 {
157 NULL); 157 ret = GNUNET_CONTAINER_multihashmap_iterate (open_files,
158 GNUNET_CONTAINER_multihashmap_destroy (open_files); 158 close_files_iter,
159 open_files = NULL; 159 NULL);
160 return ret; 160 GNUNET_CONTAINER_multihashmap_destroy (open_files);
161 open_files = NULL;
162 return ret;
163 }
164 return GNUNET_YES;
161} 165}
162 166
163 167
diff --git a/src/setu/.gitignore b/src/setu/.gitignore
index 35295449b..0ac10295e 100644
--- a/src/setu/.gitignore
+++ b/src/setu/.gitignore
@@ -4,3 +4,4 @@ gnunet-setu-ibf-profiler
4test_setu_api 4test_setu_api
5test_setu_copy 5test_setu_copy
6test_setu_result_symmetric 6test_setu_result_symmetric
7perf_setu_api
diff --git a/src/setu/Makefile.am b/src/setu/Makefile.am
index cc7711462..77d048add 100644
--- a/src/setu/Makefile.am
+++ b/src/setu/Makefile.am
@@ -69,7 +69,8 @@ libgnunetsetu_la_LDFLAGS = \
69 69
70if HAVE_TESTING 70if HAVE_TESTING
71check_PROGRAMS = \ 71check_PROGRAMS = \
72 test_setu_api 72 test_setu_api \
73 perf_setu_api
73endif 74endif
74 75
75if ENABLE_TEST_RUN 76if ENABLE_TEST_RUN
@@ -84,6 +85,15 @@ test_setu_api_LDADD = \
84 $(top_builddir)/src/testing/libgnunettesting.la \ 85 $(top_builddir)/src/testing/libgnunettesting.la \
85 libgnunetsetu.la 86 libgnunetsetu.la
86 87
88
89perf_setu_api_SOURCES = \
90 perf_setu_api.c
91perf_setu_api_LDADD = \
92 $(top_builddir)/src/util/libgnunetutil.la \
93 $(top_builddir)/src/testing/libgnunettesting.la \
94 libgnunetsetu.la
95
96
87plugin_LTLIBRARIES = \ 97plugin_LTLIBRARIES = \
88 libgnunet_plugin_block_setu_test.la 98 libgnunet_plugin_block_setu_test.la
89 99
diff --git a/src/setu/gnunet-service-setu.c b/src/setu/gnunet-service-setu.c
index 540628afa..862b78aa9 100644
--- a/src/setu/gnunet-service-setu.c
+++ b/src/setu/gnunet-service-setu.c
@@ -400,6 +400,22 @@ struct Operation
400 * was created. 400 * was created.
401 */ 401 */
402 unsigned int generation_created; 402 unsigned int generation_created;
403
404 /**
405 * User defined Bandwidth Round Trips Tradeoff
406 */
407 double rtt_bandwidth_tradeoff;
408
409 /**
410 * Number of Element per bucket in IBF
411 */
412 unsigned int ibf_number_buckets_per_element;
413
414 /**
415 * Number of buckets in IBF
416 */
417 unsigned ibf_bucket_number;
418
403}; 419};
404 420
405 421
@@ -621,6 +637,98 @@ static uint32_t suggest_id;
621 637
622 638
623/** 639/**
640 * Added Roundtripscounter
641 */
642
643
644struct perf_num_send_resived_msg {
645 int sent;
646 int sent_var_bytes;
647 int received;
648 int received_var_bytes;
649};
650
651
652struct perf_rtt_struct
653{
654 struct perf_num_send_resived_msg operation_request;
655 struct perf_num_send_resived_msg se;
656 struct perf_num_send_resived_msg request_full;
657 struct perf_num_send_resived_msg element_full;
658 struct perf_num_send_resived_msg full_done;
659 struct perf_num_send_resived_msg ibf;
660 struct perf_num_send_resived_msg inquery;
661 struct perf_num_send_resived_msg element;
662 struct perf_num_send_resived_msg demand;
663 struct perf_num_send_resived_msg offer;
664 struct perf_num_send_resived_msg done;
665 struct perf_num_send_resived_msg over;
666};
667
668struct perf_rtt_struct perf_rtt;
669
670
671static int
672sum_sent_received_bytes(int size, struct perf_num_send_resived_msg perf_rtt_struct) {
673 return (size * perf_rtt_struct.sent) +
674 (size * perf_rtt_struct.received) +
675 perf_rtt_struct.sent_var_bytes +
676 perf_rtt_struct.received_var_bytes;
677}
678
679static float
680calculate_perf_rtt() {
681 /**
682 * Calculate RTT of init phase normally always 1
683 */
684 float rtt = 1;
685 int bytes_transmitted = 0;
686
687 /**
688 * Calculate RGNUNET_SETU_AcceptMessageRT of Fullsync normaly 1 or 1.5 depending
689 */
690 if (( perf_rtt.element_full.received != 0 ) ||
691 ( perf_rtt.element_full.sent != 0)
692 ) rtt += 1;
693
694 if (( perf_rtt.request_full.received != 0 ) ||
695 ( perf_rtt.request_full.sent != 0)
696 ) rtt += 0.5;
697
698 /**
699 * In case of a differential sync 3 rtt's are needed.
700 * for every active/passive switch additional 3.5 rtt's are used
701 */
702
703 int iterations = perf_rtt.ibf.received;
704 if(iterations > 1)
705 rtt += (iterations - 1 ) * 0.5;
706 rtt += 3 * iterations;
707
708 /**
709 * Calculate data sended size
710 */
711 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL), perf_rtt.request_full);
712 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT), perf_rtt.element_full);
713 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS), perf_rtt.element);
714 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST), perf_rtt.operation_request);
715 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_SE), perf_rtt.se);
716 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE), perf_rtt.full_done);
717 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_IBF), perf_rtt.ibf);
718 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY), perf_rtt.inquery);
719 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND), perf_rtt.demand);
720 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER), perf_rtt.offer);
721 bytes_transmitted += sum_sent_received_bytes(sizeof(GNUNET_MESSAGE_TYPE_SETU_P2P_DONE), perf_rtt.done);
722
723 LOG(GNUNET_ERROR_TYPE_ERROR,"Bytes Transmitted: %d\n", bytes_transmitted);
724
725 LOG(GNUNET_ERROR_TYPE_ERROR,"Reached tradeoff bandwidth/rtt: %f\n", (bytes_transmitted / rtt ));
726
727 return rtt;
728}
729
730
731/**
624 * Iterator over hash map entries, called to 732 * Iterator over hash map entries, called to
625 * destroy the linked list of colliding ibf key entries. 733 * destroy the linked list of colliding ibf key entries.
626 * 734 *
@@ -1192,8 +1300,8 @@ send_ibf (struct Operation *op,
1192 1 << ibf_order); 1300 1 << ibf_order);
1193 1301
1194 { 1302 {
1195 char name[64] = { 0 }; 1303 char name[64];
1196 snprintf (name, sizeof(name), "# sent IBF (order %u)", ibf_order); 1304 GNUNET_snprintf (name, sizeof(name), "# sent IBF (order %u)", ibf_order);
1197 GNUNET_STATISTICS_update (_GSS_statistics, name, 1, GNUNET_NO); 1305 GNUNET_STATISTICS_update (_GSS_statistics, name, 1, GNUNET_NO);
1198 } 1306 }
1199 1307
@@ -1210,6 +1318,8 @@ send_ibf (struct Operation *op,
1210 if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE) 1318 if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE)
1211 buckets_in_message = MAX_BUCKETS_PER_MESSAGE; 1319 buckets_in_message = MAX_BUCKETS_PER_MESSAGE;
1212 1320
1321 perf_rtt.ibf.sent += 1;
1322 perf_rtt.ibf.sent_var_bytes += ( buckets_in_message * IBF_BUCKET_SIZE );
1213 ev = GNUNET_MQ_msg_extra (msg, 1323 ev = GNUNET_MQ_msg_extra (msg,
1214 buckets_in_message * IBF_BUCKET_SIZE, 1324 buckets_in_message * IBF_BUCKET_SIZE,
1215 GNUNET_MESSAGE_TYPE_SETU_P2P_IBF); 1325 GNUNET_MESSAGE_TYPE_SETU_P2P_IBF);
@@ -1281,6 +1391,8 @@ send_full_element_iterator (void *cls,
1281 LOG (GNUNET_ERROR_TYPE_DEBUG, 1391 LOG (GNUNET_ERROR_TYPE_DEBUG,
1282 "Sending element %s\n", 1392 "Sending element %s\n",
1283 GNUNET_h2s (key)); 1393 GNUNET_h2s (key));
1394 perf_rtt.element_full.received += 1;
1395 perf_rtt.element_full.received_var_bytes += el->size;
1284 ev = GNUNET_MQ_msg_extra (emsg, 1396 ev = GNUNET_MQ_msg_extra (emsg,
1285 el->size, 1397 el->size,
1286 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT); 1398 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT);
@@ -1312,6 +1424,7 @@ send_full_set (struct Operation *op)
1312 (void) GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements, 1424 (void) GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
1313 &send_full_element_iterator, 1425 &send_full_element_iterator,
1314 op); 1426 op);
1427 perf_rtt.full_done.sent += 1;
1315 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE); 1428 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE);
1316 GNUNET_MQ_send (op->mq, 1429 GNUNET_MQ_send (op->mq,
1317 ev); 1430 ev);
@@ -1360,6 +1473,8 @@ static void
1360handle_union_p2p_strata_estimator (void *cls, 1473handle_union_p2p_strata_estimator (void *cls,
1361 const struct StrataEstimatorMessage *msg) 1474 const struct StrataEstimatorMessage *msg)
1362{ 1475{
1476 perf_rtt.se.received += 1;
1477 perf_rtt.se.received_var_bytes += ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
1363 struct Operation *op = cls; 1478 struct Operation *op = cls;
1364 struct StrataEstimator *remote_se; 1479 struct StrataEstimator *remote_se;
1365 unsigned int diff; 1480 unsigned int diff;
@@ -1431,6 +1546,13 @@ handle_union_p2p_strata_estimator (void *cls,
1431 return; 1546 return;
1432 } 1547 }
1433 1548
1549 LOG (GNUNET_ERROR_TYPE_ERROR,
1550 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: %f\n", op->rtt_bandwidth_tradeoff);
1551
1552
1553 /**
1554 * Added rtt_bandwidth_tradeoff directly need future improvements
1555 */
1434 if ((GNUNET_YES == op->force_full) || 1556 if ((GNUNET_YES == op->force_full) ||
1435 (diff > op->initial_size / 4) || 1557 (diff > op->initial_size / 4) ||
1436 (0 == other_size)) 1558 (0 == other_size))
@@ -1455,6 +1577,7 @@ handle_union_p2p_strata_estimator (void *cls,
1455 LOG (GNUNET_ERROR_TYPE_DEBUG, 1577 LOG (GNUNET_ERROR_TYPE_DEBUG,
1456 "Telling other peer that we expect its full set\n"); 1578 "Telling other peer that we expect its full set\n");
1457 op->phase = PHASE_FULL_RECEIVING; 1579 op->phase = PHASE_FULL_RECEIVING;
1580 perf_rtt.request_full.sent += 1;
1458 ev = GNUNET_MQ_msg_header ( 1581 ev = GNUNET_MQ_msg_header (
1459 GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL); 1582 GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL);
1460 GNUNET_MQ_send (op->mq, 1583 GNUNET_MQ_send (op->mq,
@@ -1504,6 +1627,9 @@ send_offers_iterator (void *cls,
1504 if (ke->ibf_key.key_val != sec->ibf_key.key_val) 1627 if (ke->ibf_key.key_val != sec->ibf_key.key_val)
1505 return GNUNET_YES; 1628 return GNUNET_YES;
1506 1629
1630 perf_rtt.offer.sent += 1;
1631 perf_rtt.offer.sent_var_bytes += sizeof(struct GNUNET_HashCode);
1632
1507 ev = GNUNET_MQ_msg_header_extra (mh, 1633 ev = GNUNET_MQ_msg_header_extra (mh,
1508 sizeof(struct GNUNET_HashCode), 1634 sizeof(struct GNUNET_HashCode),
1509 GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER); 1635 GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER);
@@ -1659,6 +1785,8 @@ decode_and_send (struct Operation *op)
1659 1785
1660 LOG (GNUNET_ERROR_TYPE_DEBUG, 1786 LOG (GNUNET_ERROR_TYPE_DEBUG,
1661 "transmitted all values, sending DONE\n"); 1787 "transmitted all values, sending DONE\n");
1788
1789 perf_rtt.done.sent += 1;
1662 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_DONE); 1790 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_DONE);
1663 GNUNET_MQ_send (op->mq, ev); 1791 GNUNET_MQ_send (op->mq, ev);
1664 /* We now wait until we get a DONE message back 1792 /* We now wait until we get a DONE message back
@@ -1681,6 +1809,8 @@ decode_and_send (struct Operation *op)
1681 struct GNUNET_MQ_Envelope *ev; 1809 struct GNUNET_MQ_Envelope *ev;
1682 struct InquiryMessage *msg; 1810 struct InquiryMessage *msg;
1683 1811
1812 perf_rtt.inquery.sent += 1;
1813 perf_rtt.inquery.sent_var_bytes += sizeof(struct IBF_Key);
1684 /* It may be nice to merge multiple requests, but with CADET's corking it is not worth 1814 /* It may be nice to merge multiple requests, but with CADET's corking it is not worth
1685 * the effort additional complexity. */ 1815 * the effort additional complexity. */
1686 ev = GNUNET_MQ_msg_extra (msg, 1816 ev = GNUNET_MQ_msg_extra (msg,
@@ -1780,6 +1910,9 @@ handle_union_p2p_ibf (void *cls,
1780 struct Operation *op = cls; 1910 struct Operation *op = cls;
1781 unsigned int buckets_in_message; 1911 unsigned int buckets_in_message;
1782 1912
1913 perf_rtt.ibf.received += 1;
1914 perf_rtt.ibf.received_var_bytes += (ntohs (msg->header.size) - sizeof *msg);
1915
1783 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg) 1916 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
1784 / IBF_BUCKET_SIZE; 1917 / IBF_BUCKET_SIZE;
1785 if ((op->phase == PHASE_PASSIVE_DECODING) || 1918 if ((op->phase == PHASE_PASSIVE_DECODING) ||
@@ -1908,6 +2041,7 @@ maybe_finish (struct Operation *op)
1908 struct GNUNET_MQ_Envelope *ev; 2041 struct GNUNET_MQ_Envelope *ev;
1909 2042
1910 op->phase = PHASE_FINISHED; 2043 op->phase = PHASE_FINISHED;
2044 perf_rtt.done.sent += 1;
1911 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_DONE); 2045 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_DONE);
1912 GNUNET_MQ_send (op->mq, 2046 GNUNET_MQ_send (op->mq,
1913 ev); 2047 ev);
@@ -1968,8 +2102,12 @@ handle_union_p2p_elements (void *cls,
1968 struct KeyEntry *ke; 2102 struct KeyEntry *ke;
1969 uint16_t element_size; 2103 uint16_t element_size;
1970 2104
2105
1971 element_size = ntohs (emsg->header.size) - sizeof(struct 2106 element_size = ntohs (emsg->header.size) - sizeof(struct
1972 GNUNET_SETU_ElementMessage); 2107 GNUNET_SETU_ElementMessage);
2108 perf_rtt.element.received += 1;
2109 perf_rtt.element.received_var_bytes += element_size;
2110
1973 ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size); 2111 ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
1974 GNUNET_memcpy (&ee[1], 2112 GNUNET_memcpy (&ee[1],
1975 &emsg[1], 2113 &emsg[1],
@@ -2080,19 +2218,33 @@ handle_union_p2p_full_element (void *cls,
2080 uint16_t element_size; 2218 uint16_t element_size;
2081 2219
2082 2220
2221
2222 if(PHASE_EXPECT_IBF == op->phase) {
2223 op->phase = PHASE_FULL_RECEIVING;
2224 }
2225
2226
2227
2083 /* Allow only receiving of full element message if in expect IBF or in PHASE_FULL_RECEIVING state */ 2228 /* Allow only receiving of full element message if in expect IBF or in PHASE_FULL_RECEIVING state */
2084 if ( (PHASE_EXPECT_IBF != op->phase) && 2229 if ((PHASE_FULL_RECEIVING != op->phase) &&
2085 (PHASE_FULL_RECEIVING != op->phase) ) 2230 (PHASE_FULL_SENDING != op->phase))
2086 { 2231 {
2087 GNUNET_break_op (0); 2232 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2088 fail_union_operation (op); 2233 "Handle full element phase is %u\n",
2089 return; 2234 (unsigned) op->phase);
2090 } 2235 GNUNET_break_op (0);
2236 fail_union_operation (op);
2237 return;
2238 }
2239
2091 2240
2092 op->phase = PHASE_FULL_RECEIVING;
2093 2241
2094 element_size = ntohs (emsg->header.size) 2242 element_size = ntohs (emsg->header.size)
2095 - sizeof(struct GNUNET_SETU_ElementMessage); 2243 - sizeof(struct GNUNET_SETU_ElementMessage);
2244
2245 perf_rtt.element_full.received += 1;
2246 perf_rtt.element_full.received_var_bytes += element_size;
2247
2096 ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size); 2248 ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
2097 GNUNET_memcpy (&ee[1], &emsg[1], element_size); 2249 GNUNET_memcpy (&ee[1], &emsg[1], element_size);
2098 ee->element.size = element_size; 2250 ee->element.size = element_size;
@@ -2204,6 +2356,9 @@ handle_union_p2p_inquiry (void *cls,
2204 const struct IBF_Key *ibf_key; 2356 const struct IBF_Key *ibf_key;
2205 unsigned int num_keys; 2357 unsigned int num_keys;
2206 2358
2359 perf_rtt.inquery.received += 1;
2360 perf_rtt.inquery.received_var_bytes += (ntohs (msg->header.size) - sizeof(struct InquiryMessage));
2361
2207 LOG (GNUNET_ERROR_TYPE_DEBUG, 2362 LOG (GNUNET_ERROR_TYPE_DEBUG,
2208 "Received union inquiry\n"); 2363 "Received union inquiry\n");
2209 num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage)) 2364 num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
@@ -2247,6 +2402,7 @@ send_missing_full_elements_iter (void *cls,
2247 2402
2248 if (GNUNET_YES == ke->received) 2403 if (GNUNET_YES == ke->received)
2249 return GNUNET_YES; 2404 return GNUNET_YES;
2405 perf_rtt.element_full.received += 1;
2250 ev = GNUNET_MQ_msg_extra (emsg, 2406 ev = GNUNET_MQ_msg_extra (emsg,
2251 ee->element.size, 2407 ee->element.size,
2252 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT); 2408 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT);
@@ -2272,7 +2428,9 @@ handle_union_p2p_request_full (void *cls,
2272{ 2428{
2273 struct Operation *op = cls; 2429 struct Operation *op = cls;
2274 2430
2275 LOG (GNUNET_ERROR_TYPE_DEBUG, 2431 perf_rtt.request_full.received += 1;
2432
2433 LOG (GNUNET_ERROR_TYPE_DEBUG,
2276 "Received request for full set transmission\n"); 2434 "Received request for full set transmission\n");
2277 if (PHASE_EXPECT_IBF != op->phase) 2435 if (PHASE_EXPECT_IBF != op->phase)
2278 { 2436 {
@@ -2300,9 +2458,11 @@ handle_union_p2p_full_done (void *cls,
2300{ 2458{
2301 struct Operation *op = cls; 2459 struct Operation *op = cls;
2302 2460
2461 perf_rtt.full_done.received += 1;
2462
2303 switch (op->phase) 2463 switch (op->phase)
2304 { 2464 {
2305 case PHASE_EXPECT_IBF: 2465 case PHASE_FULL_RECEIVING:
2306 { 2466 {
2307 struct GNUNET_MQ_Envelope *ev; 2467 struct GNUNET_MQ_Envelope *ev;
2308 2468
@@ -2313,6 +2473,7 @@ handle_union_p2p_full_done (void *cls,
2313 GNUNET_CONTAINER_multihashmap32_iterate (op->key_to_element, 2473 GNUNET_CONTAINER_multihashmap32_iterate (op->key_to_element,
2314 &send_missing_full_elements_iter, 2474 &send_missing_full_elements_iter,
2315 op); 2475 op);
2476 perf_rtt.full_done.sent += 1;
2316 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE); 2477 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE);
2317 GNUNET_MQ_send (op->mq, 2478 GNUNET_MQ_send (op->mq,
2318 ev); 2479 ev);
@@ -2332,10 +2493,9 @@ handle_union_p2p_full_done (void *cls,
2332 _GSS_operation_destroy2 (op); 2493 _GSS_operation_destroy2 (op);
2333 return; 2494 return;
2334 } 2495 }
2335 break;
2336 2496
2337 default: 2497 default:
2338 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2339 "Handle full done phase is %u\n", 2499 "Handle full done phase is %u\n",
2340 (unsigned) op->phase); 2500 (unsigned) op->phase);
2341 GNUNET_break_op (0); 2501 GNUNET_break_op (0);
@@ -2392,6 +2552,9 @@ handle_union_p2p_demand (void *cls,
2392 unsigned int num_hashes; 2552 unsigned int num_hashes;
2393 struct GNUNET_MQ_Envelope *ev; 2553 struct GNUNET_MQ_Envelope *ev;
2394 2554
2555 perf_rtt.demand.received += 1;
2556 perf_rtt.demand.received_var_bytes += (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader));
2557
2395 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader)) 2558 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2396 / sizeof(struct GNUNET_HashCode); 2559 / sizeof(struct GNUNET_HashCode);
2397 for (hash = (const struct GNUNET_HashCode *) &mh[1]; 2560 for (hash = (const struct GNUNET_HashCode *) &mh[1];
@@ -2414,6 +2577,8 @@ handle_union_p2p_demand (void *cls,
2414 fail_union_operation (op); 2577 fail_union_operation (op);
2415 return; 2578 return;
2416 } 2579 }
2580 perf_rtt.element.sent += 1;
2581 perf_rtt.element.sent_var_bytes += ee->element.size;
2417 ev = GNUNET_MQ_msg_extra (emsg, 2582 ev = GNUNET_MQ_msg_extra (emsg,
2418 ee->element.size, 2583 ee->element.size,
2419 GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS); 2584 GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS);
@@ -2489,6 +2654,9 @@ handle_union_p2p_offer (void *cls,
2489 const struct GNUNET_HashCode *hash; 2654 const struct GNUNET_HashCode *hash;
2490 unsigned int num_hashes; 2655 unsigned int num_hashes;
2491 2656
2657 perf_rtt.offer.received += 1;
2658 perf_rtt.offer.received_var_bytes += (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader));
2659
2492 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader)) 2660 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2493 / sizeof(struct GNUNET_HashCode); 2661 / sizeof(struct GNUNET_HashCode);
2494 for (hash = (const struct GNUNET_HashCode *) &mh[1]; 2662 for (hash = (const struct GNUNET_HashCode *) &mh[1];
@@ -2524,6 +2692,9 @@ handle_union_p2p_offer (void *cls,
2524 LOG (GNUNET_ERROR_TYPE_DEBUG, 2692 LOG (GNUNET_ERROR_TYPE_DEBUG,
2525 "[OP %p] Requesting element (hash %s)\n", 2693 "[OP %p] Requesting element (hash %s)\n",
2526 op, GNUNET_h2s (hash)); 2694 op, GNUNET_h2s (hash));
2695
2696 perf_rtt.demand.sent += 1;
2697 perf_rtt.demand.sent_var_bytes += sizeof(struct GNUNET_HashCode);
2527 ev = GNUNET_MQ_msg_header_extra (demands, 2698 ev = GNUNET_MQ_msg_header_extra (demands,
2528 sizeof(struct GNUNET_HashCode), 2699 sizeof(struct GNUNET_HashCode),
2529 GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND); 2700 GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND);
@@ -2548,6 +2719,7 @@ handle_union_p2p_done (void *cls,
2548{ 2719{
2549 struct Operation *op = cls; 2720 struct Operation *op = cls;
2550 2721
2722 perf_rtt.done.received += 1;
2551 switch (op->phase) 2723 switch (op->phase)
2552 { 2724 {
2553 case PHASE_PASSIVE_DECODING: 2725 case PHASE_PASSIVE_DECODING:
@@ -2597,6 +2769,7 @@ static void
2597handle_union_p2p_over (void *cls, 2769handle_union_p2p_over (void *cls,
2598 const struct GNUNET_MessageHeader *mh) 2770 const struct GNUNET_MessageHeader *mh)
2599{ 2771{
2772 perf_rtt.over.received += 1;
2600 send_client_done (cls); 2773 send_client_done (cls);
2601} 2774}
2602 2775
@@ -2770,7 +2943,7 @@ check_incoming_msg (void *cls,
2770 struct Listener *listener = op->listener; 2943 struct Listener *listener = op->listener;
2771 const struct GNUNET_MessageHeader *nested_context; 2944 const struct GNUNET_MessageHeader *nested_context;
2772 2945
2773 /* double operation request */ 2946 /* double operation request */
2774 if (0 != op->suggest_id) 2947 if (0 != op->suggest_id)
2775 { 2948 {
2776 GNUNET_break_op (0); 2949 GNUNET_break_op (0);
@@ -3377,6 +3550,7 @@ handle_client_evaluate (void *cls,
3377 struct GNUNET_MQ_Envelope *ev; 3550 struct GNUNET_MQ_Envelope *ev;
3378 struct OperationRequestMessage *msg; 3551 struct OperationRequestMessage *msg;
3379 3552
3553 perf_rtt.operation_request.sent += 1;
3380 ev = GNUNET_MQ_msg_nested_mh (msg, 3554 ev = GNUNET_MQ_msg_nested_mh (msg,
3381 GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST, 3555 GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST,
3382 context); 3556 context);
@@ -3575,6 +3749,9 @@ handle_client_accept (void *cls,
3575 buf = GNUNET_malloc (se->strata_count * IBF_BUCKET_SIZE * se->ibf_size); 3749 buf = GNUNET_malloc (se->strata_count * IBF_BUCKET_SIZE * se->ibf_size);
3576 len = strata_estimator_write (se, 3750 len = strata_estimator_write (se,
3577 buf); 3751 buf);
3752 perf_rtt.se.sent += 1;
3753 perf_rtt.se.sent_var_bytes += len;
3754
3578 if (len < se->strata_count * IBF_BUCKET_SIZE * se->ibf_size) 3755 if (len < se->strata_count * IBF_BUCKET_SIZE * se->ibf_size)
3579 type = GNUNET_MESSAGE_TYPE_SETU_P2P_SEC; 3756 type = GNUNET_MESSAGE_TYPE_SETU_P2P_SEC;
3580 else 3757 else
@@ -3623,6 +3800,8 @@ shutdown_task (void *cls)
3623 GNUNET_YES); 3800 GNUNET_YES);
3624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3625 "handled shutdown request\n"); 3802 "handled shutdown request\n");
3803 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3804 "RTT:%f\n", calculate_perf_rtt());
3626} 3805}
3627 3806
3628 3807
diff --git a/src/setu/gnunet-service-setu_strata_estimator.c b/src/setu/gnunet-service-setu_strata_estimator.c
index 0fa6a6f17..7c9a4deb6 100644
--- a/src/setu/gnunet-service-setu_strata_estimator.c
+++ b/src/setu/gnunet-service-setu_strata_estimator.c
@@ -30,13 +30,6 @@
30 30
31 31
32/** 32/**
33 * Should we try compressing the strata estimator? This will
34 * break compatibility with the 0.10.1-network.
35 */
36#define FAIL_10_1_COMPATIBILTIY 1
37
38
39/**
40 * Write the given strata estimator to the buffer. 33 * Write the given strata estimator to the buffer.
41 * 34 *
42 * @param se strata estimator to serialize 35 * @param se strata estimator to serialize
@@ -48,11 +41,10 @@ strata_estimator_write (const struct StrataEstimator *se,
48 void *buf) 41 void *buf)
49{ 42{
50 char *sbuf = buf; 43 char *sbuf = buf;
51 unsigned int i;
52 size_t osize; 44 size_t osize;
53 45
54 GNUNET_assert (NULL != se); 46 GNUNET_assert (NULL != se);
55 for (i = 0; i < se->strata_count; i++) 47 for (unsigned int i = 0; i < se->strata_count; i++)
56 { 48 {
57 ibf_write_slice (se->strata[i], 49 ibf_write_slice (se->strata[i],
58 0, 50 0,
@@ -60,7 +52,6 @@ strata_estimator_write (const struct StrataEstimator *se,
60 &sbuf[se->ibf_size * IBF_BUCKET_SIZE * i]); 52 &sbuf[se->ibf_size * IBF_BUCKET_SIZE * i]);
61 } 53 }
62 osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count; 54 osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count;
63#if FAIL_10_1_COMPATIBILTIY
64 { 55 {
65 char *cbuf; 56 char *cbuf;
66 size_t nsize; 57 size_t nsize;
@@ -71,12 +62,13 @@ strata_estimator_write (const struct StrataEstimator *se,
71 &cbuf, 62 &cbuf,
72 &nsize)) 63 &nsize))
73 { 64 {
74 GNUNET_memcpy (buf, cbuf, nsize); 65 GNUNET_memcpy (buf,
66 cbuf,
67 nsize);
75 osize = nsize; 68 osize = nsize;
76 GNUNET_free (cbuf); 69 GNUNET_free (cbuf);
77 } 70 }
78 } 71 }
79#endif
80 return osize; 72 return osize;
81} 73}
82 74
@@ -97,7 +89,6 @@ strata_estimator_read (const void *buf,
97 int is_compressed, 89 int is_compressed,
98 struct StrataEstimator *se) 90 struct StrataEstimator *se)
99{ 91{
100 unsigned int i;
101 size_t osize; 92 size_t osize;
102 char *dbuf; 93 char *dbuf;
103 94
@@ -124,7 +115,7 @@ strata_estimator_read (const void *buf,
124 return GNUNET_SYSERR; 115 return GNUNET_SYSERR;
125 } 116 }
126 117
127 for (i = 0; i < se->strata_count; i++) 118 for (unsigned int i = 0; i < se->strata_count; i++)
128 { 119 {
129 ibf_read_slice (buf, 0, se->ibf_size, se->strata[i]); 120 ibf_read_slice (buf, 0, se->ibf_size, se->strata[i]);
130 buf += se->ibf_size * IBF_BUCKET_SIZE; 121 buf += se->ibf_size * IBF_BUCKET_SIZE;
@@ -190,22 +181,20 @@ strata_estimator_create (unsigned int strata_count,
190 uint8_t ibf_hashnum) 181 uint8_t ibf_hashnum)
191{ 182{
192 struct StrataEstimator *se; 183 struct StrataEstimator *se;
193 unsigned int i;
194 unsigned int j;
195 184
196 se = GNUNET_new (struct StrataEstimator); 185 se = GNUNET_new (struct StrataEstimator);
197 se->strata_count = strata_count; 186 se->strata_count = strata_count;
198 se->ibf_size = ibf_size; 187 se->ibf_size = ibf_size;
199 se->strata = GNUNET_new_array (strata_count, 188 se->strata = GNUNET_new_array (strata_count,
200 struct InvertibleBloomFilter *); 189 struct InvertibleBloomFilter *);
201 for (i = 0; i < strata_count; i++) 190 for (unsigned int i = 0; i < strata_count; i++)
202 { 191 {
203 se->strata[i] = ibf_create (ibf_size, ibf_hashnum); 192 se->strata[i] = ibf_create (ibf_size, ibf_hashnum);
204 if (NULL == se->strata[i]) 193 if (NULL == se->strata[i])
205 { 194 {
206 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
207 "Failed to allocate memory for strata estimator\n"); 196 "Failed to allocate memory for strata estimator\n");
208 for (j = 0; j < i; j++) 197 for (unsigned int j = 0; j < i; j++)
209 ibf_destroy (se->strata[i]); 198 ibf_destroy (se->strata[i]);
210 GNUNET_free (se); 199 GNUNET_free (se);
211 return NULL; 200 return NULL;
@@ -239,19 +228,23 @@ strata_estimator_difference (const struct StrataEstimator *se1,
239 228
240 /* FIXME: implement this without always allocating new IBFs */ 229 /* FIXME: implement this without always allocating new IBFs */
241 diff = ibf_dup (se1->strata[i]); 230 diff = ibf_dup (se1->strata[i]);
242 ibf_subtract (diff, se2->strata[i]); 231 ibf_subtract (diff,
232 se2->strata[i]);
243 for (int ibf_count = 0; GNUNET_YES; ibf_count++) 233 for (int ibf_count = 0; GNUNET_YES; ibf_count++)
244 { 234 {
245 int more; 235 int more;
246 236
247 more = ibf_decode (diff, NULL, NULL); 237 more = ibf_decode (diff,
238 NULL,
239 NULL);
248 if (GNUNET_NO == more) 240 if (GNUNET_NO == more)
249 { 241 {
250 count += ibf_count; 242 count += ibf_count;
251 break; 243 break;
252 } 244 }
253 /* Estimate if decoding fails or would not terminate */ 245 /* Estimate if decoding fails or would not terminate */
254 if ((GNUNET_SYSERR == more) || (ibf_count > diff->size)) 246 if ( (GNUNET_SYSERR == more) ||
247 (ibf_count > diff->size) )
255 { 248 {
256 ibf_destroy (diff); 249 ibf_destroy (diff);
257 return count * (1 << (i + 1)); 250 return count * (1 << (i + 1));
@@ -273,14 +266,13 @@ struct StrataEstimator *
273strata_estimator_dup (struct StrataEstimator *se) 266strata_estimator_dup (struct StrataEstimator *se)
274{ 267{
275 struct StrataEstimator *c; 268 struct StrataEstimator *c;
276 unsigned int i;
277 269
278 c = GNUNET_new (struct StrataEstimator); 270 c = GNUNET_new (struct StrataEstimator);
279 c->strata_count = se->strata_count; 271 c->strata_count = se->strata_count;
280 c->ibf_size = se->ibf_size; 272 c->ibf_size = se->ibf_size;
281 c->strata = GNUNET_new_array (se->strata_count, 273 c->strata = GNUNET_new_array (se->strata_count,
282 struct InvertibleBloomFilter *); 274 struct InvertibleBloomFilter *);
283 for (i = 0; i < se->strata_count; i++) 275 for (unsigned int i = 0; i < se->strata_count; i++)
284 c->strata[i] = ibf_dup (se->strata[i]); 276 c->strata[i] = ibf_dup (se->strata[i]);
285 return c; 277 return c;
286} 278}
@@ -294,9 +286,7 @@ strata_estimator_dup (struct StrataEstimator *se)
294void 286void
295strata_estimator_destroy (struct StrataEstimator *se) 287strata_estimator_destroy (struct StrataEstimator *se)
296{ 288{
297 unsigned int i; 289 for (unsigned int i = 0; i < se->strata_count; i++)
298
299 for (i = 0; i < se->strata_count; i++)
300 ibf_destroy (se->strata[i]); 290 ibf_destroy (se->strata[i]);
301 GNUNET_free (se->strata); 291 GNUNET_free (se->strata);
302 GNUNET_free (se); 292 GNUNET_free (se);
diff --git a/src/setu/ibf.c b/src/setu/ibf.c
index 79b4f28db..1beba9065 100644
--- a/src/setu/ibf.c
+++ b/src/setu/ibf.c
@@ -20,7 +20,7 @@
20 20
21/** 21/**
22 * @file set/ibf.c 22 * @file set/ibf.c
23 * @brief implementation of the invertible bloom filter 23 * @brief implementation of the invertible Bloom filter
24 * @author Florian Dold 24 * @author Florian Dold
25 */ 25 */
26 26
@@ -58,12 +58,11 @@ ibf_hashcode_from_key (struct IBF_Key key,
58 struct GNUNET_HashCode *dst) 58 struct GNUNET_HashCode *dst)
59{ 59{
60 struct IBF_Key *p; 60 struct IBF_Key *p;
61 unsigned int i;
62 const unsigned int keys_per_hashcode = sizeof(struct GNUNET_HashCode) 61 const unsigned int keys_per_hashcode = sizeof(struct GNUNET_HashCode)
63 / sizeof(struct IBF_Key); 62 / sizeof(struct IBF_Key);
64 63
65 p = (struct IBF_Key *) dst; 64 p = (struct IBF_Key *) dst;
66 for (i = 0; i < keys_per_hashcode; i++) 65 for (unsigned int i = 0; i < keys_per_hashcode; i++)
67 *p++ = key; 66 *p++ = key;
68} 67}
69 68
@@ -76,12 +75,12 @@ ibf_hashcode_from_key (struct IBF_Key key,
76 * @return the newly created invertible bloom filter, NULL on error 75 * @return the newly created invertible bloom filter, NULL on error
77 */ 76 */
78struct InvertibleBloomFilter * 77struct InvertibleBloomFilter *
79ibf_create (uint32_t size, uint8_t hash_num) 78ibf_create (uint32_t size,
79 uint8_t hash_num)
80{ 80{
81 struct InvertibleBloomFilter *ibf; 81 struct InvertibleBloomFilter *ibf;
82 82
83 GNUNET_assert (0 != size); 83 GNUNET_assert (0 != size);
84
85 ibf = GNUNET_new (struct InvertibleBloomFilter); 84 ibf = GNUNET_new (struct InvertibleBloomFilter);
86 ibf->count = GNUNET_malloc_large (size * sizeof(uint8_t)); 85 ibf->count = GNUNET_malloc_large (size * sizeof(uint8_t));
87 if (NULL == ibf->count) 86 if (NULL == ibf->count)
@@ -106,7 +105,6 @@ ibf_create (uint32_t size, uint8_t hash_num)
106 } 105 }
107 ibf->size = size; 106 ibf->size = size;
108 ibf->hash_num = hash_num; 107 ibf->hash_num = hash_num;
109
110 return ibf; 108 return ibf;
111} 109}
112 110
@@ -123,7 +121,8 @@ ibf_get_indices (const struct InvertibleBloomFilter *ibf,
123 uint32_t i; 121 uint32_t i;
124 uint32_t bucket; 122 uint32_t bucket;
125 123
126 bucket = GNUNET_CRYPTO_crc32_n (&key, sizeof key); 124 bucket = GNUNET_CRYPTO_crc32_n (&key,
125 sizeof (key));
127 for (i = 0, filled = 0; filled < ibf->hash_num; i++) 126 for (i = 0, filled = 0; filled < ibf->hash_num; i++)
128 { 127 {
129 uint64_t x; 128 uint64_t x;
@@ -134,7 +133,8 @@ ibf_get_indices (const struct InvertibleBloomFilter *ibf,
134 dst[filled++] = bucket % ibf->size; 133 dst[filled++] = bucket % ibf->size;
135try_next: 134try_next:
136 x = ((uint64_t) bucket << 32) | i; 135 x = ((uint64_t) bucket << 32) | i;
137 bucket = GNUNET_CRYPTO_crc32_n (&x, sizeof x); 136 bucket = GNUNET_CRYPTO_crc32_n (&x,
137 sizeof (x));
138 } 138 }
139} 139}
140 140
@@ -170,8 +170,13 @@ ibf_insert (struct InvertibleBloomFilter *ibf,
170 int buckets[ibf->hash_num]; 170 int buckets[ibf->hash_num];
171 171
172 GNUNET_assert (ibf->hash_num <= ibf->size); 172 GNUNET_assert (ibf->hash_num <= ibf->size);
173 ibf_get_indices (ibf, key, buckets); 173 ibf_get_indices (ibf,
174 ibf_insert_into (ibf, key, buckets, 1); 174 key,
175 buckets);
176 ibf_insert_into (ibf,
177 key,
178 buckets,
179 1);
175} 180}
176 181
177 182
@@ -188,8 +193,13 @@ ibf_remove (struct InvertibleBloomFilter *ibf,
188 int buckets[ibf->hash_num]; 193 int buckets[ibf->hash_num];
189 194
190 GNUNET_assert (ibf->hash_num <= ibf->size); 195 GNUNET_assert (ibf->hash_num <= ibf->size);
191 ibf_get_indices (ibf, key, buckets); 196 ibf_get_indices (ibf,
192 ibf_insert_into (ibf, key, buckets, -1); 197 key,
198 buckets);
199 ibf_insert_into (ibf,
200 key,
201 buckets,
202 -1);
193} 203}
194 204
195 205
@@ -234,8 +244,6 @@ ibf_decode (struct InvertibleBloomFilter *ibf,
234 244
235 for (uint32_t i = 0; i < ibf->size; i++) 245 for (uint32_t i = 0; i < ibf->size; i++)
236 { 246 {
237 int hit;
238
239 /* we can only decode from pure buckets */ 247 /* we can only decode from pure buckets */
240 if ( (1 != ibf->count[i].count_val) && 248 if ( (1 != ibf->count[i].count_val) &&
241 (-1 != ibf->count[i].count_val) ) 249 (-1 != ibf->count[i].count_val) )
@@ -249,23 +257,30 @@ ibf_decode (struct InvertibleBloomFilter *ibf,
249 257
250 /* test if key in bucket hits its own location, 258 /* test if key in bucket hits its own location,
251 * if not, the key hash was subject to collision */ 259 * if not, the key hash was subject to collision */
252 hit = GNUNET_NO; 260 {
253 ibf_get_indices (ibf, ibf->key_sum[i], buckets); 261 bool hit = false;
254 for (int j = 0; j < ibf->hash_num; j++) 262
255 if (buckets[j] == i) 263 ibf_get_indices (ibf,
256 hit = GNUNET_YES; 264 ibf->key_sum[i],
257 265 buckets);
258 if (GNUNET_NO == hit) 266 for (int j = 0; j < ibf->hash_num; j++)
259 continue; 267 if (buckets[j] == i)
260 268 {
269 hit = true;
270 break;
271 }
272 if (! hit)
273 continue;
274 }
261 if (NULL != ret_side) 275 if (NULL != ret_side)
262 *ret_side = ibf->count[i].count_val; 276 *ret_side = ibf->count[i].count_val;
263 if (NULL != ret_id) 277 if (NULL != ret_id)
264 *ret_id = ibf->key_sum[i]; 278 *ret_id = ibf->key_sum[i];
265 279
266 /* insert on the opposite side, effectively removing the element */ 280 /* insert on the opposite side, effectively removing the element */
267 ibf_insert_into (ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val); 281 ibf_insert_into (ibf,
268 282 ibf->key_sum[i], buckets,
283 -ibf->count[i].count_val);
269 return GNUNET_YES; 284 return GNUNET_YES;
270 } 285 }
271 286
@@ -287,7 +302,8 @@ ibf_decode (struct InvertibleBloomFilter *ibf,
287void 302void
288ibf_write_slice (const struct InvertibleBloomFilter *ibf, 303ibf_write_slice (const struct InvertibleBloomFilter *ibf,
289 uint32_t start, 304 uint32_t start,
290 uint32_t count, void *buf) 305 uint32_t count,
306 void *buf)
291{ 307{
292 struct IBF_Key *key_dst; 308 struct IBF_Key *key_dst;
293 struct IBF_KeyHash *key_hash_dst; 309 struct IBF_KeyHash *key_hash_dst;
diff --git a/src/setu/perf_setu_api.c b/src/setu/perf_setu_api.c
new file mode 100644
index 000000000..3b82e8af9
--- /dev/null
+++ b/src/setu/perf_setu_api.c
@@ -0,0 +1,428 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/test_setu_api.c
23 * @brief testcase for setu_api.c
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib.h"
29#include "gnunet_setu_service.h"
30
31
32static struct GNUNET_PeerIdentity local_id;
33
34static struct GNUNET_HashCode app_id;
35
36static struct GNUNET_SETU_Handle *set1;
37
38static struct GNUNET_SETU_Handle *set2;
39
40static struct GNUNET_SETU_ListenHandle *listen_handle;
41
42static struct GNUNET_SETU_OperationHandle *oh1;
43
44static struct GNUNET_SETU_OperationHandle *oh2;
45
46static const struct GNUNET_CONFIGURATION_Handle *config;
47
48static int ret;
49
50static struct GNUNET_SCHEDULER_Task *tt;
51
52
53
54static void
55result_cb_set1 (void *cls,
56 const struct GNUNET_SETU_Element *element,
57 uint64_t size,
58 enum GNUNET_SETU_Status status)
59{
60 switch (status)
61 {
62 case GNUNET_SETU_STATUS_ADD_LOCAL:
63 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: got element\n");
64 break;
65
66 case GNUNET_SETU_STATUS_FAILURE:
67 GNUNET_break (0);
68 oh1 = NULL;
69 fprintf (stderr, "set 1: received failure status!\n");
70 ret = 1;
71 if (NULL != tt)
72 {
73 GNUNET_SCHEDULER_cancel (tt);
74 tt = NULL;
75 }
76 GNUNET_SCHEDULER_shutdown ();
77 break;
78
79 case GNUNET_SETU_STATUS_DONE:
80 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: done\n");
81 oh1 = NULL;
82 if (NULL != set1)
83 {
84 GNUNET_SETU_destroy (set1);
85 set1 = NULL;
86 }
87 if (NULL == set2)
88 {
89 GNUNET_SCHEDULER_cancel (tt);
90 tt = NULL;
91 GNUNET_SCHEDULER_shutdown ();
92 }
93 break;
94
95 default:
96 GNUNET_assert (0);
97 }
98}
99
100
101static void
102result_cb_set2 (void *cls,
103 const struct GNUNET_SETU_Element *element,
104 uint64_t size,
105 enum GNUNET_SETU_Status status)
106{
107 switch (status)
108 {
109 case GNUNET_SETU_STATUS_ADD_LOCAL:
110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: got element\n");
111 break;
112
113 case GNUNET_SETU_STATUS_FAILURE:
114 GNUNET_break (0);
115 oh2 = NULL;
116 fprintf (stderr, "set 2: received failure status\n");
117 GNUNET_SCHEDULER_shutdown ();
118 ret = 1;
119 break;
120
121 case GNUNET_SETU_STATUS_DONE:
122 oh2 = NULL;
123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: done\n");
124 GNUNET_SETU_destroy (set2);
125 set2 = NULL;
126 if (NULL == set1)
127 {
128 GNUNET_SCHEDULER_cancel (tt);
129 tt = NULL;
130 GNUNET_SCHEDULER_shutdown ();
131 }
132 break;
133
134 default:
135 GNUNET_assert (0);
136 }
137}
138
139
140static void
141listen_cb (void *cls,
142 const struct GNUNET_PeerIdentity *other_peer,
143 const struct GNUNET_MessageHeader *context_msg,
144 struct GNUNET_SETU_Request *request)
145{
146 GNUNET_assert (NULL != context_msg);
147 GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "listen cb called\n");
149 oh2 = GNUNET_SETU_accept (request,
150 (struct GNUNET_SETU_Option[]){ 0 },
151 &result_cb_set2,
152 NULL);
153 GNUNET_SETU_commit (oh2, set2);
154}
155
156
157/**
158 * Start the set operation.
159 *
160 * @param cls closure, unused
161 */
162static void
163start (void *cls)
164{
165 struct GNUNET_MessageHeader context_msg;
166
167 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting reconciliation\n");
168 context_msg.size = htons (sizeof context_msg);
169 context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
170 listen_handle = GNUNET_SETU_listen (config,
171 &app_id,
172 &listen_cb,
173 NULL);
174 oh1 = GNUNET_SETU_prepare (&local_id,
175 &app_id,
176 &context_msg,
177 (struct GNUNET_SETU_Option[]){ 0 },
178 &result_cb_set1,
179 NULL);
180 GNUNET_SETU_commit (oh1, set1);
181}
182
183
184/**
185 * Initialize the second set, continue
186 *
187 * @param cls closure, unused
188 */
189static void
190init_set2 (void *cls)
191{
192 struct GNUNET_SETU_Element element;
193
194 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initializing set 2\n");
195
196 element.element_type = 0;
197 element.data = "hello1";
198 element.size = strlen (element.data);
199 GNUNET_SETU_add_element (set2, &element, NULL, NULL);
200 element.data = "quux";
201 element.size = strlen (element.data);
202 GNUNET_SETU_add_element (set2, &element, NULL, NULL);
203 element.data = "baz";
204 element.size = strlen (element.data);
205 GNUNET_SETU_add_element (set2, &element, &start, NULL);
206}
207
208/**
209 * Generate random byte stream
210 */
211
212unsigned char *gen_rdm_bytestream (size_t num_bytes)
213{
214 unsigned char *stream = GNUNET_malloc (num_bytes);
215 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, stream, num_bytes);
216 return stream;
217}
218
219/**
220 * Generate random sets
221 */
222
223static void
224initRandomSets(int overlap, int set1_size, int set2_size, int element_size_in_bytes)
225{
226 struct GNUNET_SETU_Element element;
227 element.element_type = 0;
228
229 // Add elements to both sets
230 for (int i = 0; i < overlap; i++) {
231 element.data = gen_rdm_bytestream(element_size_in_bytes);
232 element.size = element_size_in_bytes;
233 GNUNET_SETU_add_element (set1, &element, NULL, NULL);
234 GNUNET_SETU_add_element (set2, &element, NULL, NULL);
235 set1_size--;
236 set2_size--;
237 }
238 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in both sets\n");
239
240 // Add other elements to set 1
241 while(set1_size>0) {
242 element.data = gen_rdm_bytestream(element_size_in_bytes);
243 element.size = element_size_in_bytes;
244 GNUNET_SETU_add_element (set1, &element, NULL, NULL);
245 set1_size--;
246 }
247 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in set1\n");
248
249 // Add other elements to set 2
250 while(set2_size > 0) {
251 element.data = gen_rdm_bytestream(element_size_in_bytes);
252 element.size = element_size_in_bytes;
253
254 if(set2_size != 1) {
255 GNUNET_SETU_add_element (set2, &element,NULL, NULL);
256 } else {
257 GNUNET_SETU_add_element (set2, &element,&start, NULL);
258 }
259
260 set2_size--;
261 }
262 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in set2\n");
263}
264
265/**
266 * Initialize the first set, continue.
267 */
268static void
269init_set1 (void)
270{
271 struct GNUNET_SETU_Element element;
272
273 element.element_type = 0;
274 element.data = "hello";
275 element.size = strlen (element.data);
276 GNUNET_SETU_add_element (set1, &element, NULL, NULL);
277 element.data = "bar";
278 element.size = strlen (element.data);
279 GNUNET_SETU_add_element (set1, &element, &init_set2, NULL);
280 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized set 1\n");
281}
282
283
284/**
285 * Function run on timeout.
286 *
287 * @param cls closure
288 */
289static void
290timeout_fail (void *cls)
291{
292 tt = NULL;
293 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Testcase failed with timeout\n");
294 GNUNET_SCHEDULER_shutdown ();
295 ret = 1;
296}
297
298
299/**
300 * Function run on shutdown.
301 *
302 * @param cls closure
303 */
304static void
305do_shutdown (void *cls)
306{
307 if (NULL != tt)
308 {
309 GNUNET_SCHEDULER_cancel (tt);
310 tt = NULL;
311 }
312 if (NULL != oh1)
313 {
314 GNUNET_SETU_operation_cancel (oh1);
315 oh1 = NULL;
316 }
317 if (NULL != oh2)
318 {
319 GNUNET_SETU_operation_cancel (oh2);
320 oh2 = NULL;
321 }
322 if (NULL != set1)
323 {
324 GNUNET_SETU_destroy (set1);
325 set1 = NULL;
326 }
327 if (NULL != set2)
328 {
329 GNUNET_SETU_destroy (set2);
330 set2 = NULL;
331 }
332 if (NULL != listen_handle)
333 {
334 GNUNET_SETU_listen_cancel (listen_handle);
335 listen_handle = NULL;
336 }
337}
338
339
340/**
341 * Signature of the 'main' function for a (single-peer) testcase that
342 * is run using 'GNUNET_TESTING_peer_run'.
343 *
344 * @param cls closure
345 * @param cfg configuration of the peer that was started
346 * @param peer identity of the peer that was created
347 */
348static void
349run (void *cls,
350 const struct GNUNET_CONFIGURATION_Handle *cfg,
351 struct GNUNET_TESTING_Peer *peer)
352{
353 struct GNUNET_SETU_OperationHandle *my_oh;
354
355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
356 "Running preparatory tests\n");
357 tt = GNUNET_SCHEDULER_add_delayed (
358 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
359 &timeout_fail,
360 NULL);
361 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
362
363 config = cfg;
364 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_get_peer_identity (cfg,
365 &local_id));
366 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
367 "my id (from CRYPTO): %s\n",
368 GNUNET_i2s (&local_id));
369 GNUNET_TESTING_peer_get_identity (peer,
370 &local_id);
371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
372 "my id (from TESTING): %s\n",
373 GNUNET_i2s (&local_id));
374 set1 = GNUNET_SETU_create (cfg);
375 set2 = GNUNET_SETU_create (cfg);
376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
377 "Created sets %p and %p for union operation\n",
378 set1,
379 set2);
380 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id);
381
382 /* test if canceling an uncommited request works! */
383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384 "Launching and instantly stopping set operation\n");
385 my_oh = GNUNET_SETU_prepare (&local_id,
386 &app_id,
387 NULL,
388 (struct GNUNET_SETU_Option[]){ 0 },
389 NULL,
390 NULL);
391 GNUNET_SETU_operation_cancel (my_oh);
392
393 /* test the real set reconciliation */
394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
395 "Running real set-reconciliation\n");
396 //init_set1 ();
397 // limit ~23800 element total
398 initRandomSets(50,100,100,128);
399}
400
401static void execute_perf()
402{
403 for( int repeat_ctr = 0; repeat_ctr<1; repeat_ctr++ ) {
404
405 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
406 "Executing perf round %d\n", repeat_ctr);
407
408 GNUNET_TESTING_service_run ("perf_setu_api",
409 "arm",
410 "test_setu.conf",
411 &run,
412 NULL);
413 }
414 return 0;
415}
416
417
418
419int
420main (int argc, char **argv)
421{
422 GNUNET_log_setup ("perf_setu_api",
423 "WARNING",
424 NULL);
425
426 execute_perf();
427 return 0;
428}
diff --git a/src/setu/setu.h b/src/setu/setu.h
index e9a0def95..f806c8eb1 100644
--- a/src/setu/setu.h
+++ b/src/setu/setu.h
@@ -121,6 +121,7 @@ struct GNUNET_SETU_AcceptMessage
121 * byzantine mode is enabled. 121 * byzantine mode is enabled.
122 */ 122 */
123 uint32_t byzantine_lower_bound; 123 uint32_t byzantine_lower_bound;
124
124}; 125};
125 126
126 127
diff --git a/src/setu/test_setu_api.c b/src/setu/test_setu_api.c
index 95119873c..d5c9f5b7a 100644
--- a/src/setu/test_setu_api.c
+++ b/src/setu/test_setu_api.c
@@ -193,7 +193,7 @@ init_set2 (void *cls)
193 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initializing set 2\n"); 193 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initializing set 2\n");
194 194
195 element.element_type = 0; 195 element.element_type = 0;
196 element.data = "hello"; 196 element.data = "hello1";
197 element.size = strlen (element.data); 197 element.size = strlen (element.data);
198 GNUNET_SETU_add_element (set2, &element, NULL, NULL); 198 GNUNET_SETU_add_element (set2, &element, NULL, NULL);
199 element.data = "quux"; 199 element.data = "quux";
@@ -204,6 +204,62 @@ init_set2 (void *cls)
204 GNUNET_SETU_add_element (set2, &element, &start, NULL); 204 GNUNET_SETU_add_element (set2, &element, &start, NULL);
205} 205}
206 206
207/**
208 * Generate random byte stream
209 */
210
211unsigned char *gen_rdm_bytestream (size_t num_bytes)
212{
213 unsigned char *stream = GNUNET_malloc (num_bytes);
214 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, stream, num_bytes);
215 return stream;
216}
217
218/**
219 * Generate random sets
220 */
221
222static void
223initRandomSets(int overlap, int set1_size, int set2_size, int element_size_in_bytes)
224{
225 struct GNUNET_SETU_Element element;
226 element.element_type = 0;
227
228 // Add elements to both sets
229 for (int i = 0; i < overlap; i++) {
230 element.data = gen_rdm_bytestream(element_size_in_bytes);
231 element.size = element_size_in_bytes;
232 GNUNET_SETU_add_element (set1, &element, NULL, NULL);
233 GNUNET_SETU_add_element (set2, &element, NULL, NULL);
234 set1_size--;
235 set2_size--;
236 }
237 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in both sets\n");
238
239 // Add other elements to set 1
240 while(set1_size>0) {
241 element.data = gen_rdm_bytestream(element_size_in_bytes);
242 element.size = element_size_in_bytes;
243 GNUNET_SETU_add_element (set1, &element, NULL, NULL);
244 set1_size--;
245 }
246 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in set1\n");
247
248 // Add other elements to set 2
249 while(set2_size > 0) {
250 element.data = gen_rdm_bytestream(element_size_in_bytes);
251 element.size = element_size_in_bytes;
252
253 if(set2_size != 1) {
254 GNUNET_SETU_add_element (set2, &element,NULL, NULL);
255 } else {
256 GNUNET_SETU_add_element (set2, &element,&start, NULL);
257 }
258
259 set2_size--;
260 }
261 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in set2\n");
262}
207 263
208/** 264/**
209 * Initialize the first set, continue. 265 * Initialize the first set, continue.
@@ -336,7 +392,9 @@ run (void *cls,
336 /* test the real set reconciliation */ 392 /* test the real set reconciliation */
337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338 "Running real set-reconciliation\n"); 394 "Running real set-reconciliation\n");
339 init_set1 (); 395 //init_set1 ();
396 initRandomSets(19500,20000,20000,4096);
397 //initRandomSets(19500,20000,20000,32);
340} 398}
341 399
342 400
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 7c1e217bb..740be2742 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -94,6 +94,8 @@ lib_LTLIBRARIES = \
94libgnunettestbed_la_SOURCES = \ 94libgnunettestbed_la_SOURCES = \
95 testbed_api.c testbed_api.h testbed.h \ 95 testbed_api.c testbed_api.h testbed.h \
96 testbed_api_hosts.c testbed_api_hosts.h testbed_helper.h \ 96 testbed_api_hosts.c testbed_api_hosts.h testbed_helper.h \
97 testbed_api_cmd_controller.c \
98 testbed_api_cmd_peer.c \
97 testbed_api_operations.c testbed_api_operations.h \ 99 testbed_api_operations.c testbed_api_operations.h \
98 testbed_api_peers.c testbed_api_peers.h \ 100 testbed_api_peers.c testbed_api_peers.h \
99 testbed_api_services.c \ 101 testbed_api_services.c \
@@ -192,12 +194,6 @@ if ENABLE_TEST_RUN
192 $(underlay_testcases) 194 $(underlay_testcases)
193endif 195endif
194 196
195test_testbed_api_hosts_SOURCES = \
196 test_testbed_api_hosts.c
197test_testbed_api_hosts_LDADD = \
198 $(top_builddir)/src/util/libgnunetutil.la \
199 libgnunettestbed.la
200
201test_testbed_api_SOURCES = \ 197test_testbed_api_SOURCES = \
202 test_testbed_api.c 198 test_testbed_api.c
203test_testbed_api_LDADD = \ 199test_testbed_api_LDADD = \
diff --git a/src/testbed/testbed_api_cmd_controller.c b/src/testbed/testbed_api_cmd_controller.c
new file mode 100644
index 000000000..da23df1ef
--- /dev/null
+++ b/src/testbed/testbed_api_cmd_controller.c
@@ -0,0 +1,293 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testbed/testbed_api_cmd_controller.c
23 * @brief Command to create a controller.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet-service-testbed.h"
30#include "testbed_api_hosts.h"
31#include "gnunet_testbed_ng_service.h"
32
33
34/**
35 * Generic logging shortcut
36 */
37#define LOG(kind, ...) \
38 GNUNET_log (kind, __VA_ARGS__)
39
40
41/**
42 * abort task to run on test timed out
43 *
44 * @param cls NULL
45 * @param tc the task context
46 */
47static void
48do_abort (void *cls)
49{
50 struct ControllerState *cs = cls;
51
52 if (GNUNET_NO == cs->host_ready)
53 {
54 LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
55 cs->abort_task = NULL;
56 GNUNET_TESTBED_shutdown_controller (cs);
57 }
58}
59
60
61/**
62*
63*
64* @param cls closure
65* @param cmd current CMD being cleaned up.
66*/
67static void
68controller_cleanup (void *cls,
69 const struct GNUNET_TESTING_Command *cmd)
70{
71 (void) cls;
72}
73
74
75/**
76 * Signature of the event handler function called by the
77 * respective event controller.
78 *
79 * @param cls closure
80 * @param event information about the event
81 */
82static void
83controller_cb (void *cls,
84 const struct GNUNET_TESTBED_EventInformation *event)
85{
86 struct ControllerState *cs = cls;
87
88 if (NULL != event->details.operation_finished.emsg)
89 {
90 LOG (GNUNET_ERROR_TYPE_ERROR, "There was an operation error: %s\n",
91 event->details.operation_finished.emsg);
92 GNUNET_TESTBED_shutdown_controller (cs);
93 }
94 else if (NULL == event->details.operation_finished.generic)
95 {
96 GNUNET_TESTBED_operation_done (event->op);
97 }
98}
99
100
101/**
102 * Callback which will be called to after a host registration succeeded or failed
103 *
104 * @param cls the host which has been registered
105 * @param emsg the error message; NULL if host registration is successful
106 */
107static void
108registration_comp (void *cls,
109 const char *emsg)
110{
111 struct ControllerState *cs = cls;
112
113 if (NULL != emsg)
114 {
115 LOG (GNUNET_ERROR_TYPE_ERROR,
116 "There was an error during host registration: %s\n",
117 emsg);
118 GNUNET_TESTBED_shutdown_controller (cs);
119 }
120 else
121 {
122 cs->reg_handle = NULL;
123 cs->host_ready = GNUNET_YES;
124 }
125}
126
127
128/**
129 * Callback to signal successfull startup of the controller process
130 *
131 * @param cls the closure from GNUNET_TESTBED_controller_start()
132 * @param cfg the configuration with which the controller has been started;
133 * NULL if status is not #GNUNET_OK
134 * @param status #GNUNET_OK if the startup is successfull; #GNUNET_SYSERR if not,
135 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
136 */
137static void
138controller_status_cb (void *cls,
139 const struct GNUNET_CONFIGURATION_Handle *cfg_,
140 int status)
141{
142 struct ControllerState *cs = cls;
143
144 if (GNUNET_OK != status)
145 {
146 cs->cp = NULL;
147 return;
148 }
149
150 cs->controller =
151 GNUNET_TESTBED_controller_connect (cs->host, cs->event_mask, &controller_cb,
152 cs);
153 cs->reg_handle =
154 GNUNET_TESTBED_register_host (cs->controller, cs->host, &registration_comp,
155 cs);
156}
157
158
159static void
160controller_run (void *cls,
161 const struct GNUNET_TESTING_Command *cmd,
162 struct GNUNET_TESTING_Interpreter *is)
163{
164 struct ControllerState *cs = cls;
165
166 cs->is = is;
167 cs->host = GNUNET_TESTBED_host_create (cs->hostname, cs->username, cs->cfg,
168 cs->port);
169 cs->cp = GNUNET_TESTBED_controller_start (cs->trusted_ip,
170 cs->host,
171 &controller_status_cb,
172 cs);
173 cs->abort_task =
174 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
175 (GNUNET_TIME_UNIT_MINUTES, 5),
176 &do_abort,
177 cs);
178}
179
180/**
181*
182*
183* @param cls closure.
184* @param[out] ret result
185* @param trait name of the trait.
186* @param index index number of the object to offer.
187* @return #GNUNET_OK on success.
188*/
189static int
190controller_traits (void *cls,
191 const void **ret,
192 const char *trait,
193 unsigned int index)
194{
195 (void) cls;
196
197 struct ControllerState *cs = cls;
198
199
200 struct GNUNET_TESTING_Trait traits[] = {
201 {
202 .index = 0,
203 .trait_name = "controller",
204 .ptr = (const void *) cs->controller,
205 },
206 GNUNET_TESTING_trait_end ()
207 };
208
209 return GNUNET_TESTING_get_trait (traits,
210 ret,
211 trait,
212 index);
213 return GNUNET_OK;
214}
215
216
217/**
218 * Offer data from trait
219 *
220 * @param cmd command to extract the controller from.
221 * @param pt pointer to controller.
222 * @return #GNUNET_OK on success.
223 */
224int
225GNUNET_TESTBED_get_trait_controller (const struct GNUNET_TESTING_Command *cmd,
226 struct GNUNET_TESTBED_Controller **
227 controller)
228{
229 return cmd->traits (cmd->cls,
230 (const void **) controller,
231 "controller",
232 (unsigned int) 0);
233}
234
235
236/**
237 * Shutdown nicely
238 *
239 * @param cs controller state.
240 */
241void
242GNUNET_TESTBED_shutdown_controller (struct ControllerState *cs)
243{
244 LOG (GNUNET_ERROR_TYPE_DEBUG,
245 "Shutting down...\n");
246
247 cs->controller_going_down = GNUNET_YES;
248
249 if (NULL != cs->abort_task)
250 GNUNET_SCHEDULER_cancel (cs->abort_task);
251 if (NULL != cs->reg_handle)
252 GNUNET_TESTBED_cancel_registration (cs->reg_handle);
253 if (NULL != cs->controller)
254 GNUNET_TESTBED_controller_disconnect (cs->controller);
255 if (NULL != cs->cfg)
256 GNUNET_CONFIGURATION_destroy (cs->cfg);
257 if (NULL != cs->cp)
258 GNUNET_TESTBED_controller_stop (cs->cp);
259 if (NULL != cs->host)
260 GNUNET_TESTBED_host_destroy (cs->host);
261}
262
263
264
265struct GNUNET_TESTING_Command
266GNUNET_TESTBED_cmd_controller (const char *label,
267 const char *trusted_ip,
268 const char *hostname,
269 const char *username,
270 uint16_t port,
271 struct GNUNET_CONFIGURATION_Handle *cfg,
272 uint64_t event_mask)
273{
274 struct ControllerState *cs;
275
276 cs = GNUNET_new (struct ControllerState);
277 cs->event_mask = event_mask;
278 cs->trusted_ip = trusted_ip;
279 cs->hostname = hostname;
280 cs->username = username;
281 cs->port = port;
282 cs->cfg = cfg;
283
284 struct GNUNET_TESTING_Command cmd = {
285 .cls = cs,
286 .label = label,
287 .run = &controller_run,
288 .cleanup = &controller_cleanup,
289 .traits = &controller_traits
290 };
291
292 return cmd;
293}
diff --git a/src/testbed/testbed_api_cmd_peer.c b/src/testbed/testbed_api_cmd_peer.c
new file mode 100644
index 000000000..2e253e408
--- /dev/null
+++ b/src/testbed/testbed_api_cmd_peer.c
@@ -0,0 +1,281 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21
22/**
23 * @file testbed/testbed_api_cmd_peer.c
24 * @brief Command to create a peer.
25 * @author t3sserakt
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testing_ng_lib.h"
30#include "gnunet_testbed_ng_service.h"
31#include "gnunet-service-testbed.h"
32#include "testbed_api_peers.h"
33
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) \
39 GNUNET_log (kind, __VA_ARGS__)
40
41
42/**
43*
44*
45* @param cls closure.
46* @param[out] ret result
47* @param trait name of the trait.
48* @param index index number of the object to offer.
49* @return #GNUNET_OK on success.
50*/
51static int
52peer_traits (void *cls,
53 const void **ret,
54 const char *trait,
55 unsigned int index)
56{
57 struct PeerCmdState *ps = cls;
58
59 struct GNUNET_TESTING_Trait traits[] = {
60 {
61 .index = 0,
62 .trait_name = "peer",
63 .ptr = (const void *) ps->peer,
64 },
65 GNUNET_TESTING_trait_end ()
66 };
67
68 return GNUNET_TESTING_get_trait (traits,
69 ret,
70 trait,
71 index);
72
73 return GNUNET_OK;
74}
75
76/**
77 * Offer data from trait
78 *
79 * @param cmd command to extract the controller from.
80 * @param peer pointer GNUNET_TESTBED_PEER
81 * @return #GNUNET_OK on success.
82 */
83int
84GNUNET_TESTBED_get_trait_peer (const struct GNUNET_TESTING_Command *cmd,
85 struct GNUNET_TESTBED_Peer **
86 peer)
87{
88 return cmd->traits (cmd->cls,
89 (const void **) peer,
90 "peer",
91 (unsigned int) 0);
92}
93
94
95/**
96*
97*
98* @param cls closure
99* @param cmd current CMD being cleaned up.
100*/
101static void
102peer_cleanup (void *cls,
103 const struct GNUNET_TESTING_Command *cmd)
104{
105 (void) cls;
106}
107
108
109/**
110 * abort task to run on test timed out
111 *
112 * @param cls NULL
113 * @param tc the task context
114 */
115static void
116do_abort (void *cls)
117{
118 struct PeerCmdState *ps = cls;
119
120 if (GNUNET_NO == ps->peer_ready)
121 {
122 LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
123 ps->abort_task = NULL;
124 GNUNET_TESTBED_shutdown_peer (ps);
125 }
126}
127
128
129/**
130 * Functions of this signature are called when a peer has been successfully
131 * created
132 *
133 * @param cls the closure from GNUNET_TESTBED_peer_create()
134 * @param emsg MAY contain an error description, if starting peer failed.
135 */
136static void
137peer_started_cb (void *cls,
138 const char *emsg)
139{
140 struct PeerCmdState *ps = cls;
141
142 GNUNET_TESTBED_operation_done (ps->operation);
143 if (NULL == emsg)
144 {
145 ps->peer_ready = GNUNET_YES;
146 }
147 else
148 {
149 LOG (GNUNET_ERROR_TYPE_ERROR, "There was an error starting a peer: %s\n",
150 emsg);
151 }
152
153}
154
155
156/**
157 * Functions of this signature are called when a peer has been successfully
158 * created
159 *
160 * @param cls the closure from GNUNET_TESTBED_peer_create()
161 * @param peer the handle for the created peer; NULL on any error during
162 * creation
163 * @param emsg NULL if peer is not NULL; else MAY contain the error description
164 */
165static void
166peer_create_cb (void *cls,
167 struct GNUNET_TESTBED_Peer *peer,
168 const char *emsg)
169{
170 struct PeerCmdState *ps = cls;
171
172 ps->peer = peer;
173 GNUNET_TESTBED_operation_done (ps->operation);
174 ps->operation = GNUNET_TESTBED_peer_start (NULL,
175 peer,
176 &peer_started_cb,
177 ps);
178}
179
180
181static void
182peer_run (void *cls,
183 const struct GNUNET_TESTING_Command *cmd,
184 struct GNUNET_TESTING_Interpreter *is)
185{
186 struct PeerCmdState *ps = cls;
187 const struct GNUNET_TESTING_Command *controller_cmd;
188 struct GNUNET_TESTBED_Controller *controller;
189
190 ps->is = is;
191 controller_cmd = GNUNET_TESTING_interpreter_lookup_command (
192 ps->controller_label);
193 GNUNET_TESTBED_get_trait_controller (controller_cmd,
194 &controller);
195 ps->host = GNUNET_TESTBED_host_create (ps->hostname, ps->username, ps->cfg,
196 ps->port);
197 ps->operation =
198 GNUNET_TESTBED_peer_create (controller,
199 ps->host,
200 ps->cfg,
201 &peer_create_cb,
202 ps);
203
204 ps->abort_task =
205 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
206 (GNUNET_TIME_UNIT_MINUTES, 5),
207 &do_abort,
208 ps);
209}
210
211
212void
213peer_stopped_cb (void *cls,
214 const char *emsg)
215{
216 struct PeerCmdState *ps = cls;
217
218 if (NULL != emsg)
219 {
220 LOG (GNUNET_ERROR_TYPE_ERROR, "There was an error stopping a peer: %s\n",
221 emsg);
222 }
223 GNUNET_TESTBED_operation_done (ps->operation);
224 GNUNET_TESTBED_peer_destroy (ps->peer);
225}
226
227
228/**
229 * Shutdown nicely
230 *
231 * @param cs controller state.
232 */
233void
234GNUNET_TESTBED_shutdown_peer (struct PeerCmdState *ps)
235{
236 LOG (GNUNET_ERROR_TYPE_DEBUG,
237 "Shutting down...\n");
238
239 ps->peer_going_down = GNUNET_YES;
240
241 if (NULL != ps->abort_task)
242 GNUNET_SCHEDULER_cancel (ps->abort_task);
243 if (NULL != ps->cfg)
244 GNUNET_CONFIGURATION_destroy (ps->cfg);
245 if (NULL != ps->host)
246 GNUNET_TESTBED_host_destroy (ps->host);
247
248 GNUNET_TESTBED_operation_done (ps->operation);
249 ps->operation = GNUNET_TESTBED_peer_stop (NULL, ps->peer, peer_stopped_cb,
250 ps);
251
252}
253
254
255struct GNUNET_TESTING_Command
256GNUNET_TESTBED_cmd_peer (const char *label,
257 const char *controller_label,
258 const char *hostname,
259 const char *username,
260 uint16_t port,
261 struct GNUNET_CONFIGURATION_Handle *cfg)
262{
263 struct PeerCmdState *ps;
264
265 ps = GNUNET_new (struct PeerCmdState);
266 ps->hostname = hostname;
267 ps->username = username;
268 ps->port = port;
269 ps->cfg = cfg;
270 ps->controller_label = controller_label;
271
272 struct GNUNET_TESTING_Command cmd = {
273 .cls = ps,
274 .label = label,
275 .run = &peer_run,
276 .cleanup = &peer_cleanup,
277 .traits = &peer_traits
278 };
279
280 return cmd;
281}
diff --git a/src/testbed/testbed_api_cmd_peer_store.c b/src/testbed/testbed_api_cmd_peer_store.c
new file mode 100644
index 000000000..fc96f589c
--- /dev/null
+++ b/src/testbed/testbed_api_cmd_peer_store.c
@@ -0,0 +1,60 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testbed/testbed_api_cmd_peer_store.c
23 * @brief Command to start the peer store service of a peer.
24 * @author t3sserakt
25 */
26
27
28static void
29service_run (void *cls,
30 const struct GNUNET_TESTING_Command *cmd,
31 struct GNUNET_TESTING_Interpreter *is)
32{
33 struct PeerStoreState *pss = cls;
34
35 pss->psh = GNUNET_PEERSTORE_connect (pss->cfg);
36 GNUNET_TESTING_interpreter_next (ps->is);
37}
38
39
40struct GNUNET_TESTING_Command
41GNUNET_TESTBED_cmd_peer_store (const char *label,
42 struct GNUNET_CONFIGURATION_Handle *cfg)
43{
44
45 struct PeerStoreState *pss;
46
47 pss = GNUNET_new (struct PeerStoreState);
48 pss->cfg = cfg;
49
50 struct GNUNET_TESTING_Command cmd = {
51 .cls = pss,
52 .label = label,
53 .run = &peer_store_run,
54 .cleanup = &peer_store_cleanup,
55 .traits = &peer_store_traits
56 };
57
58 return cmd;
59
60}
diff --git a/src/testbed/testbed_api_cmd_tng_connect.c b/src/testbed/testbed_api_cmd_tng_connect.c
new file mode 100644
index 000000000..e52cd3c76
--- /dev/null
+++ b/src/testbed/testbed_api_cmd_tng_connect.c
@@ -0,0 +1,55 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21
22/**
23 * @file testbed/testbed_api_cmd_peer.c
24 * @brief Command to create a peer.
25 * @author t3sserakt
26 */
27
28
29static void
30tng_connect_run (void *cls,
31 const struct GNUNET_TESTING_Command *cmd,
32 struct GNUNET_TESTING_Interpreter *is)
33{
34 struct TngConnectState *tcs = cls;
35
36 tcs->ah = GNUNET_TRANSPORT_application_init (tcs->cfg);
37}
38
39struct GNUNET_TESTING_Command
40GNUNET_TESTBED_cmd_tng_connect (const char *label)
41{
42 struct TngConnectState *tcs;
43
44 ts = GNUNET_new (struct TngConnectState);
45
46 struct GNUNET_TESTING_Command cmd = {
47 .cls = tcs,
48 .label = label,
49 .run = &tng_connect_run,
50 .cleanup = &tmg_connect_cleanup,
51 .traits = &tng_connect_traits
52 };
53
54 return cmd;
55}
diff --git a/src/testbed/testbed_api_cmd_tng_service.c b/src/testbed/testbed_api_cmd_tng_service.c
new file mode 100644
index 000000000..f9ef44bad
--- /dev/null
+++ b/src/testbed/testbed_api_cmd_tng_service.c
@@ -0,0 +1,276 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testbed/testbed_api_cmd_tng.c
23 * @brief Command to start the transport service of a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet-service-testbed.h"
30#include "testbed_api_hosts.h"
31#include "gnunet_testbed_ng_service.h"
32
33/**
34 * Generic logging shortcut
35 */
36#define LOG(kind, ...) \
37 GNUNET_log (kind, __VA_ARGS__)
38
39
40/**
41 * abort task to run on test timed out
42 *
43 * @param cls NULL
44 * @param tc the task context
45 */
46static void
47do_abort (void *cls)
48{
49 struct TngState *ts = cls;
50
51 if (GNUNET_NO == ts->service_ready)
52 {
53 LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
54 ts->abort_task = NULL;
55 GNUNET_TESTBED_shutdown_service (ts);
56 }
57}
58
59/**
60*
61*
62* @param cls closure
63* @param cmd current CMD being cleaned up.
64*/
65static void
66tng_service_cleanup (void *cls,
67 const struct GNUNET_TESTING_Command *cmd)
68{
69 (void) cls;
70}
71
72/**
73*
74*
75* @param cls closure.
76* @param[out] ret result
77* @param trait name of the trait.
78* @param index index number of the object to offer.
79* @return #GNUNET_OK on success.
80*/
81static int
82tng_service_traits (void *cls,
83 const void **ret,
84 const char *trait,
85 unsigned int index)
86{
87 (void) cls;
88 return GNUNET_OK;
89}
90
91
92static void *
93notify_connect (void *cls,
94 const struct GNUNET_PeerIdentity *peer,
95 struct GNUNET_MQ_Handle *mq)
96{
97 struct TngState *ts = cls;
98
99 if (NULL != emsg)
100 {
101 LOG (GNUNET_ERROR_TYPE_ERROR,
102 "There was an error starting the transport subsystem: %s\n",
103 emsg);
104 }
105 GNUNET_TESTING_interpreter_next (ps->is);
106 return ts->nc (ts->cb_cls);
107
108}
109
110
111static void
112notify_disconnect (void *cls,
113 const struct GNUNET_PeerIdentity *peer,
114 void *handler_cls)
115{
116}
117
118
119
120
121/**
122 * Adapter function called to establish a connection to
123 * a service.
124 *
125 * @param cls closure
126 * @param cfg configuration of the peer to connect to; will be available until
127 * GNUNET_TESTBED_operation_done() is called on the operation returned
128 * from GNUNET_TESTBED_service_connect()
129 * @return service handle to return in 'op_result', NULL on error
130 */
131static void *
132connect_adapter (void *cls,
133 const struct GNUNET_CONFIGURATION_Handle *cfg)
134{
135 struct TngState *ts = cls;
136
137 service_handle = GNUNET_TRANSPORT_core_connect (cfg,
138 ts->peer_identity,
139 ts->handlers,
140 ts,
141 &notify_connect,
142 &notify_disconnect);
143 return service_handle;
144}
145
146
147/**
148 * Adapter function called to destroy a connection to
149 * a service.
150 *
151 * @param cls closure
152 * @param op_result service handle returned from the connect adapter
153 */
154static void
155disconnect_adapter (void *cls,
156 void *op_result)
157{
158}
159
160/**
161 * Callback to be called when a service connect operation is completed
162 *
163 * @param cls the callback closure from functions generating an operation
164 * @param op the operation that has been finished
165 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
166 * @param emsg error message in case the operation has failed; will be NULL if
167 * operation has executed successfully.
168 */
169static void
170service_connect_comp_cb (void *cls,
171 struct GNUNET_TESTBED_Operation *op,
172 void *ca_result,
173 const char *emsg)
174{
175 struct TngState *ts = cls;
176
177 if (NULL != emsg)
178 {
179 LOG (GNUNET_ERROR_TYPE_DEBUG,
180 "An error occured connecting to service %s\n",
181 emsg);
182 GNUNET_TESTBED_operation_done (ts->operation);
183 }
184}
185
186
187/**
188 * Callback to be called when the requested peer information is available
189 *
190 * @param cls the closure from GNUNET_TESTBED_peer_getinformation()
191 * @param op the operation this callback corresponds to
192 * @param pinfo the result; will be NULL if the operation has failed
193 * @param emsg error message if the operation has failed;
194 * NULL if the operation is successfull
195 */
196static void
197pi_cb (void *cls,
198 struct GNUNET_TESTBED_Operation *op,
199 const struct GNUNET_TESTBED_PeerInformation *pinfo,
200 const char *emsg)
201{
202 struct TngState *ts = cls;
203
204 ts->peer_identity = pinfo->id;
205 ts->operation =
206 GNUNET_TESTBED_service_connect (NULL, peer, NULL,
207 &service_connect_comp_cb, ts,
208 &connect_adapter,
209 &disconnect_adapter,
210 ts);
211}
212
213
214static void
215tng_service_run (void *cls,
216 const struct GNUNET_TESTING_Command *cmd,
217 struct GNUNET_TESTING_Interpreter *is)
218{
219 struct TngState *ts = cls;
220 struct GNUNET_TESTBED_Peer *peer;
221 const struct GNUNET_TESTING_Command *peer_cmd;
222
223 ts->is = is;
224 peer_cmd = GNUNET_TESTING_interpreter_lookup_command (
225 ts->peer_label);
226 GNUNET_TESTBED_get_trait_peer (peer_cmd,
227 &peer);
228
229 ts->operation = GNUNET_TESTBED_peer_get_information (peer,
230 GNUNET_TESTBED_PIT_IDENTITY,
231 &pi_cb,
232 ts);
233}
234
235/**
236 * Shutdown nicely
237 *
238 * @param cs service state.
239 */
240void
241GNUNET_TESTBED_shutdown_service (struct TngState *cs)
242{
243 LOG (GNUNET_ERROR_TYPE_DEBUG,
244 "Shutting down...\n");
245}
246
247
248struct GNUNET_TESTING_Command
249GNUNET_TESTBED_cmd_tng_service (const char *label,
250 const char *peer_label,
251 const struct GNUNET_MQ_MessageHandler *handlers,
252 GNUNET_TRANSPORT_NotifyConnect nc,
253 void *cb_cls)
254
255{
256 struct TngState *ts;
257
258 ts = GNUNET_new (struct TngState);
259 ts->servicename = servicename;
260 ts->peer_label = peer_label;
261 ts->handlers = handlers;
262 ts->nc = nc;
263 ts->nd = nd;
264 ts->cb_cls;
265
266
267 struct GNUNET_TESTING_Command cmd = {
268 .cls = ts,
269 .label = label,
270 .run = &tng_service_run,
271 .cleanup = &tmg_service_cleanup,
272 .traits = &tng_service_traits
273 };
274
275 return cmd;
276}
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 2b599f55b..95fc5c805 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -15,7 +15,14 @@ lib_LTLIBRARIES = \
15 libgnunettesting.la 15 libgnunettesting.la
16 16
17libgnunettesting_la_SOURCES = \ 17libgnunettesting_la_SOURCES = \
18 testing.c 18 testing.c \
19 testing_api_cmd_batch.c \
20 testing_api_cmd_hello_world.c \
21 testing_api_cmd_hello_world_birth.c \
22 testing_api_loop.c \
23 testing_api_trait_cmd.c \
24 testing_api_trait_process.c \
25 testing_api_traits.c
19libgnunettesting_la_LIBADD = \ 26libgnunettesting_la_LIBADD = \
20 $(top_builddir)/src/arm/libgnunetarm.la \ 27 $(top_builddir)/src/arm/libgnunetarm.la \
21 $(top_builddir)/src/util/libgnunetutil.la \ 28 $(top_builddir)/src/util/libgnunetutil.la \
@@ -48,6 +55,7 @@ list_keys_LDADD = \
48 55
49 56
50check_PROGRAMS = \ 57check_PROGRAMS = \
58 test_testing_hello_world \
51 test_testing_portreservation \ 59 test_testing_portreservation \
52 test_testing_servicestartup \ 60 test_testing_servicestartup \
53 test_testing_peerstartup \ 61 test_testing_peerstartup \
@@ -57,12 +65,19 @@ check_PROGRAMS = \
57if ENABLE_TEST_RUN 65if ENABLE_TEST_RUN
58AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 66AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
59TESTS = \ 67TESTS = \
68 test_testing_hello_world \
60 test_testing_portreservation \ 69 test_testing_portreservation \
61 test_testing_peerstartup \ 70 test_testing_peerstartup \
62 test_testing_peerstartup2 \ 71 test_testing_peerstartup2 \
63 test_testing_servicestartup 72 test_testing_servicestartup
64endif 73endif
65 74
75test_testing_hello_world_SOURCES = \
76 test_testing_hello_world.c
77test_testing_hello_world_LDADD = \
78 libgnunettesting.la \
79 $(top_builddir)/src/util/libgnunetutil.la
80
66test_testing_portreservation_SOURCES = \ 81test_testing_portreservation_SOURCES = \
67 test_testing_portreservation.c 82 test_testing_portreservation.c
68test_testing_portreservation_LDADD = \ 83test_testing_portreservation_LDADD = \
diff --git a/src/testing/test_testing_hello_world.c b/src/testing/test_testing_hello_world.c
new file mode 100644
index 000000000..6300e26a4
--- /dev/null
+++ b/src/testing/test_testing_hello_world.c
@@ -0,0 +1,68 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/test_testing_hello_world.c
23 * @brief hello world test case
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_util_lib.h"
29
30/**
31 * Main function to run the test cases.
32 *
33 * @param cls not used.
34 *
35 */
36static void
37run (void *cls)
38{
39 (void *) cls;
40 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
41
42 struct GNUNET_TESTING_Command commands[] = {
43 GNUNET_TESTING_cmd_hello_world_birth ("hello-world-birth-0",
44 &now),
45 GNUNET_TESTING_cmd_hello_world ("hello-world-0","hello-world-birth-0",""),
46 GNUNET_TESTING_cmd_end ()
47 };
48
49 GNUNET_TESTING_run (NULL,
50 commands,
51 GNUNET_TIME_UNIT_FOREVER_REL);
52}
53
54int
55main (int argc,
56 char *const *argv)
57{
58 int rv = 0;
59
60 GNUNET_log_setup ("test-hello-world",
61 "DEBUG",
62 NULL);
63
64 GNUNET_SCHEDULER_run (&run,
65 NULL);
66
67 return rv;
68}
diff --git a/src/testing/testing.h b/src/testing/testing.h
new file mode 100644
index 000000000..b12466530
--- /dev/null
+++ b/src/testing/testing.h
@@ -0,0 +1,74 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @author t3sserakt
23 */
24
25#include "gnunet_util_lib.h"
26
27/**
28 * Global state of the interpreter, used by a command
29 * to access information about other commands.
30 */
31// SUGGESTION: consider making this struct opaque (only known inside of libgnunettesting,
32// say main loop and a few select commands, like next/fail/batch); + helper
33// function to access 'cfg'?
34struct GNUNET_TESTING_Interpreter
35{
36
37 /**
38 * Commands the interpreter will run.
39 */
40 struct GNUNET_TESTING_Command *commands;
41
42 /**
43 * Interpreter task (if one is scheduled).
44 */
45 struct GNUNET_SCHEDULER_Task *task;
46
47 /**
48 * Finish task of a blocking call to a commands finish method.
49 */
50 struct GNUNET_SCHEDULER_Task *finish_task;
51
52 /**
53 * Our configuration.
54 */
55 const struct GNUNET_CONFIGURATION_Handle *cfg;
56
57 /**
58 * Task run on timeout.
59 */
60 struct GNUNET_SCHEDULER_Task *timeout_task;
61
62 /**
63 * Instruction pointer. Tells #interpreter_run() which instruction to run
64 * next. Need (signed) int because it gets -1 when rewinding the
65 * interpreter to the first CMD.
66 */
67 int ip;
68
69 /**
70 * Result of the testcases, #GNUNET_OK on success
71 */
72 int result;
73
74};
diff --git a/src/testing/testing_api_cmd_batch.c b/src/testing/testing_api_cmd_batch.c
new file mode 100644
index 000000000..af260f80d
--- /dev/null
+++ b/src/testing/testing_api_cmd_batch.c
@@ -0,0 +1,256 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_batch.c
23 * @brief Implement batch-execution of CMDs.
24 * @author Marcello Stanisci (GNU Taler testing)
25 * @author t3sserakt
26 */
27#include "platform.h"
28#include "gnunet_testing_ng_lib.h"
29#include "testing.h"
30
31/**
32 * State for a "batch" CMD.
33 */
34struct BatchState
35{
36 /**
37 * CMDs batch.
38 */
39 struct GNUNET_TESTING_Command *batch;
40
41 /**
42 * Internal command pointer.
43 */
44 unsigned int batch_ip;
45};
46
47
48/**
49 * Run the command.
50 *
51 * @param cls closure.
52 * @param cmd the command being executed.
53 * @param is the interpreter state.
54 */
55static void
56batch_run (void *cls,
57 const struct GNUNET_TESTING_Command *cmd,
58 struct GNUNET_TESTING_Interpreter *is)
59{
60 struct BatchState *bs = cls;
61
62 if (NULL != bs->batch[bs->batch_ip].label)
63 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
64 "Running batched command: %s\n",
65 bs->batch[bs->batch_ip].label);
66
67 /* hit end command, leap to next top-level command. */
68 if (NULL == bs->batch[bs->batch_ip].label)
69 {
70 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
71 "Exiting from batch: %s\n",
72 cmd->label);
73 return;
74 }
75 bs->batch[bs->batch_ip].start_time
76 = bs->batch[bs->batch_ip].last_req_time
77 = GNUNET_TIME_absolute_get ();
78 bs->batch[bs->batch_ip].num_tries = 1;
79 bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls,
80 &bs->batch[bs->batch_ip],
81 is);
82}
83
84
85/**
86 * Cleanup the state from a "reserve status" CMD, and possibly
87 * cancel a pending operation thereof.
88 *
89 * @param cls closure.
90 * @param cmd the command which is being cleaned up.
91 */
92static void
93batch_cleanup (void *cls,
94 const struct GNUNET_TESTING_Command *cmd)
95{
96 struct BatchState *bs = cls;
97
98 (void) cmd;
99 for (unsigned int i = 0;
100 NULL != bs->batch[i].label;
101 i++)
102 bs->batch[i].cleanup (bs->batch[i].cls,
103 &bs->batch[i]);
104 GNUNET_free (bs->batch);
105 GNUNET_free (bs);
106}
107
108
109/**
110 * Offer internal data from a "batch" CMD, to other commands.
111 *
112 * @param cls closure.
113 * @param[out] ret result.
114 * @param trait name of the trait.
115 * @param index index number of the object to offer.
116 * @return #GNUNET_OK on success.
117 */
118static int
119batch_traits (void *cls,
120 const void **ret,
121 const char *trait,
122 unsigned int index)
123{
124#define CURRENT_CMD_INDEX 0
125#define BATCH_INDEX 1
126
127 struct BatchState *bs = cls;
128
129 struct GNUNET_TESTING_Trait traits[] = {
130 GNUNET_TESTING_make_trait_cmd
131 (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]),
132 GNUNET_TESTING_make_trait_cmd
133 (BATCH_INDEX, bs->batch),
134 GNUNET_TESTING_trait_end ()
135 };
136
137 /* Always return current command. */
138 return GNUNET_TESTING_get_trait (traits,
139 ret,
140 trait,
141 index);
142}
143
144
145/**
146 * Create a "batch" command. Such command takes a
147 * end_CMD-terminated array of CMDs and executed them.
148 * Once it hits the end CMD, it passes the control
149 * to the next top-level CMD, regardless of it being
150 * another batch or ordinary CMD.
151 *
152 * @param label the command label.
153 * @param batch array of CMDs to execute.
154 *
155 * @return the command.
156 */
157struct GNUNET_TESTING_Command
158GNUNET_TESTING_cmd_batch (const char *label,
159 struct GNUNET_TESTING_Command *batch)
160{
161 struct BatchState *bs;
162 unsigned int i;
163
164 bs = GNUNET_new (struct BatchState);
165
166 /* Get number of commands. */
167 for (i = 0; NULL != batch[i].label; i++)
168 /* noop */
169 ;
170
171 bs->batch = GNUNET_new_array (i + 1,
172 struct GNUNET_TESTING_Command);
173 memcpy (bs->batch,
174 batch,
175 sizeof (struct GNUNET_TESTING_Command) * i);
176 {
177 struct GNUNET_TESTING_Command cmd = {
178 .cls = bs,
179 .label = label,
180 .run = &batch_run,
181 .cleanup = &batch_cleanup,
182 .traits = &batch_traits
183 };
184
185 return cmd;
186 }
187}
188
189
190/**
191 * Advance internal pointer to next command.
192 *
193 * @param is interpreter state.
194 */
195void
196GNUNET_TESTING_cmd_batch_next (struct GNUNET_TESTING_Interpreter *is)
197{
198 struct BatchState *bs = is->commands[is->ip].cls;
199
200 if (NULL == bs->batch[bs->batch_ip].label)
201 {
202 is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get ();
203 is->ip++;
204 return;
205 }
206 bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get ();
207 bs->batch_ip++;
208}
209
210
211/**
212 * Test if this command is a batch command.
213 *
214 * @return false if not, true if it is a batch command
215 */
216int
217GNUNET_TESTING_cmd_is_batch (const struct GNUNET_TESTING_Command *cmd)
218{
219 return cmd->run == &batch_run;
220}
221
222
223/**
224 * Obtain what command the batch is at.
225 *
226 * @return cmd current batch command
227 */
228struct GNUNET_TESTING_Command *
229GNUNET_TESTING_cmd_batch_get_current (const struct GNUNET_TESTING_Command *cmd)
230{
231 struct BatchState *bs = cmd->cls;
232
233 GNUNET_assert (cmd->run == &batch_run);
234 return &bs->batch[bs->batch_ip];
235}
236
237
238/**
239 * Set what command the batch should be at.
240 *
241 * @param cmd current batch command
242 * @param new_ip where to move the IP
243 */
244void
245GNUNET_TESTING_cmd_batch_set_current (const struct GNUNET_TESTING_Command *cmd,
246 unsigned int new_ip)
247{
248 struct BatchState *bs = cmd->cls;
249
250 /* sanity checks */
251 GNUNET_assert (cmd->run == &batch_run);
252 for (unsigned int i = 0; i < new_ip; i++)
253 GNUNET_assert (NULL != bs->batch[i].label);
254 /* actual logic */
255 bs->batch_ip = new_ip;
256}
diff --git a/src/testing/testing_api_cmd_hello_world.c b/src/testing/testing_api_cmd_hello_world.c
new file mode 100644
index 000000000..4347ac818
--- /dev/null
+++ b/src/testing/testing_api_cmd_hello_world.c
@@ -0,0 +1,121 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_hello_world.c
23 * @brief implementation of a hello world command.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28
29struct HelloWorldState
30{
31 char *message;
32 const char *birthLabel;
33};
34
35/**
36*
37*
38* @param cls closure
39* @param cmd current CMD being cleaned up.
40*/
41static void
42hello_world_cleanup (void *cls,
43 const struct GNUNET_TESTING_Command *cmd)
44{
45 struct HelloWorldState *hs = cls;
46 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
47 "Cleaning up message %s\n",
48 hs->message);
49}
50
51/**
52*
53*
54* @param cls closure.
55* @param[out] ret result
56* @param trait name of the trait.
57* @param index index number of the object to offer.
58* @return #GNUNET_OK on success.
59*/
60static int
61hello_world_traits (void *cls,
62 const void **ret,
63 const char *trait,
64 unsigned int index)
65{
66 return GNUNET_OK;
67}
68
69/**
70* Run the "hello world" CMD.
71*
72* @param cls closure.
73* @param cmd CMD being run.
74* @param is interpreter state.
75*/
76static void
77hello_world_run (void *cls,
78 const struct GNUNET_TESTING_Command *cmd,
79 struct GNUNET_TESTING_Interpreter *is)
80{
81 struct HelloWorldState *hs = cls;
82 const struct GNUNET_TESTING_Command *birth_cmd;
83
84 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
85 "%s\n",
86 hs->message);
87 birth_cmd = GNUNET_TESTING_interpreter_lookup_command (hs->birthLabel);
88 GNUNET_TESTING_get_trait_what_am_i (birth_cmd, &hs->message);
89 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
90 "Now I am a %s\n",
91 hs->message);
92}
93
94/**
95 * Create command.
96 *
97 * @param label name for command.
98 * @param message initial message.
99 * @return command.
100 */
101struct GNUNET_TESTING_Command
102GNUNET_TESTING_cmd_hello_world (const char *label,
103 const char *birthLabel,
104 char *message)
105{
106 struct HelloWorldState *hs;
107
108 hs = GNUNET_new (struct HelloWorldState);
109 hs->message = "Hello World, I was nobody!";
110 hs->birthLabel = birthLabel;
111
112 struct GNUNET_TESTING_Command cmd = {
113 .cls = hs,
114 .label = label,
115 .run = &hello_world_run,
116 .cleanup = &hello_world_cleanup,
117 .traits = &hello_world_traits
118 };
119
120 return cmd;
121}
diff --git a/src/testing/testing_api_cmd_hello_world_birth.c b/src/testing/testing_api_cmd_hello_world_birth.c
new file mode 100644
index 000000000..2a5bded92
--- /dev/null
+++ b/src/testing/testing_api_cmd_hello_world_birth.c
@@ -0,0 +1,159 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_hello_world.c
23 * @brief implementation of a hello world command.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29
30struct HelloWorldBirthState
31{
32 struct GNUNET_TIME_Absolute *date;
33 char *what_am_i;
34};
35
36/**
37*
38*
39* @param cls closure
40* @param cmd current CMD being cleaned up.
41*/
42static void
43hello_world_birth_cleanup (void *cls,
44 const struct GNUNET_TESTING_Command *cmd)
45{
46 struct HelloWorldBirthState *hbs = cls;
47 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
48 "Finished birth of %s\n",
49 hbs->what_am_i);
50}
51
52/**
53*
54*
55* @param cls closure.
56* @param[out] ret result
57* @param trait name of the trait.
58* @param index index number of the object to offer.
59* @return #GNUNET_OK on success.
60*/
61static int
62hello_world_birth_traits (void *cls,
63 const void **ret,
64 const char *trait,
65 unsigned int index)
66{
67 struct HelloWorldBirthState *hbs = cls;
68 const char *what_am_i = hbs->what_am_i;
69
70 struct GNUNET_TESTING_Trait traits[] = {
71 {
72 .index = 0,
73 .trait_name = "what_am_i",
74 .ptr = (const void *) what_am_i,
75 },
76 GNUNET_TESTING_trait_end ()
77 };
78
79 return GNUNET_TESTING_get_trait (traits,
80 ret,
81 trait,
82 index);
83}
84
85/**
86* Run the "hello world" CMD.
87*
88* @param cls closure.
89* @param cmd CMD being run.
90* @param is interpreter state.
91*/
92static void
93hello_world_birth_run (void *cls,
94 const struct GNUNET_TESTING_Command *cmd,
95 struct GNUNET_TESTING_Interpreter *is)
96{
97 struct HelloWorldBirthState *hbs = cls;
98 struct GNUNET_TIME_Relative relativ;
99
100 relativ = GNUNET_TIME_absolute_get_difference (*hbs->date,
101 GNUNET_TIME_absolute_get ());
102
103 if (0 == relativ.rel_value_us % 10)
104 {
105 hbs->what_am_i = "creature!";
106 }
107 else if (0 == relativ.rel_value_us % 2)
108 {
109 hbs->what_am_i = "girl!";
110 }
111 else
112 {
113 hbs->what_am_i = "boy!";
114 }
115}
116
117/**
118 * Offer data from trait
119 *
120 * @param cmd command to extract the message from.
121 * @param pt pointer to message.
122 * @return #GNUNET_OK on success.
123 */
124int
125GNUNET_TESTING_get_trait_what_am_i (const struct GNUNET_TESTING_Command *cmd,
126 char **what_am_i)
127{
128 return cmd->traits (cmd->cls,
129 (const void **) what_am_i,
130 "what_am_i",
131 (unsigned int) 0);
132}
133
134/**
135 * Create command.
136 *
137 * @param label name for command.
138 * @param now when the command was started.
139 * @return command.
140 */
141struct GNUNET_TESTING_Command
142GNUNET_TESTING_cmd_hello_world_birth (const char *label,
143 struct GNUNET_TIME_Absolute *now)
144{
145 struct HelloWorldBirthState *hbs;
146
147 hbs = GNUNET_new (struct HelloWorldBirthState);
148 hbs->date = now;
149
150 struct GNUNET_TESTING_Command cmd = {
151 .cls = hbs,
152 .label = label,
153 .run = &hello_world_birth_run,
154 .cleanup = &hello_world_birth_cleanup,
155 .traits = &hello_world_birth_traits
156 };
157
158 return cmd;
159}
diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c
new file mode 100644
index 000000000..dbd86ba90
--- /dev/null
+++ b/src/testing/testing_api_loop.c
@@ -0,0 +1,510 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_loop.c
23 * @brief main interpreter loop for testcases
24 * @author Christian Grothoff (GNU Taler testing)
25 * @author Marcello Stanisci (GNU Taler testing)
26 * @author t3sserakt
27*/
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testing_ng_lib.h"
31#include "testing.h"
32
33struct GNUNET_TESTING_Interpreter *is;
34
35/**
36 * Closure used to sync an asynchronous with an synchronous command.
37 */
38struct SyncTaskClosure
39{
40
41 /**
42 * The asynchronous command the synchronous command waits for.
43 */
44 const struct GNUNET_TESTING_Command *async_cmd;
45
46 /**
47 * The synchronous command that waits for the asynchronous command.
48 */
49 const struct GNUNET_TESTING_Command *sync_cmd;
50
51 /**
52 * The interpreter of the test.
53 */
54 struct GNUNET_TESTING_Interpreter *is;
55};
56
57/**
58* Closure used to run the finish task.
59*/
60struct FinishTaskClosure
61{
62
63 /**
64 * The asynchronous command the synchronous command waits for.
65 */
66 const struct GNUNET_TESTING_Command *cmd;
67
68 /**
69 * The interpreter of the test.
70 */
71 struct GNUNET_TESTING_Interpreter *is;
72};
73
74/**
75 * Lookup command by label.
76 *
77 * @param label label to look for
78 * @return NULL if command was not found
79 */
80const struct GNUNET_TESTING_Command *
81GNUNET_TESTING_interpreter_lookup_command (const char *label)
82{
83 if (NULL == label)
84 {
85 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
86 "Attempt to lookup command for empty label\n");
87 return NULL;
88 }
89 /* Search backwards as we most likely reference recent commands */
90 for (int i = is->ip; i >= 0; i--)
91 {
92 const struct GNUNET_TESTING_Command *cmd = &is->commands[i];
93
94 /* Give precedence to top-level commands. */
95 if ( (NULL != cmd->label) &&
96 (0 == strcmp (cmd->label,
97 label)) )
98 return cmd;
99
100 if (GNUNET_TESTING_cmd_is_batch (cmd))
101 {
102#define BATCH_INDEX 1
103 struct GNUNET_TESTING_Command *batch;
104 struct GNUNET_TESTING_Command *current;
105 struct GNUNET_TESTING_Command *icmd;
106 const struct GNUNET_TESTING_Command *match;
107
108 current = GNUNET_TESTING_cmd_batch_get_current (cmd);
109 GNUNET_assert (GNUNET_OK ==
110 GNUNET_TESTING_get_trait_cmd (cmd,
111 BATCH_INDEX,
112 &batch));
113 /* We must do the loop forward, but we can find the last match */
114 match = NULL;
115 for (unsigned int j = 0;
116 NULL != (icmd = &batch[j])->label;
117 j++)
118 {
119 if (current == icmd)
120 break; /* do not go past current command */
121 if ( (NULL != icmd->label) &&
122 (0 == strcmp (icmd->label,
123 label)) )
124 match = icmd;
125 }
126 if (NULL != match)
127 return match;
128 }
129 }
130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
131 "Command not found: %s\n",
132 label);
133 return NULL;
134
135}
136
137
138/**
139 * Run the main interpreter loop that performs exchange operations.
140 *
141 * @param cls contains the `struct InterpreterState`
142 */
143static void
144interpreter_run (void *cls);
145
146
147/**
148 * Current command is done, run the next one.
149 */
150static void
151interpreter_next (void *cls)
152{
153 struct GNUNET_TESTING_Interpreter *is = cls;
154 static unsigned long long ipc;
155 static struct GNUNET_TIME_Absolute last_report;
156 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
157
158 if (GNUNET_SYSERR == is->result)
159 return; /* ignore, we already failed! */
160 if (GNUNET_TESTING_cmd_is_batch (cmd))
161 {
162 GNUNET_TESTING_cmd_batch_next (is);
163 }
164 else
165 {
166 cmd->finish_time = GNUNET_TIME_absolute_get ();
167 is->ip++;
168 }
169 if (0 == (ipc % 1000))
170 {
171 if (0 != ipc)
172 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
173 "Interpreter executed 1000 instructions in %s\n",
174 GNUNET_STRINGS_relative_time_to_string (
175 GNUNET_TIME_absolute_get_duration (last_report),
176 GNUNET_YES));
177 last_report = GNUNET_TIME_absolute_get ();
178 }
179 ipc++;
180 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
181 is);
182}
183
184
185static void
186run_finish_task_next (void *cls)
187{
188 struct FinishTaskClosure *ftc = cls;
189 const struct GNUNET_TESTING_Command *cmd = ftc->cmd;
190 struct GNUNET_TESTING_Interpreter *is = ftc->is;
191
192 if (cmd->finish (cmd->cls, &interpreter_next, is))
193 {
194 is->finish_task = GNUNET_SCHEDULER_add_now (&run_finish_task_next, ftc);
195 }
196 else
197 {
198 is->finish_task = NULL;
199 }
200
201}
202
203
204static void
205run_finish_task_sync (void *cls)
206{
207 struct SyncTaskClosure *stc = cls;
208 const struct GNUNET_TESTING_Command *cmd = stc->async_cmd;
209 const struct GNUNET_TESTING_Command *sync_cmd = stc->sync_cmd;
210 struct FinishTaskClosure *ftc;
211 struct SyncState *sync_state = sync_cmd->cls;
212 struct GNUNET_SCHEDULER_Task *finish_task = sync_state->finish_task;
213
214 GNUNET_assert (NULL != finish_task);
215 ftc = GNUNET_new (struct FinishTaskClosure);
216 ftc->cmd = stc->sync_cmd;
217 ftc->is = stc->is;
218 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
219 if (cmd->default_timeout.rel_value_us < now.abs_value_us
220 - sync_state->start_finish_time.abs_value_us)
221 {
222 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
223 "The command with label %s did not finish its asyncronous task in time.\n",
224 cmd->label);
225 is->result = GNUNET_SYSERR;
226 GNUNET_SCHEDULER_shutdown ();
227 }
228
229 if (cmd->finish (cmd->cls, run_finish_task_next, ftc))
230 {
231 finish_task = GNUNET_SCHEDULER_add_now (&run_finish_task_sync, stc);
232 }
233 else
234 {
235 finish_task = NULL;
236 }
237}
238
239
240static void
241start_finish_on_ref (void *cls,
242 const struct GNUNET_TESTING_Command *cmd,
243 struct GNUNET_TESTING_Interpreter *is)
244{
245 struct SyncState *sync_state = cls;
246 struct SyncTaskClosure *stc;
247 const struct GNUNET_TESTING_Command *async_cmd;
248
249 async_cmd = sync_state->async_cmd;
250 stc = GNUNET_new (struct SyncTaskClosure);
251 stc->async_cmd = async_cmd;
252 stc->sync_cmd = cmd;
253 stc->is = is;
254 sync_state->start_finish_time = GNUNET_TIME_absolute_get ();
255 sync_state->finish_task = GNUNET_SCHEDULER_add_now (&run_finish_task_sync,
256 stc);
257}
258
259
260const struct GNUNET_TESTING_Command
261GNUNET_TESTING_cmd_finish (const char *finish_label,
262 const char *cmd_ref,
263 struct GNUNET_TIME_Relative timeout)
264{
265 const struct GNUNET_TESTING_Command *async_cmd;
266 struct SyncState *sync_state;
267
268 async_cmd = GNUNET_TESTING_interpreter_lookup_command (cmd_ref);
269 sync_state = GNUNET_new (struct SyncState);
270 sync_state->async_cmd = async_cmd;
271
272 struct GNUNET_TESTING_Command cmd = {
273 .cls = sync_state,
274 .label = finish_label,
275 .run = &start_finish_on_ref,
276 .asynchronous_finish = GNUNET_NO
277 };
278
279 return cmd;
280}
281
282
283const struct GNUNET_TESTING_Command
284GNUNET_TESTING_cmd_make_asynchronous (const struct GNUNET_TESTING_Command cmd)
285{
286
287 GNUNET_assert (NULL != cmd.finish);
288 const struct GNUNET_TESTING_Command async_cmd = {
289 .cls = cmd.cls,
290 .label = cmd.label,
291 .run = cmd.run,
292 .cleanup = cmd.cleanup,
293 .traits = cmd.traits,
294 .finish = cmd.finish,
295 .asynchronous_finish = GNUNET_YES
296 };
297
298 return async_cmd;
299}
300
301
302/**
303 * Current command failed, clean up and fail the test case.
304 *
305 * @param is interpreter of the test
306 */
307void
308GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
309{
310 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
311
312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
313 "Failed at command `%s'\n",
314 cmd->label);
315 while (GNUNET_TESTING_cmd_is_batch (cmd))
316 {
317 cmd = GNUNET_TESTING_cmd_batch_get_current (cmd);
318 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
319 "Batch is at command `%s'\n",
320 cmd->label);
321 }
322 is->result = GNUNET_SYSERR;
323 GNUNET_SCHEDULER_shutdown ();
324}
325
326
327/**
328 * Create command array terminator.
329 *
330 * @return a end-command.
331 */
332struct GNUNET_TESTING_Command
333GNUNET_TESTING_cmd_end (void)
334{
335 static struct GNUNET_TESTING_Command cmd;
336 cmd.label = NULL;
337
338 return cmd;
339}
340
341
342/**
343 * Obtain current label.
344 */
345const char *
346GNUNET_TESTING_interpreter_get_current_label (struct
347 GNUNET_TESTING_Interpreter *is)
348{
349 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
350
351 return cmd->label;
352}
353
354
355/**
356 * Run the main interpreter loop.
357 *
358 * @param cls contains the `struct GNUNET_TESTING_Interpreter`
359 */
360static void
361interpreter_run (void *cls)
362{
363 struct FinishTaskClosure *ftc;
364 struct GNUNET_TESTING_Interpreter *is = cls;
365 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
366
367 is->task = NULL;
368
369 if (NULL == cmd->label)
370 {
371
372 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
373 "Running command END\n");
374 is->result = GNUNET_OK;
375 GNUNET_SCHEDULER_shutdown ();
376 return;
377 }
378
379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
380 "Running command `%s'\n",
381 cmd->label);
382 cmd->start_time
383 = cmd->last_req_time
384 = GNUNET_TIME_absolute_get ();
385 cmd->num_tries = 1;
386 cmd->run (cmd->cls,
387 cmd,
388 is);
389 if ((NULL != cmd->finish) && (GNUNET_NO == cmd->asynchronous_finish))
390 {
391 ftc = GNUNET_new (struct FinishTaskClosure);
392 ftc->cmd = cmd;
393 ftc->is = is;
394 cmd->finish_task = GNUNET_SCHEDULER_add_now (run_finish_task_next, ftc);
395 }
396 else
397 {
398 interpreter_next (is);
399 }
400}
401
402
403/**
404 * Function run when the test terminates (good or bad).
405 * Cleans up our state.
406 *
407 * @param cls the interpreter state.
408 */
409static void
410do_shutdown (void *cls)
411{
412 (void) cls;
413 struct GNUNET_TESTING_Command *cmd;
414 const char *label;
415
416 label = is->commands[is->ip].label;
417 if (NULL == label)
418 label = "END";
419
420 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
421 "Executing shutdown at `%s'\n",
422 label);
423
424 for (unsigned int j = 0;
425 NULL != (cmd = &is->commands[j])->label;
426 j++) {
427 cmd->cleanup (cmd->cls,
428 cmd);
429 if (NULL != cmd->finish_task)
430 {
431 GNUNET_SCHEDULER_cancel (cmd->finish_task);
432 cmd->finish_task = NULL;
433 }
434 }
435
436 if (NULL != is->task)
437 {
438 GNUNET_SCHEDULER_cancel (is->task);
439 is->task = NULL;
440 }
441 if (NULL != is->timeout_task)
442 {
443 GNUNET_SCHEDULER_cancel (is->timeout_task);
444 is->timeout_task = NULL;
445 }
446 GNUNET_free (is->commands);
447}
448
449
450/**
451 * Function run when the test terminates (good or bad) with timeout.
452 *
453 * @param cls NULL
454 */
455static void
456do_timeout (void *cls)
457{
458 (void) cls;
459
460 is->timeout_task = NULL;
461 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
462 "Terminating test due to timeout\n");
463 GNUNET_SCHEDULER_shutdown ();
464}
465
466
467/**
468 * Run the testsuite. Note, CMDs are copied into
469 * the interpreter state because they are _usually_
470 * defined into the "run" method that returns after
471 * having scheduled the test interpreter.
472 *
473 * @param is the interpreter state
474 * @param commands the list of command to execute
475 * @param timeout how long to wait
476 */
477int
478GNUNET_TESTING_run (const char *cfg_filename,
479 struct GNUNET_TESTING_Command *commands,
480 struct GNUNET_TIME_Relative timeout)
481{
482 unsigned int i;
483
484 is = GNUNET_new (struct GNUNET_TESTING_Interpreter);
485
486 if (NULL != is->timeout_task)
487 {
488 GNUNET_SCHEDULER_cancel (is->timeout_task);
489 is->timeout_task = NULL;
490 }
491 /* get the number of commands */
492 for (i = 0; NULL != commands[i].label; i++)
493 ;
494 is->commands = GNUNET_new_array (i + 1,
495 struct GNUNET_TESTING_Command);
496 memcpy (is->commands,
497 commands,
498 sizeof (struct GNUNET_TESTING_Command) * i);
499
500 is->timeout_task = GNUNET_SCHEDULER_add_delayed
501 (timeout,
502 &do_timeout,
503 is);
504 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
505 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is);
506 return GNUNET_OK;
507}
508
509
510/* end of testing_api_loop.c */
diff --git a/src/testing/testing_api_trait_cmd.c b/src/testing/testing_api_trait_cmd.c
new file mode 100644
index 000000000..886baee5b
--- /dev/null
+++ b/src/testing/testing_api_trait_cmd.c
@@ -0,0 +1,79 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_trait_cmd.c
23 * @brief offers CMDs as traits.
24 * @author Marcello Stanisci (GNU Taler testing)
25 * @author t3sserakt
26 */
27#include "platform.h"
28#include "gnunet_testing_ng_lib.h"
29
30#define GNUNET_TESTING_TRAIT_CMD "cmd"
31
32
33/**
34 * Obtain a command from @a cmd.
35 *
36 * @param cmd command to extract the command from.
37 * @param index always zero. Commands offering this
38 * kind of traits do not need this index. For
39 * example, a "batch" CMD returns always the
40 * CMD currently being executed.
41 * @param[out] _cmd where to write the wire details.
42 * @return #GNUNET_OK on success.
43 */
44int
45GNUNET_TESTING_get_trait_cmd (const struct GNUNET_TESTING_Command *cmd,
46 unsigned int index,
47 struct GNUNET_TESTING_Command **_cmd)
48{
49 return cmd->traits (cmd->cls,
50 (const void **) _cmd,
51 GNUNET_TESTING_TRAIT_CMD,
52 index);
53}
54
55
56/**
57 * Offer a command in a trait.
58 *
59 * @param index always zero. Commands offering this
60 * kind of traits do not need this index. For
61 * example, a "meta" CMD returns always the
62 * CMD currently being executed.
63 * @param cmd wire details to offer.
64 * @return the trait.
65 */
66struct GNUNET_TESTING_Trait
67GNUNET_TESTING_make_trait_cmd (unsigned int index,
68 const struct GNUNET_TESTING_Command *cmd)
69{
70 struct GNUNET_TESTING_Trait ret = {
71 .index = index,
72 .trait_name = GNUNET_TESTING_TRAIT_CMD,
73 .ptr = (const struct GNUNET_TESTING_Command *) cmd
74 };
75 return ret;
76}
77
78
79/* end of testing_api_trait_cmd.c */
diff --git a/src/testing/testing_api_trait_process.c b/src/testing/testing_api_trait_process.c
new file mode 100644
index 000000000..31cdb01df
--- /dev/null
+++ b/src/testing/testing_api_trait_process.c
@@ -0,0 +1,81 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_trait_process.c
23 * @brief trait offering process handles.
24 * @author Christian Grothoff (GNU Taler testing)
25 * @author Marcello Stanisci (GNU Taler testing)
26 * @author t3sserakt
27 */
28#include "platform.h"
29#include "gnunet_testing_ng_lib.h"
30
31#define GNUNET_TESTING_TRAIT_PROCESS "process"
32
33
34/**
35 * Obtain location where a command stores a pointer to a process.
36 *
37 * @param cmd command to extract trait from.
38 * @param index which process to pick if @a cmd
39 * has multiple on offer.
40 * @param[out] processp set to the address of the pointer to the
41 * process.
42 * @return #GNUNET_OK on success.
43 */
44int
45GNUNET_TESTING_get_trait_process
46 (const struct GNUNET_TESTING_Command *cmd,
47 unsigned int index,
48 struct GNUNET_OS_Process ***processp)
49{
50 return cmd->traits (cmd->cls,
51 (const void **) processp,
52 GNUNET_TESTING_TRAIT_PROCESS,
53 index);
54}
55
56
57/**
58 * Offer location where a command stores a pointer to a process.
59 *
60 * @param index offered location index number, in case there are
61 * multiple on offer.
62 * @param processp process location to offer.
63 *
64 * @return the trait.
65 */
66struct GNUNET_TESTING_Trait
67GNUNET_TESTING_make_trait_process
68 (unsigned int index,
69 struct GNUNET_OS_Process **processp)
70{
71 struct GNUNET_TESTING_Trait ret = {
72 .index = index,
73 .trait_name = GNUNET_TESTING_TRAIT_PROCESS,
74 .ptr = (const void *) processp
75 };
76
77 return ret;
78}
79
80
81/* end of testing_api_trait_process.c */
diff --git a/src/testing/testing_api_traits.c b/src/testing/testing_api_traits.c
new file mode 100644
index 000000000..66626833d
--- /dev/null
+++ b/src/testing/testing_api_traits.c
@@ -0,0 +1,81 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_traits.c
23 * @brief loop for trait resolution
24 * @author Christian Grothoff (GNU Taler testing)
25 * @author Marcello Stanisci (GNU Taler testing)
26 * @author t3sserakt
27 */
28#include "platform.h"
29#include "gnunet_testing_ng_lib.h"
30
31
32/**
33 * End a trait array. Usually, commands offer several traits,
34 * and put them in arrays.
35 */
36struct GNUNET_TESTING_Trait
37GNUNET_TESTING_trait_end ()
38{
39 struct GNUNET_TESTING_Trait end = {
40 .index = 0,
41 .trait_name = NULL,
42 .ptr = NULL
43 };
44
45 return end;
46}
47
48
49/**
50 * Pick the chosen trait from the traits array.
51 *
52 * @param traits the traits array.
53 * @param ret where to store the result.
54 * @param trait type of the trait to extract.
55 * @param index index number of the object to extract.
56 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
57 */
58int
59GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits,
60 const void **ret,
61 const char *trait,
62 unsigned int index)
63{
64 for (unsigned int i = 0; NULL != traits[i].trait_name; i++)
65 {
66 if ( (0 == strcmp (trait, traits[i].trait_name)) &&
67 (index == traits[i].index) )
68 {
69 *ret = (void *) traits[i].ptr;
70 return GNUNET_OK;
71 }
72 }
73 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
74 "Trait %s/%u not found.\n",
75 trait, index);
76
77 return GNUNET_SYSERR;
78}
79
80
81/* end of testing_api_traits.c */
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 67b35365d..bc3004a70 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -174,7 +174,6 @@ libgnunettransporttesting2_la_SOURCES = \
174 transport-testing-send2.c \ 174 transport-testing-send2.c \
175 transport-testing-communicator.c transport-testing-communicator.h 175 transport-testing-communicator.c transport-testing-communicator.h
176libgnunettransporttesting2_la_LIBADD = \ 176libgnunettransporttesting2_la_LIBADD = \
177 libgnunettransport.la \
178 libgnunettransportapplication.la \ 177 libgnunettransportapplication.la \
179 libgnunettransportcore.la \ 178 libgnunettransportcore.la \
180 $(top_builddir)/src/arm/libgnunetarm.la \ 179 $(top_builddir)/src/arm/libgnunetarm.la \
@@ -954,9 +953,8 @@ test_transport_api_tcp_LDADD = \
954 libgnunettransporttesting.la 953 libgnunettransporttesting.la
955 954
956test_transport_api2_tcp_SOURCES = \ 955test_transport_api2_tcp_SOURCES = \
957 test_transport_api.c 956 test_transport_api2.c
958test_transport_api2_tcp_LDADD = \ 957test_transport_api2_tcp_LDADD = \
959 libgnunettransport.la \
960 $(top_builddir)/src/hello/libgnunethello.la \ 958 $(top_builddir)/src/hello/libgnunethello.la \
961 $(top_builddir)/src/util/libgnunetutil.la \ 959 $(top_builddir)/src/util/libgnunetutil.la \
962 libgnunettransporttesting2.la 960 libgnunettransporttesting2.la
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c
index ed82dba9f..9dd2797df 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -739,7 +739,6 @@ struct Addresses
739}; 739};
740 740
741 741
742
743/** 742/**
744 * Maximum queue length before we stop reading towards the transport service. 743 * Maximum queue length before we stop reading towards the transport service.
745 */ 744 */
@@ -878,12 +877,14 @@ queue_destroy (struct Queue *queue)
878{ 877{
879 struct ListenTask *lt = NULL; 878 struct ListenTask *lt = NULL;
880 struct GNUNET_HashCode h_sock; 879 struct GNUNET_HashCode h_sock;
880 int sockfd;
881 881
882 GNUNET_CRYPTO_hash (queue->listen_sock, 882 sockfd = GNUNET_NETWORK_get_fd (queue->listen_sock);
883 sizeof(queue->listen_sock), 883 GNUNET_CRYPTO_hash (&sockfd,
884 sizeof(int),
884 &h_sock); 885 &h_sock);
885 886
886 lt = GNUNET_CONTAINER_multihashmap_get (lt_map, &h_sock); 887 lt = GNUNET_CONTAINER_multihashmap_get (lt_map, &h_sock);
887 888
888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
889 "Disconnecting queue for peer `%s'\n", 890 "Disconnecting queue for peer `%s'\n",
@@ -953,6 +954,9 @@ queue_destroy (struct Queue *queue)
953 else 954 else
954 GNUNET_free (queue); 955 GNUNET_free (queue);
955 956
957 if (NULL == lt)
958 return;
959
956 if ((! shutdown_running) && (NULL == lt->listen_task)) 960 if ((! shutdown_running) && (NULL == lt->listen_task))
957 { 961 {
958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 962 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1193,6 +1197,7 @@ setup_cipher (const struct GNUNET_HashCode *dh,
1193 0)); 1197 0));
1194} 1198}
1195 1199
1200
1196/** 1201/**
1197 * Callback called when peerstore store operation for rekey monotime value is finished. 1202 * Callback called when peerstore store operation for rekey monotime value is finished.
1198 * @param cls Queue context the store operation was executed. 1203 * @param cls Queue context the store operation was executed.
@@ -1210,6 +1215,7 @@ rekey_monotime_store_cb (void *cls, int success)
1210 queue->rekey_monotime_sc = NULL; 1215 queue->rekey_monotime_sc = NULL;
1211} 1216}
1212 1217
1218
1213/** 1219/**
1214 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY 1220 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY
1215 * where found. 1221 * where found.
@@ -1259,13 +1265,15 @@ rekey_monotime_cb (void *cls,
1259 pid, 1265 pid,
1260 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY, 1266 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY,
1261 rekey_monotonic_time, 1267 rekey_monotonic_time,
1262 sizeof(rekey_monotonic_time), 1268 sizeof(*
1269 rekey_monotonic_time),
1263 GNUNET_TIME_UNIT_FOREVER_ABS, 1270 GNUNET_TIME_UNIT_FOREVER_ABS,
1264 GNUNET_PEERSTORE_STOREOPTION_REPLACE, 1271 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
1265 &rekey_monotime_store_cb, 1272 &rekey_monotime_store_cb,
1266 queue); 1273 queue);
1267} 1274}
1268 1275
1276
1269/** 1277/**
1270 * Setup cipher of @a queue for decryption. 1278 * Setup cipher of @a queue for decryption.
1271 * 1279 *
@@ -1344,6 +1352,7 @@ do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
1344 setup_in_cipher (&rekey->ephemeral, queue); 1352 setup_in_cipher (&rekey->ephemeral, queue);
1345} 1353}
1346 1354
1355
1347/** 1356/**
1348 * Callback called when peerstore store operation for handshake ack monotime value is finished. 1357 * Callback called when peerstore store operation for handshake ack monotime value is finished.
1349 * @param cls Queue context the store operation was executed. 1358 * @param cls Queue context the store operation was executed.
@@ -1362,6 +1371,7 @@ handshake_ack_monotime_store_cb (void *cls, int success)
1362 queue->handshake_ack_monotime_sc = NULL; 1371 queue->handshake_ack_monotime_sc = NULL;
1363} 1372}
1364 1373
1374
1365/** 1375/**
1366 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK 1376 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK
1367 * where found. 1377 * where found.
@@ -1406,20 +1416,21 @@ handshake_ack_monotime_cb (void *cls,
1406 queue_finish (queue); 1416 queue_finish (queue);
1407 return; 1417 return;
1408 } 1418 }
1409 queue->handshake_ack_monotime_sc = GNUNET_PEERSTORE_store (peerstore, 1419 queue->handshake_ack_monotime_sc =
1410 "transport_tcp_communicator", 1420 GNUNET_PEERSTORE_store (peerstore,
1411 pid, 1421 "transport_tcp_communicator",
1412 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK, 1422 pid,
1413 handshake_ack_monotonic_time, 1423 GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK,
1414 sizeof( 1424 handshake_ack_monotonic_time,
1415 handshake_ack_monotonic_time), 1425 sizeof(*handshake_ack_monotonic_time),
1416 GNUNET_TIME_UNIT_FOREVER_ABS, 1426 GNUNET_TIME_UNIT_FOREVER_ABS,
1417 GNUNET_PEERSTORE_STOREOPTION_REPLACE, 1427 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
1418 & 1428 &
1419 handshake_ack_monotime_store_cb, 1429 handshake_ack_monotime_store_cb,
1420 queue); 1430 queue);
1421} 1431}
1422 1432
1433
1423/** 1434/**
1424 * Sending challenge with TcpConfirmationAck back to sender of ephemeral key. 1435 * Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
1425 * 1436 *
@@ -1465,6 +1476,7 @@ send_challenge (struct ChallengeNonceP challenge, struct Queue *queue)
1465 "sending challenge done\n"); 1476 "sending challenge done\n");
1466} 1477}
1467 1478
1479
1468/** 1480/**
1469 * Setup cipher for outgoing data stream based on target and 1481 * Setup cipher for outgoing data stream based on target and
1470 * our ephemeral private key. 1482 * our ephemeral private key.
@@ -1545,6 +1557,7 @@ inject_rekey (struct Queue *queue)
1545 setup_out_cipher (queue); 1557 setup_out_cipher (queue);
1546} 1558}
1547 1559
1560
1548/** 1561/**
1549 * We have been notified that our socket is ready to write. 1562 * We have been notified that our socket is ready to write.
1550 * Then reschedule this function to be called again once more is available. 1563 * Then reschedule this function to be called again once more is available.
@@ -1634,6 +1647,7 @@ queue_write (void *cls)
1634 queue); 1647 queue);
1635} 1648}
1636 1649
1650
1637/** 1651/**
1638 * Test if we have received a full message in plaintext. 1652 * Test if we have received a full message in plaintext.
1639 * If so, handle it. 1653 * If so, handle it.
@@ -1778,7 +1792,7 @@ try_handle_plaintext (struct Queue *queue)
1778 queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, 1792 queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch,
1779 &queue->target, 1793 &queue->target,
1780 foreign_addr, 1794 foreign_addr,
1781 0 /* no MTU */, 1795 UINT32_MAX, /* no MTU */
1782 GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, 1796 GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED,
1783 0, /* Priority */ 1797 0, /* Priority */
1784 queue->nt, 1798 queue->nt,
@@ -1975,6 +1989,7 @@ queue_read (void *cls)
1975 queue_finish (queue); 1989 queue_finish (queue);
1976} 1990}
1977 1991
1992
1978/** 1993/**
1979 * Convert a `struct sockaddr_in6 to a `struct sockaddr *` 1994 * Convert a `struct sockaddr_in6 to a `struct sockaddr *`
1980 * 1995 *
@@ -2001,6 +2016,7 @@ tcp_address_to_sockaddr_numeric_v6 (socklen_t *sock_len, struct sockaddr_in6 v6,
2001 return in; 2016 return in;
2002} 2017}
2003 2018
2019
2004/** 2020/**
2005 * Convert a `struct sockaddr_in4 to a `struct sockaddr *` 2021 * Convert a `struct sockaddr_in4 to a `struct sockaddr *`
2006 * 2022 *
@@ -2024,6 +2040,7 @@ tcp_address_to_sockaddr_numeric_v4 (socklen_t *sock_len, struct sockaddr_in v4,
2024 return in; 2040 return in;
2025} 2041}
2026 2042
2043
2027/** 2044/**
2028 * Convert TCP bind specification to a `struct PortOnlyIpv4Ipv6 *` 2045 * Convert TCP bind specification to a `struct PortOnlyIpv4Ipv6 *`
2029 * 2046 *
@@ -2083,6 +2100,7 @@ tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
2083 return po; 2100 return po;
2084} 2101}
2085 2102
2103
2086/** 2104/**
2087 * This Method extracts the address part of the BINDTO string. 2105 * This Method extracts the address part of the BINDTO string.
2088 * 2106 *
@@ -2117,7 +2135,8 @@ extract_address (const char *bindto)
2117 start++; /* skip over '['*/ 2135 start++; /* skip over '['*/
2118 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/ 2136 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/
2119 } 2137 }
2120 else { 2138 else
2139 {
2121 token = strtok_r (cp, "]", &rest); 2140 token = strtok_r (cp, "]", &rest);
2122 if (strlen (bindto) == strlen (token)) 2141 if (strlen (bindto) == strlen (token))
2123 { 2142 {
@@ -2139,6 +2158,7 @@ extract_address (const char *bindto)
2139 return start; 2158 return start;
2140} 2159}
2141 2160
2161
2142/** 2162/**
2143 * This Method extracts the port part of the BINDTO string. 2163 * This Method extracts the port part of the BINDTO string.
2144 * 2164 *
@@ -2217,6 +2237,7 @@ extract_port (const char *addr_and_port)
2217 return port; 2237 return port;
2218} 2238}
2219 2239
2240
2220/** 2241/**
2221 * Convert TCP bind specification to a `struct sockaddr *` 2242 * Convert TCP bind specification to a `struct sockaddr *`
2222 * 2243 *
@@ -2245,7 +2266,6 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2245 bindto); 2266 bindto);
2246 2267
2247 2268
2248
2249 if (1 == inet_pton (AF_INET, start, &v4.sin_addr)) 2269 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
2250 { 2270 {
2251 // colon = strrchr (cp, ':'); 2271 // colon = strrchr (cp, ':');
@@ -2263,7 +2283,8 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2263 port = extract_port (bindto); 2283 port = extract_port (bindto);
2264 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port); 2284 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
2265 } 2285 }
2266 else{ 2286 else
2287 {
2267 GNUNET_assert (0); 2288 GNUNET_assert (0);
2268 } 2289 }
2269 2290
@@ -2272,6 +2293,7 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2272 return in; 2293 return in;
2273} 2294}
2274 2295
2296
2275/** 2297/**
2276 * Signature of functions implementing the sending functionality of a 2298 * Signature of functions implementing the sending functionality of a
2277 * message queue. 2299 * message queue.
@@ -2510,6 +2532,7 @@ start_initial_kx_out (struct Queue *queue)
2510 transmit_kx (queue, &epub); 2532 transmit_kx (queue, &epub);
2511} 2533}
2512 2534
2535
2513/** 2536/**
2514 * Callback called when peerstore store operation for handshake monotime is finished. 2537 * Callback called when peerstore store operation for handshake monotime is finished.
2515 * @param cls Queue context the store operation was executed. 2538 * @param cls Queue context the store operation was executed.
@@ -2527,6 +2550,7 @@ handshake_monotime_store_cb (void *cls, int success)
2527 queue->handshake_monotime_sc = NULL; 2550 queue->handshake_monotime_sc = NULL;
2528} 2551}
2529 2552
2553
2530/** 2554/**
2531 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE 2555 * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE
2532 * where found. 2556 * where found.
@@ -2585,6 +2609,7 @@ handshake_monotime_cb (void *cls,
2585 queue); 2609 queue);
2586} 2610}
2587 2611
2612
2588/** 2613/**
2589 * We have received the first bytes from the other side on a @a queue. 2614 * We have received the first bytes from the other side on a @a queue.
2590 * Decrypt the @a tc contained in @a ibuf and check the signature. 2615 * Decrypt the @a tc contained in @a ibuf and check the signature.
@@ -2651,6 +2676,7 @@ free_proto_queue (struct ProtoQueue *pq)
2651 GNUNET_free (pq); 2676 GNUNET_free (pq);
2652} 2677}
2653 2678
2679
2654/** 2680/**
2655 * Read from the socket of the proto queue until we have enough data 2681 * Read from the socket of the proto queue until we have enough data
2656 * to upgrade to full queue. 2682 * to upgrade to full queue.
@@ -2892,6 +2918,7 @@ queue_read_kx (void *cls)
2892 queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue); 2918 queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue);
2893} 2919}
2894 2920
2921
2895/** 2922/**
2896 * Function called by the transport service to initialize a 2923 * Function called by the transport service to initialize a
2897 * message queue given address information about another peer. 2924 * message queue given address information about another peer.
@@ -2991,6 +3018,7 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
2991 return GNUNET_OK; 3018 return GNUNET_OK;
2992} 3019}
2993 3020
3021
2994/** 3022/**
2995 * Iterator over all ListenTasks to clean up. 3023 * Iterator over all ListenTasks to clean up.
2996 * 3024 *
@@ -3021,6 +3049,7 @@ get_lt_delete_it (void *cls,
3021 return GNUNET_OK; 3049 return GNUNET_OK;
3022} 3050}
3023 3051
3052
3024/** 3053/**
3025 * Iterator over all message queues to clean up. 3054 * Iterator over all message queues to clean up.
3026 * 3055 *
@@ -3042,6 +3071,7 @@ get_queue_delete_it (void *cls,
3042 return GNUNET_OK; 3071 return GNUNET_OK;
3043} 3072}
3044 3073
3074
3045/** 3075/**
3046 * Shutdown the UNIX communicator. 3076 * Shutdown the UNIX communicator.
3047 * 3077 *
@@ -3182,6 +3212,7 @@ nat_address_cb (void *cls,
3182 } 3212 }
3183} 3213}
3184 3214
3215
3185/** 3216/**
3186 * This method adds addresses to the DLL, that are later register at the NAT service. 3217 * This method adds addresses to the DLL, that are later register at the NAT service.
3187 */ 3218 */
@@ -3211,6 +3242,7 @@ add_addr (struct sockaddr *in, socklen_t in_len)
3211 addrs_lens++; 3242 addrs_lens++;
3212} 3243}
3213 3244
3245
3214/** 3246/**
3215 * This method launch network interactions for each address we like to bind to. 3247 * This method launch network interactions for each address we like to bind to.
3216 * 3248 *
@@ -3226,6 +3258,7 @@ init_socket (struct sockaddr *addr,
3226 socklen_t sto_len; 3258 socklen_t sto_len;
3227 struct GNUNET_NETWORK_Handle *listen_sock; 3259 struct GNUNET_NETWORK_Handle *listen_sock;
3228 struct ListenTask *lt; 3260 struct ListenTask *lt;
3261 int sockfd;
3229 struct GNUNET_HashCode h_sock; 3262 struct GNUNET_HashCode h_sock;
3230 3263
3231 if (NULL == addr) 3264 if (NULL == addr)
@@ -3314,8 +3347,9 @@ init_socket (struct sockaddr *addr,
3314 3347
3315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3316 "creating hash\n"); 3349 "creating hash\n");
3317 GNUNET_CRYPTO_hash (lt->listen_sock, 3350 sockfd = GNUNET_NETWORK_get_fd (lt->listen_sock);
3318 sizeof(lt->listen_sock), 3351 GNUNET_CRYPTO_hash (&sockfd,
3352 sizeof(int),
3319 &h_sock); 3353 &h_sock);
3320 3354
3321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -3336,7 +3370,7 @@ init_socket (struct sockaddr *addr,
3336 if (NULL == queue_map) 3370 if (NULL == queue_map)
3337 queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); 3371 queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
3338 3372
3339 if (NULL == ch ) 3373 if (NULL == ch)
3340 ch = GNUNET_TRANSPORT_communicator_connect (cfg, 3374 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
3341 COMMUNICATOR_CONFIG_SECTION, 3375 COMMUNICATOR_CONFIG_SECTION,
3342 COMMUNICATOR_ADDRESS_PREFIX, 3376 COMMUNICATOR_ADDRESS_PREFIX,
@@ -3360,6 +3394,7 @@ init_socket (struct sockaddr *addr,
3360 3394
3361} 3395}
3362 3396
3397
3363/** 3398/**
3364 * This method reads from the DLL addrs_head to register them at the NAT service. 3399 * This method reads from the DLL addrs_head to register them at the NAT service.
3365 */ 3400 */
@@ -3421,6 +3456,7 @@ nat_register ()
3421 } 3456 }
3422} 3457}
3423 3458
3459
3424/** 3460/**
3425 * This method is the callback called by the resolver API, and wraps method init_socket. 3461 * This method is the callback called by the resolver API, and wraps method init_socket.
3426 * 3462 *
@@ -3476,6 +3512,7 @@ init_socket_resolv (void *cls,
3476 } 3512 }
3477} 3513}
3478 3514
3515
3479/** 3516/**
3480 * Setup communicator and launch network interactions. 3517 * Setup communicator and launch network interactions.
3481 * 3518 *
@@ -3532,6 +3569,7 @@ run (void *cls,
3532 peerstore = GNUNET_PEERSTORE_connect (cfg); 3569 peerstore = GNUNET_PEERSTORE_connect (cfg);
3533 if (NULL == peerstore) 3570 if (NULL == peerstore)
3534 { 3571 {
3572 GNUNET_free (bindto);
3535 GNUNET_break (0); 3573 GNUNET_break (0);
3536 GNUNET_SCHEDULER_shutdown (); 3574 GNUNET_SCHEDULER_shutdown ();
3537 return; 3575 return;
@@ -3564,7 +3602,6 @@ run (void *cls,
3564 GNUNET_free (po); 3602 GNUNET_free (po);
3565 nat_register (); 3603 nat_register ();
3566 GNUNET_free (bindto); 3604 GNUNET_free (bindto);
3567
3568 return; 3605 return;
3569 } 3606 }
3570 3607
@@ -3577,8 +3614,8 @@ run (void *cls,
3577 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, v4, bind_port); 3614 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, v4, bind_port);
3578 init_socket (in, in_len); 3615 init_socket (in, in_len);
3579 nat_register (); 3616 nat_register ();
3617 GNUNET_free (start);
3580 GNUNET_free (bindto); 3618 GNUNET_free (bindto);
3581
3582 return; 3619 return;
3583 } 3620 }
3584 3621
@@ -3588,8 +3625,8 @@ run (void *cls,
3588 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, v6, bind_port); 3625 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, v6, bind_port);
3589 init_socket (in, in_len); 3626 init_socket (in, in_len);
3590 nat_register (); 3627 nat_register ();
3628 GNUNET_free (start);
3591 GNUNET_free (bindto); 3629 GNUNET_free (bindto);
3592
3593 return; 3630 return;
3594 } 3631 }
3595 3632
@@ -3603,6 +3640,7 @@ run (void *cls,
3603 &init_socket_resolv, 3640 &init_socket_resolv,
3604 &port); 3641 &port);
3605 GNUNET_free (bindto); 3642 GNUNET_free (bindto);
3643 GNUNET_free (start);
3606} 3644}
3607 3645
3608 3646
diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c
index 415dc4b48..d75f4ae00 100644
--- a/src/transport/gnunet-communicator-udp.c
+++ b/src/transport/gnunet-communicator-udp.c
@@ -1492,16 +1492,9 @@ add_acks (struct SharedSecret *ss, int acks_to_add)
1492 1492
1493 struct ReceiverAddress *receiver = ss->receiver; 1493 struct ReceiverAddress *receiver = ss->receiver;
1494 1494
1495 if (NULL == ss) 1495 GNUNET_assert (NULL != ss);
1496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1496 GNUNET_assert (NULL != receiver);
1497 "secret NULL!\n"); 1497 GNUNET_assert (NULL != receiver->d_qh);
1498
1499 if (NULL == receiver)
1500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1501 "Receiver NULL!\n");
1502 if (NULL == receiver->d_qh)
1503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1504 "Queue NULL!\n");
1505 1498
1506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507 "Tell transport we have %u more acks!\n", 1500 "Tell transport we have %u more acks!\n",
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index 9c37f15e2..cbf795eea 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -2693,12 +2693,12 @@ static struct GNUNET_CONTAINER_MultiShortmap *dvlearn_map;
2693/** 2693/**
2694 * Head of a DLL sorted by launch time. 2694 * Head of a DLL sorted by launch time.
2695 */ 2695 */
2696static struct LearnLaunchEntry *lle_head; 2696static struct LearnLaunchEntry *lle_head = NULL;
2697 2697
2698/** 2698/**
2699 * Tail of a DLL sorted by launch time. 2699 * Tail of a DLL sorted by launch time.
2700 */ 2700 */
2701static struct LearnLaunchEntry *lle_tail; 2701static struct LearnLaunchEntry *lle_tail = NULL;
2702 2702
2703/** 2703/**
2704 * MIN Heap sorted by "next_challenge" to `struct ValidationState` entries 2704 * MIN Heap sorted by "next_challenge" to `struct ValidationState` entries
@@ -2772,6 +2772,11 @@ static unsigned int pa_count;
2772 */ 2772 */
2773static struct GNUNET_TIME_Absolute hello_mono_time; 2773static struct GNUNET_TIME_Absolute hello_mono_time;
2774 2774
2775/**
2776 * Indication if we have received a shutdown signal
2777 * and are in the process of cleaning up.
2778 */
2779static int in_shutdown;
2775 2780
2776/** 2781/**
2777 * Get an offset into the transmission history buffer for `struct 2782 * Get an offset into the transmission history buffer for `struct
@@ -2805,6 +2810,7 @@ free_incoming_request (struct IncomingRequest *ir)
2805 GNUNET_assert (ir_total > 0); 2810 GNUNET_assert (ir_total > 0);
2806 ir_total--; 2811 ir_total--;
2807 GNUNET_PEERSTORE_watch_cancel (ir->wc); 2812 GNUNET_PEERSTORE_watch_cancel (ir->wc);
2813 ir->wc = NULL;
2808 GNUNET_free (ir); 2814 GNUNET_free (ir);
2809} 2815}
2810 2816
@@ -3333,6 +3339,8 @@ free_neighbour (struct Neighbour *neighbour)
3333 GNUNET_CONTAINER_multipeermap_remove (neighbours, 3339 GNUNET_CONTAINER_multipeermap_remove (neighbours,
3334 &neighbour->pid, 3340 &neighbour->pid,
3335 neighbour)); 3341 neighbour));
3342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3343 "Freeing neighbour\n");
3336 if (NULL != neighbour->reassembly_map) 3344 if (NULL != neighbour->reassembly_map)
3337 { 3345 {
3338 GNUNET_CONTAINER_multihashmap32_iterate (neighbour->reassembly_map, 3346 GNUNET_CONTAINER_multihashmap32_iterate (neighbour->reassembly_map,
@@ -3451,6 +3459,8 @@ schedule_transmit_on_queue (struct Queue *queue,
3451 if (queue->tc->details.communicator.total_queue_length >= 3459 if (queue->tc->details.communicator.total_queue_length >=
3452 COMMUNICATOR_TOTAL_QUEUE_LIMIT) 3460 COMMUNICATOR_TOTAL_QUEUE_LIMIT)
3453 { 3461 {
3462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3463 "Transmission throttled due to communicator queue limit\n");
3454 GNUNET_STATISTICS_update ( 3464 GNUNET_STATISTICS_update (
3455 GST_stats, 3465 GST_stats,
3456 "# Transmission throttled due to communicator queue limit", 3466 "# Transmission throttled due to communicator queue limit",
@@ -3461,6 +3471,8 @@ schedule_transmit_on_queue (struct Queue *queue,
3461 } 3471 }
3462 if (queue->queue_length >= QUEUE_LENGTH_LIMIT) 3472 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3463 { 3473 {
3474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3475 "Transmission throttled due to communicator queue length limit\n");
3464 GNUNET_STATISTICS_update (GST_stats, 3476 GNUNET_STATISTICS_update (GST_stats,
3465 "# Transmission throttled due to queue queue limit", 3477 "# Transmission throttled due to queue queue limit",
3466 1, 3478 1,
@@ -3495,15 +3507,21 @@ check_link_down (void *cls)
3495 struct GNUNET_TIME_Absolute dvh_timeout; 3507 struct GNUNET_TIME_Absolute dvh_timeout;
3496 struct GNUNET_TIME_Absolute q_timeout; 3508 struct GNUNET_TIME_Absolute q_timeout;
3497 3509
3510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3511 "Checking if link is down\n");
3498 vl->visibility_task = NULL; 3512 vl->visibility_task = NULL;
3499 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS; 3513 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3500 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos; 3514 if (NULL != dv)
3501 pos = pos->next_dv)
3502 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout, pos->path_valid_until);
3503 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3504 { 3515 {
3505 vl->dv->vl = NULL; 3516 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3506 vl->dv = NULL; 3517 pos = pos->next_dv)
3518 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
3519 pos->path_valid_until);
3520 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3521 {
3522 vl->dv->vl = NULL;
3523 vl->dv = NULL;
3524 }
3507 } 3525 }
3508 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS; 3526 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3509 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour) 3527 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
@@ -3543,6 +3561,8 @@ free_queue (struct Queue *queue)
3543 struct PendingAcknowledgement *pa; 3561 struct PendingAcknowledgement *pa;
3544 struct VirtualLink *vl; 3562 struct VirtualLink *vl;
3545 3563
3564 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3565 "Cleaning up queue %u\n", queue->qid);
3546 if (NULL != queue->transmit_task) 3566 if (NULL != queue->transmit_task)
3547 { 3567 {
3548 GNUNET_SCHEDULER_cancel (queue->transmit_task); 3568 GNUNET_SCHEDULER_cancel (queue->transmit_task);
@@ -3650,6 +3670,7 @@ stop_peer_request (void *cls,
3650 struct PeerRequest *pr = value; 3670 struct PeerRequest *pr = value;
3651 3671
3652 GNUNET_PEERSTORE_watch_cancel (pr->wc); 3672 GNUNET_PEERSTORE_watch_cancel (pr->wc);
3673 pr->wc = NULL;
3653 GNUNET_assert ( 3674 GNUNET_assert (
3654 GNUNET_YES == 3675 GNUNET_YES ==
3655 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests, 3676 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
@@ -3661,6 +3682,9 @@ stop_peer_request (void *cls,
3661} 3682}
3662 3683
3663 3684
3685static void
3686do_shutdown (void *cls);
3687
3664/** 3688/**
3665 * Called whenever a client is disconnected. Frees our 3689 * Called whenever a client is disconnected. Frees our
3666 * resources associated with that client. 3690 * resources associated with that client.
@@ -3678,16 +3702,20 @@ client_disconnect_cb (void *cls,
3678 3702
3679 (void) cls; 3703 (void) cls;
3680 (void) client; 3704 (void) client;
3681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3682 "Client %p disconnected, cleaning up.\n",
3683 tc);
3684 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc); 3705 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
3685 switch (tc->type) 3706 switch (tc->type)
3686 { 3707 {
3687 case CT_NONE: 3708 case CT_NONE:
3709 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3710 "Unknown Client %p disconnected, cleaning up.\n",
3711 tc);
3688 break; 3712 break;
3689 3713
3690 case CT_CORE: { 3714 case CT_CORE: {
3715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3716 "CORE Client %p disconnected, cleaning up.\n",
3717 tc);
3718
3691 struct PendingMessage *pm; 3719 struct PendingMessage *pm;
3692 3720
3693 while (NULL != (pm = tc->details.core.pending_msg_head)) 3721 while (NULL != (pm = tc->details.core.pending_msg_head))
@@ -3702,9 +3730,17 @@ client_disconnect_cb (void *cls,
3702 break; 3730 break;
3703 3731
3704 case CT_MONITOR: 3732 case CT_MONITOR:
3733 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3734 "MONITOR Client %p disconnected, cleaning up.\n",
3735 tc);
3736
3705 break; 3737 break;
3706 3738
3707 case CT_COMMUNICATOR: { 3739 case CT_COMMUNICATOR: {
3740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3741 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
3742 tc);
3743
3708 struct Queue *q; 3744 struct Queue *q;
3709 struct AddressListEntry *ale; 3745 struct AddressListEntry *ale;
3710 3746
@@ -3717,6 +3753,10 @@ client_disconnect_cb (void *cls,
3717 break; 3753 break;
3718 3754
3719 case CT_APPLICATION: 3755 case CT_APPLICATION:
3756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3757 "APPLICATION Client %p disconnected, cleaning up.\n",
3758 tc);
3759
3720 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests, 3760 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
3721 &stop_peer_request, 3761 &stop_peer_request,
3722 tc); 3762 tc);
@@ -3724,6 +3764,12 @@ client_disconnect_cb (void *cls,
3724 break; 3764 break;
3725 } 3765 }
3726 GNUNET_free (tc); 3766 GNUNET_free (tc);
3767 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
3768 {
3769 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3770 "Our last client disconnected\n");
3771 do_shutdown (cls);
3772 }
3727} 3773}
3728 3774
3729 3775
@@ -4153,7 +4199,6 @@ queue_send_msg (struct Queue *queue,
4153 struct GNUNET_TRANSPORT_SendMessageTo *smt; 4199 struct GNUNET_TRANSPORT_SendMessageTo *smt;
4154 struct GNUNET_MQ_Envelope *env; 4200 struct GNUNET_MQ_Envelope *env;
4155 4201
4156 queue->idle = GNUNET_NO;
4157 GNUNET_log ( 4202 GNUNET_log (
4158 GNUNET_ERROR_TYPE_DEBUG, 4203 GNUNET_ERROR_TYPE_DEBUG,
4159 "Queueing %u bytes of payload for transmission <%llu> on queue %llu to %s\n", 4204 "Queueing %u bytes of payload for transmission <%llu> on queue %llu to %s\n",
@@ -4226,7 +4271,7 @@ route_via_neighbour (const struct Neighbour *n,
4226 for (struct Queue *pos = n->queue_head; NULL != pos; 4271 for (struct Queue *pos = n->queue_head; NULL != pos;
4227 pos = pos->next_neighbour) 4272 pos = pos->next_neighbour)
4228 { 4273 {
4229 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) || 4274 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4230 (pos->validated_until.abs_value_us > now.abs_value_us)) 4275 (pos->validated_until.abs_value_us > now.abs_value_us))
4231 candidates++; 4276 candidates++;
4232 } 4277 }
@@ -4255,7 +4300,7 @@ route_via_neighbour (const struct Neighbour *n,
4255 for (struct Queue *pos = n->queue_head; NULL != pos; 4300 for (struct Queue *pos = n->queue_head; NULL != pos;
4256 pos = pos->next_neighbour) 4301 pos = pos->next_neighbour)
4257 { 4302 {
4258 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) || 4303 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4259 (pos->validated_until.abs_value_us > now.abs_value_us)) 4304 (pos->validated_until.abs_value_us > now.abs_value_us))
4260 { 4305 {
4261 if ((sel1 == candidates) || (sel2 == candidates)) 4306 if ((sel1 == candidates) || (sel2 == candidates))
@@ -4702,6 +4747,24 @@ route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
4702} 4747}
4703 4748
4704 4749
4750static void
4751consider_sending_fc (void *cls);
4752
4753/**
4754 * Something changed on the virtual link with respect to flow
4755 * control. Consider retransmitting the FC window size.
4756 *
4757 * @param cls a `struct VirtualLink` to work with
4758 */
4759static void
4760task_consider_sending_fc (void *cls)
4761{
4762 struct VirtualLink *vl = cls;
4763 vl->fc_retransmit_task = NULL;
4764 consider_sending_fc (cls);
4765}
4766
4767
4705/** 4768/**
4706 * Something changed on the virtual link with respect to flow 4769 * Something changed on the virtual link with respect to flow
4707 * control. Consider retransmitting the FC window size. 4770 * control. Consider retransmitting the FC window size.
@@ -4759,7 +4822,7 @@ consider_sending_fc (void *cls)
4759 if (NULL != vl->fc_retransmit_task) 4822 if (NULL != vl->fc_retransmit_task)
4760 GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task); 4823 GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
4761 vl->fc_retransmit_task = 4824 vl->fc_retransmit_task =
4762 GNUNET_SCHEDULER_add_delayed (rtt, &consider_sending_fc, vl); 4825 GNUNET_SCHEDULER_add_delayed (rtt, &task_consider_sending_fc, vl);
4763} 4826}
4764 4827
4765 4828
@@ -4812,16 +4875,22 @@ check_vl_transmission (struct VirtualLink *vl)
4812 } 4875 }
4813 if (GNUNET_NO == elig) 4876 if (GNUNET_NO == elig)
4814 return; 4877 return;
4815 4878 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4879 "Not stalled. Scheduling transmission on queue\n");
4816 /* Notify queues at direct neighbours that we are interested */ 4880 /* Notify queues at direct neighbours that we are interested */
4817 now = GNUNET_TIME_absolute_get (); 4881 now = GNUNET_TIME_absolute_get ();
4818 if (NULL != n) 4882 if (NULL != n)
4819 { 4883 {
4820 for (struct Queue *queue = n->queue_head; NULL != queue; 4884 for (struct Queue *queue = n->queue_head; NULL != queue;
4821 queue = queue->next_neighbour) 4885 queue = queue->next_neighbour)
4886 {
4822 if ((GNUNET_YES == queue->idle) && 4887 if ((GNUNET_YES == queue->idle) &&
4823 (queue->validated_until.abs_value_us > now.abs_value_us)) 4888 (queue->validated_until.abs_value_us > now.abs_value_us))
4824 schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT); 4889 schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
4890 else
4891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4892 "Queue busy or invalid\n");
4893 }
4825 } 4894 }
4826 /* Notify queues via DV that we are interested */ 4895 /* Notify queues via DV that we are interested */
4827 if (NULL != dv) 4896 if (NULL != dv)
@@ -4869,6 +4938,9 @@ handle_client_send (void *cls, const struct OutboundMessage *obm)
4869 vl = lookup_virtual_link (&obm->peer); 4938 vl = lookup_virtual_link (&obm->peer);
4870 if (NULL == vl) 4939 if (NULL == vl)
4871 { 4940 {
4941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4942 "Don't have %s as a neighbour (anymore).\n",
4943 GNUNET_i2s (&obm->peer));
4872 /* Failure: don't have this peer as a neighbour (anymore). 4944 /* Failure: don't have this peer as a neighbour (anymore).
4873 Might have gone down asynchronously, so this is NOT 4945 Might have gone down asynchronously, so this is NOT
4874 a protocol violation by CORE. Still count the event, 4946 a protocol violation by CORE. Still count the event,
@@ -5127,9 +5199,12 @@ handle_del_address (void *cls,
5127 ale->address); 5199 ale->address);
5128 free_address_list_entry (ale); 5200 free_address_list_entry (ale);
5129 GNUNET_SERVICE_client_continue (tc->client); 5201 GNUNET_SERVICE_client_continue (tc->client);
5202 return;
5130 } 5203 }
5131 GNUNET_break (0); 5204 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5132 GNUNET_SERVICE_client_drop (tc->client); 5205 "Communicator removed address we did not even have.\n");
5206 GNUNET_SERVICE_client_continue (tc->client);
5207 // GNUNET_SERVICE_client_drop (tc->client);
5133} 5208}
5134 5209
5135 5210
@@ -5208,7 +5283,8 @@ handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
5208 we pass this on, CORE would be confused (link down, messages 5283 we pass this on, CORE would be confused (link down, messages
5209 arrive). We should investigate more if this happens often, 5284 arrive). We should investigate more if this happens often,
5210 or in a persistent manner, and possibly do "something" about 5285 or in a persistent manner, and possibly do "something" about
5211 it. Thus logging as error for now. */GNUNET_break_op (0); 5286 it. Thus logging as error for now. */
5287 GNUNET_break_op (0);
5212 GNUNET_STATISTICS_update (GST_stats, 5288 GNUNET_STATISTICS_update (GST_stats,
5213 "# CORE messages droped (virtual link still down)", 5289 "# CORE messages droped (virtual link still down)",
5214 1, 5290 1,
@@ -6100,6 +6176,7 @@ activate_core_visible_dv_path (struct DistanceVectorHop *hop)
6100 dv->vl = vl; 6176 dv->vl = vl;
6101 vl->core_recv_window = RECV_WINDOW_SIZE; 6177 vl->core_recv_window = RECV_WINDOW_SIZE;
6102 vl->available_fc_window_size = DEFAULT_WINDOW_SIZE; 6178 vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
6179 vl->incoming_fc_window_size = DEFAULT_WINDOW_SIZE;
6103 vl->visibility_task = 6180 vl->visibility_task =
6104 GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl); 6181 GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl);
6105 GNUNET_break (GNUNET_YES == 6182 GNUNET_break (GNUNET_YES ==
@@ -6899,7 +6976,6 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6899 if (MAX_DV_HOPS_ALLOWED == nhops) 6976 if (MAX_DV_HOPS_ALLOWED == nhops)
6900 { 6977 {
6901 /* At limit, we're out of here! */ 6978 /* At limit, we're out of here! */
6902 finish_cmc_handling (cmc);
6903 return; 6979 return;
6904 } 6980 }
6905 6981
@@ -7637,7 +7713,7 @@ start_address_validation (const struct GNUNET_PeerIdentity *pid,
7637 validation_map, 7713 validation_map,
7638 &vs->pid, 7714 &vs->pid,
7639 vs, 7715 vs,
7640 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 7716 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
7641 update_next_challenge_time (vs, now); 7717 update_next_challenge_time (vs, now);
7642} 7718}
7643 7719
@@ -7730,13 +7806,26 @@ handle_validation_challenge (
7730 &tvp, 7806 &tvp,
7731 &tvr.signature); 7807 &tvr.signature);
7732 } 7808 }
7733 route_control_message_without_fc (&cmc->im.sender,
7734 &tvr.header,
7735 RMO_ANYTHING_GOES | RMO_REDUNDANT);
7736 sender = cmc->im.sender; 7809 sender = cmc->im.sender;
7737 finish_cmc_handling (cmc);
7738 vl = lookup_virtual_link (&sender); 7810 vl = lookup_virtual_link (&sender);
7739 if (NULL != vl) 7811 if (NULL != vl)
7812 {
7813 route_control_message_without_fc (&cmc->im.sender,
7814 &tvr.header,
7815 RMO_ANYTHING_GOES | RMO_REDUNDANT);
7816 }
7817 else
7818 {
7819 /* Use route via neighbour */
7820 n = lookup_neighbour (&sender);
7821 if (NULL != n)
7822 route_via_neighbour (n, &tvr.header,
7823 RMO_ANYTHING_GOES | RMO_REDUNDANT
7824 | RMO_UNCONFIRMED_ALLOWED);
7825 }
7826
7827 finish_cmc_handling (cmc);
7828 if (NULL != vl)
7740 return; 7829 return;
7741 7830
7742 /* For us, the link is still down, but we need bi-directional 7831 /* For us, the link is still down, but we need bi-directional
@@ -8010,8 +8099,10 @@ handle_validation_response (
8010 vl->target = n->pid; 8099 vl->target = n->pid;
8011 vl->n = n; 8100 vl->n = n;
8012 n->vl = vl; 8101 n->vl = vl;
8102 q->idle = GNUNET_YES;
8013 vl->core_recv_window = RECV_WINDOW_SIZE; 8103 vl->core_recv_window = RECV_WINDOW_SIZE;
8014 vl->available_fc_window_size = DEFAULT_WINDOW_SIZE; 8104 vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
8105 vl->incoming_fc_window_size = DEFAULT_WINDOW_SIZE;
8015 vl->visibility_task = 8106 vl->visibility_task =
8016 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl); 8107 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
8017 GNUNET_break (GNUNET_YES == 8108 GNUNET_break (GNUNET_YES ==
@@ -8067,11 +8158,15 @@ handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
8067 uint64_t os; 8158 uint64_t os;
8068 uint64_t wnd; 8159 uint64_t wnd;
8069 8160
8161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8162 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
8070 vl = lookup_virtual_link (&cmc->im.sender); 8163 vl = lookup_virtual_link (&cmc->im.sender);
8071 if (NULL == vl) 8164 if (NULL == vl)
8072 { 8165 {
8166 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8167 "FC dropped: VL unknown\n");
8073 GNUNET_STATISTICS_update (GST_stats, 8168 GNUNET_STATISTICS_update (GST_stats,
8074 "# FC dropped: virtual link unknown", 8169 "# FC dropped: Virtual link unknown",
8075 1, 8170 1,
8076 GNUNET_NO); 8171 GNUNET_NO);
8077 finish_cmc_handling (cmc); 8172 finish_cmc_handling (cmc);
@@ -8080,6 +8175,8 @@ handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
8080 st = GNUNET_TIME_absolute_ntoh (fc->sender_time); 8175 st = GNUNET_TIME_absolute_ntoh (fc->sender_time);
8081 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us) 8176 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
8082 { 8177 {
8178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8179 "FC dropped: Message out of order\n");
8083 /* out of order, drop */ 8180 /* out of order, drop */
8084 GNUNET_STATISTICS_update (GST_stats, 8181 GNUNET_STATISTICS_update (GST_stats,
8085 "# FC dropped: message out of order", 8182 "# FC dropped: message out of order",
@@ -8112,8 +8209,10 @@ handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
8112 (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX) 8209 (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)
8113 % FC_NO_CHANGE_REPLY_PROBABILITY)) 8210 % FC_NO_CHANGE_REPLY_PROBABILITY))
8114 { 8211 {
8115 /* Consider re-sending our FC message, as clearly the 8212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8116 other peer's idea of the window is not up-to-date */ 8213 "Consider re-sending our FC message, as clearly the ther peer's idea of the window is not up-to-date (%llu vs %llu)\n",
8214 (unsigned long long) wnd,
8215 (unsigned long long) vl->incoming_fc_window_size);
8117 consider_sending_fc (vl); 8216 consider_sending_fc (vl);
8118 } 8217 }
8119 if ((wnd == vl->incoming_fc_window_size) && 8218 if ((wnd == vl->incoming_fc_window_size) &&
@@ -8149,41 +8248,41 @@ demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
8149 { GNUNET_MQ_hd_var_size (fragment_box, 8248 { GNUNET_MQ_hd_var_size (fragment_box,
8150 GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT, 8249 GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT,
8151 struct TransportFragmentBoxMessage, 8250 struct TransportFragmentBoxMessage,
8152 &cmc), 8251 cmc),
8153 GNUNET_MQ_hd_var_size (reliability_box, 8252 GNUNET_MQ_hd_var_size (reliability_box,
8154 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX, 8253 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX,
8155 struct TransportReliabilityBoxMessage, 8254 struct TransportReliabilityBoxMessage,
8156 &cmc), 8255 cmc),
8157 GNUNET_MQ_hd_var_size (reliability_ack, 8256 GNUNET_MQ_hd_var_size (reliability_ack,
8158 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK, 8257 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK,
8159 struct TransportReliabilityAckMessage, 8258 struct TransportReliabilityAckMessage,
8160 &cmc), 8259 cmc),
8161 GNUNET_MQ_hd_var_size (backchannel_encapsulation, 8260 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
8162 GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION, 8261 GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION,
8163 struct TransportBackchannelEncapsulationMessage, 8262 struct TransportBackchannelEncapsulationMessage,
8164 &cmc), 8263 cmc),
8165 GNUNET_MQ_hd_var_size (dv_learn, 8264 GNUNET_MQ_hd_var_size (dv_learn,
8166 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, 8265 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN,
8167 struct TransportDVLearnMessage, 8266 struct TransportDVLearnMessage,
8168 &cmc), 8267 cmc),
8169 GNUNET_MQ_hd_var_size (dv_box, 8268 GNUNET_MQ_hd_var_size (dv_box,
8170 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, 8269 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX,
8171 struct TransportDVBoxMessage, 8270 struct TransportDVBoxMessage,
8172 &cmc), 8271 cmc),
8173 GNUNET_MQ_hd_fixed_size ( 8272 GNUNET_MQ_hd_fixed_size (
8174 validation_challenge, 8273 validation_challenge,
8175 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE, 8274 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE,
8176 struct TransportValidationChallengeMessage, 8275 struct TransportValidationChallengeMessage,
8177 &cmc), 8276 cmc),
8178 GNUNET_MQ_hd_fixed_size (flow_control, 8277 GNUNET_MQ_hd_fixed_size (flow_control,
8179 GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL, 8278 GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL,
8180 struct TransportFlowControlMessage, 8279 struct TransportFlowControlMessage,
8181 &cmc), 8280 cmc),
8182 GNUNET_MQ_hd_fixed_size ( 8281 GNUNET_MQ_hd_fixed_size (
8183 validation_response, 8282 validation_response,
8184 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE, 8283 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE,
8185 struct TransportValidationResponseMessage, 8284 struct TransportValidationResponseMessage,
8186 &cmc), 8285 cmc),
8187 GNUNET_MQ_handler_end () }; 8286 GNUNET_MQ_handler_end () };
8188 int ret; 8287 int ret;
8189 8288
@@ -8202,7 +8301,7 @@ demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
8202 if (GNUNET_NO == ret) 8301 if (GNUNET_NO == ret)
8203 { 8302 {
8204 /* unencapsulated 'raw' message */ 8303 /* unencapsulated 'raw' message */
8205 handle_raw_message (&cmc, msg); 8304 handle_raw_message (cmc, msg);
8206 } 8305 }
8207} 8306}
8208 8307
@@ -8770,6 +8869,8 @@ transmit_on_queue (void *cls)
8770 queue->idle = GNUNET_YES; 8869 queue->idle = GNUNET_YES;
8771 return; 8870 return;
8772 } 8871 }
8872 /* There is a message pending, we are certainly not idle */
8873 queue->idle = GNUNET_NO;
8773 8874
8774 /* Given selection in `sc`, do transmission */ 8875 /* Given selection in `sc`, do transmission */
8775 pm = sc.best; 8876 pm = sc.best;
@@ -8838,7 +8939,8 @@ transmit_on_queue (void *cls)
8838 via DV (and thus the ultimate target of the pending message is for 8939 via DV (and thus the ultimate target of the pending message is for
8839 a different virtual link than the one of the queue), then we need 8940 a different virtual link than the one of the queue), then we need
8840 to use up not only the window of the direct link but also the 8941 to use up not only the window of the direct link but also the
8841 flow control window for the DV link! */pm->vl->outbound_fc_window_size_used += pm->bytes_msg; 8942 flow control window for the DV link! */
8943 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
8842 8944
8843 if (pm->vl != queue->neighbour->vl) 8945 if (pm->vl != queue->neighbour->vl)
8844 { 8946 {
@@ -8877,7 +8979,8 @@ transmit_on_queue (void *cls)
8877 8979
8878 OPTIMIZE: Note that in the future this heuristic should likely 8980 OPTIMIZE: Note that in the future this heuristic should likely
8879 be improved further (measure RTT stability, consider message 8981 be improved further (measure RTT stability, consider message
8880 urgency and size when delaying ACKs, etc.) */update_pm_next_attempt (pm, 8982 urgency and size when delaying ACKs, etc.) */
8983 update_pm_next_attempt (pm,
8881 GNUNET_TIME_relative_to_absolute ( 8984 GNUNET_TIME_relative_to_absolute (
8882 GNUNET_TIME_relative_multiply (queue->pd.aged_rtt, 8985 GNUNET_TIME_relative_multiply (queue->pd.aged_rtt,
8883 4))); 8986 4)));
@@ -8949,20 +9052,30 @@ handle_send_message_ack (void *cls,
8949 9052
8950 /* find our queue entry matching the ACK */ 9053 /* find our queue entry matching the ACK */
8951 qe = NULL; 9054 qe = NULL;
9055 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9056 "Looking for queue for PID %s\n",
9057 GNUNET_i2s (&sma->receiver));
8952 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue; 9058 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
8953 queue = queue->next_client) 9059 queue = queue->next_client)
8954 { 9060 {
8955 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver)) 9061 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
8956 continue; 9062 continue;
9063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9064 "Found PID %s\n",
9065 GNUNET_i2s (&queue->neighbour->pid));
9066
9067
8957 for (struct QueueEntry *qep = queue->queue_head; NULL != qep; 9068 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
8958 qep = qep->next) 9069 qep = qep->next)
8959 { 9070 {
9071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9072 "QueueEntry MID: %lu, Ack MID: %lu\n",
9073 qep->mid, sma->mid);
8960 if (qep->mid != sma->mid) 9074 if (qep->mid != sma->mid)
8961 continue; 9075 continue;
8962 qe = qep; 9076 qe = qep;
8963 break; 9077 break;
8964 } 9078 }
8965 break;
8966 } 9079 }
8967 if (NULL == qe) 9080 if (NULL == qe)
8968 { 9081 {
@@ -8998,7 +9111,9 @@ handle_send_message_ack (void *cls,
8998 for (struct Queue *queue = tc->details.communicator.queue_head; 9111 for (struct Queue *queue = tc->details.communicator.queue_head;
8999 NULL != queue; 9112 NULL != queue;
9000 queue = queue->next_client) 9113 queue = queue->next_client)
9114 {
9001 schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT); 9115 schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
9116 }
9002 } 9117 }
9003 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length) 9118 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
9004 { 9119 {
@@ -9211,6 +9326,9 @@ validation_start_cb (void *cls)
9211 (NULL != vs) && 9326 (NULL != vs) &&
9212 (0 == GNUNET_TIME_absolute_get_remaining (vs->valid_until).rel_value_us)) 9327 (0 == GNUNET_TIME_absolute_get_remaining (vs->valid_until).rel_value_us))
9213 { 9328 {
9329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9330 "Validation response %s cleaned up\n",
9331 GNUNET_sh2s (&vs->challenge.value));
9214 free_validation_state (vs); 9332 free_validation_state (vs);
9215 vs = GNUNET_CONTAINER_heap_peek (validation_heap); 9333 vs = GNUNET_CONTAINER_heap_peek (validation_heap);
9216 } 9334 }
@@ -9333,6 +9451,7 @@ start_dv_learn (void *cls)
9333 return; /* lost all connectivity, cannot do learning */ 9451 return; /* lost all connectivity, cannot do learning */
9334 qqc.quality_count = 0; 9452 qqc.quality_count = 0;
9335 qqc.num_queues = 0; 9453 qqc.num_queues = 0;
9454 qqc.k = GNUNET_CONTAINER_multipeermap_size (neighbours);
9336 GNUNET_CONTAINER_multipeermap_iterate (neighbours, 9455 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
9337 &check_connection_quality, 9456 &check_connection_quality,
9338 &qqc); 9457 &qqc);
@@ -9352,7 +9471,7 @@ start_dv_learn (void *cls)
9352 return; 9471 return;
9353 } 9472 }
9354 /* remove old entries in #dvlearn_map if it has grown too big */ 9473 /* remove old entries in #dvlearn_map if it has grown too big */
9355 while (MAX_DV_LEARN_PENDING >= 9474 while (MAX_DV_LEARN_PENDING <=
9356 GNUNET_CONTAINER_multishortmap_size (dvlearn_map)) 9475 GNUNET_CONTAINER_multishortmap_size (dvlearn_map))
9357 { 9476 {
9358 lle = lle_tail; 9477 lle = lle_tail;
@@ -9505,8 +9624,7 @@ handle_add_queue_message (void *cls,
9505 const char *addr; 9624 const char *addr;
9506 uint16_t addr_len; 9625 uint16_t addr_len;
9507 9626
9508 if ((0 != ntohl (aqm->mtu)) && 9627 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
9509 (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage)))
9510 { 9628 {
9511 /* MTU so small as to be useless for transmissions, 9629 /* MTU so small as to be useless for transmissions,
9512 required for #fragment_message()! */ 9630 required for #fragment_message()! */
@@ -9514,57 +9632,73 @@ handle_add_queue_message (void *cls,
9514 GNUNET_SERVICE_client_drop (tc->client); 9632 GNUNET_SERVICE_client_drop (tc->client);
9515 return; 9633 return;
9516 } 9634 }
9517 neighbour = lookup_neighbour (&aqm->receiver); 9635 /* This may simply be a queue update */
9518 if (NULL == neighbour) 9636 for (queue = tc->details.communicator.queue_head;
9637 NULL != queue;
9638 queue = queue->next_client)
9519 { 9639 {
9520 neighbour = GNUNET_new (struct Neighbour); 9640 if (queue->qid != aqm->qid)
9521 neighbour->pid = aqm->receiver; 9641 continue;
9522 GNUNET_assert (GNUNET_OK == 9642 break;
9523 GNUNET_CONTAINER_multipeermap_put ( 9643 }
9524 neighbours, 9644
9525 &neighbour->pid, 9645 if (NULL != queue)
9526 neighbour, 9646 {
9527 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 9647 neighbour = queue->neighbour;
9528 neighbour->get = 9648 } else {
9529 GNUNET_PEERSTORE_iterate (peerstore, 9649 neighbour = lookup_neighbour (&aqm->receiver);
9530 "transport", 9650 if (NULL == neighbour)
9531 &neighbour->pid, 9651 {
9532 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME, 9652 neighbour = GNUNET_new (struct Neighbour);
9533 &neighbour_dv_monotime_cb, 9653 neighbour->pid = aqm->receiver;
9534 neighbour); 9654 GNUNET_assert (GNUNET_OK ==
9655 GNUNET_CONTAINER_multipeermap_put (
9656 neighbours,
9657 &neighbour->pid,
9658 neighbour,
9659 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
9660 neighbour->get =
9661 GNUNET_PEERSTORE_iterate (peerstore,
9662 "transport",
9663 &neighbour->pid,
9664 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
9665 &neighbour_dv_monotime_cb,
9666 neighbour);
9667 }
9668 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
9669 addr = (const char *) &aqm[1];
9670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9671 "New queue %s to %s available with QID %llu\n",
9672 addr,
9673 GNUNET_i2s (&aqm->receiver),
9674 (unsigned long long) aqm->qid);
9675 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
9676 queue->tc = tc;
9677 queue->address = (const char *) &queue[1];
9678 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9679 queue->qid = aqm->qid;
9680 queue->neighbour = neighbour;
9681 memcpy (&queue[1], addr, addr_len);
9682 /* notify monitors about new queue */
9683 {
9684 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
9685
9686 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
9687 }
9688 GNUNET_CONTAINER_MDLL_insert (neighbour,
9689 neighbour->queue_head,
9690 neighbour->queue_tail,
9691 queue);
9692 GNUNET_CONTAINER_MDLL_insert (client,
9693 tc->details.communicator.queue_head,
9694 tc->details.communicator.queue_tail,
9695 queue);
9696
9535 } 9697 }
9536 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
9537 addr = (const char *) &aqm[1];
9538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9539 "New queue %s to %s available with QID %llu\n",
9540 addr,
9541 GNUNET_i2s (&aqm->receiver),
9542 (unsigned long long) aqm->qid);
9543 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
9544 queue->tc = tc;
9545 queue->address = (const char *) &queue[1];
9546 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9547 queue->qid = aqm->qid;
9548 queue->mtu = ntohl (aqm->mtu); 9698 queue->mtu = ntohl (aqm->mtu);
9549 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt); 9699 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
9550 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs); 9700 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
9551 queue->neighbour = neighbour;
9552 queue->idle = GNUNET_YES; 9701 queue->idle = GNUNET_YES;
9553 memcpy (&queue[1], addr, addr_len);
9554 /* notify monitors about new queue */
9555 {
9556 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
9557
9558 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
9559 }
9560 GNUNET_CONTAINER_MDLL_insert (neighbour,
9561 neighbour->queue_head,
9562 neighbour->queue_tail,
9563 queue);
9564 GNUNET_CONTAINER_MDLL_insert (client,
9565 tc->details.communicator.queue_head,
9566 tc->details.communicator.queue_tail,
9567 queue);
9568 /* check if valdiations are waiting for the queue */ 9702 /* check if valdiations are waiting for the queue */
9569 (void) 9703 (void)
9570 GNUNET_CONTAINER_multipeermap_get_multiple (validation_map, 9704 GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
@@ -9623,7 +9757,6 @@ handle_update_queue_message (void *cls,
9623} 9757}
9624 9758
9625 9759
9626
9627/** 9760/**
9628 * Communicator tells us that our request to create a queue "worked", that 9761 * Communicator tells us that our request to create a queue "worked", that
9629 * is setting up the queue is now in process. 9762 * is setting up the queue is now in process.
@@ -9965,12 +10098,17 @@ do_shutdown (void *cls)
9965 struct LearnLaunchEntry *lle; 10098 struct LearnLaunchEntry *lle;
9966 10099
9967 (void) cls; 10100 (void) cls;
9968 10101 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
9969 GNUNET_CONTAINER_multipeermap_iterate (neighbours, &free_neighbour_cb, NULL); 10102 &free_neighbour_cb, NULL);
9970 if (NULL != peerstore) 10103 if (NULL != validation_task)
9971 { 10104 {
9972 GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_NO); 10105 GNUNET_SCHEDULER_cancel (validation_task);
9973 peerstore = NULL; 10106 validation_task = NULL;
10107 }
10108 if (NULL != dvlearn_task)
10109 {
10110 GNUNET_SCHEDULER_cancel (dvlearn_task);
10111 dvlearn_task = NULL;
9974 } 10112 }
9975 if (NULL != GST_stats) 10113 if (NULL != GST_stats)
9976 { 10114 {
@@ -10016,6 +10154,13 @@ do_shutdown (void *cls)
10016 GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle); 10154 GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle);
10017 GNUNET_free (lle); 10155 GNUNET_free (lle);
10018 } 10156 }
10157 if (NULL != peerstore)
10158 {
10159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
10160 "Disconnecting from PEERSTORE service\n");
10161 GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_NO);
10162 peerstore = NULL;
10163 }
10019 GNUNET_CONTAINER_multishortmap_destroy (dvlearn_map); 10164 GNUNET_CONTAINER_multishortmap_destroy (dvlearn_map);
10020 dvlearn_map = NULL; 10165 dvlearn_map = NULL;
10021 GNUNET_CONTAINER_heap_destroy (validation_heap); 10166 GNUNET_CONTAINER_heap_destroy (validation_heap);
@@ -10023,6 +10168,16 @@ do_shutdown (void *cls)
10023 GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL); 10168 GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL);
10024 GNUNET_CONTAINER_multipeermap_destroy (dv_routes); 10169 GNUNET_CONTAINER_multipeermap_destroy (dv_routes);
10025 dv_routes = NULL; 10170 dv_routes = NULL;
10171 GNUNET_SCHEDULER_shutdown ();
10172}
10173
10174
10175static void
10176shutdown_task (void *cls)
10177{
10178 in_shutdown = GNUNET_YES;
10179 if (NULL == clients_head)
10180 do_shutdown (cls);
10026} 10181}
10027 10182
10028 10183
@@ -10042,6 +10197,7 @@ run (void *cls,
10042 (void) service; 10197 (void) service;
10043 /* setup globals */ 10198 /* setup globals */
10044 hello_mono_time = GNUNET_TIME_absolute_get_monotonic (c); 10199 hello_mono_time = GNUNET_TIME_absolute_get_monotonic (c);
10200 in_shutdown = GNUNET_NO;
10045 GST_cfg = c; 10201 GST_cfg = c;
10046 backtalkers = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES); 10202 backtalkers = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES);
10047 pending_acks = GNUNET_CONTAINER_multiuuidmap_create (32768, GNUNET_YES); 10203 pending_acks = GNUNET_CONTAINER_multiuuidmap_create (32768, GNUNET_YES);
@@ -10071,7 +10227,7 @@ run (void *cls,
10071 "My identity is `%s'\n", 10227 "My identity is `%s'\n",
10072 GNUNET_i2s_full (&GST_my_identity)); 10228 GNUNET_i2s_full (&GST_my_identity));
10073 GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg); 10229 GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg);
10074 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); 10230 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
10075 peerstore = GNUNET_PEERSTORE_connect (GST_cfg); 10231 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
10076 if (NULL == peerstore) 10232 if (NULL == peerstore)
10077 { 10233 {
diff --git a/src/transport/test_transport_api2_tcp_peer1.conf b/src/transport/test_transport_api2_tcp_peer1.conf
new file mode 100644
index 000000000..745ed6887
--- /dev/null
+++ b/src/transport/test_transport_api2_tcp_peer1.conf
@@ -0,0 +1,23 @@
1@INLINE@ template_cfg_peer1.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
4
5[transport]
6BINARY = gnunet-service-tng
7PLUGINS = tcp
8#PREFIX = valgrind --log-file=/tmp/vg_peer1-%p
9UNIXPATH = $GNUNET_RUNTIME_DIR/tng-p1.sock
10
11[communicator-tcp]
12BINARY = gnunet-communicator-tcp
13BINDTO = 60002
14DISABLE_V6 = YES
15IMMEDIATE_START = YES
16UNIXPATH = $GNUNET_RUNTIME_DIR/tcp-comm-p1.sock
17#PREFIX = valgrind --log-file=/tmp/vg_cpeer1-%p
18
19[peerstore]
20IMMEDIATE_START = YES
21
22#[transport]
23#PREFIX = valgrind
diff --git a/src/transport/test_transport_api2_tcp_peer2.conf b/src/transport/test_transport_api2_tcp_peer2.conf
new file mode 100644
index 000000000..022468bcd
--- /dev/null
+++ b/src/transport/test_transport_api2_tcp_peer2.conf
@@ -0,0 +1,22 @@
1@INLINE@ template_cfg_peer2.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
4
5[transport]
6BINARY = gnunet-service-tng
7#PREFIX = valgrind --log-file=/tmp/vg_peer2-%p
8UNIXPATH = $GNUNET_RUNTIME_DIR/tng-p2.sock
9
10[communicator-tcp]
11BINARY = gnunet-communicator-tcp
12BINDTO = 60003
13DISABLE_V6 = YES
14IMMEDIATE_START = YES
15#PREFIX = valgrind --log-file=/tmp/vg_comm2-%p
16UNIXPATH = $GNUNET_RUNTIME_DIR/tcp-comm-p2.sock
17
18[peerstore]
19IMMEDIATE_START = YES
20
21#[transport]
22#PREFIX = valgrind
diff --git a/src/transport/transport-testing-communicator.c b/src/transport/transport-testing-communicator.c
index de356fb9c..040f16d5d 100644
--- a/src/transport/transport-testing-communicator.c
+++ b/src/transport/transport-testing-communicator.c
@@ -548,6 +548,11 @@ handle_update_queue_message (void *cls,
548 tc_queue = tc_queue->next; 548 tc_queue = tc_queue->next;
549 } 549 }
550 } 550 }
551 if (NULL == tc_queue)
552 {
553 GNUNET_SERVICE_client_continue (client->client);
554 return;
555 }
551 GNUNET_assert (tc_queue->qid == msg->qid); 556 GNUNET_assert (tc_queue->qid == msg->qid);
552 GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver)); 557 GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver));
553 tc_queue->nt = msg->nt; 558 tc_queue->nt = msg->nt;
diff --git a/src/transport/transport-testing-ng.h b/src/transport/transport-testing-ng.h
new file mode 100644
index 000000000..cd5ba65a9
--- /dev/null
+++ b/src/transport/transport-testing-ng.h
@@ -0,0 +1,71 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @author t3sserakt
23 */
24
25struct TngState
26{
27 /**
28 * Handle to operation
29 */
30 struct GNUNET_TESTBED_Operation *operation;
31
32 /**
33 * Flag indicating if service is ready.
34 */
35 int service_ready;
36
37 /**
38 * Abort task identifier
39 */
40 struct GNUNET_SCHEDULER_Task *abort_task;
41
42 /**
43 * Label of peer command.
44 */
45 const char *peer_label;
46
47 /**
48 * Name of service to start.
49 */
50 const char *servicename;
51
52 /**
53 * Peer identity of the system.
54 */
55 struct GNUNET_PeerIdentity *peer_identity;
56
57 /**
58 * Message handler for transport service.
59 */
60 const struct GNUNET_MQ_MessageHandler *handlers;
61
62 /**
63 * Notify connect callback
64 */
65 GNUNET_TRANSPORT_NotifyConnect nc;
66
67 /**
68 * Closure for the @a nc callback
69 */
70 void *cb_cls;
71};
diff --git a/src/transport/transport-testing2.c b/src/transport/transport-testing2.c
index d9f1d5e56..eaa8a5f15 100644
--- a/src/transport/transport-testing2.c
+++ b/src/transport/transport-testing2.c
@@ -328,6 +328,8 @@ notify_disconnect (void *cls,
328 } 328 }
329} 329}
330 330
331static void
332retrieve_hello (void *cls);
331 333
332static void 334static void
333hello_iter_cb (void *cb_cls, 335hello_iter_cb (void *cb_cls,
@@ -337,16 +339,19 @@ hello_iter_cb (void *cb_cls,
337 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cb_cls; 339 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cb_cls;
338 if ((NULL == record) && (NULL == emsg)) 340 if ((NULL == record) && (NULL == emsg))
339 { 341 {
340 LOG (GNUNET_ERROR_TYPE_DEBUG, "Iteration End\n"); 342 p->pic = NULL;
343 if (NULL != p->start_cb)
344 p->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, p);
341 return; 345 return;
342 } 346 }
343 //Check record type et al? 347 // Check record type et al?
344 p->hello_size = record->value_size; 348 p->hello_size = record->value_size;
345 p->hello = GNUNET_malloc (p->hello_size); 349 p->hello = GNUNET_malloc (p->hello_size);
346 memcpy (p->hello, record->value, p->hello_size); 350 memcpy (p->hello, record->value, p->hello_size);
347 p->hello[p->hello_size-1] = '\0'; 351 p->hello[p->hello_size - 1] = '\0';
348 352
349 GNUNET_PEERSTORE_iterate_cancel (p->pic); 353 GNUNET_PEERSTORE_iterate_cancel (p->pic);
354 p->pic = NULL;
350 if (NULL != p->start_cb) 355 if (NULL != p->start_cb)
351 { 356 {
352 LOG (GNUNET_ERROR_TYPE_DEBUG, 357 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -358,13 +363,12 @@ hello_iter_cb (void *cb_cls,
358 } 363 }
359} 364}
360 365
366
361static void 367static void
362retrieve_hello(void *cls) 368retrieve_hello (void *cls)
363{ 369{
364 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls; 370 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
365 LOG (GNUNET_ERROR_TYPE_DEBUG, 371 p->rh_task = NULL;
366 "Getting hello...\n");
367
368 p->pic = GNUNET_PEERSTORE_iterate (p->ph, 372 p->pic = GNUNET_PEERSTORE_iterate (p->ph,
369 "transport", 373 "transport",
370 &p->id, 374 &p->id,
@@ -375,7 +379,6 @@ retrieve_hello(void *cls)
375} 379}
376 380
377 381
378
379/** 382/**
380 * Start a peer with the given configuration 383 * Start a peer with the given configuration
381 * @param tth the testing handle 384 * @param tth the testing handle
@@ -504,15 +507,13 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct
504 "Peer %u configured with identity `%s'\n", 507 "Peer %u configured with identity `%s'\n",
505 p->no, 508 p->no,
506 GNUNET_i2s_full (&p->id)); 509 GNUNET_i2s_full (&p->id));
507 p->tmh = GNUNET_TRANSPORT_manipulation_connect (p->cfg);
508 p->th = GNUNET_TRANSPORT_core_connect (p->cfg, 510 p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
509 NULL, 511 NULL,
510 handlers, 512 handlers,
511 p, 513 p,
512 &notify_connect, 514 &notify_connect,
513 &notify_disconnect); 515 &notify_disconnect);
514 if ((NULL == p->th) || 516 if (NULL == p->th)
515 (NULL == p->tmh))
516 { 517 {
517 LOG (GNUNET_ERROR_TYPE_ERROR, 518 LOG (GNUNET_ERROR_TYPE_ERROR,
518 "Failed to connect to transport service for peer `%s': `%s'\n", 519 "Failed to connect to transport service for peer `%s': `%s'\n",
@@ -535,11 +536,8 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct
535 // FIXME Error handling 536 // FIXME Error handling
536 p->ah = GNUNET_TRANSPORT_application_init (p->cfg); 537 p->ah = GNUNET_TRANSPORT_application_init (p->cfg);
537 GNUNET_assert (NULL != p->ah); 538 GNUNET_assert (NULL != p->ah);
538 // FIXME Error handleing 539 // FIXME Error handling
539 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, 540 p->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, p);
540 retrieve_hello,
541 p);
542 //GNUNET_assert (NULL != p->pic);
543 541
544 return p; 542 return p;
545} 543}
@@ -577,11 +575,6 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct
577 GNUNET_TRANSPORT_core_disconnect (p->th); 575 GNUNET_TRANSPORT_core_disconnect (p->th);
578 p->th = NULL; 576 p->th = NULL;
579 } 577 }
580 if (NULL != p->tmh)
581 {
582 GNUNET_TRANSPORT_manipulation_disconnect (p->tmh);
583 p->tmh = NULL;
584 }
585 for (cc = p->tth->cc_head; NULL != cc; cc = ccn) 578 for (cc = p->tth->cc_head; NULL != cc; cc = ccn)
586 { 579 {
587 ccn = cc->next; 580 ccn = cc->next;
@@ -655,6 +648,11 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct
655 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth; 648 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
656 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; 649 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
657 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn; 650 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
651 /* shutdown */
652 LOG (GNUNET_ERROR_TYPE_DEBUG,
653 "Stopping peer %u (`%s')\n",
654 p->no,
655 GNUNET_i2s (&p->id));
658 656
659 for (cc = tth->cc_head; NULL != cc; cc = ccn) 657 for (cc = tth->cc_head; NULL != cc; cc = ccn)
660 { 658 {
@@ -668,16 +666,29 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct
668 GNUNET_PEERSTORE_iterate_cancel (p->pic); 666 GNUNET_PEERSTORE_iterate_cancel (p->pic);
669 p->pic = NULL; 667 p->pic = NULL;
670 } 668 }
671 if (NULL != p->tmh)
672 {
673 GNUNET_TRANSPORT_manipulation_disconnect (p->tmh);
674 p->tmh = NULL;
675 }
676 if (NULL != p->th) 669 if (NULL != p->th)
677 { 670 {
678 GNUNET_TRANSPORT_core_disconnect (p->th); 671 GNUNET_TRANSPORT_core_disconnect (p->th);
679 p->th = NULL; 672 p->th = NULL;
680 } 673 }
674 if (NULL != p->ats)
675 {
676 GNUNET_ATS_connectivity_done (p->ats);
677 p->ats = NULL;
678 }
679 if (NULL != p->ah)
680 {
681 GNUNET_TRANSPORT_application_done (p->ah);
682 p->ah = NULL;
683 }
684 if (NULL != p->ph)
685 {
686 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
687 "Disconnecting from PEERSTORE service\n");
688 GNUNET_PEERSTORE_disconnect (p->ph, GNUNET_NO);
689 p->ph = NULL;
690 }
691
681 if (NULL != p->peer) 692 if (NULL != p->peer)
682 { 693 {
683 if (GNUNET_OK != 694 if (GNUNET_OK !=
@@ -691,11 +702,6 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct
691 GNUNET_TESTING_peer_destroy (p->peer); 702 GNUNET_TESTING_peer_destroy (p->peer);
692 p->peer = NULL; 703 p->peer = NULL;
693 } 704 }
694 if (NULL != p->ats)
695 {
696 GNUNET_ATS_connectivity_done (p->ats);
697 p->ats = NULL;
698 }
699 if (NULL != p->hello) 705 if (NULL != p->hello)
700 { 706 {
701 GNUNET_free (p->hello); 707 GNUNET_free (p->hello);
@@ -718,6 +724,9 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct
718 "Peer %u (`%s') stopped\n", 724 "Peer %u (`%s') stopped\n",
719 p->no, 725 p->no,
720 GNUNET_i2s (&p->id)); 726 GNUNET_i2s (&p->id));
727 if (NULL != p->rh_task)
728 GNUNET_SCHEDULER_cancel (p->rh_task);
729 p->rh_task = NULL;
721 GNUNET_free (p); 730 GNUNET_free (p);
722} 731}
723 732
@@ -728,16 +737,16 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct
728 * FIXME maybe schedule the application_validate somehow 737 * FIXME maybe schedule the application_validate somehow
729 */ 738 */
730/* 739/*
731static void 740 static void
732hello_offered (void *cls) 741 hello_offered (void *cls)
733{ 742 {
734 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls; 743 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
735 744
736 cc->oh = NULL; 745 cc->oh = NULL;
737 cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, 746 cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
738 &offer_hello, 747 &offer_hello,
739 cc); 748 cc);
740}*/ 749 }*/
741 750
742 751
743/** 752/**
diff --git a/src/transport/transport-testing2.h b/src/transport/transport-testing2.h
index 3554436d8..db8700df9 100644
--- a/src/transport/transport-testing2.h
+++ b/src/transport/transport-testing2.h
@@ -85,11 +85,6 @@ struct GNUNET_TRANSPORT_TESTING_PeerContext
85 struct GNUNET_TRANSPORT_CoreHandle *th; 85 struct GNUNET_TRANSPORT_CoreHandle *th;
86 86
87 /** 87 /**
88 * Peer's transport service manipulation handle
89 */
90 struct GNUNET_TRANSPORT_ManipulationHandle *tmh;
91
92 /**
93 * Peer's ATS handle. 88 * Peer's ATS handle.
94 */ 89 */
95 struct GNUNET_ATS_ConnectivityHandle *ats; 90 struct GNUNET_ATS_ConnectivityHandle *ats;
@@ -150,6 +145,11 @@ struct GNUNET_TRANSPORT_TESTING_PeerContext
150 GNUNET_SCHEDULER_TaskCallback start_cb; 145 GNUNET_SCHEDULER_TaskCallback start_cb;
151 146
152 /** 147 /**
148 * Hello get task
149 */
150 struct GNUNET_SCHEDULER_Task *rh_task;
151
152 /**
153 * Closure for the @a nc and @a nd callbacks 153 * Closure for the @a nc and @a nd callbacks
154 */ 154 */
155 void *cb_cls; 155 void *cb_cls;
diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c
index b048ad851..3d9da08e4 100644
--- a/src/transport/transport_api2_communication.c
+++ b/src/transport/transport_api2_communication.c
@@ -677,7 +677,7 @@ handle_send_msg (void *cls, const struct GNUNET_TRANSPORT_SendMessageTo *smt)
677 struct GNUNET_TRANSPORT_QueueHandle *qh; 677 struct GNUNET_TRANSPORT_QueueHandle *qh;
678 678
679 for (qh = ch->queue_head; NULL != qh; qh = qh->next) 679 for (qh = ch->queue_head; NULL != qh; qh = qh->next)
680 if ((qh->queue_id == smt->qid) && 680 if ((qh->queue_id == ntohl (smt->qid)) &&
681 (0 == memcmp (&qh->peer, 681 (0 == memcmp (&qh->peer,
682 &smt->receiver, 682 &smt->receiver,
683 sizeof(struct GNUNET_PeerIdentity)))) 683 sizeof(struct GNUNET_PeerIdentity))))
diff --git a/src/util/.gitignore b/src/util/.gitignore
index 8556ee7b8..7c7b7045d 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -80,3 +80,4 @@ python27_location
80perf_malloc 80perf_malloc
81perf_mq 81perf_mq
82perf_scheduler 82perf_scheduler
83gnunet-base32
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 33fe26e34..e2614e5e3 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -25,6 +25,11 @@ if ENABLE_BENCHMARK
25 PTHREAD = -lpthread 25 PTHREAD = -lpthread
26endif 26endif
27 27
28if HAVE_NOLIBGCRYPT19
29 DLOG = crypto_ecc_dlog.c
30 DLOG_TEST = test_crypto_ecc_dlog
31endif
32
28gnunet_config_diff_SOURCES = \ 33gnunet_config_diff_SOURCES = \
29 gnunet-config-diff.c 34 gnunet-config-diff.c
30gnunet_config_diff_LDADD = \ 35gnunet_config_diff_LDADD = \
@@ -58,7 +63,7 @@ libgnunetutil_la_SOURCES = \
58 crypto_symmetric.c \ 63 crypto_symmetric.c \
59 crypto_crc.c \ 64 crypto_crc.c \
60 crypto_ecc.c \ 65 crypto_ecc.c \
61 crypto_ecc_dlog.c \ 66 $(DLOG) \
62 crypto_ecc_setup.c \ 67 crypto_ecc_setup.c \
63 crypto_hash.c \ 68 crypto_hash.c \
64 crypto_hash_file.c \ 69 crypto_hash_file.c \
@@ -152,9 +157,10 @@ libexec_PROGRAMS = \
152 gnunet-timeout 157 gnunet-timeout
153 158
154bin_PROGRAMS = \ 159bin_PROGRAMS = \
155 gnunet-resolver \ 160 gnunet-base32 \
156 gnunet-config \ 161 gnunet-config \
157 gnunet-crypto-tvg \ 162 gnunet-crypto-tvg \
163 gnunet-resolver \
158 $(GNUNET_ECC) \ 164 $(GNUNET_ECC) \
159 $(GNUNET_SCRYPT) \ 165 $(GNUNET_SCRYPT) \
160 gnunet-uri 166 gnunet-uri
@@ -203,6 +209,12 @@ gnunet_ecc_LDADD = \
203 libgnunetutil.la \ 209 libgnunetutil.la \
204 $(GN_LIBINTL) -lgcrypt 210 $(GN_LIBINTL) -lgcrypt
205 211
212gnunet_base32_SOURCES = \
213 gnunet-base32.c
214gnunet_base32_LDADD = \
215 libgnunetutil.la \
216 $(GN_LIBINTL)
217
206gnunet_scrypt_SOURCES = \ 218gnunet_scrypt_SOURCES = \
207 gnunet-scrypt.c 219 gnunet-scrypt.c
208gnunet_scrypt_LDADD = \ 220gnunet_scrypt_LDADD = \
@@ -241,7 +253,6 @@ libgnunet_plugin_test_la_LDFLAGS = \
241if HAVE_BENCHMARKS 253if HAVE_BENCHMARKS
242 BENCHMARKS = \ 254 BENCHMARKS = \
243 perf_crypto_hash \ 255 perf_crypto_hash \
244 perf_crypto_ecc_dlog \
245 perf_crypto_rsa \ 256 perf_crypto_rsa \
246 perf_crypto_paillier \ 257 perf_crypto_paillier \
247 perf_crypto_symmetric \ 258 perf_crypto_symmetric \
@@ -249,6 +260,10 @@ if HAVE_BENCHMARKS
249 perf_malloc \ 260 perf_malloc \
250 perf_mq \ 261 perf_mq \
251 perf_scheduler 262 perf_scheduler
263
264if HAVE_NOLIBGCRYPT19
265 BENCHMARKS += perf_crypto_ecc_dlog
266endif
252endif 267endif
253 268
254if HAVE_SSH_KEY 269if HAVE_SSH_KEY
@@ -280,7 +295,7 @@ check_PROGRAMS = \
280 test_crypto_ecdhe \ 295 test_crypto_ecdhe \
281 test_crypto_ecdh_eddsa \ 296 test_crypto_ecdh_eddsa \
282 test_crypto_ecdh_ecdsa \ 297 test_crypto_ecdh_ecdsa \
283 test_crypto_ecc_dlog \ 298 $(DLOG_TEST) \
284 test_crypto_hash \ 299 test_crypto_hash \
285 test_crypto_hash_context \ 300 test_crypto_hash_context \
286 test_crypto_hkdf \ 301 test_crypto_hkdf \
@@ -441,11 +456,13 @@ test_crypto_eddsa_LDADD = \
441 libgnunetutil.la \ 456 libgnunetutil.la \
442 $(LIBGCRYPT_LIBS) 457 $(LIBGCRYPT_LIBS)
443 458
459if HAVE_NOLIBGCRYPT19
444test_crypto_ecc_dlog_SOURCES = \ 460test_crypto_ecc_dlog_SOURCES = \
445 test_crypto_ecc_dlog.c 461 test_crypto_ecc_dlog.c
446test_crypto_ecc_dlog_LDADD = \ 462test_crypto_ecc_dlog_LDADD = \
447 libgnunetutil.la \ 463 libgnunetutil.la \
448 $(LIBGCRYPT_LIBS) 464 $(LIBGCRYPT_LIBS)
465endif
449 466
450test_crypto_ecdhe_SOURCES = \ 467test_crypto_ecdhe_SOURCES = \
451 test_crypto_ecdhe.c 468 test_crypto_ecdhe.c
@@ -588,11 +605,13 @@ perf_crypto_hash_SOURCES = \
588perf_crypto_hash_LDADD = \ 605perf_crypto_hash_LDADD = \
589 libgnunetutil.la 606 libgnunetutil.la
590 607
608if HAVE_NOLIBGCRYPT19
591perf_crypto_ecc_dlog_SOURCES = \ 609perf_crypto_ecc_dlog_SOURCES = \
592 perf_crypto_ecc_dlog.c 610 perf_crypto_ecc_dlog.c
593perf_crypto_ecc_dlog_LDADD = \ 611perf_crypto_ecc_dlog_LDADD = \
594 libgnunetutil.la \ 612 libgnunetutil.la \
595 -lgcrypt 613 -lgcrypt
614endif
596 615
597perf_crypto_rsa_SOURCES = \ 616perf_crypto_rsa_SOURCES = \
598 perf_crypto_rsa.c 617 perf_crypto_rsa.c
diff --git a/src/util/configuration.c b/src/util/configuration.c
index bda643b83..3294d11f4 100644
--- a/src/util/configuration.c
+++ b/src/util/configuration.c
@@ -606,6 +606,7 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg,
606 if (NULL == h) 606 if (NULL == h)
607 { 607 {
608 GNUNET_free (fn); 608 GNUNET_free (fn);
609 GNUNET_free (cfg_buf);
609 return GNUNET_SYSERR; 610 return GNUNET_SYSERR;
610 } 611 }
611 if (((ssize_t) size) != 612 if (((ssize_t) size) !=
diff --git a/src/util/container_meta_data.c b/src/util/container_meta_data.c
index b66a7b258..efaac1136 100644
--- a/src/util/container_meta_data.c
+++ b/src/util/container_meta_data.c
@@ -964,6 +964,9 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
964 { 964 {
965 /* does not fit! */ 965 /* does not fit! */
966 GNUNET_free (ent); 966 GNUNET_free (ent);
967 if (NULL != cdata)
968 GNUNET_free (cdata);
969 cdata = NULL;
967 return GNUNET_SYSERR; 970 return GNUNET_SYSERR;
968 } 971 }
969 972
@@ -976,9 +979,9 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
976 if (NULL != pos->mime_type) 979 if (NULL != pos->mime_type)
977 left -= strlen (pos->mime_type) + 1; 980 left -= strlen (pos->mime_type) + 1;
978 981
979 GNUNET_free (cdata); 982 if (NULL != cdata)
983 GNUNET_free (cdata);
980 cdata = NULL; 984 cdata = NULL;
981
982 i++; 985 i++;
983 } 986 }
984 GNUNET_free (ent); 987 GNUNET_free (ent);
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index bc58142c2..efbf2ee17 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -33,6 +33,22 @@
33 33
34#define EXTRA_CHECKS 0 34#define EXTRA_CHECKS 0
35 35
36/**
37 * IMPLEMENTATION NOTICE:
38 *
39 * ECDSA: We use a non-standard curve for ECDSA: Ed25519.
40 * For performance reasons, we use cryptographic operations from
41 * libsodium wherever we can get away with it, even though libsodium
42 * itself does not support ECDSA.
43 * This is why the sign and verifiy functionality from libgcrypt is
44 * required and used.
45 *
46 * EdDSA: We use a standard EdDSA construction.
47 * (We still use libgcrypt for hashing and RNG, but not EC)
48 *
49 * ECDHE: For both EdDSA and ECDSA keys, we use libsodium for
50 * ECDHE due to performance benefits over libgcrypt.
51 */
36 52
37/** 53/**
38 * Name of the curve we are using. Note that we have hard-coded 54 * Name of the curve we are using. Note that we have hard-coded
@@ -476,6 +492,10 @@ GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
476 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d, 492 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
477 sizeof(anonymous.d), 493 sizeof(anonymous.d),
478 GCRYMPI_CONST_ONE); 494 GCRYMPI_CONST_ONE);
495 anonymous.d[0] &= 248;
496 anonymous.d[31] &= 127;
497 anonymous.d[31] |= 64;
498
479 once = 1; 499 once = 1;
480 return &anonymous; 500 return &anonymous;
481} 501}
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
index 63232cab6..5e4c4d1e6 100644
--- a/src/util/crypto_rsa.c
+++ b/src/util/crypto_rsa.c
@@ -863,6 +863,7 @@ rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
863 __FILE__, 863 __FILE__,
864 __LINE__, 864 __LINE__,
865 gcry_strerror (rc)); 865 gcry_strerror (rc));
866 gcry_sexp_release (data);
866 GNUNET_break (0); 867 GNUNET_break (0);
867 return NULL; 868 return NULL;
868 } 869 }
diff --git a/src/util/gnunet-base32.c b/src/util/gnunet-base32.c
new file mode 100644
index 000000000..2c797f56e
--- /dev/null
+++ b/src/util/gnunet-base32.c
@@ -0,0 +1,152 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/gnunet-base32.c
23 * @brief tool to encode/decode from/to the Crockford Base32 encoding GNUnet uses
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28
29
30/**
31 * The main function of gnunet-base32
32 *
33 * @param argc number of arguments from the command line
34 * @param argv command line arguments
35 * @return 0 ok, 1 on error
36 */
37int
38main (int argc,
39 char *const *argv)
40{
41 int decode = 0;
42 const struct GNUNET_GETOPT_CommandLineOption options[] = {
43 GNUNET_GETOPT_option_flag ('d',
44 "decode",
45 gettext_noop ("run decoder modus, otherwise runs as encoder"),
46 &decode),
47 GNUNET_GETOPT_option_help ("Crockford base32 encoder/decoder"),
48 GNUNET_GETOPT_option_version (PACKAGE_VERSION),
49 GNUNET_GETOPT_OPTION_END
50 };
51 int ret;
52 char *in;
53 unsigned int in_size;
54 ssize_t iret;
55 char *out;
56 size_t out_size;
57
58 if (GNUNET_OK !=
59 GNUNET_STRINGS_get_utf8_args (argc, argv,
60 &argc, &argv))
61 return 2;
62 ret = GNUNET_GETOPT_run ("gnunet-base32",
63 options,
64 argc,
65 argv);
66 if (ret < 0)
67 return 1;
68 if (0 == ret)
69 return 0;
70 in_size = 0;
71 in = NULL;
72 iret = 1;
73 while (iret > 0)
74 {
75 /* read in blocks of 4k */
76 char buf[4092];
77
78 iret = read (0,
79 buf,
80 sizeof (buf));
81 if (iret < 0)
82 {
83 GNUNET_free (in);
84 return 2;
85 }
86 if (iret > 0)
87 {
88 if (iret + in_size < in_size)
89 {
90 GNUNET_break (0);
91 GNUNET_free (in);
92 return 1;
93 }
94 GNUNET_array_grow (in,
95 in_size,
96 in_size + iret);
97 memcpy (&in[in_size - iret],
98 buf,
99 iret);
100 }
101 }
102 if (decode)
103 {
104 /* This formula can overestimate by 1 byte, so we try both
105 out_size and out_size-1 below */
106 out_size = in_size * 5 / 8;
107 out = GNUNET_malloc (out_size);
108 if (GNUNET_OK !=
109 GNUNET_STRINGS_string_to_data (in,
110 in_size,
111 out,
112 out_size))
113 {
114 out_size--;
115 if (GNUNET_OK !=
116 GNUNET_STRINGS_string_to_data (in,
117 in_size,
118 out,
119 out_size))
120 {
121 GNUNET_free (out);
122 GNUNET_free (in);
123 return 3;
124 }
125 }
126 }
127 else
128 {
129 out = GNUNET_STRINGS_data_to_string_alloc (in,
130 in_size);
131 out_size = strlen (out);
132 }
133 {
134 size_t pos = 0;
135
136 while (pos < out_size)
137 {
138 iret = write (1,
139 &out[pos],
140 out_size - pos);
141 if (iret <= 0)
142 return 4;
143 pos += iret;
144 }
145 }
146 GNUNET_free (out);
147 GNUNET_free_nz ((void *) argv);
148 return 0;
149}
150
151
152/* end of gnunet-uri.c */
diff --git a/src/util/gnunet-crypto-tvg.c b/src/util/gnunet-crypto-tvg.c
index 8949f427c..28e44e28b 100644
--- a/src/util/gnunet-crypto-tvg.c
+++ b/src/util/gnunet-crypto-tvg.c
@@ -128,6 +128,7 @@ d2j (json_t *vec,
128 json_object_set_new (vec, label, json); 128 json_object_set_new (vec, label, json);
129} 129}
130 130
131
131/** 132/**
132 * Add a number to a test vector. 133 * Add a number to a test vector.
133 * 134 *
@@ -138,8 +139,8 @@ d2j (json_t *vec,
138 */ 139 */
139static void 140static void
140uint2j (json_t *vec, 141uint2j (json_t *vec,
141 const char *label, 142 const char *label,
142 unsigned int num) 143 unsigned int num)
143{ 144{
144 json_t *json = json_integer (num); 145 json_t *json = json_integer (num);
145 146
@@ -154,7 +155,7 @@ expect_data_fixed (json_t *vec,
154 size_t expect_len) 155 size_t expect_len)
155{ 156{
156 const char *s = json_string_value (json_object_get (vec, name)); 157 const char *s = json_string_value (json_object_get (vec, name));
157 158
158 if (NULL == s) 159 if (NULL == s)
159 return GNUNET_NO; 160 return GNUNET_NO;
160 161
@@ -166,6 +167,7 @@ expect_data_fixed (json_t *vec,
166 return GNUNET_OK; 167 return GNUNET_OK;
167} 168}
168 169
170
169static int 171static int
170expect_data_dynamic (json_t *vec, 172expect_data_dynamic (json_t *vec,
171 const char *name, 173 const char *name,
@@ -173,6 +175,7 @@ expect_data_dynamic (json_t *vec,
173 size_t *ret_len) 175 size_t *ret_len)
174{ 176{
175 const char *s = json_string_value (json_object_get (vec, name)); 177 const char *s = json_string_value (json_object_get (vec, name));
178 char *tmp;
176 size_t len; 179 size_t len;
177 180
178 if (NULL == s) 181 if (NULL == s)
@@ -181,10 +184,14 @@ expect_data_dynamic (json_t *vec,
181 len = (strlen (s) * 5) / 8; 184 len = (strlen (s) * 5) / 8;
182 if (NULL != ret_len) 185 if (NULL != ret_len)
183 *ret_len = len; 186 *ret_len = len;
184 *data = GNUNET_malloc (len); 187 tmp = GNUNET_malloc (len);
185 188
186 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (s, strlen (s), *data, len)) 189 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (s, strlen (s), tmp, len))
190 {
191 GNUNET_free (tmp);
187 return GNUNET_NO; 192 return GNUNET_NO;
193 }
194 *data = tmp;
188 return GNUNET_OK; 195 return GNUNET_OK;
189} 196}
190 197
@@ -197,7 +204,7 @@ expect_data_dynamic (json_t *vec,
197 * 204 *
198 * @returns GNUNET_OK if the vector is okay 205 * @returns GNUNET_OK if the vector is okay
199 */ 206 */
200static int 207static int
201checkvec (const char *operation, 208checkvec (const char *operation,
202 json_t *vec) 209 json_t *vec)
203{ 210{
@@ -220,10 +227,11 @@ checkvec (const char *operation,
220 return GNUNET_SYSERR; 227 return GNUNET_SYSERR;
221 } 228 }
222 if (GNUNET_OK != expect_data_fixed (vec, 229 if (GNUNET_OK != expect_data_fixed (vec,
223 "output", 230 "output",
224 &hash_out, 231 &hash_out,
225 sizeof (hash_out))) 232 sizeof (hash_out)))
226 { 233 {
234 GNUNET_free (data);
227 GNUNET_break (0); 235 GNUNET_break (0);
228 return GNUNET_NO; 236 return GNUNET_NO;
229 } 237 }
@@ -232,9 +240,11 @@ checkvec (const char *operation,
232 240
233 if (0 != GNUNET_memcmp (&hc, &hash_out)) 241 if (0 != GNUNET_memcmp (&hc, &hash_out))
234 { 242 {
243 GNUNET_free (data);
235 GNUNET_break (0); 244 GNUNET_break (0);
236 return GNUNET_NO; 245 return GNUNET_NO;
237 } 246 }
247 GNUNET_free (data);
238 } 248 }
239 else if (0 == strcmp (operation, "ecc_ecdh")) 249 else if (0 == strcmp (operation, "ecc_ecdh"))
240 { 250 {
@@ -245,33 +255,33 @@ checkvec (const char *operation,
245 struct GNUNET_HashCode skm_comp; 255 struct GNUNET_HashCode skm_comp;
246 256
247 if (GNUNET_OK != expect_data_fixed (vec, 257 if (GNUNET_OK != expect_data_fixed (vec,
248 "priv1", 258 "priv1",
249 &priv1, 259 &priv1,
250 sizeof (priv1))) 260 sizeof (priv1)))
251 { 261 {
252 GNUNET_break (0); 262 GNUNET_break (0);
253 return GNUNET_NO; 263 return GNUNET_NO;
254 } 264 }
255 if (GNUNET_OK != expect_data_fixed (vec, 265 if (GNUNET_OK != expect_data_fixed (vec,
256 "priv2", 266 "priv2",
257 &priv2, 267 &priv2,
258 sizeof (priv2))) 268 sizeof (priv2)))
259 { 269 {
260 GNUNET_break (0); 270 GNUNET_break (0);
261 return GNUNET_NO; 271 return GNUNET_NO;
262 } 272 }
263 if (GNUNET_OK != expect_data_fixed (vec, 273 if (GNUNET_OK != expect_data_fixed (vec,
264 "pub1", 274 "pub1",
265 &pub1, 275 &pub1,
266 sizeof (pub1))) 276 sizeof (pub1)))
267 { 277 {
268 GNUNET_break (0); 278 GNUNET_break (0);
269 return GNUNET_NO; 279 return GNUNET_NO;
270 } 280 }
271 if (GNUNET_OK != expect_data_fixed (vec, 281 if (GNUNET_OK != expect_data_fixed (vec,
272 "skm", 282 "skm",
273 &skm, 283 &skm,
274 sizeof (skm))) 284 sizeof (skm)))
275 { 285 {
276 GNUNET_break (0); 286 GNUNET_break (0);
277 return GNUNET_NO; 287 return GNUNET_NO;
@@ -407,6 +417,8 @@ checkvec (const char *operation,
407 &ikm, 417 &ikm,
408 &ikm_len)) 418 &ikm_len))
409 { 419 {
420 GNUNET_free (out);
421 GNUNET_free (out_comp);
410 GNUNET_break (0); 422 GNUNET_break (0);
411 return GNUNET_SYSERR; 423 return GNUNET_SYSERR;
412 } 424 }
@@ -416,6 +428,9 @@ checkvec (const char *operation,
416 &salt, 428 &salt,
417 &salt_len)) 429 &salt_len))
418 { 430 {
431 GNUNET_free (out);
432 GNUNET_free (out_comp);
433 GNUNET_free (ikm);
419 GNUNET_break (0); 434 GNUNET_break (0);
420 return GNUNET_SYSERR; 435 return GNUNET_SYSERR;
421 } 436 }
@@ -425,6 +440,10 @@ checkvec (const char *operation,
425 &ctx, 440 &ctx,
426 &ctx_len)) 441 &ctx_len))
427 { 442 {
443 GNUNET_free (out);
444 GNUNET_free (out_comp);
445 GNUNET_free (ikm);
446 GNUNET_free (salt);
428 GNUNET_break (0); 447 GNUNET_break (0);
429 return GNUNET_SYSERR; 448 return GNUNET_SYSERR;
430 } 449 }
@@ -442,10 +461,19 @@ checkvec (const char *operation,
442 461
443 if (0 != memcmp (out, out_comp, out_len)) 462 if (0 != memcmp (out, out_comp, out_len))
444 { 463 {
464 GNUNET_free (out);
465 GNUNET_free (out_comp);
466 GNUNET_free (ikm);
467 GNUNET_free (salt);
468 GNUNET_free (ctx);
445 GNUNET_break (0); 469 GNUNET_break (0);
446 return GNUNET_NO; 470 return GNUNET_NO;
447 } 471 }
448 472 GNUNET_free (out);
473 GNUNET_free (out_comp);
474 GNUNET_free (ikm);
475 GNUNET_free (salt);
476 GNUNET_free (ctx);
449 } 477 }
450 else if (0 == strcmp (operation, "eddsa_ecdh")) 478 else if (0 == strcmp (operation, "eddsa_ecdh"))
451 { 479 {
@@ -562,6 +590,7 @@ checkvec (const char *operation,
562 &public_enc_data, 590 &public_enc_data,
563 &public_enc_len)) 591 &public_enc_len))
564 { 592 {
593 GNUNET_free (blinded_data);
565 GNUNET_break (0); 594 GNUNET_break (0);
566 return GNUNET_SYSERR; 595 return GNUNET_SYSERR;
567 } 596 }
@@ -571,6 +600,8 @@ checkvec (const char *operation,
571 &secret_enc_data, 600 &secret_enc_data,
572 &secret_enc_len)) 601 &secret_enc_len))
573 { 602 {
603 GNUNET_free (blinded_data);
604 GNUNET_free (public_enc_data);
574 GNUNET_break (0); 605 GNUNET_break (0);
575 return GNUNET_SYSERR; 606 return GNUNET_SYSERR;
576 } 607 }
@@ -580,6 +611,9 @@ checkvec (const char *operation,
580 &sig_enc_data, 611 &sig_enc_data,
581 &sig_enc_length)) 612 &sig_enc_length))
582 { 613 {
614 GNUNET_free (blinded_data);
615 GNUNET_free (public_enc_data);
616 GNUNET_free (secret_enc_data);
583 GNUNET_break (0); 617 GNUNET_break (0);
584 return GNUNET_SYSERR; 618 return GNUNET_SYSERR;
585 } 619 }
@@ -601,6 +635,11 @@ checkvec (const char *operation,
601 blinded_data_comp, 635 blinded_data_comp,
602 blinded_len)) ) 636 blinded_len)) )
603 { 637 {
638 GNUNET_free (blinded_data);
639 GNUNET_free (public_enc_data);
640 GNUNET_free (secret_enc_data);
641 GNUNET_free (sig_enc_data);
642 GNUNET_free (skey);
604 GNUNET_break (0); 643 GNUNET_break (0);
605 return GNUNET_NO; 644 return GNUNET_NO;
606 } 645 }
@@ -611,14 +650,27 @@ checkvec (const char *operation,
611 pkey)); 650 pkey));
612 public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, 651 public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey,
613 &public_enc_data); 652 &public_enc_data);
614 sig_enc_length_comp = GNUNET_CRYPTO_rsa_signature_encode (sig, &sig_enc_data_comp); 653 sig_enc_length_comp = GNUNET_CRYPTO_rsa_signature_encode (sig,
654 &sig_enc_data_comp);
615 655
616 if ( (sig_enc_length != sig_enc_length_comp) || 656 if ( (sig_enc_length != sig_enc_length_comp) ||
617 (0 != memcmp (sig_enc_data, sig_enc_data_comp, sig_enc_length) )) 657 (0 != memcmp (sig_enc_data, sig_enc_data_comp, sig_enc_length) ))
618 { 658 {
659 GNUNET_free (blinded_sig);
660 GNUNET_free (blinded_data);
661 GNUNET_free (public_enc_data);
662 GNUNET_free (secret_enc_data);
663 GNUNET_free (sig_enc_data);
664 GNUNET_free (skey);
619 GNUNET_break (0); 665 GNUNET_break (0);
620 return GNUNET_NO; 666 return GNUNET_NO;
621 } 667 }
668 GNUNET_free (blinded_sig);
669 GNUNET_free (blinded_data);
670 GNUNET_free (public_enc_data);
671 GNUNET_free (secret_enc_data);
672 GNUNET_free (sig_enc_data);
673 GNUNET_free (skey);
622 } 674 }
623 else 675 else
624 { 676 {
@@ -629,6 +681,7 @@ checkvec (const char *operation,
629 return GNUNET_OK; 681 return GNUNET_OK;
630} 682}
631 683
684
632/** 685/**
633 * Check test vectors from stdin. 686 * Check test vectors from stdin.
634 * 687 *
@@ -656,7 +709,7 @@ check_vectors ()
656 return 1; 709 return 1;
657 } 710 }
658 vectors = json_object_get (vecfile, "vectors"); 711 vectors = json_object_get (vecfile, "vectors");
659 if (!json_is_array (vectors)) 712 if (! json_is_array (vectors))
660 { 713 {
661 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bad vectors\n"); 714 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bad vectors\n");
662 json_decref (vecfile); 715 json_decref (vecfile);
@@ -692,6 +745,7 @@ check_vectors ()
692 } 745 }
693} 746}
694 747
748
695/** 749/**
696 * Output test vectors. 750 * Output test vectors.
697 * 751 *
@@ -868,20 +922,20 @@ output_vectors ()
868 GNUNET_CRYPTO_ecdh_eddsa (&priv_ecdhe, &pub_eddsa, &key_material); 922 GNUNET_CRYPTO_ecdh_eddsa (&priv_ecdhe, &pub_eddsa, &key_material);
869 923
870 d2j (vec, "priv_ecdhe", 924 d2j (vec, "priv_ecdhe",
871 &priv_ecdhe, 925 &priv_ecdhe,
872 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); 926 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
873 d2j (vec, "pub_ecdhe", 927 d2j (vec, "pub_ecdhe",
874 &pub_ecdhe, 928 &pub_ecdhe,
875 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); 929 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
876 d2j (vec, "priv_eddsa", 930 d2j (vec, "priv_eddsa",
877 &priv_eddsa, 931 &priv_eddsa,
878 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); 932 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
879 d2j (vec, "pub_eddsa", 933 d2j (vec, "pub_eddsa",
880 &pub_eddsa, 934 &pub_eddsa,
881 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); 935 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
882 d2j (vec, "key_material", 936 d2j (vec, "key_material",
883 &key_material, 937 &key_material,
884 sizeof (struct GNUNET_HashCode)); 938 sizeof (struct GNUNET_HashCode));
885 } 939 }
886 940
887 { 941 {
@@ -968,6 +1022,7 @@ output_vectors ()
968 GNUNET_free (blinded_data); 1022 GNUNET_free (blinded_data);
969 GNUNET_free (sig_enc_data); 1023 GNUNET_free (sig_enc_data);
970 GNUNET_free (blinded_sig_enc_data); 1024 GNUNET_free (blinded_sig_enc_data);
1025 GNUNET_free (secret_enc_data);
971 } 1026 }
972 1027
973 json_dumpf (vecfile, stdout, JSON_INDENT (2)); 1028 json_dumpf (vecfile, stdout, JSON_INDENT (2));
@@ -977,6 +1032,7 @@ output_vectors ()
977 return 0; 1032 return 0;
978} 1033}
979 1034
1035
980/** 1036/**
981 * Main function that will be run. 1037 * Main function that will be run.
982 * 1038 *
diff --git a/src/util/gnunet-scrypt.c b/src/util/gnunet-scrypt.c
index 5c3dfc12e..fe8b6769f 100644
--- a/src/util/gnunet-scrypt.c
+++ b/src/util/gnunet-scrypt.c
@@ -290,8 +290,8 @@ run (void *cls,
290int 290int
291main (int argc, char *const *argv) 291main (int argc, char *const *argv)
292{ 292{
293 struct GNUNET_GETOPT_CommandLineOption options[] = 293 struct GNUNET_GETOPT_CommandLineOption options[] = {
294 { GNUNET_GETOPT_option_ulong ( 294 GNUNET_GETOPT_option_ulong (
295 'b', 295 'b',
296 "bits", 296 "bits",
297 "BITS", 297 "BITS",
@@ -315,7 +315,8 @@ main (int argc, char *const *argv)
315 gettext_noop ( 315 gettext_noop (
316 "time to wait between calculations"), 316 "time to wait between calculations"),
317 &proof_find_delay), 317 &proof_find_delay),
318 GNUNET_GETOPT_OPTION_END }; 318 GNUNET_GETOPT_OPTION_END
319 };
319 int ret; 320 int ret;
320 321
321 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 322 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
diff --git a/src/util/mq.c b/src/util/mq.c
index 2342b2c5c..9b59cd338 100644
--- a/src/util/mq.c
+++ b/src/util/mq.c
@@ -363,7 +363,7 @@ GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
363 GNUNET_assert (NULL == ev->parent_queue); 363 GNUNET_assert (NULL == ev->parent_queue);
364 364
365 mq->queue_length++; 365 mq->queue_length++;
366 if (mq->queue_length >= 10000) 366 if (mq->queue_length >= 10000000)
367 { 367 {
368 /* This would seem like a bug... */ 368 /* This would seem like a bug... */
369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/util/os_installation.c b/src/util/os_installation.c
index d1e5e0da5..02d4d439d 100644
--- a/src/util/os_installation.c
+++ b/src/util/os_installation.c
@@ -736,7 +736,12 @@ GNUNET_OS_get_suid_binary_path (const struct GNUNET_CONFIGURATION_Handle *cfg,
736 "SUID_BINARY_PATH", 736 "SUID_BINARY_PATH",
737 &path); 737 &path);
738 if ((NULL == path) || (0 == strlen (path))) 738 if ((NULL == path) || (0 == strlen (path)))
739 {
740 if (NULL != path)
741 GNUNET_free (path);
742 cache = NULL;
739 return GNUNET_OS_get_libexec_binary_path (progname); 743 return GNUNET_OS_get_libexec_binary_path (progname);
744 }
740 path_len = strlen (path); 745 path_len = strlen (path);
741 GNUNET_asprintf (&binary, 746 GNUNET_asprintf (&binary,
742 "%s%s%s", 747 "%s%s%s",
diff --git a/src/util/plugin.c b/src/util/plugin.c
index d169bc911..feb661f24 100644
--- a/src/util/plugin.c
+++ b/src/util/plugin.c
@@ -388,6 +388,11 @@ find_libraries (void *cls,
388 * `basename_ANYTHING_init` and `basename_ANYTHING__done`. These will 388 * `basename_ANYTHING_init` and `basename_ANYTHING__done`. These will
389 * be called when the library is loaded and unloaded respectively. 389 * be called when the library is loaded and unloaded respectively.
390 * 390 *
391 * If you are writing a service to which third-party applications can connect,
392 * like GNUnet's own GNS service for example, you should use
393 * #GNUNET_PLUGIN_load_all_in_context instead of this function, passing your
394 * service's project data as context.
395 *
391 * @param basename basename of the plugins to load 396 * @param basename basename of the plugins to load
392 * @param arg argument to the plugin initialization function 397 * @param arg argument to the plugin initialization function
393 * @param cb function to call for each plugin found 398 * @param cb function to call for each plugin found
@@ -420,4 +425,32 @@ GNUNET_PLUGIN_load_all (const char *basename,
420} 425}
421 426
422 427
428/**
429 * Load all compatible plugins with the given base name while inside the given
430 * context (i.e. a specific project data structure.)
431 *
432 * Note that the library must export symbols called `basename_ANYTHING_init`
433 * and `basename_ANYTHING__done`. These will be called when the library is
434 * loaded and unloaded respectively.
435 *
436 * @param ctx the context used to find the plugins
437 * @param basename basename of the plugins to load
438 * @param arg argument to the plugin initialization function
439 * @param cb function to call for each plugin found
440 * @param cb_cls closure for @a cb
441 */
442void
443GNUNET_PLUGIN_load_all_in_context (const struct GNUNET_OS_ProjectData *ctx,
444 const char *basename,
445 void *arg,
446 GNUNET_PLUGIN_LoaderCallback cb,
447 void *cb_cls)
448{
449 const struct GNUNET_OS_ProjectData *cpd = GNUNET_OS_project_data_get ();
450 GNUNET_OS_init (ctx);
451 GNUNET_PLUGIN_load_all (basename, arg, cb, cb_cls);
452 GNUNET_OS_init (cpd);
453}
454
455
423/* end of plugin.c */ 456/* end of plugin.c */
diff --git a/src/util/time.c b/src/util/time.c
index 9e41305f1..456ee660b 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -44,11 +44,6 @@
44 */ 44 */
45static long long timestamp_offset; 45static long long timestamp_offset;
46 46
47/**
48 * Set the timestamp offset for this instance.
49 *
50 * @param offset the offset to skew the locale time by
51 */
52void 47void
53GNUNET_TIME_set_offset (long long offset) 48GNUNET_TIME_set_offset (long long offset)
54{ 49{
@@ -56,11 +51,6 @@ GNUNET_TIME_set_offset (long long offset)
56} 51}
57 52
58 53
59/**
60 * Get the timestamp offset for this instance.
61 *
62 * @return the offset we currently skew the locale time by
63 */
64long long 54long long
65GNUNET_TIME_get_offset () 55GNUNET_TIME_get_offset ()
66{ 56{
@@ -68,14 +58,6 @@ GNUNET_TIME_get_offset ()
68} 58}
69 59
70 60
71/**
72 * Round a time value so that it is suitable for transmission
73 * via JSON encodings.
74 *
75 * @param at time to round
76 * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
77 * it was just now rounded
78 */
79int 61int
80GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at) 62GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at)
81{ 63{
@@ -88,14 +70,6 @@ GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at)
88} 70}
89 71
90 72
91/**
92 * Round a time value so that it is suitable for transmission
93 * via JSON encodings.
94 *
95 * @param rt time to round
96 * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
97 * it was just now rounded
98 */
99int 73int
100GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt) 74GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt)
101{ 75{
@@ -108,12 +82,6 @@ GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt)
108} 82}
109 83
110 84
111/**
112 * Get the current time (works just as "time", just that we use the
113 * unit of time that the cron-jobs use (and is 64 bit)).
114 *
115 * @return the current time
116 */
117struct GNUNET_TIME_Absolute 85struct GNUNET_TIME_Absolute
118GNUNET_TIME_absolute_get () 86GNUNET_TIME_absolute_get ()
119{ 87{
@@ -128,9 +96,6 @@ GNUNET_TIME_absolute_get ()
128} 96}
129 97
130 98
131/**
132 * Return relative time of 0ms.
133 */
134struct GNUNET_TIME_Relative 99struct GNUNET_TIME_Relative
135GNUNET_TIME_relative_get_zero_ () 100GNUNET_TIME_relative_get_zero_ ()
136{ 101{
@@ -140,9 +105,6 @@ GNUNET_TIME_relative_get_zero_ ()
140} 105}
141 106
142 107
143/**
144 * Return absolute time of 0ms.
145 */
146struct GNUNET_TIME_Absolute 108struct GNUNET_TIME_Absolute
147GNUNET_TIME_absolute_get_zero_ () 109GNUNET_TIME_absolute_get_zero_ ()
148{ 110{
@@ -152,9 +114,6 @@ GNUNET_TIME_absolute_get_zero_ ()
152} 114}
153 115
154 116
155/**
156 * Return relative time of 1us.
157 */
158struct GNUNET_TIME_Relative 117struct GNUNET_TIME_Relative
159GNUNET_TIME_relative_get_unit_ () 118GNUNET_TIME_relative_get_unit_ ()
160{ 119{
@@ -164,9 +123,6 @@ GNUNET_TIME_relative_get_unit_ ()
164} 123}
165 124
166 125
167/**
168 * Return relative time of 1ms.
169 */
170struct GNUNET_TIME_Relative 126struct GNUNET_TIME_Relative
171GNUNET_TIME_relative_get_millisecond_ () 127GNUNET_TIME_relative_get_millisecond_ ()
172{ 128{
@@ -176,9 +132,6 @@ GNUNET_TIME_relative_get_millisecond_ ()
176} 132}
177 133
178 134
179/**
180 * Return relative time of 1s.
181 */
182struct GNUNET_TIME_Relative 135struct GNUNET_TIME_Relative
183GNUNET_TIME_relative_get_second_ () 136GNUNET_TIME_relative_get_second_ ()
184{ 137{
@@ -188,9 +141,6 @@ GNUNET_TIME_relative_get_second_ ()
188} 141}
189 142
190 143
191/**
192 * Return relative time of 1 minute.
193 */
194struct GNUNET_TIME_Relative 144struct GNUNET_TIME_Relative
195GNUNET_TIME_relative_get_minute_ () 145GNUNET_TIME_relative_get_minute_ ()
196{ 146{
@@ -200,9 +150,6 @@ GNUNET_TIME_relative_get_minute_ ()
200} 150}
201 151
202 152
203/**
204 * Return relative time of 1 hour.
205 */
206struct GNUNET_TIME_Relative 153struct GNUNET_TIME_Relative
207GNUNET_TIME_relative_get_hour_ () 154GNUNET_TIME_relative_get_hour_ ()
208{ 155{
@@ -212,9 +159,6 @@ GNUNET_TIME_relative_get_hour_ ()
212} 159}
213 160
214 161
215/**
216 * Return "forever".
217 */
218struct GNUNET_TIME_Relative 162struct GNUNET_TIME_Relative
219GNUNET_TIME_relative_get_forever_ () 163GNUNET_TIME_relative_get_forever_ ()
220{ 164{
@@ -224,9 +168,6 @@ GNUNET_TIME_relative_get_forever_ ()
224} 168}
225 169
226 170
227/**
228 * Return "forever".
229 */
230struct GNUNET_TIME_Absolute 171struct GNUNET_TIME_Absolute
231GNUNET_TIME_absolute_get_forever_ () 172GNUNET_TIME_absolute_get_forever_ ()
232{ 173{
@@ -236,12 +177,6 @@ GNUNET_TIME_absolute_get_forever_ ()
236} 177}
237 178
238 179
239/**
240 * Convert relative time to an absolute time in the
241 * future.
242 *
243 * @return timestamp that is "rel" in the future, or FOREVER if rel==FOREVER (or if we would overflow)
244 */
245struct GNUNET_TIME_Absolute 180struct GNUNET_TIME_Absolute
246GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel) 181GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
247{ 182{
@@ -261,13 +196,6 @@ GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
261} 196}
262 197
263 198
264/**
265 * Return the minimum of two relative time values.
266 *
267 * @param t1 first timestamp
268 * @param t2 other timestamp
269 * @return timestamp that is smaller
270 */
271struct GNUNET_TIME_Relative 199struct GNUNET_TIME_Relative
272GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1, 200GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
273 struct GNUNET_TIME_Relative t2) 201 struct GNUNET_TIME_Relative t2)
@@ -276,13 +204,6 @@ GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
276} 204}
277 205
278 206
279/**
280 * Return the maximum of two relative time values.
281 *
282 * @param t1 first timestamp
283 * @param t2 other timestamp
284 * @return timestamp that is larger
285 */
286struct GNUNET_TIME_Relative 207struct GNUNET_TIME_Relative
287GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1, 208GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1,
288 struct GNUNET_TIME_Relative t2) 209 struct GNUNET_TIME_Relative t2)
@@ -291,13 +212,6 @@ GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1,
291} 212}
292 213
293 214
294/**
295 * Return the minimum of two relative time values.
296 *
297 * @param t1 first timestamp
298 * @param t2 other timestamp
299 * @return timestamp that is smaller
300 */
301struct GNUNET_TIME_Absolute 215struct GNUNET_TIME_Absolute
302GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1, 216GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1,
303 struct GNUNET_TIME_Absolute t2) 217 struct GNUNET_TIME_Absolute t2)
@@ -306,13 +220,6 @@ GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1,
306} 220}
307 221
308 222
309/**
310 * Return the maximum of two relative time values.
311 *
312 * @param t1 first timestamp
313 * @param t2 other timestamp
314 * @return timestamp that is bigger
315 */
316struct GNUNET_TIME_Absolute 223struct GNUNET_TIME_Absolute
317GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1, 224GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
318 struct GNUNET_TIME_Absolute t2) 225 struct GNUNET_TIME_Absolute t2)
@@ -321,12 +228,6 @@ GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
321} 228}
322 229
323 230
324/**
325 * Given a timestamp in the future, how much time
326 * remains until then?
327 *
328 * @return future - now, or 0 if now >= future, or FOREVER if future==FOREVER.
329 */
330struct GNUNET_TIME_Relative 231struct GNUNET_TIME_Relative
331GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future) 232GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
332{ 233{
@@ -343,13 +244,6 @@ GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
343} 244}
344 245
345 246
346/**
347 * Compute the time difference between the given start and end times.
348 * Use this function instead of actual subtraction to ensure that
349 * "FOREVER" and overflows are handled correctly.
350 *
351 * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start
352 */
353struct GNUNET_TIME_Relative 247struct GNUNET_TIME_Relative
354GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start, 248GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
355 struct GNUNET_TIME_Absolute end) 249 struct GNUNET_TIME_Absolute end)
@@ -365,12 +259,6 @@ GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
365} 259}
366 260
367 261
368/**
369 * Get the duration of an operation as the
370 * difference of the current time and the given start time "whence".
371 *
372 * @return 0 if whence > now, otherwise now-whence.
373 */
374struct GNUNET_TIME_Relative 262struct GNUNET_TIME_Relative
375GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence) 263GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence)
376{ 264{
@@ -385,12 +273,6 @@ GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence)
385} 273}
386 274
387 275
388/**
389 * Add a given relative duration to the
390 * given start time.
391 *
392 * @return FOREVER if either argument is FOREVER or on overflow; start+duration otherwise
393 */
394struct GNUNET_TIME_Absolute 276struct GNUNET_TIME_Absolute
395GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start, 277GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
396 struct GNUNET_TIME_Relative duration) 278 struct GNUNET_TIME_Relative duration)
@@ -410,14 +292,6 @@ GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
410} 292}
411 293
412 294
413/**
414 * Subtract a given relative duration from the
415 * given start time.
416 *
417 * @param start some absolute time
418 * @param duration some relative time to subtract
419 * @return ZERO if start <= duration, or FOREVER if start time is FOREVER; start-duration otherwise
420 */
421struct GNUNET_TIME_Absolute 295struct GNUNET_TIME_Absolute
422GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start, 296GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start,
423 struct GNUNET_TIME_Relative duration) 297 struct GNUNET_TIME_Relative duration)
@@ -433,11 +307,6 @@ GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start,
433} 307}
434 308
435 309
436/**
437 * Multiply relative time by a given factor.
438 *
439 * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
440 */
441struct GNUNET_TIME_Relative 310struct GNUNET_TIME_Relative
442GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel, 311GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
443 unsigned long long factor) 312 unsigned long long factor)
@@ -458,12 +327,6 @@ GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
458} 327}
459 328
460 329
461/**
462 * Multiply relative time by a given floating-point factor. The factor must be
463 * positive.
464 *
465 * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
466 */
467struct GNUNET_TIME_Relative 330struct GNUNET_TIME_Relative
468relative_multiply_double (struct GNUNET_TIME_Relative rel, double factor) 331relative_multiply_double (struct GNUNET_TIME_Relative rel, double factor)
469{ 332{
@@ -490,13 +353,6 @@ relative_multiply_double (struct GNUNET_TIME_Relative rel, double factor)
490} 353}
491 354
492 355
493/**
494 * Saturating multiply relative time by a given factor.
495 *
496 * @param rel some duration
497 * @param factor integer to multiply with
498 * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
499 */
500struct GNUNET_TIME_Relative 356struct GNUNET_TIME_Relative
501GNUNET_TIME_relative_saturating_multiply (struct GNUNET_TIME_Relative rel, 357GNUNET_TIME_relative_saturating_multiply (struct GNUNET_TIME_Relative rel,
502 unsigned long long factor) 358 unsigned long long factor)
@@ -516,13 +372,6 @@ GNUNET_TIME_relative_saturating_multiply (struct GNUNET_TIME_Relative rel,
516} 372}
517 373
518 374
519/**
520 * Divide relative time by a given factor.
521 *
522 * @param rel some duration
523 * @param factor integer to divide by
524 * @return FOREVER if rel=FOREVER or factor==0; otherwise rel/factor
525 */
526struct GNUNET_TIME_Relative 375struct GNUNET_TIME_Relative
527GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel, 376GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
528 unsigned long long factor) 377 unsigned long long factor)
@@ -537,16 +386,6 @@ GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
537} 386}
538 387
539 388
540/**
541 * Calculate the estimate time of arrival/completion
542 * for an operation.
543 *
544 * @param start when did the operation start?
545 * @param finished how much has been done?
546 * @param total how much must be done overall (same unit as for "finished")
547 * @return remaining duration for the operation,
548 * assuming it continues at the same speed
549 */
550struct GNUNET_TIME_Relative 389struct GNUNET_TIME_Relative
551GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, 390GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
552 uint64_t finished, 391 uint64_t finished,
@@ -568,13 +407,6 @@ GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
568} 407}
569 408
570 409
571/**
572 * Add relative times together.
573 *
574 * @param a1 first timestamp
575 * @param a2 second timestamp
576 * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise
577 */
578struct GNUNET_TIME_Relative 410struct GNUNET_TIME_Relative
579GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1, 411GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
580 struct GNUNET_TIME_Relative a2) 412 struct GNUNET_TIME_Relative a2)
@@ -593,13 +425,6 @@ GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
593} 425}
594 426
595 427
596/**
597 * Subtract relative timestamp from the other.
598 *
599 * @param a1 first timestamp
600 * @param a2 second timestamp
601 * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise
602 */
603struct GNUNET_TIME_Relative 428struct GNUNET_TIME_Relative
604GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1, 429GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1,
605 struct GNUNET_TIME_Relative a2) 430 struct GNUNET_TIME_Relative a2)
@@ -615,12 +440,6 @@ GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1,
615} 440}
616 441
617 442
618/**
619 * Convert relative time to network byte order.
620 *
621 * @param a time to convert
622 * @return time in network byte order
623 */
624struct GNUNET_TIME_RelativeNBO 443struct GNUNET_TIME_RelativeNBO
625GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) 444GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
626{ 445{
@@ -631,12 +450,6 @@ GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
631} 450}
632 451
633 452
634/**
635 * Convert relative time from network byte order.
636 *
637 * @param a time to convert
638 * @return time in host byte order
639 */
640struct GNUNET_TIME_Relative 453struct GNUNET_TIME_Relative
641GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) 454GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
642{ 455{
@@ -647,12 +460,6 @@ GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
647} 460}
648 461
649 462
650/**
651 * Convert absolute time to network byte order.
652 *
653 * @param a time to convert
654 * @return time in network byte order
655 */
656struct GNUNET_TIME_AbsoluteNBO 463struct GNUNET_TIME_AbsoluteNBO
657GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) 464GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
658{ 465{
@@ -663,12 +470,6 @@ GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
663} 470}
664 471
665 472
666/**
667 * Convert absolute time from network byte order.
668 *
669 * @param a time to convert
670 * @return time in host byte order
671 */
672struct GNUNET_TIME_Absolute 473struct GNUNET_TIME_Absolute
673GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) 474GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
674{ 475{
@@ -679,9 +480,6 @@ GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
679} 480}
680 481
681 482
682/**
683 * Return the current year (i.e. '2011').
684 */
685unsigned int 483unsigned int
686GNUNET_TIME_get_current_year () 484GNUNET_TIME_get_current_year ()
687{ 485{
@@ -696,12 +494,6 @@ GNUNET_TIME_get_current_year ()
696} 494}
697 495
698 496
699/**
700 * Convert an expiration time to the respective year (rounds)
701 *
702 * @param at absolute time
703 * @return year a year (after 1970), 0 on error
704 */
705unsigned int 497unsigned int
706GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at) 498GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at)
707{ 499{
@@ -742,12 +534,6 @@ my_timegm (struct tm *tm)
742#endif 534#endif
743 535
744 536
745/**
746 * Convert a year to an expiration time of January 1st of that year.
747 *
748 * @param year a year (after 1970, please ;-)).
749 * @return absolute time for January 1st of that year.
750 */
751struct GNUNET_TIME_Absolute 537struct GNUNET_TIME_Absolute
752GNUNET_TIME_year_to_time (unsigned int year) 538GNUNET_TIME_year_to_time (unsigned int year)
753{ 539{
@@ -777,15 +563,6 @@ GNUNET_TIME_year_to_time (unsigned int year)
777} 563}
778 564
779 565
780/**
781 * Randomized exponential back-off, starting at 1 ms
782 * and going up by a factor of 2+r, where 0 <= r <= 0.5, up
783 * to a maximum of the given threshold.
784 *
785 * @param r current backoff time, initially zero
786 * @param threshold maximum value for backoff
787 * @return the next backoff time
788 */
789struct GNUNET_TIME_Relative 566struct GNUNET_TIME_Relative
790GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt, 567GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt,
791 struct GNUNET_TIME_Relative threshold) 568 struct GNUNET_TIME_Relative threshold)
@@ -800,39 +577,15 @@ GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt,
800} 577}
801 578
802 579
803/**
804 * Return a random time value between 0.5*r and 1.5*r.
805 *
806 * @param r input time for scaling
807 * @return randomized time
808 */
809struct GNUNET_TIME_Relative 580struct GNUNET_TIME_Relative
810GNUNET_TIME_randomize (struct GNUNET_TIME_Relative r) 581GNUNET_TIME_randomize (struct GNUNET_TIME_Relative r)
811{ 582{
812 double d = ((rand () % 1001) - 500) / 1000.0; 583 double d = ((rand () % 1001) + 500) / 1000.0;
813 584
814 return relative_multiply_double (r, d); 585 return relative_multiply_double (r, d);
815} 586}
816 587
817 588
818/**
819 * Obtain the current time and make sure it is monotonically
820 * increasing. Guards against systems without an RTC or
821 * clocks running backwards and other nasty surprises. Does
822 * not guarantee that the returned time is near the current
823 * time returned by #GNUNET_TIME_absolute_get(). Two
824 * subsequent calls (within a short time period) may return the
825 * same value. Persists the last returned time on disk to
826 * ensure that time never goes backwards. As a result, the
827 * resulting value can be used to check if a message is the
828 * "most recent" value and replays of older messages (from
829 * the same origin) would be discarded.
830 *
831 * @param cfg configuration, used to determine where to
832 * store the time; user can also insist RTC is working
833 * nicely and disable the feature
834 * @return monotonically increasing time
835 */
836struct GNUNET_TIME_Absolute 589struct GNUNET_TIME_Absolute
837GNUNET_TIME_absolute_get_monotonic ( 590GNUNET_TIME_absolute_get_monotonic (
838 const struct GNUNET_CONFIGURATION_Handle *cfg) 591 const struct GNUNET_CONFIGURATION_Handle *cfg)