aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-01-02 16:48:03 +0100
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-01-02 16:48:03 +0100
commit7c1f035ed971e12882cd7a65c7d36883842945b1 (patch)
tree3828089ef8124270b976ac94902ba27210d275a3 /src
parent92d8c8a77e242a61927acc0e22fcecea479e6c43 (diff)
parent61f532f18450e0d7c72f0c17f4a20b5854cf53bf (diff)
downloadgnunet-7c1f035ed971e12882cd7a65c7d36883842945b1.tar.gz
gnunet-7c1f035ed971e12882cd7a65c7d36883842945b1.zip
-merge
Diffstat (limited to 'src')
-rw-r--r--src/arm/gnunet-service-arm.c3
-rw-r--r--src/auction/Makefile.am5
-rw-r--r--src/cadet/cadet_api.c124
-rw-r--r--src/cadet/cadet_test_lib.c1
-rw-r--r--src/cadet/gnunet-cadet.c1
-rw-r--r--src/cadet/gnunet-service-cadet_core.c42
-rw-r--r--src/cadet/gnunet-service-cadet_paths.c169
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c53
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.c4
-rw-r--r--src/cadet/test_cadet.c133
-rw-r--r--src/conversation/gnunet-helper-audio-playback-gst.c5
-rw-r--r--src/conversation/gnunet-helper-audio-playback.c5
-rw-r--r--src/conversation/gnunet_gst.c5
-rw-r--r--src/conversation/microphone.c4
-rw-r--r--src/core/gnunet-service-core.c3
-rw-r--r--src/core/gnunet-service-core_kx.c5
-rw-r--r--src/core/gnunet-service-core_sessions.c19
-rw-r--r--src/dht/Makefile.am1
-rw-r--r--src/dht/gnunet-service-dht.c1
-rw-r--r--src/fs/fs_dirmetascan.c3
-rw-r--r--src/fs/test_fs_download_persistence.c1
-rw-r--r--src/fs/test_fs_publish_persistence.c1
-rw-r--r--src/hello/hello.c7
-rw-r--r--src/include/Makefile.am7
-rw-r--r--src/include/gnunet_common.h15
-rw-r--r--src/include/gnunet_mst_lib.h4
-rw-r--r--src/include/gnunet_network_lib.h6
-rw-r--r--src/include/gnunet_protocols.h30
-rw-r--r--src/include/gnunet_rest_lib.h2
-rw-r--r--src/include/gnunet_scheduler_lib.h44
-rw-r--r--src/include/gnunet_service_lib.h7
-rw-r--r--src/jsonapi/Makefile.am2
-rw-r--r--src/multicast/Makefile.am2
-rw-r--r--src/multicast/gnunet-service-multicast.c248
-rw-r--r--src/multicast/multicast_api.c51
-rw-r--r--src/multicast/test_multicast_multipeer.c312
-rw-r--r--src/psyc/gnunet-service-psyc.c131
-rw-r--r--src/psyc/psyc_api.c103
-rw-r--r--src/psyc/test_psyc.c28
-rw-r--r--src/psyc/test_psyc.conf16
-rw-r--r--src/psycstore/psycstore_api.c10
-rw-r--r--src/rest/Makefile.am2
-rw-r--r--src/rps/.gitignore12
-rw-r--r--src/rps/Makefile.am15
-rw-r--r--src/rps/gnunet-service-rps.c1798
-rw-r--r--src/rps/gnunet-service-rps_peers.c1694
-rw-r--r--src/rps/gnunet-service-rps_peers.h437
-rw-r--r--src/rps/rps.h96
-rw-r--r--src/rps/test_rps.c86
-rw-r--r--src/rps/test_rps.conf38
-rw-r--r--src/rps/test_service_rps_peers.c137
-rw-r--r--src/set/Makefile.am2
-rw-r--r--src/set/gnunet-service-set_union.c4
-rw-r--r--src/social/gnunet-service-social.c774
-rw-r--r--src/social/gnunet-social.c26
-rw-r--r--src/social/social_api.c292
-rw-r--r--src/social/test_social.c268
-rw-r--r--src/social/test_social.conf19
-rw-r--r--src/statistics/gnunet-service-statistics.c4
-rw-r--r--src/testbed/Makefile.am2
-rw-r--r--src/testbed/gnunet-daemon-testbed-underlay.c6
-rw-r--r--src/testbed/gnunet-helper-testbed.c7
-rw-r--r--src/testbed/gnunet-service-testbed_oc.c15
-rw-r--r--src/testbed/gnunet-testbed-profiler.c15
-rw-r--r--src/transport/Makefile.am9
-rw-r--r--src/transport/gnunet-helper-transport-wlan-dummy.c6
-rw-r--r--src/transport/gnunet-service-transport.c4
-rw-r--r--src/transport/gnunet-service-transport_validation.c13
-rw-r--r--src/transport/plugin_transport_http_server.c2
-rw-r--r--src/util/client.c41
-rw-r--r--src/util/mq.c22
-rw-r--r--src/util/mst.c27
-rw-r--r--src/util/network.c6
-rw-r--r--src/util/program.c12
-rw-r--r--src/util/scheduler.c1535
-rw-r--r--src/util/service.c31
-rw-r--r--src/util/time.c2
-rw-r--r--src/vpn/gnunet-service-vpn.c3
78 files changed, 4836 insertions, 4239 deletions
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index 2db2ba0d1..bf5982d10 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.c
@@ -1915,7 +1915,6 @@ setup_service (void *cls,
1915 struct sockaddr **addrs; 1915 struct sockaddr **addrs;
1916 socklen_t *addr_lens; 1916 socklen_t *addr_lens;
1917 int ret; 1917 int ret;
1918 unsigned int i;
1919 1918
1920 if (0 == strcasecmp (section, 1919 if (0 == strcasecmp (section,
1921 "arm")) 1920 "arm"))
@@ -2027,7 +2026,7 @@ setup_service (void *cls,
2027 &addr_lens))) 2026 &addr_lens)))
2028 return; 2027 return;
2029 /* this will free (or capture) addrs[i] */ 2028 /* this will free (or capture) addrs[i] */
2030 for (i = 0; i < ret; i++) 2029 for (unsigned int i = 0; i < ret; i++)
2031 create_listen_socket (addrs[i], 2030 create_listen_socket (addrs[i],
2032 addr_lens[i], 2031 addr_lens[i],
2033 sl); 2032 sl);
diff --git a/src/auction/Makefile.am b/src/auction/Makefile.am
index bdede0ce0..f86e846e2 100644
--- a/src/auction/Makefile.am
+++ b/src/auction/Makefile.am
@@ -68,6 +68,11 @@ test_auction_api_LDADD = \
68check_SCRIPTS = \ 68check_SCRIPTS = \
69 test_auction_create.sh 69 test_auction_create.sh
70 70
71EXTRA_DIST = \
72 auction.h \
73 auction.conf \
74 $(check_SCRIPTS)
75
71if ENABLE_TEST_RUN 76if ENABLE_TEST_RUN
72 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 77 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
73 TESTS = $(check_PROGRAMS) $(check_SCRIPTS) 78 TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c
index 00a482452..497c9a4f0 100644
--- a/src/cadet/cadet_api.c
+++ b/src/cadet/cadet_api.c
@@ -391,6 +391,8 @@ destroy_channel_on_reconnect_cb (void *cls,
391 /* struct GNUNET_CADET_Handle *handle = cls; */ 391 /* struct GNUNET_CADET_Handle *handle = cls; */
392 struct GNUNET_CADET_Channel *ch = value; 392 struct GNUNET_CADET_Channel *ch = value;
393 393
394 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
395 "Destroying channel due to reconnect\n");
394 destroy_channel (ch); 396 destroy_channel (ch);
395 return GNUNET_OK; 397 return GNUNET_OK;
396} 398}
@@ -824,6 +826,29 @@ handle_mq_error (void *cls,
824 826
825 827
826/** 828/**
829 * Check that message received from CADET service is well-formed.
830 *
831 * @param cls the `struct GNUNET_CADET_Handle`
832 * @param message the message we got
833 * @return #GNUNET_OK if the message is well-formed,
834 * #GNUNET_SYSERR otherwise
835 */
836static int
837check_get_peers (void *cls,
838 const struct GNUNET_MessageHeader *message)
839{
840 size_t esize;
841
842 esize = ntohs (message->size);
843 if (sizeof (struct GNUNET_CADET_LocalInfoPeer) == esize)
844 return GNUNET_OK;
845 if (sizeof (struct GNUNET_MessageHeader) == esize)
846 return GNUNET_OK;
847 return GNUNET_SYSERR;
848}
849
850
851/**
827 * Process a local reply about info on all tunnels, pass info to the user. 852 * Process a local reply about info on all tunnels, pass info to the user.
828 * 853 *
829 * @param cls Closure (Cadet handle). 854 * @param cls Closure (Cadet handle).
@@ -831,17 +856,26 @@ handle_mq_error (void *cls,
831 */ 856 */
832static void 857static void
833handle_get_peers (void *cls, 858handle_get_peers (void *cls,
834 const struct GNUNET_CADET_LocalInfoPeer *msg) 859 const struct GNUNET_MessageHeader *msg)
835{ 860{
836 struct GNUNET_CADET_Handle *h = cls; 861 struct GNUNET_CADET_Handle *h = cls;
862 const struct GNUNET_CADET_LocalInfoPeer *info =
863 (const struct GNUNET_CADET_LocalInfoPeer *) msg;
837 864
838 if (NULL == h->info_cb.peers_cb) 865 if (NULL == h->info_cb.peers_cb)
839 return; 866 return;
840 h->info_cb.peers_cb (h->info_cls, 867 if (sizeof (struct GNUNET_CADET_LocalInfoPeer) == ntohs (msg->size))
841 &msg->destination, 868 h->info_cb.peers_cb (h->info_cls,
842 (int) ntohs (msg->tunnel), 869 &info->destination,
843 (unsigned int) ntohs (msg->paths), 870 (int) ntohs (info->tunnel),
844 0); 871 (unsigned int) ntohs (info->paths),
872 0);
873 else
874 h->info_cb.peers_cb (h->info_cls,
875 NULL,
876 0,
877 0,
878 0);
845} 879}
846 880
847 881
@@ -946,6 +980,29 @@ handle_get_peer (void *cls,
946 980
947 981
948/** 982/**
983 * Check that message received from CADET service is well-formed.
984 *
985 * @param cls the `struct GNUNET_CADET_Handle`
986 * @param message the message we got
987 * @return #GNUNET_OK if the message is well-formed,
988 * #GNUNET_SYSERR otherwise
989 */
990static int
991check_get_tunnels (void *cls,
992 const struct GNUNET_MessageHeader *message)
993{
994 size_t esize;
995
996 esize = ntohs (message->size);
997 if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) == esize)
998 return GNUNET_OK;
999 if (sizeof (struct GNUNET_MessageHeader) == esize)
1000 return GNUNET_OK;
1001 return GNUNET_SYSERR;
1002}
1003
1004
1005/**
949 * Process a local reply about info on all tunnels, pass info to the user. 1006 * Process a local reply about info on all tunnels, pass info to the user.
950 * 1007 *
951 * @param cls Closure (Cadet handle). 1008 * @param cls Closure (Cadet handle).
@@ -953,19 +1010,28 @@ handle_get_peer (void *cls,
953 */ 1010 */
954static void 1011static void
955handle_get_tunnels (void *cls, 1012handle_get_tunnels (void *cls,
956 const struct GNUNET_CADET_LocalInfoTunnel *msg) 1013 const struct GNUNET_MessageHeader *msg)
957{ 1014{
958 struct GNUNET_CADET_Handle *h = cls; 1015 struct GNUNET_CADET_Handle *h = cls;
1016 const struct GNUNET_CADET_LocalInfoTunnel *info =
1017 (const struct GNUNET_CADET_LocalInfoTunnel *) msg;
959 1018
960 if (NULL == h->info_cb.tunnels_cb) 1019 if (NULL == h->info_cb.tunnels_cb)
961 return; 1020 return;
962 h->info_cb.tunnels_cb (h->info_cls, 1021 if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) == ntohs (msg->size))
963 &msg->destination, 1022 h->info_cb.tunnels_cb (h->info_cls,
964 ntohl (msg->channels), 1023 &info->destination,
965 ntohl (msg->connections), 1024 ntohl (info->channels),
966 ntohs (msg->estate), 1025 ntohl (info->connections),
967 ntohs (msg->cstate)); 1026 ntohs (info->estate),
968 1027 ntohs (info->cstate));
1028 else
1029 h->info_cb.tunnels_cb (h->info_cls,
1030 NULL,
1031 0,
1032 0,
1033 0,
1034 0);
969} 1035}
970 1036
971 1037
@@ -1075,18 +1141,18 @@ reconnect (struct GNUNET_CADET_Handle *h)
1075 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, 1141 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1076 struct GNUNET_CADET_LocalAck, 1142 struct GNUNET_CADET_LocalAck,
1077 h), 1143 h),
1078 GNUNET_MQ_hd_fixed_size (get_peers, 1144 GNUNET_MQ_hd_var_size (get_peers,
1079 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, 1145 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
1080 struct GNUNET_CADET_LocalInfoPeer, 1146 struct GNUNET_MessageHeader,
1081 h), 1147 h),
1082 GNUNET_MQ_hd_var_size (get_peer, 1148 GNUNET_MQ_hd_var_size (get_peer,
1083 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, 1149 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
1084 struct GNUNET_CADET_LocalInfoPeer, 1150 struct GNUNET_CADET_LocalInfoPeer,
1085 h), 1151 h),
1086 GNUNET_MQ_hd_fixed_size (get_tunnels, 1152 GNUNET_MQ_hd_var_size (get_tunnels,
1087 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, 1153 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
1088 struct GNUNET_CADET_LocalInfoTunnel, 1154 struct GNUNET_MessageHeader,
1089 h), 1155 h),
1090 GNUNET_MQ_hd_var_size (get_tunnel, 1156 GNUNET_MQ_hd_var_size (get_tunnel,
1091 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, 1157 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
1092 struct GNUNET_CADET_LocalInfoTunnel, 1158 struct GNUNET_CADET_LocalInfoTunnel,
@@ -1094,6 +1160,7 @@ reconnect (struct GNUNET_CADET_Handle *h)
1094 GNUNET_MQ_handler_end () 1160 GNUNET_MQ_handler_end ()
1095 }; 1161 };
1096 1162
1163 GNUNET_assert (NULL == h->mq);
1097 h->mq = GNUNET_CLIENT_connect (h->cfg, 1164 h->mq = GNUNET_CLIENT_connect (h->cfg,
1098 "cadet", 1165 "cadet",
1099 handlers, 1166 handlers,
@@ -1132,6 +1199,8 @@ destroy_channel_cb (void *cls,
1132 "channel %X not destroyed\n", 1199 "channel %X not destroyed\n",
1133 ntohl (ch->ccn.channel_of_client)); 1200 ntohl (ch->ccn.channel_of_client));
1134 } 1201 }
1202 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1203 "Destroying channel due to GNUNET_CADET_disconnect()\n");
1135 destroy_channel (ch); 1204 destroy_channel (ch);
1136 return GNUNET_OK; 1205 return GNUNET_OK;
1137} 1206}
@@ -1246,6 +1315,8 @@ GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
1246 GNUNET_MQ_send (h->mq, 1315 GNUNET_MQ_send (h->mq,
1247 env); 1316 env);
1248 } 1317 }
1318 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1319 "Destroying channel due to GNUNET_CADET_channel_destroy()\n");
1249 destroy_channel (channel); 1320 destroy_channel (channel);
1250} 1321}
1251 1322
@@ -1600,7 +1671,10 @@ GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
1600 1671
1601 GNUNET_assert (NULL != connects); 1672 GNUNET_assert (NULL != connects);
1602 GNUNET_assert (NULL != disconnects); 1673 GNUNET_assert (NULL != disconnects);
1603 1674 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1675 "Listening to CADET port %s\n",
1676 GNUNET_h2s (port));
1677
1604 p = GNUNET_new (struct GNUNET_CADET_Port); 1678 p = GNUNET_new (struct GNUNET_CADET_Port);
1605 p->cadet = h; 1679 p->cadet = h;
1606 p->id = *port; 1680 p->id = *port;
@@ -1663,6 +1737,10 @@ GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
1663 struct GNUNET_MQ_Envelope *env; 1737 struct GNUNET_MQ_Envelope *env;
1664 1738
1665 GNUNET_assert (NULL != disconnects); 1739 GNUNET_assert (NULL != disconnects);
1740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1741 "Creating channel to peer %s at port %s\n",
1742 GNUNET_i2s (destination),
1743 GNUNET_h2s (port));
1666 ch = create_channel (h, 1744 ch = create_channel (h,
1667 NULL); 1745 NULL);
1668 ch->ctx = channel_cls; 1746 ch->ctx = channel_cls;
diff --git a/src/cadet/cadet_test_lib.c b/src/cadet/cadet_test_lib.c
index 1df6bff0d..20ef028b2 100644
--- a/src/cadet/cadet_test_lib.c
+++ b/src/cadet/cadet_test_lib.c
@@ -241,6 +241,7 @@ GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
241 } 241 }
242 GNUNET_free (ctx->ops); 242 GNUNET_free (ctx->ops);
243 GNUNET_free (ctx->cadets); 243 GNUNET_free (ctx->cadets);
244 GNUNET_free (ctx->handlers);
244 GNUNET_free (ctx); 245 GNUNET_free (ctx);
245 GNUNET_SCHEDULER_shutdown (); 246 GNUNET_SCHEDULER_shutdown ();
246} 247}
diff --git a/src/cadet/gnunet-cadet.c b/src/cadet/gnunet-cadet.c
index 675e7faf0..a9b02714b 100644
--- a/src/cadet/gnunet-cadet.c
+++ b/src/cadet/gnunet-cadet.c
@@ -693,6 +693,7 @@ show_tunnel (void *cls)
693{ 693{
694 struct GNUNET_PeerIdentity pid; 694 struct GNUNET_PeerIdentity pid;
695 695
696 job = NULL;
696 if (GNUNET_OK != 697 if (GNUNET_OK !=
697 GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id, 698 GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id,
698 strlen (tunnel_id), 699 strlen (tunnel_id),
diff --git a/src/cadet/gnunet-service-cadet_core.c b/src/cadet/gnunet-service-cadet_core.c
index ae03b4f35..84aff1857 100644
--- a/src/cadet/gnunet-service-cadet_core.c
+++ b/src/cadet/gnunet-service-cadet_core.c
@@ -623,7 +623,7 @@ timeout_cb (void *cls)
623 { 623 {
624 exp = GNUNET_TIME_absolute_add (r->last_use, 624 exp = GNUNET_TIME_absolute_add (r->last_use,
625 linger); 625 linger);
626 if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us) 626 if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
627 { 627 {
628 /* Route not yet timed out, wait until it does. */ 628 /* Route not yet timed out, wait until it does. */
629 timeout_task = GNUNET_SCHEDULER_add_at (exp, 629 timeout_task = GNUNET_SCHEDULER_add_at (exp,
@@ -631,6 +631,11 @@ timeout_cb (void *cls)
631 NULL); 631 NULL);
632 return; 632 return;
633 } 633 }
634 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
635 "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
636 GNUNET_STRINGS_absolute_time_to_string (r->last_use),
637 GNUNET_STRINGS_relative_time_to_string (linger,
638 GNUNET_YES));
634 send_broken (&r->prev, 639 send_broken (&r->prev,
635 &r->cid, 640 &r->cid,
636 NULL, 641 NULL,
@@ -688,6 +693,8 @@ dir_ready_cb (void *cls,
688 return; 693 return;
689 } 694 }
690 odir = (dir == &route->next) ? &route->prev : &route->next; 695 odir = (dir == &route->next) ? &route->prev : &route->next;
696 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
697 "Sending BROKEN due to MQ going down\n");
691 send_broken (&route->next, 698 send_broken (&route->next,
692 &route->cid, 699 &route->cid,
693 GCP_get_id (odir->hop), 700 GCP_get_id (odir->hop),
@@ -771,6 +778,33 @@ handle_connection_create (void *cls,
771 778
772 options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options); 779 options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options);
773 path_length = size / sizeof (struct GNUNET_PeerIdentity); 780 path_length = size / sizeof (struct GNUNET_PeerIdentity);
781 if (0 == path_length)
782 {
783 LOG (GNUNET_ERROR_TYPE_DEBUG,
784 "Dropping CADET_CONNECTION_CREATE with empty path\n");
785 GNUNET_break_op (0);
786 return;
787 }
788 /* Check for loops */
789 struct GNUNET_CONTAINER_MultiPeerMap *map;
790 map = GNUNET_CONTAINER_multipeermap_create (path_length * 2,
791 GNUNET_YES);
792 GNUNET_assert (NULL != map);
793 for (off = 0; off < path_length; off++) {
794 if (GNUNET_SYSERR ==
795 GNUNET_CONTAINER_multipeermap_put (map,
796 &pids[off],
797 NULL,
798 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) {
799 /* bogus request */
800 GNUNET_CONTAINER_multipeermap_destroy (map);
801 LOG (GNUNET_ERROR_TYPE_DEBUG,
802 "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
803 GNUNET_break_op (0);
804 return;
805 }
806 }
807 GNUNET_CONTAINER_multipeermap_destroy (map);
774 /* Initiator is at offset 0. */ 808 /* Initiator is at offset 0. */
775 for (off=1;off<path_length;off++) 809 for (off=1;off<path_length;off++)
776 if (0 == memcmp (&my_full_id, 810 if (0 == memcmp (&my_full_id,
@@ -779,7 +813,8 @@ handle_connection_create (void *cls,
779 break; 813 break;
780 if (off == path_length) 814 if (off == path_length)
781 { 815 {
782 /* We are not on the path, bogus request */ 816 LOG (GNUNET_ERROR_TYPE_DEBUG,
817 "Dropping CADET_CONNECTION_CREATE without us in the path\n");
783 GNUNET_break_op (0); 818 GNUNET_break_op (0);
784 return; 819 return;
785 } 820 }
@@ -787,7 +822,8 @@ handle_connection_create (void *cls,
787 if (sender != GCP_get (&pids[off - 1], 822 if (sender != GCP_get (&pids[off - 1],
788 GNUNET_NO)) 823 GNUNET_NO))
789 { 824 {
790 /* sender is not on the path, not allowed */ 825 LOG (GNUNET_ERROR_TYPE_DEBUG,
826 "Dropping CADET_CONNECTION_CREATE without sender in the path\n");
791 GNUNET_break_op (0); 827 GNUNET_break_op (0);
792 return; 828 return;
793 } 829 }
diff --git a/src/cadet/gnunet-service-cadet_paths.c b/src/cadet/gnunet-service-cadet_paths.c
index 7b90fe152..9dd6f1ddd 100644
--- a/src/cadet/gnunet-service-cadet_paths.c
+++ b/src/cadet/gnunet-service-cadet_paths.c
@@ -179,7 +179,7 @@ GCPP_del_connection (struct CadetPeerPath *path,
179 GCC_2s (cc), 179 GCC_2s (cc),
180 GCPP_2s (path), 180 GCPP_2s (path),
181 off); 181 off);
182 GNUNET_assert (off < path->entries_length); /* FIXME: #4909: This assertion fails sometimes! */ 182 GNUNET_assert (off < path->entries_length);
183 entry = path->entries[off]; 183 entry = path->entries[off];
184 GNUNET_assert (cc == entry->cc); 184 GNUNET_assert (cc == entry->cc);
185 entry->cc = NULL; 185 entry->cc = NULL;
@@ -187,33 +187,51 @@ GCPP_del_connection (struct CadetPeerPath *path,
187 187
188 188
189/** 189/**
190 * This path is no longer needed, free resources. 190 * Tries to attach @a path to a peer, working backwards from the end
191 * and stopping at @a stop_at. If path->hn is NULL on return then the
192 * path was not attached and you can assume that path->entries_length
193 * is equal to @a stop_at.
191 * 194 *
192 * @param path path resources to free 195 * @param path the path to attach
196 * @param stop_at the path length at which to stop trying
193 */ 197 */
194static void 198static void
195path_destroy (struct CadetPeerPath *path) 199attach_path (struct CadetPeerPath *path, unsigned int stop_at)
196{ 200{
197 LOG (GNUNET_ERROR_TYPE_DEBUG, 201 GNUNET_assert (NULL == path->hn);
198 "Destroying path %s\n", 202
199 GCPP_2s (path)); 203 /* Try to attach this path to a peer, working backwards from the end. */
200 for (unsigned int i=0;i<path->entries_length;i++) 204 while (path->entries_length > stop_at)
201 { 205 {
202 struct CadetPeerPathEntry *entry = path->entries[i]; 206 unsigned int end = path->entries_length - 1;
207 struct CadetPeerPathEntry *entry = path->entries[end];
208 int force = GNUNET_NO;
203 209
210 recalculate_path_desirability (path);
211 /* If the entry already has a connection using it, force attach. */
204 if (NULL != entry->cc) 212 if (NULL != entry->cc)
205 { 213 force = GNUNET_YES;
206 struct CadetTConnection *ct; 214 path->hn = GCP_attach_path (entry->peer,
215 path,
216 end,
217 force);
218 if (NULL != path->hn)
219 break;
207 220
208 ct = GCC_get_ct (entry->cc); 221 /* Attach failed, trim this entry from the path. */
209 if (NULL != ct) 222 GNUNET_assert (NULL == entry->cc);
210 GCT_connection_lost (ct); 223 GCP_path_entry_remove (entry->peer,
211 GCC_destroy_without_tunnel (entry->cc); 224 entry,
212 } 225 end);
213 GNUNET_free (entry); 226 GNUNET_free (entry);
227 path->entries[end] = NULL;
228 path->entries_length--;
214 } 229 }
215 GNUNET_free (path->entries); 230
216 GNUNET_free (path); 231 /* Shrink array to actual path length. */
232 GNUNET_array_grow (path->entries,
233 path->entries_length,
234 path->entries_length);
217} 235}
218 236
219 237
@@ -228,7 +246,6 @@ void
228GCPP_release (struct CadetPeerPath *path) 246GCPP_release (struct CadetPeerPath *path)
229{ 247{
230 struct CadetPeerPathEntry *entry; 248 struct CadetPeerPathEntry *entry;
231 int force;
232 249
233 LOG (GNUNET_ERROR_TYPE_DEBUG, 250 LOG (GNUNET_ERROR_TYPE_DEBUG,
234 "Owner releases path %s\n", 251 "Owner releases path %s\n",
@@ -236,34 +253,23 @@ GCPP_release (struct CadetPeerPath *path)
236 path->hn = NULL; 253 path->hn = NULL;
237 entry = path->entries[path->entries_length - 1]; 254 entry = path->entries[path->entries_length - 1];
238 GNUNET_assert (path == entry->path); 255 GNUNET_assert (path == entry->path);
239 while (1) 256 GNUNET_assert (NULL == entry->cc);
257 /* cut 'off' end of path */
258 GCP_path_entry_remove (entry->peer,
259 entry,
260 path->entries_length - 1);
261 GNUNET_free (entry);
262 path->entries[path->entries_length - 1] = NULL;
263 path->entries_length--;
264 /* see if new peer at the end likes this path any better */
265 attach_path (path, 0);
266 if (NULL == path->hn)
240 { 267 {
241 /* cut 'off' end of path */ 268 /* nobody wants us, discard the path */
242 GNUNET_assert (NULL == entry->cc); 269 GNUNET_assert (0 == path->entries_length);
243 GCP_path_entry_remove (entry->peer, 270 GNUNET_assert (NULL == path->entries);
244 entry, 271 GNUNET_free (path);
245 path->entries_length - 1);
246 path->entries_length--; /* We don't bother shrinking the 'entries' array,
247 as it's probably not worth it. */
248 GNUNET_free (entry);
249 if (0 == path->entries_length)
250 break; /* the end */
251
252 /* see if new peer at the end likes this path any better */
253 entry = path->entries[path->entries_length - 1];
254 GNUNET_assert (path == entry->path);
255 force = (NULL == entry->cc) ? GNUNET_NO : GNUNET_YES;
256 path->hn = GCP_attach_path (entry->peer,
257 path,
258 path->entries_length - 1,
259 force);
260 if (NULL != path->hn)
261 return; /* yep, got attached, we are done. */
262 GNUNET_assert (GNUNET_NO == force);
263 } 272 }
264
265 /* nobody wants us, discard the path */
266 path_destroy (path);
267} 273}
268 274
269 275
@@ -422,33 +428,13 @@ extend_path (struct CadetPeerPath *path,
422 path, 428 path,
423 path->hn); 429 path->hn);
424 path->hn = NULL; 430 path->hn = NULL;
425 for (i=num_peers-1;i>=0;i--) 431 path->entries_length = old_len + num_peers;
426 { 432 attach_path (path, old_len);
427 struct CadetPeerPathEntry *entry = path->entries[old_len + i];
428
429 path->entries_length = old_len + i + 1;
430 recalculate_path_desirability (path);
431 if (NULL != entry->cc)
432 force = GNUNET_YES;
433 path->hn = GCP_attach_path (peers[i],
434 path,
435 old_len + (unsigned int) i,
436 force);
437 if (NULL != path->hn)
438 break;
439 GCP_path_entry_remove (entry->peer,
440 entry,
441 old_len + i);
442 GNUNET_free (entry);
443 path->entries[old_len + i] = NULL;
444 }
445 if (NULL == path->hn) 433 if (NULL == path->hn)
446 { 434 {
447 /* none of the peers is interested in this path; 435 /* none of the peers is interested in this path;
448 shrink path back and re-attach. */ 436 re-attach. */
449 GNUNET_array_grow (path->entries, 437 GNUNET_assert (old_len == path->entries_length);
450 path->entries_length,
451 old_len);
452 path->hn = GCP_attach_path (path->entries[old_len - 1]->peer, 438 path->hn = GCP_attach_path (path->entries[old_len - 1]->peer,
453 path, 439 path,
454 old_len - 1, 440 old_len - 1,
@@ -483,7 +469,6 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
483 struct CadetPeer *cpath[get_path_length + put_path_length]; 469 struct CadetPeer *cpath[get_path_length + put_path_length];
484 struct CheckMatchContext cm_ctx; 470 struct CheckMatchContext cm_ctx;
485 struct CadetPeerPath *path; 471 struct CadetPeerPath *path;
486 struct GNUNET_CONTAINER_HeapNode *hn;
487 int i; 472 int i;
488 unsigned int skip; 473 unsigned int skip;
489 unsigned int total_len; 474 unsigned int total_len;
@@ -501,6 +486,14 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
501 pid = (off < get_path_length) 486 pid = (off < get_path_length)
502 ? &get_path[get_path_length - off - 1] 487 ? &get_path[get_path_length - off - 1]
503 : &put_path[get_path_length + put_path_length - off - 1]; 488 : &put_path[get_path_length + put_path_length - off - 1];
489 /* Check that I am not in the path */
490 if (0 == memcmp (&my_full_id,
491 pid,
492 sizeof (struct GNUNET_PeerIdentity)))
493 {
494 skip = off + 1;
495 continue;
496 }
504 cpath[off - skip] = GCP_get (pid, 497 cpath[off - skip] = GCP_get (pid,
505 GNUNET_YES); 498 GNUNET_YES);
506 /* Check that no peer is twice on the path */ 499 /* Check that no peer is twice on the path */
@@ -513,6 +506,12 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
513 } 506 }
514 } 507 }
515 } 508 }
509 if (skip >= total_len)
510 {
511 LOG (GNUNET_ERROR_TYPE_DEBUG,
512 "Path discovered from DHT is one big cycle?\n");
513 return;
514 }
516 total_len -= skip; 515 total_len -= skip;
517 516
518 /* First figure out if this path is a subset of an existing path, an 517 /* First figure out if this path is a subset of an existing path, an
@@ -573,39 +572,17 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
573 } 572 }
574 573
575 /* Finally, try to attach it */ 574 /* Finally, try to attach it */
576 hn = NULL; 575 attach_path (path, 0);
577 for (i=total_len-1;i>=0;i--) 576 if (NULL == path->hn)
578 {
579 struct CadetPeerPathEntry *entry = path->entries[i];
580
581 path->entries_length = i + 1;
582 recalculate_path_desirability (path);
583 hn = GCP_attach_path (cpath[i],
584 path,
585 (unsigned int) i,
586 GNUNET_NO);
587 if (NULL != hn)
588 break;
589 GCP_path_entry_remove (entry->peer,
590 entry,
591 i);
592 GNUNET_free (entry);
593 path->entries[i] = NULL;
594 }
595 if (NULL == hn)
596 { 577 {
597 /* None of the peers on the path care about it. */ 578 /* None of the peers on the path care about it. */
598 LOG (GNUNET_ERROR_TYPE_DEBUG, 579 LOG (GNUNET_ERROR_TYPE_DEBUG,
599 "Path discovered from DHT is not interesting to us\n"); 580 "Path discovered from DHT is not interesting to us\n");
600 GNUNET_free (path->entries); 581 GNUNET_assert (0 == path->entries_length);
582 GNUNET_assert (NULL == path->entries);
601 GNUNET_free (path); 583 GNUNET_free (path);
602 return; 584 return;
603 } 585 }
604 path->hn = hn;
605 /* Shrink path to actual useful length */
606 GNUNET_array_grow (path->entries,
607 path->entries_length,
608 i + 1);
609 LOG (GNUNET_ERROR_TYPE_DEBUG, 586 LOG (GNUNET_ERROR_TYPE_DEBUG,
610 "Created new path %s based on information from DHT\n", 587 "Created new path %s based on information from DHT\n",
611 GCPP_2s (path)); 588 GCPP_2s (path));
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
index c4e2c0ccf..da78a03c4 100644
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ b/src/cadet/gnunet-service-cadet_peer.c
@@ -532,49 +532,32 @@ GCP_set_mq (struct CadetPeer *cp,
532 GCP_2s (cp), 532 GCP_2s (cp),
533 mq); 533 mq);
534 cp->core_mq = mq; 534 cp->core_mq = mq;
535 /* Since these callbacks can remove any items from this list, we must take a 535 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
536 * snapshot and then test each one to see if it's still in the list. */
537 int count = 0;
538 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
539 NULL != mqm; 536 NULL != mqm;
540 mqm = mqm->next) 537 mqm = next)
541 ++count;
542 struct GCP_MessageQueueManager *mqms[count];
543 int i = 0;
544 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
545 NULL != mqm;
546 mqm = mqm->next)
547 mqms[i++] = mqm;
548 for (i = 0; i < count; ++i)
549 { 538 {
550 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head; 539 /* Save next pointer in case mqm gets freed by the callback */
551 NULL != mqm; 540 next = mqm->next;
552 mqm = mqm->next) 541 if (NULL == mq)
553 { 542 {
554 if (mqms[i] != mqm) 543 if (NULL != mqm->env)
555 continue;
556 if (NULL == mq)
557 { 544 {
558 if (NULL != mqm->env) 545 GNUNET_MQ_discard (mqm->env);
559 { 546 mqm->env = NULL;
560 GNUNET_MQ_discard (mqm->env); 547 mqm->cb (mqm->cb_cls,
561 mqm->env = NULL; 548 GNUNET_SYSERR);
562 mqm->cb (mqm->cb_cls,
563 GNUNET_SYSERR);
564 }
565 else
566 {
567 mqm->cb (mqm->cb_cls,
568 GNUNET_NO);
569 }
570 } 549 }
571 else 550 else
572 { 551 {
573 GNUNET_assert (NULL == mqm->env);
574 mqm->cb (mqm->cb_cls, 552 mqm->cb (mqm->cb_cls,
575 GNUNET_YES); 553 GNUNET_NO);
576 } 554 }
577 break; 555 }
556 else
557 {
558 GNUNET_assert (NULL == mqm->env);
559 mqm->cb (mqm->cb_cls,
560 GNUNET_YES);
578 } 561 }
579 } 562 }
580 if ( (NULL != mq) || 563 if ( (NULL != mq) ||
@@ -996,7 +979,7 @@ GCP_attach_path (struct CadetPeer *cp,
996 (desirability < root_desirability) ) 979 (desirability < root_desirability) )
997 { 980 {
998 LOG (GNUNET_ERROR_TYPE_DEBUG, 981 LOG (GNUNET_ERROR_TYPE_DEBUG,
999 "Decided to not attach path %p to peer %s due to undesirability\n", 982 "Decided to not attach path %s to peer %s due to undesirability\n",
1000 GCPP_2s (path), 983 GCPP_2s (path),
1001 GCP_2s (cp)); 984 GCP_2s (cp));
1002 return NULL; 985 return NULL;
diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c
index 22e19ef70..fb91a4a6a 100644
--- a/src/cadet/gnunet-service-cadet_tunnels.c
+++ b/src/cadet/gnunet-service-cadet_tunnels.c
@@ -2856,7 +2856,9 @@ handle_plaintext_channel_destroy (void *cls,
2856 * 2856 *
2857 * @param cls the `struct CadetTunnel` that got the message 2857 * @param cls the `struct CadetTunnel` that got the message
2858 * @param msg the message 2858 * @param msg the message
2859 * @return #GNUNET_OK (continue to process) 2859 * @return #GNUNET_OK on success (always)
2860 * #GNUNET_NO to stop further processing (no error)
2861 * #GNUNET_SYSERR to stop further processing with error
2860 */ 2862 */
2861static int 2863static int
2862handle_decrypted (void *cls, 2864handle_decrypted (void *cls,
diff --git a/src/cadet/test_cadet.c b/src/cadet/test_cadet.c
index 72df2203c..b9f177652 100644
--- a/src/cadet/test_cadet.c
+++ b/src/cadet/test_cadet.c
@@ -58,6 +58,11 @@ struct CadetTestChannelWrapper
58#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) 58#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
59 59
60/** 60/**
61 * How fast do we send messages?
62 */
63#define SEND_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10)
64
65/**
61 * DIFFERENT TESTS TO RUN 66 * DIFFERENT TESTS TO RUN
62 */ 67 */
63#define SETUP 0 68#define SETUP 0
@@ -269,12 +274,20 @@ show_end_data (void)
269 274
270 end_time = GNUNET_TIME_absolute_get (); 275 end_time = GNUNET_TIME_absolute_get ();
271 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time); 276 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
272 FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); 277 FPRINTF (stderr,
273 FPRINTF (stderr, "Test time %s\n", 278 "\nResults of test \"%s\"\n",
279 test_name);
280 FPRINTF (stderr,
281 "Test time %s\n",
274 GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES)); 282 GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES));
275 FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms 283 FPRINTF (stderr,
276 FPRINTF (stderr, "Test throughput: %f packets/s\n\n", total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms 284 "Test bandwidth: %f kb/s\n",
277 GAUGER ("CADET", test_name, 285 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
286 FPRINTF (stderr,
287 "Test throughput: %f packets/s\n\n",
288 total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
289 GAUGER ("CADET",
290 test_name,
278 total_packets * 1000.0 / (total_time.rel_value_us / 1000), 291 total_packets * 1000.0 / (total_time.rel_value_us / 1000),
279 "packets/s"); 292 "packets/s");
280} 293}
@@ -290,13 +303,12 @@ static void
290disconnect_cadet_peers (void *cls) 303disconnect_cadet_peers (void *cls)
291{ 304{
292 long line = (long) cls; 305 long line = (long) cls;
293 unsigned int i;
294 306
295 disconnect_task = NULL; 307 disconnect_task = NULL;
296 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 308 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
297 "disconnecting cadet service of peers, called from line %ld\n", 309 "disconnecting cadet service of peers, called from line %ld\n",
298 line); 310 line);
299 for (i = 0; i < 2; i++) 311 for (unsigned int i = 0; i < 2; i++)
300 { 312 {
301 GNUNET_TESTBED_operation_done (t_op[i]); 313 GNUNET_TESTBED_operation_done (t_op[i]);
302 } 314 }
@@ -324,7 +336,8 @@ disconnect_cadet_peers (void *cls)
324static void 336static void
325shutdown_task (void *cls) 337shutdown_task (void *cls)
326{ 338{
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); 339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
340 "Ending test.\n");
328 if (NULL != send_next_msg_task) 341 if (NULL != send_next_msg_task)
329 { 342 {
330 GNUNET_SCHEDULER_cancel (send_next_msg_task); 343 GNUNET_SCHEDULER_cancel (send_next_msg_task);
@@ -339,7 +352,8 @@ shutdown_task (void *cls)
339 { 352 {
340 GNUNET_SCHEDULER_cancel (disconnect_task); 353 GNUNET_SCHEDULER_cancel (disconnect_task);
341 disconnect_task = 354 disconnect_task =
342 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) __LINE__); 355 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
356 (void *) __LINE__);
343 } 357 }
344} 358}
345 359
@@ -354,10 +368,14 @@ shutdown_task (void *cls)
354 * operation has executed successfully. 368 * operation has executed successfully.
355 */ 369 */
356static void 370static void
357stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) 371stats_cont (void *cls,
372 struct GNUNET_TESTBED_Operation *op,
373 const char *emsg)
358{ 374{
359 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n", 375 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
360 ka_sent, ka_received); 376 "KA sent: %u, KA received: %u\n",
377 ka_sent,
378 ka_received);
361 if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1))) 379 if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1)))
362 { 380 {
363 GNUNET_break (0); 381 GNUNET_break (0);
@@ -367,7 +385,8 @@ stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
367 385
368 if (NULL != disconnect_task) 386 if (NULL != disconnect_task)
369 GNUNET_SCHEDULER_cancel (disconnect_task); 387 GNUNET_SCHEDULER_cancel (disconnect_task);
370 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, cls); 388 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
389 cls);
371} 390}
372 391
373 392
@@ -438,7 +457,6 @@ gather_stats_and_exit (void *cls)
438} 457}
439 458
440 459
441
442/** 460/**
443 * Abort test: schedule disconnect and shutdown immediately 461 * Abort test: schedule disconnect and shutdown immediately
444 * 462 *
@@ -450,9 +468,12 @@ abort_test (long line)
450 if (NULL != disconnect_task) 468 if (NULL != disconnect_task)
451 { 469 {
452 GNUNET_SCHEDULER_cancel (disconnect_task); 470 GNUNET_SCHEDULER_cancel (disconnect_task);
453 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line); 471 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
472 "Aborting test from %ld\n",
473 line);
454 disconnect_task = 474 disconnect_task =
455 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) line); 475 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
476 (void *) line);
456 } 477 }
457} 478}
458 479
@@ -525,6 +546,7 @@ send_test_message (struct GNUNET_CADET_Channel *channel)
525 GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env); 546 GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env);
526} 547}
527 548
549
528/** 550/**
529 * Task to request a new data transmission in a SPEED test, without waiting 551 * Task to request a new data transmission in a SPEED test, without waiting
530 * for previous messages to be sent/arrrive. 552 * for previous messages to be sent/arrrive.
@@ -537,7 +559,9 @@ send_next_msg (void *cls)
537 struct GNUNET_CADET_Channel *channel; 559 struct GNUNET_CADET_Channel *channel;
538 560
539 send_next_msg_task = NULL; 561 send_next_msg_task = NULL;
540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending next message: %d\n", data_sent); 562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
563 "Sending next message: %d\n",
564 data_sent);
541 565
542 channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch; 566 channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch;
543 GNUNET_assert (NULL != channel); 567 GNUNET_assert (NULL != channel);
@@ -550,9 +574,9 @@ send_next_msg (void *cls)
550 "Scheduling message %d\n", 574 "Scheduling message %d\n",
551 data_sent + 1); 575 data_sent + 1);
552 send_next_msg_task = 576 send_next_msg_task =
553 GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, 577 GNUNET_SCHEDULER_add_delayed (SEND_INTERVAL,
554 &send_next_msg, 578 &send_next_msg,
555 NULL); 579 NULL);
556 } 580 }
557} 581}
558 582
@@ -571,7 +595,7 @@ reschedule_timeout_task (long line)
571 if (NULL != disconnect_task) 595 if (NULL != disconnect_task)
572 { 596 {
573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
574 " reschedule timeout every 10 messages\n"); 598 "reschedule timeout every 10 messages\n");
575 GNUNET_SCHEDULER_cancel (disconnect_task); 599 GNUNET_SCHEDULER_cancel (disconnect_task);
576 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time, 600 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
577 &gather_stats_and_exit, 601 &gather_stats_and_exit,
@@ -605,7 +629,8 @@ check_data (void *cls, const struct GNUNET_MessageHeader *message)
605 * @param message the actual message 629 * @param message the actual message
606 */ 630 */
607static void 631static void
608handle_data (void *cls, const struct GNUNET_MessageHeader *message) 632handle_data (void *cls,
633 const struct GNUNET_MessageHeader *message)
609{ 634{
610 struct CadetTestChannelWrapper *ch = cls; 635 struct CadetTestChannelWrapper *ch = cls;
611 struct GNUNET_CADET_Channel *channel = ch->ch; 636 struct GNUNET_CADET_Channel *channel = ch->ch;
@@ -770,19 +795,21 @@ connect_handler (void *cls, struct GNUNET_CADET_Channel *channel,
770 * @param channel Connection to the other end (henceforth invalid). 795 * @param channel Connection to the other end (henceforth invalid).
771 */ 796 */
772static void 797static void
773disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel) 798disconnect_handler (void *cls,
799 const struct GNUNET_CADET_Channel *channel)
774{ 800{
775 struct CadetTestChannelWrapper *ch_w = cls; 801 struct CadetTestChannelWrapper *ch_w = cls;
776 802
777 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Channel disconnected\n"); 803 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
804 "Channel disconnected at %d\n",
805 ok);
778 GNUNET_assert (ch_w->ch == channel); 806 GNUNET_assert (ch_w->ch == channel);
779 if (channel == incoming_ch) 807 if (channel == incoming_ch)
780 { 808 {
781 ok++; 809 ok++;
782 incoming_ch = NULL; 810 incoming_ch = NULL;
783 } 811 }
784 else if (outgoing_ch == channel 812 else if (outgoing_ch == channel)
785 )
786 { 813 {
787 if (P2P_SIGNAL == test) 814 if (P2P_SIGNAL == test)
788 { 815 {
@@ -791,15 +818,17 @@ disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel)
791 outgoing_ch = NULL; 818 outgoing_ch = NULL;
792 } 819 }
793 else 820 else
794 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown channel! %p\n", channel); 821 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
795 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); 822 "Unknown channel! %p\n",
796 823 channel);
797 if (NULL != disconnect_task) 824 if (NULL != disconnect_task)
798 { 825 {
799 GNUNET_SCHEDULER_cancel (disconnect_task); 826 GNUNET_SCHEDULER_cancel (disconnect_task);
800 disconnect_task = 827 disconnect_task =
801 GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, (void *) __LINE__); 828 GNUNET_SCHEDULER_add_now (&gather_stats_and_exit,
829 (void *) __LINE__);
802 } 830 }
831 GNUNET_free (ch_w);
803} 832}
804 833
805 834
@@ -879,25 +908,34 @@ start_test (void *cls)
879 * NULL if the operation is successfull 908 * NULL if the operation is successfull
880 */ 909 */
881static void 910static void
882pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op, 911pi_cb (void *cls,
883 const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) 912 struct GNUNET_TESTBED_Operation *op,
913 const struct GNUNET_TESTBED_PeerInformation *pinfo,
914 const char *emsg)
884{ 915{
885 long i = (long) cls; 916 long i = (long) cls;
886 917
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ID callback for %ld\n", i); 918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
888 919 "ID callback for %ld\n",
889 if ((NULL == pinfo) || (NULL != emsg)) 920 i);
921 if ( (NULL == pinfo) ||
922 (NULL != emsg) )
890 { 923 {
891 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); 924 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
925 "pi_cb: %s\n",
926 emsg);
892 abort_test (__LINE__); 927 abort_test (__LINE__);
893 return; 928 return;
894 } 929 }
895 p_id[i] = pinfo->result.id; 930 p_id[i] = pinfo->result.id;
896 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); 931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
932 "id: %s\n",
933 GNUNET_i2s (p_id[i]));
897 p_ids++; 934 p_ids++;
898 if (p_ids < 2) 935 if (p_ids < 2)
899 return; 936 return;
900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); 937 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
938 "Got all IDs, starting test\n");
901 test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL); 939 test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL);
902} 940}
903 941
@@ -929,7 +967,8 @@ tmain (void *cls,
929 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time, 967 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
930 &disconnect_cadet_peers, 968 &disconnect_cadet_peers,
931 (void *) __LINE__); 969 (void *) __LINE__);
932 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); 970 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
971 NULL);
933 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], 972 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
934 GNUNET_TESTBED_PIT_IDENTITY, 973 GNUNET_TESTBED_PIT_IDENTITY,
935 &pi_cb, 974 &pi_cb,
@@ -960,16 +999,16 @@ main (int argc, char *argv[])
960 char port_id[] = "test port"; 999 char port_id[] = "test port";
961 struct GNUNET_GETOPT_CommandLineOption options[] = { 1000 struct GNUNET_GETOPT_CommandLineOption options[] = {
962 GNUNET_GETOPT_option_relative_time ('t', 1001 GNUNET_GETOPT_option_relative_time ('t',
963 "time", 1002 "time",
964 "short_time", 1003 "short_time",
965 gettext_noop ("set short timeout"), 1004 gettext_noop ("set short timeout"),
966 &short_time), 1005 &short_time),
967 1006
968 GNUNET_GETOPT_option_uint ('m', 1007 GNUNET_GETOPT_option_uint ('m',
969 "messages", 1008 "messages",
970 "NUM_MESSAGES", 1009 "NUM_MESSAGES",
971 gettext_noop ("set number of messages to send"), 1010 gettext_noop ("set number of messages to send"),
972 &total_packets), 1011 &total_packets),
973 1012
974 GNUNET_GETOPT_OPTION_END 1013 GNUNET_GETOPT_OPTION_END
975 }; 1014 };
diff --git a/src/conversation/gnunet-helper-audio-playback-gst.c b/src/conversation/gnunet-helper-audio-playback-gst.c
index 264b14e76..002fed6c7 100644
--- a/src/conversation/gnunet-helper-audio-playback-gst.c
+++ b/src/conversation/gnunet-helper-audio-playback-gst.c
@@ -221,6 +221,11 @@ feed_buffer_to_gst (const char *audio, size_t b_len)
221 221
222/** 222/**
223 * Message callback 223 * Message callback
224 *
225 * @param msg message we received.
226 * @return #GNUNET_OK on success,
227 * #GNUNET_NO to stop further processing due to disconnect (no error)
228 * #GNUNET_SYSERR to stop further processing due to error
224 */ 229 */
225static int 230static int
226stdin_receiver (void *cls, 231stdin_receiver (void *cls,
diff --git a/src/conversation/gnunet-helper-audio-playback.c b/src/conversation/gnunet-helper-audio-playback.c
index 4344e1d41..18f63ad18 100644
--- a/src/conversation/gnunet-helper-audio-playback.c
+++ b/src/conversation/gnunet-helper-audio-playback.c
@@ -546,6 +546,11 @@ ogg_demux_and_decode ()
546 546
547/** 547/**
548 * Message callback 548 * Message callback
549 *
550 * @param msg message we received.
551 * @return #GNUNET_OK on success,
552 * #GNUNET_NO to stop further processing due to disconnect (no error)
553 * #GNUNET_SYSERR to stop further processing due to error
549 */ 554 */
550static int 555static int
551stdin_receiver (void *cls, 556stdin_receiver (void *cls,
diff --git a/src/conversation/gnunet_gst.c b/src/conversation/gnunet_gst.c
index 52cb2ccbc..828b35077 100644
--- a/src/conversation/gnunet_gst.c
+++ b/src/conversation/gnunet_gst.c
@@ -649,6 +649,11 @@ gnunet_read (GNUNET_gstData * d)
649 649
650/** 650/**
651 * Message callback 651 * Message callback
652 *
653 * @param msg message we received.
654 * @return #GNUNET_OK on success,
655 * #GNUNET_NO to stop further processing due to disconnect (no error)
656 * #GNUNET_SYSERR to stop further processing due to error
652 */ 657 */
653static int 658static int
654stdin_receiver (void *cls, 659stdin_receiver (void *cls,
diff --git a/src/conversation/microphone.c b/src/conversation/microphone.c
index 7871433a3..11468fc59 100644
--- a/src/conversation/microphone.c
+++ b/src/conversation/microphone.c
@@ -65,7 +65,9 @@ struct Microphone
65 * 65 *
66 * @param cls clsoure with our `struct Microphone` 66 * @param cls clsoure with our `struct Microphone`
67 * @param msg the message from the helper 67 * @param msg the message from the helper
68 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 68 * @return #GNUNET_OK on success,
69 * #GNUNET_NO to stop further processing (no error)
70 * #GNUNET_SYSERR to stop further processing with error
69 */ 71 */
70static int 72static int
71process_record_messages (void *cls, 73process_record_messages (void *cls,
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 625bf9655..214f72904 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -426,6 +426,9 @@ struct TokenizerContext
426 * 426 *
427 * @param cls reservation request (`struct TokenizerContext`) 427 * @param cls reservation request (`struct TokenizerContext`)
428 * @param message the actual message 428 * @param message the actual message
429 * @return #GNUNET_OK on success,
430 * #GNUNET_NO to stop further processing (no error)
431 * #GNUNET_SYSERR to stop further processing with error
429 */ 432 */
430static int 433static int
431tokenized_cb (void *cls, 434tokenized_cb (void *cls,
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c
index 8a7cada5c..944d1e692 100644
--- a/src/core/gnunet-service-core_kx.c
+++ b/src/core/gnunet-service-core_kx.c
@@ -708,6 +708,9 @@ setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
708 * 708 *
709 * @param cls the `struct GSC_KeyExchangeInfo` 709 * @param cls the `struct GSC_KeyExchangeInfo`
710 * @param m the message 710 * @param m the message
711 * @return #GNUNET_OK on success,
712 * #GNUNET_NO to stop further processing (no error)
713 * #GNUNET_SYSERR to stop further processing with error
711 */ 714 */
712static int 715static int
713deliver_message (void *cls, 716deliver_message (void *cls,
@@ -950,7 +953,7 @@ handle_ephemeral_key (void *cls,
950 kx->peer, 953 kx->peer,
951 sizeof (struct GNUNET_PeerIdentity))) 954 sizeof (struct GNUNET_PeerIdentity)))
952 { 955 {
953 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 956 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
954 "Received EPHEMERAL_KEY from %s, but expected %s\n", 957 "Received EPHEMERAL_KEY from %s, but expected %s\n",
955 GNUNET_i2s (&m->origin_identity), 958 GNUNET_i2s (&m->origin_identity),
956 GNUNET_i2s_full (kx->peer)); 959 GNUNET_i2s_full (kx->peer));
diff --git a/src/core/gnunet-service-core_sessions.c b/src/core/gnunet-service-core_sessions.c
index 5d34b7c26..babf169c0 100644
--- a/src/core/gnunet-service-core_sessions.c
+++ b/src/core/gnunet-service-core_sessions.c
@@ -147,12 +147,6 @@ struct Session
147 struct GNUNET_TIME_Relative typemap_delay; 147 struct GNUNET_TIME_Relative typemap_delay;
148 148
149 /** 149 /**
150 * Is the neighbour queue empty and thus ready for us
151 * to transmit an encrypted message?
152 */
153 int ready_to_transmit;
154
155 /**
156 * Is this the first time we're sending the typemap? If so, 150 * Is this the first time we're sending the typemap? If so,
157 * we want to send it a bit faster the second time. 0 if 151 * we want to send it a bit faster the second time. 0 if
158 * we are sending for the first time, 1 if not. 152 * we are sending for the first time, 1 if not.
@@ -641,13 +635,7 @@ try_transmission (struct Session *session)
641 enum GNUNET_CORE_Priority maxpc; 635 enum GNUNET_CORE_Priority maxpc;
642 struct GSC_ClientActiveRequest *car; 636 struct GSC_ClientActiveRequest *car;
643 int excess; 637 int excess;
644 638
645 if (GNUNET_YES != session->ready_to_transmit)
646 {
647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
648 "Not yet ready to transmit, not evaluating queue\n");
649 return;
650 }
651 msize = 0; 639 msize = 0;
652 min_deadline = GNUNET_TIME_UNIT_FOREVER_ABS; 640 min_deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
653 /* if the peer has excess bandwidth, background traffic is allowed, 641 /* if the peer has excess bandwidth, background traffic is allowed,
@@ -801,7 +789,6 @@ try_transmission (struct Session *session)
801 total_bytes / total_msgs, 789 total_bytes / total_msgs,
802 GNUNET_NO); 790 GNUNET_NO);
803 /* now actually transmit... */ 791 /* now actually transmit... */
804 session->ready_to_transmit = GNUNET_NO;
805 GSC_KX_encrypt_and_transmit (session->kx, 792 GSC_KX_encrypt_and_transmit (session->kx,
806 pbuf, 793 pbuf,
807 used); 794 used);
@@ -888,10 +875,12 @@ GSC_SESSIONS_solicit (const struct GNUNET_PeerIdentity *pid)
888{ 875{
889 struct Session *session; 876 struct Session *session;
890 877
878 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
879 "Transport solicits for %s\n",
880 GNUNET_i2s (pid));
891 session = find_session (pid); 881 session = find_session (pid);
892 if (NULL == session) 882 if (NULL == session)
893 return; 883 return;
894 session->ready_to_transmit = GNUNET_YES;
895 try_transmission (session); 884 try_transmission (session);
896} 885}
897 886
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index 4a78ea4c7..d60ff62d6 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -197,6 +197,7 @@ test_dht_monitor_LDADD = \
197 197
198EXTRA_DIST = \ 198EXTRA_DIST = \
199 $(check_SCRIPTS) \ 199 $(check_SCRIPTS) \
200 gnunet-service-dht_clients.c \
200 test_dht_api_data.conf \ 201 test_dht_api_data.conf \
201 test_dht_api_peer1.conf \ 202 test_dht_api_peer1.conf \
202 test_dht_monitor.conf \ 203 test_dht_monitor.conf \
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index f2b922dc4..829c53aea 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -55,7 +55,6 @@ static struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
55struct GNUNET_TIME_Relative hello_expiration; 55struct GNUNET_TIME_Relative hello_expiration;
56 56
57 57
58/* Code shared between different DHT implementations */
59#include "gnunet-service-dht_clients.c" 58#include "gnunet-service-dht_clients.c"
60 59
61 60
diff --git a/src/fs/fs_dirmetascan.c b/src/fs/fs_dirmetascan.c
index 7b9f178fd..8a3e37b49 100644
--- a/src/fs/fs_dirmetascan.c
+++ b/src/fs/fs_dirmetascan.c
@@ -246,6 +246,9 @@ finish_scan (void *cls)
246 * 246 *
247 * @param cls the closure (directory scanner object) 247 * @param cls the closure (directory scanner object)
248 * @param msg message from the helper process 248 * @param msg message from the helper process
249 * @return #GNUNET_OK on success,
250 * #GNUNET_NO to stop further processing (no error)
251 * #GNUNET_SYSERR to stop further processing with error
249 */ 252 */
250static int 253static int
251process_helper_msgs (void *cls, 254process_helper_msgs (void *cls,
diff --git a/src/fs/test_fs_download_persistence.c b/src/fs/test_fs_download_persistence.c
index 76a1ea911..8f27e82af 100644
--- a/src/fs/test_fs_download_persistence.c
+++ b/src/fs/test_fs_download_persistence.c
@@ -179,7 +179,6 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event)
179 GNUNET_FS_DOWNLOAD_OPTION_NONE, "download", NULL); 179 GNUNET_FS_DOWNLOAD_OPTION_NONE, "download", NULL);
180 break; 180 break;
181 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: 181 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
182 consider_restart (event->status);
183 printf ("Download complete, %llu kbps.\n", 182 printf ("Download complete, %llu kbps.\n",
184 (unsigned long long) (FILESIZE * 1000000LL / 183 (unsigned long long) (FILESIZE * 1000000LL /
185 (1 + 184 (1 +
diff --git a/src/fs/test_fs_publish_persistence.c b/src/fs/test_fs_publish_persistence.c
index be9006d42..103ca01b8 100644
--- a/src/fs/test_fs_publish_persistence.c
+++ b/src/fs/test_fs_publish_persistence.c
@@ -134,7 +134,6 @@ progress_cb (void *cls,
134 switch (event->status) 134 switch (event->status)
135 { 135 {
136 case GNUNET_FS_STATUS_PUBLISH_COMPLETED: 136 case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
137 consider_restart (event->status);
138 ret = event->value.publish.cctx; 137 ret = event->value.publish.cctx;
139 printf ("Publish complete, %llu kbps.\n", 138 printf ("Publish complete, %llu kbps.\n",
140 (unsigned long long) (FILESIZE * 1000000LL / 139 (unsigned long long) (FILESIZE * 1000000LL /
diff --git a/src/hello/hello.c b/src/hello/hello.c
index 27580275f..690a0961a 100644
--- a/src/hello/hello.c
+++ b/src/hello/hello.c
@@ -271,7 +271,10 @@ GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg,
271 msize = GNUNET_HELLO_size (msg); 271 msize = GNUNET_HELLO_size (msg);
272 if ((msize < sizeof (struct GNUNET_HELLO_Message)) || 272 if ((msize < sizeof (struct GNUNET_HELLO_Message)) ||
273 (ntohs (msg->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) 273 (ntohs (msg->header.type) != GNUNET_MESSAGE_TYPE_HELLO))
274 {
275 GNUNET_break_op (0);
274 return NULL; 276 return NULL;
277 }
275 ret = NULL; 278 ret = NULL;
276 if (return_modified) 279 if (return_modified)
277 { 280 {
@@ -285,6 +288,10 @@ GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg,
285 wpos = 0; 288 wpos = 0;
286 woff = (NULL != ret) ? (char *) &ret[1] : NULL; 289 woff = (NULL != ret) ? (char *) &ret[1] : NULL;
287 address.peer.public_key = msg->publicKey; 290 address.peer.public_key = msg->publicKey;
291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
292 "HELLO has %u bytes of address data\n",
293 (unsigned int) insize);
294
288 while (insize > 0) 295 while (insize > 0)
289 { 296 {
290 esize = get_hello_address_size (inptr, 297 esize = get_hello_address_size (inptr,
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index e5abec416..08e9dd156 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -33,6 +33,7 @@ gnunetinclude_HEADERS = \
33 gnunet_bandwidth_lib.h \ 33 gnunet_bandwidth_lib.h \
34 gnunet_bio_lib.h \ 34 gnunet_bio_lib.h \
35 gnunet_block_lib.h \ 35 gnunet_block_lib.h \
36 gnunet_block_group_lib.h \
36 gnunet_block_plugin.h \ 37 gnunet_block_plugin.h \
37 gnunet_client_lib.h \ 38 gnunet_client_lib.h \
38 gnunet_common.h \ 39 gnunet_common.h \
@@ -65,7 +66,10 @@ gnunetinclude_HEADERS = \
65 gnunet_hello_lib.h \ 66 gnunet_hello_lib.h \
66 gnunet_helper_lib.h \ 67 gnunet_helper_lib.h \
67 gnunet_identity_service.h \ 68 gnunet_identity_service.h \
69 gnunet_identity_provider_service.h \
68 gnunet_json_lib.h \ 70 gnunet_json_lib.h \
71 gnunet_jsonapi_lib.h \
72 gnunet_jsonapi_util.h \
69 gnunet_load_lib.h \ 73 gnunet_load_lib.h \
70 gnunet_cadet_service.h \ 74 gnunet_cadet_service.h \
71 gnunet_microphone_lib.h \ 75 gnunet_microphone_lib.h \
@@ -102,6 +106,8 @@ gnunetinclude_HEADERS = \
102 gnunet_protocols.h \ 106 gnunet_protocols.h \
103 gnunet_resolver_service.h \ 107 gnunet_resolver_service.h \
104 gnunet_regex_service.h \ 108 gnunet_regex_service.h \
109 gnunet_rest_lib.h \
110 gnunet_rest_plugin.h \
105 gnunet_revocation_service.h \ 111 gnunet_revocation_service.h \
106 gnunet_scalarproduct_service.h \ 112 gnunet_scalarproduct_service.h \
107 gnunet_scheduler_lib.h \ 113 gnunet_scheduler_lib.h \
@@ -111,6 +117,7 @@ gnunetinclude_HEADERS = \
111 gnunet_signal_lib.h \ 117 gnunet_signal_lib.h \
112 gnunet_signatures.h \ 118 gnunet_signatures.h \
113 gnunet_social_service.h \ 119 gnunet_social_service.h \
120 gnunet_socks.h \
114 gnunet_speaker_lib.h \ 121 gnunet_speaker_lib.h \
115 gnunet_sq_lib.h \ 122 gnunet_sq_lib.h \
116 gnunet_statistics_service.h \ 123 gnunet_statistics_service.h \
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index d7f7b76ff..7d23e6f9b 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -988,7 +988,8 @@ GNUNET_ntoh_double (double d);
988 * arr is important since size is the number of elements and 988 * arr is important since size is the number of elements and
989 * not the size in bytes 989 * not the size in bytes
990 * @param size the number of elements in the existing vector (number 990 * @param size the number of elements in the existing vector (number
991 * of elements to copy over) 991 * of elements to copy over), will be updated with the new
992 * array size
992 * @param tsize the target size for the resulting vector, use 0 to 993 * @param tsize the target size for the resulting vector, use 0 to
993 * free the vector (then, arr will be NULL afterwards). 994 * free the vector (then, arr will be NULL afterwards).
994 */ 995 */
@@ -996,8 +997,16 @@ GNUNET_ntoh_double (double d);
996 997
997/** 998/**
998 * @ingroup memory 999 * @ingroup memory
999 * Append an element to a list (growing the 1000 * Append an element to a list (growing the list by one).
1000 * list by one). 1001 *
1002 * @param arr base-pointer of the vector, may be NULL if size is 0;
1003 * will be updated to reflect the new address. The TYPE of
1004 * arr is important since size is the number of elements and
1005 * not the size in bytes
1006 * @param size the number of elements in the existing vector (number
1007 * of elements to copy over), will be updated with the new
1008 * array size
1009 * @param element the element that will be appended to the array
1001 */ 1010 */
1002#define GNUNET_array_append(arr,size,element) do { GNUNET_array_grow(arr,size,size+1); arr[size-1] = element; } while(0) 1011#define GNUNET_array_append(arr,size,element) do { GNUNET_array_grow(arr,size,size+1); arr[size-1] = element; } while(0)
1003 1012
diff --git a/src/include/gnunet_mst_lib.h b/src/include/gnunet_mst_lib.h
index 7a1ca7a55..fe6524eb3 100644
--- a/src/include/gnunet_mst_lib.h
+++ b/src/include/gnunet_mst_lib.h
@@ -61,7 +61,9 @@ struct GNUNET_MessageStreamTokenizer;
61 * 61 *
62 * @param cls closure 62 * @param cls closure
63 * @param message the actual message 63 * @param message the actual message
64 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing 64 * @return #GNUNET_OK on success,
65 * #GNUNET_NO to stop further processing due to disconnect (no error)
66 * #GNUNET_SYSERR to stop further processing due to error
65 */ 67 */
66typedef int 68typedef int
67(*GNUNET_MessageTokenizerCallback) (void *cls, 69(*GNUNET_MessageTokenizerCallback) (void *cls,
diff --git a/src/include/gnunet_network_lib.h b/src/include/gnunet_network_lib.h
index d9d3d90e7..9e692bbbf 100644
--- a/src/include/gnunet_network_lib.h
+++ b/src/include/gnunet_network_lib.h
@@ -464,7 +464,7 @@ GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
464 * @return POSIX file descriptor 464 * @return POSIX file descriptor
465 */ 465 */
466int 466int
467GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc); 467GNUNET_NETWORK_get_fd (const struct GNUNET_NETWORK_Handle *desc);
468 468
469 469
470/** 470/**
@@ -474,7 +474,7 @@ GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc);
474 * @return POSIX file descriptor 474 * @return POSIX file descriptor
475 */ 475 */
476struct sockaddr* 476struct sockaddr*
477GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc); 477GNUNET_NETWORK_get_addr (const struct GNUNET_NETWORK_Handle *desc);
478 478
479 479
480/** 480/**
@@ -484,7 +484,7 @@ GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc);
484 * @return socklen_t for sockaddr 484 * @return socklen_t for sockaddr
485 */ 485 */
486socklen_t 486socklen_t
487GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc); 487GNUNET_NETWORK_get_addrlen (const struct GNUNET_NETWORK_Handle *desc);
488 488
489 489
490/** 490/**
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 6710d749f..436adc5a4 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2067,7 +2067,11 @@ extern "C"
2067/** S->C: slave join acknowledgement */ 2067/** S->C: slave join acknowledgement */
2068#define GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK 684 2068#define GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK 684
2069 2069
2070/* 685-686 */ 2070/** C->S: request to part from a channel */
2071#define GNUNET_MESSAGE_TYPE_PSYC_PART_REQUEST 685
2072
2073/** S->C: acknowledgement that a slave of master parted from a channel */
2074#define GNUNET_MESSAGE_TYPE_PSYC_PART_ACK 686
2071 2075
2072/** M->S->C: incoming join request from multicast */ 2076/** M->S->C: incoming join request from multicast */
2073#define GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST 687 2077#define GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST 687
@@ -2258,6 +2262,7 @@ extern "C"
2258 */ 2262 */
2259#define GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK 755 2263#define GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK 755
2260 2264
2265// FIXME: this is never used!
2261/** 2266/**
2262 * Group terminated. 2267 * Group terminated.
2263 */ 2268 */
@@ -2398,35 +2403,38 @@ extern "C"
2398/** C->S: request to leave a place */ 2403/** C->S: request to leave a place */
2399#define GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE 848 2404#define GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE 848
2400 2405
2406/** S->C: place leave acknowledgement */
2407#define GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK 849
2408
2401/** C->S: add place to GNS zone */ 2409/** C->S: add place to GNS zone */
2402#define GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE 849 2410#define GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE 850
2403 2411
2404/** C->S: add nym to GNS zone */ 2412/** C->S: add nym to GNS zone */
2405#define GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM 850 2413#define GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM 851
2406 2414
2407/** C->S: connect application */ 2415/** C->S: connect application */
2408#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT 851 2416#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT 852
2409 2417
2410/** C->S: detach a place from application */ 2418/** C->S: detach a place from application */
2411#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH 852 2419#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH 853
2412 2420
2413/** S->C: notify about an existing ego */ 2421/** S->C: notify about an existing ego */
2414#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO 853 2422#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO 854
2415 2423
2416/** S->C: end of ego list */ 2424/** S->C: end of ego list */
2417#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO_END 854 2425#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO_END 855
2418 2426
2419/** S->C: notify about an existing place */ 2427/** S->C: notify about an existing place */
2420#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE 855 2428#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE 856
2421 2429
2422/** S->C: end of place list */ 2430/** S->C: end of place list */
2423#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE_END 856 2431#define GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE_END 857
2424 2432
2425/** C->S: set message processing flags */ 2433/** C->S: set message processing flags */
2426#define GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_SET 860 2434#define GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_SET 858
2427 2435
2428/** C->S: clear message processing flags */ 2436/** C->S: clear message processing flags */
2429#define GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_CLEAR 861 2437#define GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_CLEAR 859
2430 2438
2431/******************************************************************************* 2439/*******************************************************************************
2432 * X-VINE DHT messages 2440 * X-VINE DHT messages
diff --git a/src/include/gnunet_rest_lib.h b/src/include/gnunet_rest_lib.h
index 243c38403..a4dbb0696 100644
--- a/src/include/gnunet_rest_lib.h
+++ b/src/include/gnunet_rest_lib.h
@@ -32,7 +32,7 @@
32#define GNUNET_REST_LIB_H 32#define GNUNET_REST_LIB_H
33 33
34#include "gnunet_util_lib.h" 34#include "gnunet_util_lib.h"
35#include "microhttpd.h" 35#include <microhttpd.h>
36 36
37#define GNUNET_REST_HANDLER_END {NULL, NULL, NULL} 37#define GNUNET_REST_HANDLER_END {NULL, NULL, NULL}
38 38
diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h
index a855ab8ab..d2805a685 100644
--- a/src/include/gnunet_scheduler_lib.h
+++ b/src/include/gnunet_scheduler_lib.h
@@ -152,14 +152,14 @@ struct GNUNET_SCHEDULER_FdInfo
152 * NULL if this is about a file handle or if no network 152 * NULL if this is about a file handle or if no network
153 * handle was given to the scheduler originally. 153 * handle was given to the scheduler originally.
154 */ 154 */
155 struct GNUNET_NETWORK_Handle *fd; 155 const struct GNUNET_NETWORK_Handle *fd;
156 156
157 /** 157 /**
158 * GNUnet file handle the event is about, matches @a sock, 158 * GNUnet file handle the event is about, matches @a sock,
159 * NULL if this is about a network socket or if no network 159 * NULL if this is about a network socket or if no network
160 * handle was given to the scheduler originally. 160 * handle was given to the scheduler originally.
161 */ 161 */
162 struct GNUNET_DISK_FileHandle *fh; 162 const struct GNUNET_DISK_FileHandle *fh;
163 163
164 /** 164 /**
165 * Type of the event that was generated related to @e sock. 165 * Type of the event that was generated related to @e sock.
@@ -216,17 +216,18 @@ struct GNUNET_SCHEDULER_TaskContext
216 216
217/** 217/**
218 * Function used by event-loop implementations to signal the scheduler 218 * Function used by event-loop implementations to signal the scheduler
219 * that a particular @a task is ready due to an event of type @a et. 219 * that a particular @a task is ready due to an event specified in the
220 * et field of @a fdi.
220 * 221 *
221 * This function will then queue the task to notify the application 222 * This function will then queue the task to notify the application
222 * that the task is ready (with the respective priority). 223 * that the task is ready (with the respective priority).
223 * 224 *
224 * @param task the task that is ready 225 * @param task the task that is ready
225 * @param et information about why the task is ready 226 * @param fdi information about the related FD
226 */ 227 */
227void 228void
228GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, 229GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
229 enum GNUNET_SCHEDULER_EventType et); 230 struct GNUNET_SCHEDULER_FdInfo *fdi);
230 231
231 232
232/** 233/**
@@ -241,15 +242,16 @@ struct GNUNET_SCHEDULER_Handle;
241 * there are tasks left to run just to give other tasks a chance as 242 * there are tasks left to run just to give other tasks a chance as
242 * well. If we return #GNUNET_YES, the driver should call this 243 * well. If we return #GNUNET_YES, the driver should call this
243 * function again as soon as possible, while if we return #GNUNET_NO 244 * function again as soon as possible, while if we return #GNUNET_NO
244 * it must block until the operating system has more work as the 245 * it must block until either the operating system has more work (the
245 * scheduler has no more work to do right now. 246 * scheduler has no more work to do right now) or the timeout set by
247 * the scheduler (using the set_wakeup callback) is reached.
246 * 248 *
247 * @param sh scheduler handle that was given to the `loop` 249 * @param sh scheduler handle that was given to the `loop`
248 * @return #GNUNET_OK if there are more tasks that are ready, 250 * @return #GNUNET_OK if there are more tasks that are ready,
249 * and thus we would like to run more (yield to avoid 251 * and thus we would like to run more (yield to avoid
250 * blocking other activities for too long) 252 * blocking other activities for too long)
251 * #GNUNET_NO if we are done running tasks (yield to block) 253 * #GNUNET_NO if we are done running tasks (yield to block)
252 * #GNUNET_SYSERR on error 254 * #GNUNET_SYSERR on error, e.g. no tasks were ready
253 */ 255 */
254int 256int
255GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh); 257GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh);
@@ -268,8 +270,11 @@ struct GNUNET_SCHEDULER_Driver
268 void *cls; 270 void *cls;
269 271
270 /** 272 /**
271 * Add a @a task to be run if the conditions given 273 * Add a @a task to be run if the conditions specified in the
272 * in @a fdi are satisfied. 274 * et field of the given @a fdi are satisfied. The et field will
275 * be cleared after this call and the driver is expected to set
276 * the type of the actual event before passing @a fdi to
277 * #GNUNET_SCHEDULER_task_ready.
273 * 278 *
274 * @param cls closure 279 * @param cls closure
275 * @param task task to add 280 * @param task task to add
@@ -280,21 +285,21 @@ struct GNUNET_SCHEDULER_Driver
280 int 285 int
281 (*add)(void *cls, 286 (*add)(void *cls,
282 struct GNUNET_SCHEDULER_Task *task, 287 struct GNUNET_SCHEDULER_Task *task,
283 struct GNUNET_SCHEDULER_FdInfo *fdi); 288 struct GNUNET_SCHEDULER_FdInfo *fdi);
284 289
285 /** 290 /**
286 * Delete a @a task from the set of tasks to be run. 291 * Delete a @a task from the set of tasks to be run. A task may
292 * comprise multiple FdInfo entries previously added with the add
293 * function. The driver is expected to delete them all.
287 * 294 *
288 * @param cls closure 295 * @param cls closure
289 * @param task task to delete 296 * @param task task to delete
290 * @param fdi conditions to watch for (must match @e add call)
291 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure 297 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
292 * (i.e. @a task or @a fdi do not match prior @e add call) 298 * (i.e. @a task does not match prior @e add call)
293 */ 299 */
294 int 300 int
295 (*del)(void *cls, 301 (*del)(void *cls,
296 struct GNUNET_SCHEDULER_Task *task, 302 struct GNUNET_SCHEDULER_Task *task);
297 const struct GNUNET_SCHEDULER_FdInfo *fdi);
298 303
299 /** 304 /**
300 * Set time at which we definitively want to get a wakeup call. 305 * Set time at which we definitively want to get a wakeup call.
@@ -309,7 +314,10 @@ struct GNUNET_SCHEDULER_Driver
309 /** 314 /**
310 * Event loop's "main" function, to be called from 315 * Event loop's "main" function, to be called from
311 * #GNUNET_SCHEDULER_run_with_driver() to actually 316 * #GNUNET_SCHEDULER_run_with_driver() to actually
312 * launch the loop. 317 * launch the loop. The loop should run as long as
318 * tasks (added by the add callback) are available
319 * OR the wakeup time (added by the set_wakeup
320 * callback) is not FOREVER.
313 * 321 *
314 * @param cls closure 322 * @param cls closure
315 * @param sh scheduler handle to pass to 323 * @param sh scheduler handle to pass to
@@ -359,7 +367,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
359 * 367 *
360 * @return NULL on error 368 * @return NULL on error
361 */ 369 */
362const struct GNUNET_SCHEDULER_Driver * 370struct GNUNET_SCHEDULER_Driver *
363GNUNET_SCHEDULER_driver_select (void); 371GNUNET_SCHEDULER_driver_select (void);
364 372
365 373
diff --git a/src/include/gnunet_service_lib.h b/src/include/gnunet_service_lib.h
index aacafe956..dda827c95 100644
--- a/src/include/gnunet_service_lib.h
+++ b/src/include/gnunet_service_lib.h
@@ -366,11 +366,16 @@ GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
366/** 366/**
367 * Ask the server to disconnect from the given client. This is the 367 * Ask the server to disconnect from the given client. This is the
368 * same as returning #GNUNET_SYSERR within the check procedure when 368 * same as returning #GNUNET_SYSERR within the check procedure when
369 * handling a message, wexcept that it allows dropping of a client even 369 * handling a message, except that it allows dropping of a client even
370 * when not handling a message from that client. The `disconnect_cb` 370 * when not handling a message from that client. The `disconnect_cb`
371 * will be called on @a c even if the application closes the connection 371 * will be called on @a c even if the application closes the connection
372 * using this function. 372 * using this function.
373 * 373 *
374 * This function should be called (outside of util's internal logic)
375 * if (and usually only if) the client has violated the
376 * protocol. Otherwise, we should leave it to the client to disconnect
377 * from the service.
378 *
374 * @param c client to disconnect now 379 * @param c client to disconnect now
375 */ 380 */
376void 381void
diff --git a/src/jsonapi/Makefile.am b/src/jsonapi/Makefile.am
index 3cf3a4cd2..054d3c550 100644
--- a/src/jsonapi/Makefile.am
+++ b/src/jsonapi/Makefile.am
@@ -24,7 +24,7 @@ libgnunetjsonapi_la_LDFLAGS = \
24 -version-info 0:0:0 \ 24 -version-info 0:0:0 \
25 -no-undefined 25 -no-undefined
26libgnunetjsonapi_la_SOURCES = \ 26libgnunetjsonapi_la_SOURCES = \
27 jsonapi_document.c \ 27 jsonapi_document.c jsonapi_objects.h \
28 jsonapi_resource.c \ 28 jsonapi_resource.c \
29 jsonapi_error.c \ 29 jsonapi_error.c \
30 jsonapi_relationship.c 30 jsonapi_relationship.c
diff --git a/src/multicast/Makefile.am b/src/multicast/Makefile.am
index 13212bca3..48185e1a4 100644
--- a/src/multicast/Makefile.am
+++ b/src/multicast/Makefile.am
@@ -19,7 +19,7 @@ endif
19lib_LTLIBRARIES = libgnunetmulticast.la 19lib_LTLIBRARIES = libgnunetmulticast.la
20 20
21libgnunetmulticast_la_SOURCES = \ 21libgnunetmulticast_la_SOURCES = \
22 multicast_api.c 22 multicast_api.c multicast.h
23libgnunetmulticast_la_LIBADD = \ 23libgnunetmulticast_la_LIBADD = \
24 $(top_builddir)/src/util/libgnunetutil.la \ 24 $(top_builddir)/src/util/libgnunetutil.la \
25 $(GN_LIBINTL) $(XLIB) 25 $(GN_LIBINTL) $(XLIB)
diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c
index 2f4dc8a14..ba1086cc5 100644
--- a/src/multicast/gnunet-service-multicast.c
+++ b/src/multicast/gnunet-service-multicast.c
@@ -137,6 +137,7 @@ struct Channel
137 */ 137 */
138 struct GNUNET_CADET_Channel *channel; 138 struct GNUNET_CADET_Channel *channel;
139 139
140 // FIXME: not used
140 /** 141 /**
141 * CADET transmission handle. 142 * CADET transmission handle.
142 */ 143 */
@@ -228,7 +229,7 @@ struct Group
228 /** 229 /**
229 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO 230 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
230 */ 231 */
231 uint8_t disconnected; 232 uint8_t is_disconnected;
232 233
233 /** 234 /**
234 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)? 235 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
@@ -365,6 +366,8 @@ client_send_join_decision (struct Member *mem,
365static void 366static void
366shutdown_task (void *cls) 367shutdown_task (void *cls)
367{ 368{
369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
370 "shutting down\n");
368 if (NULL != cadet) 371 if (NULL != cadet)
369 { 372 {
370 GNUNET_CADET_disconnect (cadet); 373 GNUNET_CADET_disconnect (cadet);
@@ -420,6 +423,11 @@ cleanup_member (struct Member *mem)
420 GNUNET_free (mem->join_dcsn); 423 GNUNET_free (mem->join_dcsn);
421 mem->join_dcsn = NULL; 424 mem->join_dcsn = NULL;
422 } 425 }
426 if (NULL != mem->origin_channel)
427 {
428 GNUNET_CADET_channel_destroy (mem->origin_channel->channel);
429 mem->origin_channel = NULL;
430 }
423 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem); 431 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
424 GNUNET_free (mem); 432 GNUNET_free (mem);
425} 433}
@@ -553,36 +561,47 @@ client_send (struct GNUNET_SERVICE_Client *client,
553 * Send message to all clients connected to the group. 561 * Send message to all clients connected to the group.
554 */ 562 */
555static void 563static void
556client_send_group (const struct Group *grp, 564client_send_group_keep_envelope (const struct Group *grp,
557 const struct GNUNET_MessageHeader *msg) 565 struct GNUNET_MQ_Envelope *env)
558{ 566{
559 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 567 struct ClientList *cli = grp->clients_head;
560 "%p Sending message to all clients of the group.\n", grp);
561 568
562 struct ClientList *cl = grp->clients_head; 569 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
563 while (NULL != cl) 570 "%p Sending message to all clients of the group.\n",
571 grp);
572 while (NULL != cli)
564 { 573 {
565 struct GNUNET_MQ_Envelope * 574 GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client),
566 env = GNUNET_MQ_msg_copy (msg); 575 env);
567 576 cli = cli->next;
568 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cl->client),
569 env);
570 cl = cl->next;
571 } 577 }
572} 578}
573 579
574 580
575/** 581/**
582 * Send message to all clients connected to the group and
583 * takes care of freeing @env.
584 */
585static void
586client_send_group (const struct Group *grp,
587 struct GNUNET_MQ_Envelope *env)
588{
589 client_send_group_keep_envelope (grp, env);
590 GNUNET_MQ_discard (env);
591}
592
593
594/**
576 * Iterator callback for sending a message to origin clients. 595 * Iterator callback for sending a message to origin clients.
577 */ 596 */
578static int 597static int
579client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, 598client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
580 void *origin) 599 void *origin)
581{ 600{
582 const struct GNUNET_MessageHeader *msg = cls; 601 struct GNUNET_MQ_Envelope *env = cls;
583 struct Member *orig = origin; 602 struct Member *orig = origin;
584 603
585 client_send_group (&orig->group, msg); 604 client_send_group_keep_envelope (&orig->group, env);
586 return GNUNET_YES; 605 return GNUNET_YES;
587} 606}
588 607
@@ -594,12 +613,12 @@ static int
594client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, 613client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
595 void *member) 614 void *member)
596{ 615{
597 const struct GNUNET_MessageHeader *msg = cls; 616 struct GNUNET_MQ_Envelope *env = cls;
598 struct Member *mem = member; 617 struct Member *mem = member;
599 618
600 if (NULL != mem->join_dcsn) 619 if (NULL != mem->join_dcsn)
601 { /* Only send message to admitted members */ 620 { /* Only send message to admitted members */
602 client_send_group (&mem->group, msg); 621 client_send_group_keep_envelope (&mem->group, env);
603 } 622 }
604 return GNUNET_YES; 623 return GNUNET_YES;
605} 624}
@@ -615,15 +634,16 @@ client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
615 */ 634 */
616static int 635static int
617client_send_all (struct GNUNET_HashCode *pub_key_hash, 636client_send_all (struct GNUNET_HashCode *pub_key_hash,
618 const struct GNUNET_MessageHeader *msg) 637 struct GNUNET_MQ_Envelope *env)
619{ 638{
620 int n = 0; 639 int n = 0;
621 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, 640 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
622 client_send_origin_cb, 641 client_send_origin_cb,
623 (void *) msg); 642 (void *) env);
624 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash, 643 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
625 client_send_member_cb, 644 client_send_member_cb,
626 (void *) msg); 645 (void *) env);
646 GNUNET_MQ_discard (env);
627 return n; 647 return n;
628} 648}
629 649
@@ -636,14 +656,14 @@ client_send_all (struct GNUNET_HashCode *pub_key_hash,
636 */ 656 */
637static int 657static int
638client_send_random (struct GNUNET_HashCode *pub_key_hash, 658client_send_random (struct GNUNET_HashCode *pub_key_hash,
639 const struct GNUNET_MessageHeader *msg) 659 struct GNUNET_MQ_Envelope *env)
640{ 660{
641 int n = 0; 661 int n = 0;
642 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb, 662 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
643 (void *) msg); 663 (void *) env);
644 if (n <= 0) 664 if (n <= 0)
645 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb, 665 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
646 (void *) msg); 666 (void *) env);
647 return n; 667 return n;
648} 668}
649 669
@@ -658,12 +678,12 @@ client_send_random (struct GNUNET_HashCode *pub_key_hash,
658 */ 678 */
659static int 679static int
660client_send_origin (struct GNUNET_HashCode *pub_key_hash, 680client_send_origin (struct GNUNET_HashCode *pub_key_hash,
661 const struct GNUNET_MessageHeader *msg) 681 struct GNUNET_MQ_Envelope *env)
662{ 682{
663 int n = 0; 683 int n = 0;
664 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, 684 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
665 client_send_origin_cb, 685 client_send_origin_cb,
666 (void *) msg); 686 (void *) env);
667 return n; 687 return n;
668} 688}
669 689
@@ -677,17 +697,12 @@ client_send_origin (struct GNUNET_HashCode *pub_key_hash,
677static void 697static void
678client_send_ack (struct GNUNET_HashCode *pub_key_hash) 698client_send_ack (struct GNUNET_HashCode *pub_key_hash)
679{ 699{
700 struct GNUNET_MQ_Envelope *env;
701
680 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 702 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
681 "Sending message ACK to client.\n"); 703 "Sending message ACK to client.\n");
682 704 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
683 static struct GNUNET_MessageHeader *msg = NULL; 705 client_send_all (pub_key_hash, env);
684 if (NULL == msg)
685 {
686 msg = GNUNET_malloc (sizeof (*msg));
687 msg->type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
688 msg->size = htons (sizeof (*msg));
689 }
690 client_send_all (pub_key_hash, msg);
691} 706}
692 707
693 708
@@ -983,7 +998,8 @@ handle_cadet_join_request (void *cls,
983 chn->peer = req->peer; 998 chn->peer = req->peer;
984 chn->join_status = JOIN_WAITING; 999 chn->join_status = JOIN_WAITING;
985 1000
986 client_send_all (&group_pub_hash, &req->header); 1001 client_send_all (&group_pub_hash,
1002 GNUNET_MQ_msg_copy (&req->header));
987} 1003}
988 1004
989 1005
@@ -1102,7 +1118,8 @@ handle_cadet_message (void *cls,
1102{ 1118{
1103 struct Channel *chn = cls; 1119 struct Channel *chn = cls;
1104 GNUNET_CADET_receive_done (chn->channel); 1120 GNUNET_CADET_receive_done (chn->channel);
1105 client_send_all (&chn->group_pub_hash, &msg->header); 1121 client_send_all (&chn->group_pub_hash,
1122 GNUNET_MQ_msg_copy (&msg->header));
1106} 1123}
1107 1124
1108 1125
@@ -1153,30 +1170,32 @@ handle_cadet_request (void *cls,
1153{ 1170{
1154 struct Channel *chn = cls; 1171 struct Channel *chn = cls;
1155 GNUNET_CADET_receive_done (chn->channel); 1172 GNUNET_CADET_receive_done (chn->channel);
1156 client_send_origin (&chn->group_pub_hash, &req->header); 1173 client_send_origin (&chn->group_pub_hash,
1174 GNUNET_MQ_msg_copy (&req->header));
1157} 1175}
1158 1176
1159 1177
1160static int 1178// FIXME: do checks in handle_cadet_replay_request
1161check_cadet_replay_request (void *cls, 1179//static int
1162 const struct MulticastReplayRequestMessage *req) 1180//check_cadet_replay_request (void *cls,
1163{ 1181// const struct MulticastReplayRequestMessage *req)
1164 uint16_t size = ntohs (req->header.size); 1182//{
1165 if (size < sizeof (*req)) 1183// uint16_t size = ntohs (req->header.size);
1166 { 1184// if (size < sizeof (*req))
1167 GNUNET_break_op (0); 1185// {
1168 return GNUNET_SYSERR; 1186// GNUNET_break_op (0);
1169 } 1187// return GNUNET_SYSERR;
1170 1188// }
1171 struct Channel *chn = cls; 1189//
1172 if (NULL == chn) 1190// struct Channel *chn = cls;
1173 { 1191// if (NULL == chn)
1174 GNUNET_break_op (0); 1192// {
1175 return GNUNET_SYSERR; 1193// GNUNET_break_op (0);
1176 } 1194// return GNUNET_SYSERR;
1177 1195// }
1178 return GNUNET_OK; 1196//
1179} 1197// return GNUNET_OK;
1198//}
1180 1199
1181 1200
1182/** 1201/**
@@ -1187,6 +1206,7 @@ handle_cadet_replay_request (void *cls,
1187 const struct MulticastReplayRequestMessage *req) 1206 const struct MulticastReplayRequestMessage *req)
1188{ 1207{
1189 struct Channel *chn = cls; 1208 struct Channel *chn = cls;
1209
1190 GNUNET_CADET_receive_done (chn->channel); 1210 GNUNET_CADET_receive_done (chn->channel);
1191 1211
1192 struct MulticastReplayRequestMessage rep = *req; 1212 struct MulticastReplayRequestMessage rep = *req;
@@ -1203,12 +1223,16 @@ handle_cadet_replay_request (void *cls,
1203 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1223 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1204 } 1224 }
1205 struct GNUNET_HashCode key_hash; 1225 struct GNUNET_HashCode key_hash;
1206 replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset, 1226 replay_key_hash (rep.fragment_id,
1207 rep.flags, &key_hash); 1227 rep.message_id,
1228 rep.fragment_offset,
1229 rep.flags,
1230 &key_hash);
1208 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn, 1231 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1209 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1232 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1210 1233
1211 client_send_random (&chn->group_pub_hash, &rep.header); 1234 client_send_random (&chn->group_pub_hash,
1235 GNUNET_MQ_msg_copy (&rep.header));
1212} 1236}
1213 1237
1214 1238
@@ -1290,10 +1314,10 @@ cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
1290 struct MulticastJoinDecisionMessageHeader, 1314 struct MulticastJoinDecisionMessageHeader,
1291 chn), 1315 chn),
1292 1316
1293 GNUNET_MQ_hd_var_size (cadet_replay_request, 1317 GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1294 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 1318 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1295 struct MulticastReplayRequestMessage, 1319 struct MulticastReplayRequestMessage,
1296 chn), 1320 chn),
1297 1321
1298 GNUNET_MQ_hd_var_size (cadet_replay_response, 1322 GNUNET_MQ_hd_var_size (cadet_replay_response,
1299 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 1323 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
@@ -1357,6 +1381,7 @@ handle_client_origin_start (void *cls,
1357 grp->is_origin = GNUNET_YES; 1381 grp->is_origin = GNUNET_YES;
1358 grp->pub_key = pub_key; 1382 grp->pub_key = pub_key;
1359 grp->pub_key_hash = pub_key_hash; 1383 grp->pub_key_hash = pub_key_hash;
1384 grp->is_disconnected = GNUNET_NO;
1360 1385
1361 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig, 1386 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
1362 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1387 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
@@ -1379,10 +1404,10 @@ handle_client_origin_start (void *cls,
1379 struct MulticastJoinRequestMessage, 1404 struct MulticastJoinRequestMessage,
1380 grp), 1405 grp),
1381 1406
1382 GNUNET_MQ_hd_var_size (cadet_replay_request, 1407 GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1383 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 1408 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1384 struct MulticastReplayRequestMessage, 1409 struct MulticastReplayRequestMessage,
1385 grp), 1410 grp),
1386 1411
1387 GNUNET_MQ_hd_var_size (cadet_replay_response, 1412 GNUNET_MQ_hd_var_size (cadet_replay_response,
1388 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 1413 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
@@ -1484,6 +1509,7 @@ handle_client_member_join (void *cls,
1484 grp->is_origin = GNUNET_NO; 1509 grp->is_origin = GNUNET_NO;
1485 grp->pub_key = msg->group_pub_key; 1510 grp->pub_key = msg->group_pub_key;
1486 grp->pub_key_hash = pub_key_hash; 1511 grp->pub_key_hash = pub_key_hash;
1512 grp->is_disconnected = GNUNET_NO;
1487 group_set_cadet_port_hash (grp); 1513 group_set_cadet_port_hash (grp);
1488 1514
1489 if (NULL == grp_mem) 1515 if (NULL == grp_mem)
@@ -1494,7 +1520,8 @@ handle_client_member_join (void *cls,
1494 } 1520 }
1495 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem, 1521 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1496 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1522 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1497 1523
1524 // FIXME: should the members hash map have option UNIQUE_FAST?
1498 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem, 1525 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1499 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1526 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1500 } 1527 }
@@ -1509,10 +1536,11 @@ handle_client_member_join (void *cls,
1509 1536
1510 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key); 1537 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1512 "Client connected to group %s as member %s (%s).\n", 1539 "Client connected to group %s as member %s (%s). size = %d\n",
1513 GNUNET_h2s (&grp->pub_key_hash), 1540 GNUNET_h2s (&grp->pub_key_hash),
1514 GNUNET_h2s2 (&mem->pub_key_hash), 1541 GNUNET_h2s2 (&mem->pub_key_hash),
1515 str); 1542 str,
1543 GNUNET_CONTAINER_multihashmap_size (members));
1516 GNUNET_free (str); 1544 GNUNET_free (str);
1517 1545
1518 if (NULL != mem->join_dcsn) 1546 if (NULL != mem->join_dcsn)
@@ -1567,7 +1595,9 @@ handle_client_member_join (void *cls,
1567 GNUNET_free (mem->join_req); 1595 GNUNET_free (mem->join_req);
1568 mem->join_req = req; 1596 mem->join_req = req;
1569 1597
1570 if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header)) 1598 if (0 ==
1599 client_send_origin (&grp->pub_key_hash,
1600 GNUNET_MQ_msg_copy (&mem->join_req->header)))
1571 { /* No local origins, send to remote origin */ 1601 { /* No local origins, send to remote origin */
1572 cadet_send_join_request (mem); 1602 cadet_send_join_request (mem);
1573 } 1603 }
@@ -1580,7 +1610,7 @@ static void
1580client_send_join_decision (struct Member *mem, 1610client_send_join_decision (struct Member *mem,
1581 const struct MulticastJoinDecisionMessageHeader *hdcsn) 1611 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1582{ 1612{
1583 client_send_group (&mem->group, &hdcsn->header); 1613 client_send_group (&mem->group, GNUNET_MQ_msg_copy (&hdcsn->header));
1584 1614
1585 const struct MulticastJoinDecisionMessage * 1615 const struct MulticastJoinDecisionMessage *
1586 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1]; 1616 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
@@ -1621,8 +1651,9 @@ handle_client_join_decision (void *cls,
1621 GNUNET_SERVICE_client_drop (client); 1651 GNUNET_SERVICE_client_drop (client);
1622 return; 1652 return;
1623 } 1653 }
1654 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1655 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1625 "%p Got join decision from client for group %s..\n", 1656 "%p got join decision from client for group %s..\n",
1626 grp, GNUNET_h2s (&grp->pub_key_hash)); 1657 grp, GNUNET_h2s (&grp->pub_key_hash));
1627 1658
1628 struct GNUNET_CONTAINER_MultiHashMap * 1659 struct GNUNET_CONTAINER_MultiHashMap *
@@ -1652,6 +1683,32 @@ handle_client_join_decision (void *cls,
1652} 1683}
1653 1684
1654 1685
1686static void
1687handle_client_part_request (void *cls,
1688 const struct GNUNET_MessageHeader *msg)
1689{
1690 struct Client *c = cls;
1691 struct GNUNET_SERVICE_Client *client = c->client;
1692 struct Group *grp = c->group;
1693 struct GNUNET_MQ_Envelope *env;
1694
1695 if (NULL == grp)
1696 {
1697 GNUNET_break (0);
1698 GNUNET_SERVICE_client_drop (client);
1699 return;
1700 }
1701 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1703 "%p got part request from client for group %s.\n",
1704 grp, GNUNET_h2s (&grp->pub_key_hash));
1705 grp->is_disconnected = GNUNET_YES;
1706 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK);
1707 client_send_group (grp, env);
1708 GNUNET_SERVICE_client_continue (client);
1709}
1710
1711
1655static int 1712static int
1656check_client_multicast_message (void *cls, 1713check_client_multicast_message (void *cls,
1657 const struct GNUNET_MULTICAST_MessageHeader *msg) 1714 const struct GNUNET_MULTICAST_MessageHeader *msg)
@@ -1667,6 +1724,7 @@ static void
1667handle_client_multicast_message (void *cls, 1724handle_client_multicast_message (void *cls,
1668 const struct GNUNET_MULTICAST_MessageHeader *msg) 1725 const struct GNUNET_MULTICAST_MessageHeader *msg)
1669{ 1726{
1727 // FIXME: what if GNUNET_YES == grp->is_disconnected? Do we allow sending messages?
1670 struct Client *c = cls; 1728 struct Client *c = cls;
1671 struct GNUNET_SERVICE_Client *client = c->client; 1729 struct GNUNET_SERVICE_Client *client = c->client;
1672 struct Group *grp = c->group; 1730 struct Group *grp = c->group;
@@ -1680,6 +1738,7 @@ handle_client_multicast_message (void *cls,
1680 GNUNET_assert (GNUNET_YES == grp->is_origin); 1738 GNUNET_assert (GNUNET_YES == grp->is_origin);
1681 struct Origin *orig = grp->origin; 1739 struct Origin *orig = grp->origin;
1682 1740
1741 // FIXME: use GNUNET_MQ_msg_copy
1683 /* FIXME: yucky, should use separate message structs for P2P and CS! */ 1742 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1684 struct GNUNET_MULTICAST_MessageHeader * 1743 struct GNUNET_MULTICAST_MessageHeader *
1685 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header); 1744 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
@@ -1696,7 +1755,7 @@ handle_client_multicast_message (void *cls,
1696 GNUNET_assert (0); 1755 GNUNET_assert (0);
1697 } 1756 }
1698 1757
1699 client_send_all (&grp->pub_key_hash, &out->header); 1758 client_send_all (&grp->pub_key_hash, GNUNET_MQ_msg_copy (&out->header));
1700 cadet_send_children (&grp->pub_key_hash, &out->header); 1759 cadet_send_children (&grp->pub_key_hash, &out->header);
1701 client_send_ack (&grp->pub_key_hash); 1760 client_send_ack (&grp->pub_key_hash);
1702 GNUNET_free (out); 1761 GNUNET_free (out);
@@ -1730,6 +1789,7 @@ handle_client_multicast_request (void *cls,
1730 GNUNET_SERVICE_client_drop (client); 1789 GNUNET_SERVICE_client_drop (client);
1731 return; 1790 return;
1732 } 1791 }
1792 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1733 GNUNET_assert (GNUNET_NO == grp->is_origin); 1793 GNUNET_assert (GNUNET_NO == grp->is_origin);
1734 struct Member *mem = grp->member; 1794 struct Member *mem = grp->member;
1735 1795
@@ -1751,7 +1811,9 @@ handle_client_multicast_request (void *cls,
1751 } 1811 }
1752 1812
1753 uint8_t send_ack = GNUNET_YES; 1813 uint8_t send_ack = GNUNET_YES;
1754 if (0 == client_send_origin (&grp->pub_key_hash, &out->header)) 1814 if (0 ==
1815 client_send_origin (&grp->pub_key_hash,
1816 GNUNET_MQ_msg_copy (&out->header)))
1755 { /* No local origins, send to remote origin */ 1817 { /* No local origins, send to remote origin */
1756 if (NULL != mem->origin_channel) 1818 if (NULL != mem->origin_channel)
1757 { 1819 {
@@ -1792,6 +1854,7 @@ handle_client_replay_request (void *cls,
1792 GNUNET_SERVICE_client_drop (client); 1854 GNUNET_SERVICE_client_drop (client);
1793 return; 1855 return;
1794 } 1856 }
1857 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1795 GNUNET_assert (GNUNET_NO == grp->is_origin); 1858 GNUNET_assert (GNUNET_NO == grp->is_origin);
1796 struct Member *mem = grp->member; 1859 struct Member *mem = grp->member;
1797 1860
@@ -1812,7 +1875,9 @@ handle_client_replay_request (void *cls,
1812 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client, 1875 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1813 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1876 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1814 1877
1815 if (0 == client_send_origin (&grp->pub_key_hash, &rep->header)) 1878 if (0 ==
1879 client_send_origin (&grp->pub_key_hash,
1880 GNUNET_MQ_msg_copy (&rep->header)))
1816 { /* No local origin, replay from remote members / origin. */ 1881 { /* No local origin, replay from remote members / origin. */
1817 if (NULL != mem->origin_channel) 1882 if (NULL != mem->origin_channel)
1818 { 1883 {
@@ -1821,6 +1886,7 @@ handle_client_replay_request (void *cls,
1821 else 1886 else
1822 { 1887 {
1823 /* FIXME: not yet connected to origin */ 1888 /* FIXME: not yet connected to origin */
1889 GNUNET_assert (0);
1824 GNUNET_SERVICE_client_drop (client); 1890 GNUNET_SERVICE_client_drop (client);
1825 return; 1891 return;
1826 } 1892 }
@@ -1880,6 +1946,7 @@ handle_client_replay_response_end (void *cls,
1880 GNUNET_SERVICE_client_drop (client); 1946 GNUNET_SERVICE_client_drop (client);
1881 return; 1947 return;
1882 } 1948 }
1949 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1883 1950
1884 struct GNUNET_HashCode key_hash; 1951 struct GNUNET_HashCode key_hash;
1885 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset, 1952 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
@@ -1939,6 +2006,7 @@ handle_client_replay_response (void *cls,
1939 GNUNET_SERVICE_client_drop (client); 2006 GNUNET_SERVICE_client_drop (client);
1940 return; 2007 return;
1941 } 2008 }
2009 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1942 2010
1943 const struct GNUNET_MessageHeader *msg = &res->header; 2011 const struct GNUNET_MessageHeader *msg = &res->header;
1944 if (GNUNET_MULTICAST_REC_OK == res->error_code) 2012 if (GNUNET_MULTICAST_REC_OK == res->error_code)
@@ -2033,9 +2101,14 @@ client_notify_disconnect (void *cls,
2033 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member", 2101 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
2034 GNUNET_h2s (&grp->pub_key_hash)); 2102 GNUNET_h2s (&grp->pub_key_hash));
2035 2103
2104 // FIXME (due to protocol change): here we must not remove all clients,
2105 // only the one we were notified about!
2036 struct ClientList *cl = grp->clients_head; 2106 struct ClientList *cl = grp->clients_head;
2037 while (NULL != cl) 2107 while (NULL != cl)
2038 { 2108 {
2109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2110 "iterating clients for group %p\n",
2111 grp);
2039 if (cl->client == client) 2112 if (cl->client == client)
2040 { 2113 {
2041 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl); 2114 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
@@ -2049,16 +2122,7 @@ client_notify_disconnect (void *cls,
2049 2122
2050 if (NULL == grp->clients_head) 2123 if (NULL == grp->clients_head)
2051 { /* Last client disconnected. */ 2124 { /* Last client disconnected. */
2052#if FIXME 2125 cleanup_group (grp);
2053 if (NULL != grp->tmit_head)
2054 { /* Send pending messages via CADET before cleanup. */
2055 transmit_message (grp);
2056 }
2057 else
2058#endif
2059 {
2060 cleanup_group (grp);
2061 }
2062 } 2126 }
2063} 2127}
2064 2128
@@ -2103,9 +2167,9 @@ run (void *cls,
2103GNUNET_SERVICE_MAIN 2167GNUNET_SERVICE_MAIN
2104("multicast", 2168("multicast",
2105 GNUNET_SERVICE_OPTION_NONE, 2169 GNUNET_SERVICE_OPTION_NONE,
2106 run, 2170 &run,
2107 client_notify_connect, 2171 &client_notify_connect,
2108 client_notify_disconnect, 2172 &client_notify_disconnect,
2109 NULL, 2173 NULL,
2110 GNUNET_MQ_hd_fixed_size (client_origin_start, 2174 GNUNET_MQ_hd_fixed_size (client_origin_start,
2111 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 2175 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
@@ -2119,6 +2183,10 @@ GNUNET_SERVICE_MAIN
2119 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 2183 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
2120 struct MulticastJoinDecisionMessageHeader, 2184 struct MulticastJoinDecisionMessageHeader,
2121 NULL), 2185 NULL),
2186 GNUNET_MQ_hd_fixed_size (client_part_request,
2187 GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST,
2188 struct GNUNET_MessageHeader,
2189 NULL),
2122 GNUNET_MQ_hd_var_size (client_multicast_message, 2190 GNUNET_MQ_hd_var_size (client_multicast_message,
2123 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 2191 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
2124 struct GNUNET_MULTICAST_MessageHeader, 2192 struct GNUNET_MULTICAST_MessageHeader,
diff --git a/src/multicast/multicast_api.c b/src/multicast/multicast_api.c
index a8b1dee40..3c911f48a 100644
--- a/src/multicast/multicast_api.c
+++ b/src/multicast/multicast_api.c
@@ -542,31 +542,12 @@ group_cleanup (struct GNUNET_MULTICAST_Group *grp)
542 542
543 543
544static void 544static void
545group_disconnect (struct GNUNET_MULTICAST_Group *grp, 545handle_group_part_ack (void *cls,
546 GNUNET_ContinuationCallback cb, 546 const struct GNUNET_MessageHeader *msg)
547 void *cls)
548{ 547{
549 grp->is_disconnecting = GNUNET_YES; 548 struct GNUNET_MULTICAST_Group *grp = cls;
550 grp->disconnect_cb = cb;
551 grp->disconnect_cls = cls;
552 549
553 if (NULL != grp->mq) 550 group_cleanup (grp);
554 {
555 struct GNUNET_MQ_Envelope *last = GNUNET_MQ_get_last_envelope (grp->mq);
556 if (NULL != last)
557 {
558 GNUNET_MQ_notify_sent (last,
559 (GNUNET_SCHEDULER_TaskCallback) group_cleanup, grp);
560 }
561 else
562 {
563 group_cleanup (grp);
564 }
565 }
566 else
567 {
568 group_cleanup (grp);
569 }
570} 551}
571 552
572 553
@@ -779,6 +760,10 @@ origin_connect (struct GNUNET_MULTICAST_Origin *orig)
779 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 760 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
780 struct MulticastJoinRequestMessage, 761 struct MulticastJoinRequestMessage,
781 grp), 762 grp),
763 GNUNET_MQ_hd_fixed_size (group_part_ack,
764 GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK,
765 struct GNUNET_MessageHeader,
766 grp),
782 GNUNET_MQ_hd_fixed_size (group_replay_request, 767 GNUNET_MQ_hd_fixed_size (group_replay_request,
783 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 768 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
784 struct MulticastReplayRequestMessage, 769 struct MulticastReplayRequestMessage,
@@ -879,8 +864,13 @@ GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *orig,
879 void *stop_cls) 864 void *stop_cls)
880{ 865{
881 struct GNUNET_MULTICAST_Group *grp = &orig->grp; 866 struct GNUNET_MULTICAST_Group *grp = &orig->grp;
867 struct GNUNET_MQ_Envelope *env;
882 868
883 group_disconnect (grp, stop_cb, stop_cls); 869 grp->is_disconnecting = GNUNET_YES;
870 grp->disconnect_cb = stop_cb;
871 grp->disconnect_cls = stop_cls;
872 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST);
873 GNUNET_MQ_send (grp->mq, env);
884} 874}
885 875
886 876
@@ -1065,6 +1055,10 @@ member_connect (struct GNUNET_MULTICAST_Member *mem)
1065 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 1055 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
1066 struct MulticastJoinDecisionMessageHeader, 1056 struct MulticastJoinDecisionMessageHeader,
1067 mem), 1057 mem),
1058 GNUNET_MQ_hd_fixed_size (group_part_ack,
1059 GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK,
1060 struct GNUNET_MessageHeader,
1061 grp),
1068 GNUNET_MQ_hd_fixed_size (group_replay_request, 1062 GNUNET_MQ_hd_fixed_size (group_replay_request,
1069 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 1063 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1070 struct MulticastReplayRequestMessage, 1064 struct MulticastReplayRequestMessage,
@@ -1198,16 +1192,19 @@ GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *mem,
1198 GNUNET_ContinuationCallback part_cb, 1192 GNUNET_ContinuationCallback part_cb,
1199 void *part_cls) 1193 void *part_cls)
1200{ 1194{
1201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Member parting.\n", mem);
1202 struct GNUNET_MULTICAST_Group *grp = &mem->grp; 1195 struct GNUNET_MULTICAST_Group *grp = &mem->grp;
1196 struct GNUNET_MQ_Envelope *env;
1203 1197
1204 mem->join_dcsn_cb = NULL; 1198 mem->join_dcsn_cb = NULL;
1205 grp->join_req_cb = NULL; 1199 grp->join_req_cb = NULL;
1206 grp->message_cb = NULL; 1200 grp->message_cb = NULL;
1207 grp->replay_msg_cb = NULL; 1201 grp->replay_msg_cb = NULL;
1208 grp->replay_frag_cb = NULL; 1202 grp->replay_frag_cb = NULL;
1209 1203 grp->is_disconnecting = GNUNET_YES;
1210 group_disconnect (grp, part_cb, part_cls); 1204 grp->disconnect_cb = part_cb;
1205 grp->disconnect_cls = part_cls;
1206 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST);
1207 GNUNET_MQ_send (grp->mq, env);
1211} 1208}
1212 1209
1213 1210
diff --git a/src/multicast/test_multicast_multipeer.c b/src/multicast/test_multicast_multipeer.c
index 5f4493993..7df1a8213 100644
--- a/src/multicast/test_multicast_multipeer.c
+++ b/src/multicast/test_multicast_multipeer.c
@@ -35,9 +35,10 @@
35 35
36#define PEERS_REQUESTED 12 36#define PEERS_REQUESTED 12
37 37
38struct multicast_peer 38struct MulticastPeerContext
39{ 39{
40 int peer; /* peer number */ 40 int peer; /* peer number */
41 struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
41 const struct GNUNET_PeerIdentity *id; 42 const struct GNUNET_PeerIdentity *id;
42 struct GNUNET_TESTBED_Operation *op; /* not yet in use */ 43 struct GNUNET_TESTBED_Operation *op; /* not yet in use */
43 struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */ 44 struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */
@@ -61,7 +62,7 @@ static void service_connect (void *cls,
61 void *ca_result, 62 void *ca_result,
62 const char *emsg); 63 const char *emsg);
63 64
64static struct multicast_peer **mc_peers; 65static struct MulticastPeerContext **multicast_peers;
65static struct GNUNET_TESTBED_Peer **peers; 66static struct GNUNET_TESTBED_Peer **peers;
66 67
67// FIXME: refactor 68// FIXME: refactor
@@ -69,18 +70,14 @@ static struct GNUNET_TESTBED_Operation *op[PEERS_REQUESTED];
69static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED]; 70static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED];
70 71
71static struct GNUNET_MULTICAST_Origin *origin; 72static struct GNUNET_MULTICAST_Origin *origin;
72static struct GNUNET_MULTICAST_Member *member[PEERS_REQUESTED]; /* first element always empty */ 73static struct GNUNET_MULTICAST_Member *members[PEERS_REQUESTED]; /* first element always empty */
73 74
74static struct GNUNET_SCHEDULER_Task *timeout_tid; 75static struct GNUNET_SCHEDULER_Task *timeout_tid;
75 76
76static struct GNUNET_CRYPTO_EddsaPrivateKey group_key; 77//static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
77static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key; 78static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
78static struct GNUNET_HashCode group_pub_key_hash; 79static struct GNUNET_HashCode group_pub_key_hash;
79 80
80static struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key[PEERS_REQUESTED];
81static struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key[PEERS_REQUESTED];
82
83
84/** 81/**
85 * Global result for testcase. 82 * Global result for testcase.
86 */ 83 */
@@ -93,6 +90,8 @@ static int result;
93static void 90static void
94shutdown_task (void *cls) 91shutdown_task (void *cls)
95{ 92{
93 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
94 "shutdown_task!\n");
96 for (int i=0;i<PEERS_REQUESTED;i++) 95 for (int i=0;i<PEERS_REQUESTED;i++)
97 { 96 {
98 if (NULL != op[i]) 97 if (NULL != op[i])
@@ -107,14 +106,16 @@ shutdown_task (void *cls)
107 } 106 }
108 } 107 }
109 108
110 if (NULL != mc_peers) 109 if (NULL != multicast_peers)
111 { 110 {
112 for (int i=0; i < PEERS_REQUESTED; i++) 111 for (int i=0; i < PEERS_REQUESTED; i++)
113 { 112 {
114 GNUNET_free (mc_peers[i]); 113 GNUNET_free (multicast_peers[i]->key);
115 mc_peers[i] = NULL; 114 GNUNET_free (multicast_peers[i]);
115 multicast_peers[i] = NULL;
116 } 116 }
117 GNUNET_free (mc_peers); 117 GNUNET_free (multicast_peers);
118 multicast_peers = NULL;
118 } 119 }
119 120
120 if (NULL != timeout_tid) 121 if (NULL != timeout_tid)
@@ -141,11 +142,11 @@ member_join_request (void *cls,
141 const struct GNUNET_MessageHeader *join_msg, 142 const struct GNUNET_MessageHeader *join_msg,
142 struct GNUNET_MULTICAST_JoinHandle *jh) 143 struct GNUNET_MULTICAST_JoinHandle *jh)
143{ 144{
144 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 145 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
145 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 146 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
146 "Peer #%u (%s) sent a join request.\n", 147 "Peer #%u (%s) sent a join request.\n",
147 mc_peer->peer, 148 mc_peer->peer,
148 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 149 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
149} 150}
150 151
151 152
@@ -154,7 +155,7 @@ notify (void *cls,
154 size_t *data_size, 155 size_t *data_size,
155 void *data) 156 void *data)
156{ 157{
157 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 158 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
158 159
159 struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg); 160 struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
160 pp_msg->peer = mc_peer->peer; 161 pp_msg->peer = mc_peer->peer;
@@ -178,18 +179,18 @@ member_join_decision (void *cls,
178 const struct GNUNET_PeerIdentity *relays, 179 const struct GNUNET_PeerIdentity *relays,
179 const struct GNUNET_MessageHeader *join_msg) 180 const struct GNUNET_MessageHeader *join_msg)
180{ 181{
181 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 182 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
182 struct GNUNET_MULTICAST_MemberTransmitHandle *req; 183 struct GNUNET_MULTICAST_MemberTransmitHandle *req;
183 184
184 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 185 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
185 "Peer #%u (%s) received a decision from origin: %s\n", 186 "Peer #%u (%s) received a decision from origin: %s\n",
186 mc_peer->peer, 187 mc_peer->peer,
187 GNUNET_i2s (mc_peers[mc_peer->peer]->id), 188 GNUNET_i2s (multicast_peers[mc_peer->peer]->id),
188 (GNUNET_YES == is_admitted)?"accepted":"rejected"); 189 (GNUNET_YES == is_admitted)?"accepted":"rejected");
189 190
190 if (GNUNET_YES == is_admitted) 191 if (GNUNET_YES == is_admitted)
191 { 192 {
192 req = GNUNET_MULTICAST_member_to_origin (member[mc_peer->peer], 193 req = GNUNET_MULTICAST_member_to_origin (members[mc_peer->peer],
193 0, 194 0,
194 notify, 195 notify,
195 cls); 196 cls);
@@ -215,10 +216,32 @@ member_replay_msg ()
215 216
216 217
217static void 218static void
219origin_disconnected_cb (void *cls)
220{
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
222 "Origin disconnected. Shutting down.\n");
223 result = GNUNET_YES;
224 GNUNET_SCHEDULER_shutdown ();
225}
226
227
228static void
229member_disconnected_cb (void *cls)
230{
231 for (int i = 1; i < PEERS_REQUESTED; ++i)
232 if (GNUNET_NO == multicast_peers[i]->test_ok)
233 return;
234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
235 "All member disconnected. Stopping origin.\n");
236 GNUNET_MULTICAST_origin_stop (origin, origin_disconnected_cb, cls);
237}
238
239
240static void
218member_message (void *cls, 241member_message (void *cls,
219 const struct GNUNET_MULTICAST_MessageHeader *msg) 242 const struct GNUNET_MULTICAST_MessageHeader *msg)
220{ 243{
221 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 244 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
222 struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]); 245 struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]);
223 246
224 if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer) 247 if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer)
@@ -226,18 +249,15 @@ member_message (void *cls,
226 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 249 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
227 "peer #%i (%s) receives a pong\n", 250 "peer #%i (%s) receives a pong\n",
228 mc_peer->peer, 251 mc_peer->peer,
229 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 252 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
230
231 mc_peer->test_ok = GNUNET_OK; 253 mc_peer->test_ok = GNUNET_OK;
232 } 254 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
233 255 "peer #%u (%s) parting from multicast group\n",
234 // Test for completeness of received PONGs 256 mc_peer->peer,
235 for (int i=1; i<PEERS_REQUESTED; i++) 257 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
236 if (GNUNET_NO == mc_peers[i]->test_ok)
237 return;
238 258
239 result = GNUNET_YES; 259 GNUNET_MULTICAST_member_part (members[mc_peer->peer], member_disconnected_cb, cls);
240 GNUNET_SCHEDULER_shutdown(); 260 }
241} 261}
242 262
243 263
@@ -349,81 +369,53 @@ origin_message (void *cls,
349 369
350 370
351static void 371static void
352multicast_da (void *cls, 372multicast_disconnect (void *cls,
353 void *op_result) 373 void *op_result)
354{ 374{
355 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
356 375
357 if (0 == mc_peer->peer)
358 {
359 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
360 "Origin closes multicast group\n");
361
362 GNUNET_MULTICAST_origin_stop (origin, NULL, cls);
363 }
364 else
365 {
366 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
367 "peer #%u (%s) parting from multicast group\n",
368 mc_peer->peer,
369 GNUNET_i2s (mc_peers[mc_peer->peer]->id));
370
371 GNUNET_MULTICAST_member_part (member[mc_peer->peer], NULL, cls);
372 }
373} 376}
374 377
375 378
376static void * 379static void *
377multicast_ca (void *cls, 380multicast_connect (void *cls,
378 const struct GNUNET_CONFIGURATION_Handle *cfg) 381 const struct GNUNET_CONFIGURATION_Handle *cfg)
379{ 382{
380 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 383 struct MulticastPeerContext *multicast_peer = cls;
381 struct GNUNET_MessageHeader *join_msg; 384 struct GNUNET_MessageHeader *join_msg;
382 char data[64]; 385 char data[64];
383 386
384 if (0 == mc_peer->peer) 387 multicast_peer->key = GNUNET_CRYPTO_ecdsa_key_create ();
388 if (0 == multicast_peer->peer)
385 { 389 {
386 struct GNUNET_CRYPTO_EddsaPrivateKey *key = GNUNET_CRYPTO_eddsa_key_create (); 390 GNUNET_CRYPTO_eddsa_key_get_public (multicast_peer->key, &group_pub_key);
387 GNUNET_CRYPTO_eddsa_key_get_public (key, &group_pub_key);
388 GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash); 391 GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash);
389
390 group_key = *key;
391
392 origin = GNUNET_MULTICAST_origin_start (cfg, 392 origin = GNUNET_MULTICAST_origin_start (cfg,
393 &group_key, 393 multicast_peer->key,
394 0, 394 0,
395 origin_join_request, 395 origin_join_request,
396 origin_replay_frag, 396 origin_replay_frag,
397 origin_replay_msg, 397 origin_replay_msg,
398 origin_request, 398 origin_request,
399 origin_message, 399 origin_message,
400 cls); 400 cls);
401 401 if (NULL == origin)
402 if (NULL == origin) { 402 {
403 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 403 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
404 "Peer #%u could not create a multicast group", 404 "Peer #%u could not create a multicast group",
405 mc_peer->peer); 405 multicast_peer->peer);
406 return NULL; 406 return NULL;
407 } 407 }
408
409 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 408 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
410 "Peer #%u connected as origin to group %s\n", 409 "Peer #%u connected as origin to group %s\n",
411 mc_peer->peer, 410 multicast_peer->peer,
412 GNUNET_h2s (&group_pub_key_hash)); 411 GNUNET_h2s (&group_pub_key_hash));
413
414 return origin; 412 return origin;
415 } 413 }
416 else 414 else
417 { 415 {
418 // Get members keys
419 member_pub_key[mc_peer->peer] = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
420 member_key[mc_peer->peer] = GNUNET_CRYPTO_ecdsa_key_create ();
421 GNUNET_CRYPTO_ecdsa_key_get_public (member_key[mc_peer->peer],
422 member_pub_key[mc_peer->peer]);
423
424 sprintf(data, "Hi, I am peer #%u (%s). Can I enter?", 416 sprintf(data, "Hi, I am peer #%u (%s). Can I enter?",
425 mc_peer->peer, 417 multicast_peer->peer,
426 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 418 GNUNET_i2s (multicast_peers[multicast_peer->peer]->id));
427 uint8_t data_size = strlen (data) + 1; 419 uint8_t data_size = strlen (data) + 1;
428 join_msg = GNUNET_malloc (sizeof (join_msg) + data_size); 420 join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
429 join_msg->size = htons (sizeof (join_msg) + data_size); 421 join_msg->size = htons (sizeof (join_msg) + data_size);
@@ -432,24 +424,25 @@ multicast_ca (void *cls,
432 424
433 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 425 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
434 "Peer #%u (%s) tries to join multicast group %s\n", 426 "Peer #%u (%s) tries to join multicast group %s\n",
435 mc_peer->peer, 427 multicast_peer->peer,
436 GNUNET_i2s (mc_peers[mc_peer->peer]->id), 428 GNUNET_i2s (multicast_peers[multicast_peer->peer]->id),
437 GNUNET_h2s (&group_pub_key_hash)); 429 GNUNET_h2s (&group_pub_key_hash));
438 430
439 member[mc_peer->peer] = GNUNET_MULTICAST_member_join (cfg, 431 members[multicast_peer->peer] =
440 &group_pub_key, 432 GNUNET_MULTICAST_member_join (cfg,
441 member_key[mc_peer->peer], 433 &group_pub_key,
442 mc_peers[0]->id, 434 multicast_peer->key,
443 0, 435 multicast_peers[0]->id,
444 NULL, 436 0,
445 join_msg, /* join message */ 437 NULL,
446 member_join_request, 438 join_msg, /* join message */
447 member_join_decision, 439 member_join_request,
448 member_replay_frag, 440 member_join_decision,
449 member_replay_msg, 441 member_replay_frag,
450 member_message, 442 member_replay_msg,
451 cls); 443 member_message,
452 return member[mc_peer->peer]; 444 cls);
445 return members[multicast_peer->peer];
453 } 446 }
454} 447}
455 448
@@ -460,7 +453,7 @@ peer_information_cb (void *cls,
460 const struct GNUNET_TESTBED_PeerInformation *pinfo, 453 const struct GNUNET_TESTBED_PeerInformation *pinfo,
461 const char *emsg) 454 const char *emsg)
462{ 455{
463 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 456 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
464 457
465 if (NULL == pinfo) { 458 if (NULL == pinfo) {
466 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n"); 459 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n");
@@ -468,7 +461,7 @@ peer_information_cb (void *cls,
468 GNUNET_SCHEDULER_shutdown (); 461 GNUNET_SCHEDULER_shutdown ();
469 } 462 }
470 463
471 mc_peers[mc_peer->peer]->id = pinfo->result.id; 464 multicast_peers[mc_peer->peer]->id = pinfo->result.id;
472 465
473 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 466 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
474 "Got peer information of %s (%s)\n", 467 "Got peer information of %s (%s)\n",
@@ -478,22 +471,28 @@ peer_information_cb (void *cls,
478 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 471 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
479 "Create peer #%u (%s)\n", 472 "Create peer #%u (%s)\n",
480 mc_peer->peer, 473 mc_peer->peer,
481 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 474 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
482 475
483 if (0 != mc_peer->peer) 476 if (0 != mc_peer->peer)
484 { 477 {
485 /* connect to multicast service of members */ 478 /* connect to multicast service of members */
486 op[mc_peer->peer] = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */ 479 op[mc_peer->peer] =
487 peers[mc_peer->peer], /* The peer whose service to connect to */ 480 GNUNET_TESTBED_service_connect (/* Closure for operation */
488 "multicast", /* The name of the service */ 481 NULL,
489 service_connect, /* callback to call after a handle to service 482 /* The peer whose service to connect to */
490 is opened */ 483 peers[mc_peer->peer],
491 cls, /* closure for the above callback */ 484 /* The name of the service */
492 multicast_ca, /* callback to call with peer's configuration; 485 "multicast",
493 this should open the needed service connection */ 486 /* called after a handle to service is opened */
494 multicast_da, /* callback to be called when closing the 487 service_connect,
495 opened service connection */ 488 /* closure for the above callback */
496 cls); /* closure for the above two callbacks */ 489 cls,
490 /* called when opening the service connection */
491 multicast_connect,
492 /* called when closing the service connection */
493 multicast_disconnect,
494 /* closure for the above two callbacks */
495 cls);
497 } 496 }
498} 497}
499 498
@@ -504,14 +503,14 @@ service_connect (void *cls,
504 void *ca_result, 503 void *ca_result,
505 const char *emsg) 504 const char *emsg)
506{ 505{
507 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 506 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
508 507
509 if (NULL == ca_result) 508 if (NULL == ca_result)
510 { 509 {
511 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 510 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
512 "Connection adapter not created for peer #%u (%s)\n", 511 "Connection adapter not created for peer #%u (%s)\n",
513 mc_peer->peer, 512 mc_peer->peer,
514 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 513 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
515 514
516 result = GNUNET_SYSERR; 515 result = GNUNET_SYSERR;
517 GNUNET_SCHEDULER_shutdown(); 516 GNUNET_SCHEDULER_shutdown();
@@ -525,7 +524,7 @@ service_connect (void *cls,
525 pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i], 524 pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i],
526 GNUNET_TESTBED_PIT_IDENTITY, 525 GNUNET_TESTBED_PIT_IDENTITY,
527 peer_information_cb, 526 peer_information_cb,
528 mc_peers[i]); 527 multicast_peers[i]);
529 } 528 }
530 } 529 }
531} 530}
@@ -549,50 +548,51 @@ service_connect (void *cls,
549 * @param links_failed number of links testbed was unable to establish 548 * @param links_failed number of links testbed was unable to establish
550 */ static void 549 */ static void
551testbed_master (void *cls, 550testbed_master (void *cls,
552 struct GNUNET_TESTBED_RunHandle *h, 551 struct GNUNET_TESTBED_RunHandle *h,
553 unsigned int num_peers, 552 unsigned int num_peers,
554 struct GNUNET_TESTBED_Peer **p, 553 struct GNUNET_TESTBED_Peer **p,
555 unsigned int links_succeeded, 554 unsigned int links_succeeded,
556 unsigned int links_failed) 555 unsigned int links_failed)
557{ 556{
558 /* Testbed is ready with peers running and connected in a pre-defined overlay 557 /* Testbed is ready with peers running and connected in a pre-defined overlay
559 topology (FIXME) */ 558 topology (FIXME) */
560
561 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
562 "Connected to testbed_master()\n");
563
564 peers = p; 559 peers = p;
565 560 multicast_peers = GNUNET_new_array (PEERS_REQUESTED, struct MulticastPeerContext*);
566 mc_peers = GNUNET_new_array (PEERS_REQUESTED, struct multicast_peer*);
567 561
568 // Create test contexts for members 562 // Create test contexts for members
569 for (int i = 0; i<PEERS_REQUESTED; i++) 563 for (int i = 0; i<PEERS_REQUESTED; i++)
570 { 564 {
571 mc_peers[i] = GNUNET_new (struct multicast_peer); 565 multicast_peers[i] = GNUNET_new (struct MulticastPeerContext);
572 mc_peers[i]->peer = i; 566 multicast_peers[i]->peer = i;
573 mc_peers[i]->test_ok = GNUNET_NO; 567 multicast_peers[i]->test_ok = GNUNET_NO;
574 } 568 }
575
576 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 569 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
577 "Create origin peer\n"); 570 "Create origin peer\n");
578 571 op[0] =
579 op[0] = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */ 572 GNUNET_TESTBED_service_connect (/* Closure for operation */
580 peers[0], /* The peer whose service to connect to */ 573 NULL,
581 "multicast", /* The name of the service */ 574 /* The peer whose service to connect to */
582 service_connect, /* callback to call after a handle to service 575 peers[0],
583 is opened */ 576 /* The name of the service */
584 mc_peers[0], /* closure for the above callback */ 577 "multicast",
585 multicast_ca, /* callback to call with peer's configuration; 578 /* called after a handle to service is opened */
586 this should open the needed service connection */ 579 service_connect,
587 multicast_da, /* callback to be called when closing the 580 /* closure for the above callback */
588 opened service connection */ 581 multicast_peers[0],
589 mc_peers[0]); /* closure for the above two callbacks */ 582 /* called when opening the service connection */
590 583 multicast_connect,
591 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */ 584 /* called when closing the service connection */
592 585 multicast_disconnect,
586 /* closure for the above two callbacks */
587 multicast_peers[0]);
588 /* Schedule a new task on shutdown */
589 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
593 /* Schedule the shutdown task with a delay of a few Seconds */ 590 /* Schedule the shutdown task with a delay of a few Seconds */
594 timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 400), 591 timeout_tid =
595 &timeout_task, NULL); 592 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
593 (GNUNET_TIME_UNIT_SECONDS, 400),
594 &timeout_task,
595 NULL);
596} 596}
597 597
598 598
@@ -616,15 +616,21 @@ main (int argc, char *argv[])
616 } 616 }
617 617
618 result = GNUNET_SYSERR; 618 result = GNUNET_SYSERR;
619 ret = GNUNET_TESTBED_test_run 619 ret =
620 ("test-multicast-multipeer", /* test case name */ 620 GNUNET_TESTBED_test_run ("test-multicast-multipeer",
621 config_file, /* template configuration */ 621 config_file,
622 PEERS_REQUESTED, /* number of peers to start */ 622 /* number of peers to start */
623 0LL, /* Event mask - set to 0 for no event notifications */ 623 PEERS_REQUESTED,
624 NULL, /* Controller event callback */ 624 /* Event mask - set to 0 for no event notifications */
625 NULL, /* Closure for controller event callback */ 625 0LL,
626 testbed_master, /* continuation callback to be called when testbed setup is complete */ 626 /* Controller event callback */
627 NULL); /* Closure for the test_master callback */ 627 NULL,
628 /* Closure for controller event callback */
629 NULL,
630 /* called when testbed setup is complete */
631 testbed_master,
632 /* Closure for the test_master callback */
633 NULL);
628 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) ) 634 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
629 return 1; 635 return 1;
630 return 0; 636 return 0;
diff --git a/src/psyc/gnunet-service-psyc.c b/src/psyc/gnunet-service-psyc.c
index 73a3ae4ee..cf161435a 100644
--- a/src/psyc/gnunet-service-psyc.c
+++ b/src/psyc/gnunet-service-psyc.c
@@ -279,7 +279,7 @@ struct Channel
279 * Is the client disconnected? 279 * Is the client disconnected?
280 * #GNUNET_YES or #GNUNET_NO 280 * #GNUNET_YES or #GNUNET_NO
281 */ 281 */
282 uint8_t is_disconnected; 282 uint8_t is_disconnecting;
283 283
284 /** 284 /**
285 * Is this a channel master (#GNUNET_YES), or slave (#GNUNET_NO)? 285 * Is this a channel master (#GNUNET_YES), or slave (#GNUNET_NO)?
@@ -508,8 +508,6 @@ cleanup_master (struct Master *mst)
508{ 508{
509 struct Channel *chn = &mst->channel; 509 struct Channel *chn = &mst->channel;
510 510
511 if (NULL != mst->origin)
512 GNUNET_MULTICAST_origin_stop (mst->origin, NULL, NULL); // FIXME
513 GNUNET_CONTAINER_multihashmap_destroy (mst->join_reqs); 511 GNUNET_CONTAINER_multihashmap_destroy (mst->join_reqs);
514 GNUNET_CONTAINER_multihashmap_remove (masters, &chn->pub_key_hash, mst); 512 GNUNET_CONTAINER_multihashmap_remove (masters, &chn->pub_key_hash, mst);
515} 513}
@@ -546,11 +544,6 @@ cleanup_slave (struct Slave *slv)
546 GNUNET_free (slv->relays); 544 GNUNET_free (slv->relays);
547 slv->relays = NULL; 545 slv->relays = NULL;
548 } 546 }
549 if (NULL != slv->member)
550 {
551 GNUNET_MULTICAST_member_part (slv->member, NULL, NULL); // FIXME
552 slv->member = NULL;
553 }
554 GNUNET_CONTAINER_multihashmap_remove (slaves, &chn->pub_key_hash, slv); 547 GNUNET_CONTAINER_multihashmap_remove (slaves, &chn->pub_key_hash, slv);
555} 548}
556 549
@@ -603,15 +596,16 @@ client_notify_disconnect (void *cls,
603 if (NULL == chn) 596 if (NULL == chn)
604 { 597 {
605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606 "%p User context is NULL in client_disconnect()\n", 599 "%p User context is NULL in client_notify_disconnect ()\n",
607 chn); 600 chn);
608 GNUNET_break (0); 601 GNUNET_break (0);
609 return; 602 return;
610 } 603 }
611 604
612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
613 "%p Client (%s) disconnected from channel %s\n", 606 "%p Client %p (%s) disconnected from channel %s\n",
614 chn, 607 chn,
608 client,
615 (GNUNET_YES == chn->is_master) ? "master" : "slave", 609 (GNUNET_YES == chn->is_master) ? "master" : "slave",
616 GNUNET_h2s (&chn->pub_key_hash)); 610 GNUNET_h2s (&chn->pub_key_hash));
617 611
@@ -645,15 +639,8 @@ client_notify_disconnect (void *cls,
645 chn, 639 chn,
646 (GNUNET_YES == chn->is_master) ? "master" : "slave", 640 (GNUNET_YES == chn->is_master) ? "master" : "slave",
647 GNUNET_h2s (&chn->pub_key_hash)); 641 GNUNET_h2s (&chn->pub_key_hash));
648 chn->is_disconnected = GNUNET_YES; 642 chn->is_disconnecting = GNUNET_YES;
649 if (NULL != chn->tmit_head) 643 cleanup_channel (chn);
650 { /* Send pending messages to multicast before cleanup. */
651 transmit_message (chn);
652 }
653 else
654 {
655 cleanup_channel (chn);
656 }
657 } 644 }
658} 645}
659 646
@@ -688,7 +675,7 @@ client_send_msg (const struct Channel *chn,
688 const struct GNUNET_MessageHeader *msg) 675 const struct GNUNET_MessageHeader *msg)
689{ 676{
690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
691 "%p Sending message to clients.\n", 678 "Sending message to clients of channel %p.\n",
692 chn); 679 chn);
693 680
694 struct ClientList *cli = chn->clients_head; 681 struct ClientList *cli = chn->clients_head;
@@ -699,7 +686,6 @@ client_send_msg (const struct Channel *chn,
699 686
700 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cli->client), 687 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cli->client),
701 env); 688 env);
702
703 cli = cli->next; 689 cli = cli->next;
704 } 690 }
705} 691}
@@ -734,7 +720,7 @@ client_send_result (struct GNUNET_SERVICE_Client *client, uint64_t op_id,
734 GNUNET_memcpy (&res[1], data, data_size); 720 GNUNET_memcpy (&res[1], data, data_size);
735 721
736 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
737 "%p Sending result to client for operation #%" PRIu64 ": %" PRId64 " (size: %u)\n", 723 "%p Sending result to client for OP ID %" PRIu64 ": %" PRId64 " (size: %u)\n",
738 client, 724 client,
739 GNUNET_ntohll (op_id), 725 GNUNET_ntohll (op_id),
740 result_code, 726 result_code,
@@ -1202,12 +1188,12 @@ fragment_queue_insert (struct Channel *chn,
1202 else if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == first_ptype 1188 else if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == first_ptype
1203 || frag_offset == fragq->header_size) 1189 || frag_offset == fragq->header_size)
1204 { /* header is now complete */ 1190 { /* header is now complete */
1205 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1206 "%p Header of message %" PRIu64 " is complete.\n", 1192 "%p Header of message %" PRIu64 " is complete.\n",
1207 chn, 1193 chn,
1208 GNUNET_ntohll (mmsg->message_id)); 1194 GNUNET_ntohll (mmsg->message_id));
1209 1195
1210 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1211 "%p Adding message %" PRIu64 " to queue.\n", 1197 "%p Adding message %" PRIu64 " to queue.\n",
1212 chn, 1198 chn,
1213 GNUNET_ntohll (mmsg->message_id)); 1199 GNUNET_ntohll (mmsg->message_id));
@@ -1215,7 +1201,7 @@ fragment_queue_insert (struct Channel *chn,
1215 } 1201 }
1216 else 1202 else
1217 { 1203 {
1218 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1219 "%p Header of message %" PRIu64 " is NOT complete yet: %" PRIu64 " != %" PRIu64 "\n", 1205 "%p Header of message %" PRIu64 " is NOT complete yet: %" PRIu64 " != %" PRIu64 "\n",
1220 chn, 1206 chn,
1221 GNUNET_ntohll (mmsg->message_id), 1207 GNUNET_ntohll (mmsg->message_id),
@@ -1230,7 +1216,7 @@ fragment_queue_insert (struct Channel *chn,
1230 if (frag_offset == fragq->size) 1216 if (frag_offset == fragq->size)
1231 fragq->state = MSG_FRAG_STATE_END; 1217 fragq->state = MSG_FRAG_STATE_END;
1232 else 1218 else
1233 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1234 "%p Message %" PRIu64 " is NOT complete yet: %" PRIu64 " != %" PRIu64 "\n", 1220 "%p Message %" PRIu64 " is NOT complete yet: %" PRIu64 " != %" PRIu64 "\n",
1235 chn, 1221 chn,
1236 GNUNET_ntohll (mmsg->message_id), 1222 GNUNET_ntohll (mmsg->message_id),
@@ -1285,7 +1271,7 @@ static void
1285fragment_queue_run (struct Channel *chn, uint64_t msg_id, 1271fragment_queue_run (struct Channel *chn, uint64_t msg_id,
1286 struct FragmentQueue *fragq, uint8_t drop) 1272 struct FragmentQueue *fragq, uint8_t drop)
1287{ 1273{
1288 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1289 "%p Running message fragment queue for message %" PRIu64 " (state: %u).\n", 1275 "%p Running message fragment queue for message %" PRIu64 " (state: %u).\n",
1290 chn, 1276 chn,
1291 msg_id, 1277 msg_id,
@@ -1413,7 +1399,7 @@ store_recv_state_modify_result (void *cls, int64_t result,
1413static uint64_t 1399static uint64_t
1414message_queue_run (struct Channel *chn) 1400message_queue_run (struct Channel *chn)
1415{ 1401{
1416 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1417 "%p Running message queue.\n", chn); 1403 "%p Running message queue.\n", chn);
1418 uint64_t n = 0; 1404 uint64_t n = 0;
1419 uint64_t msg_id; 1405 uint64_t msg_id;
@@ -1421,7 +1407,7 @@ message_queue_run (struct Channel *chn)
1421 while (GNUNET_YES == GNUNET_CONTAINER_heap_peek2 (chn->recv_msgs, NULL, 1407 while (GNUNET_YES == GNUNET_CONTAINER_heap_peek2 (chn->recv_msgs, NULL,
1422 &msg_id)) 1408 &msg_id))
1423 { 1409 {
1424 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1425 "%p Processing message %" PRIu64 " in queue.\n", chn, msg_id); 1411 "%p Processing message %" PRIu64 " in queue.\n", chn, msg_id);
1426 struct GNUNET_HashCode msg_id_hash; 1412 struct GNUNET_HashCode msg_id_hash;
1427 hash_key_from_hll (&msg_id_hash, msg_id); 1413 hash_key_from_hll (&msg_id_hash, msg_id);
@@ -1431,7 +1417,7 @@ message_queue_run (struct Channel *chn)
1431 1417
1432 if (NULL == fragq || fragq->state <= MSG_FRAG_STATE_HEADER) 1418 if (NULL == fragq || fragq->state <= MSG_FRAG_STATE_HEADER)
1433 { 1419 {
1434 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1420 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1435 "%p No fragq (%p) or header not complete.\n", 1421 "%p No fragq (%p) or header not complete.\n",
1436 chn, fragq); 1422 chn, fragq);
1437 break; 1423 break;
@@ -1453,7 +1439,7 @@ message_queue_run (struct Channel *chn)
1453 && (chn->max_message_id != msg_id - 1 1439 && (chn->max_message_id != msg_id - 1
1454 && chn->max_message_id != msg_id)) 1440 && chn->max_message_id != msg_id))
1455 { 1441 {
1456 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1442 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1457 "%p Out of order message. " 1443 "%p Out of order message. "
1458 "(%" PRIu64 " != %" PRIu64 " - 1)\n", 1444 "(%" PRIu64 " != %" PRIu64 " - 1)\n",
1459 chn, chn->max_message_id, msg_id); 1445 chn, chn->max_message_id, msg_id);
@@ -1469,7 +1455,7 @@ message_queue_run (struct Channel *chn)
1469 { 1455 {
1470 if (msg_id - fragq->state_delta != chn->max_state_message_id) 1456 if (msg_id - fragq->state_delta != chn->max_state_message_id)
1471 { 1457 {
1472 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1473 "%p Out of order stateful message. " 1459 "%p Out of order stateful message. "
1474 "(%" PRIu64 " - %" PRIu64 " != %" PRIu64 ")\n", 1460 "(%" PRIu64 " - %" PRIu64 " != %" PRIu64 ")\n",
1475 chn, msg_id, fragq->state_delta, chn->max_state_message_id); 1461 chn, msg_id, fragq->state_delta, chn->max_state_message_id);
@@ -1515,8 +1501,6 @@ message_queue_run (struct Channel *chn)
1515static uint64_t 1501static uint64_t
1516message_queue_drop (struct Channel *chn) 1502message_queue_drop (struct Channel *chn)
1517{ 1503{
1518 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1519 "%p Dropping message queue.\n", chn);
1520 uint64_t n = 0; 1504 uint64_t n = 0;
1521 uint64_t msg_id; 1505 uint64_t msg_id;
1522 while (GNUNET_YES == GNUNET_CONTAINER_heap_peek2 (chn->recv_msgs, NULL, 1506 while (GNUNET_YES == GNUNET_CONTAINER_heap_peek2 (chn->recv_msgs, NULL,
@@ -1703,7 +1687,7 @@ store_recv_slave_counters (void *cls, int result, uint64_t max_fragment_id,
1703 res.result_code = htonl (result); 1687 res.result_code = htonl (result);
1704 res.max_message_id = GNUNET_htonll (max_message_id); 1688 res.max_message_id = GNUNET_htonll (max_message_id);
1705 1689
1706 if (GNUNET_OK == result || GNUNET_NO == result) 1690 if (GNUNET_YES == result || GNUNET_NO == result)
1707 { 1691 {
1708 chn->max_message_id = max_message_id; 1692 chn->max_message_id = max_message_id;
1709 chn->max_state_message_id = max_state_message_id; 1693 chn->max_state_message_id = max_state_message_id;
@@ -1831,6 +1815,9 @@ handle_client_slave_join (void *cls,
1831 struct GNUNET_CRYPTO_EcdsaPublicKey slv_pub_key; 1815 struct GNUNET_CRYPTO_EcdsaPublicKey slv_pub_key;
1832 struct GNUNET_HashCode pub_key_hash, slv_pub_hash; 1816 struct GNUNET_HashCode pub_key_hash, slv_pub_hash;
1833 1817
1818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1819 "got join request from client %p\n",
1820 client);
1834 GNUNET_CRYPTO_ecdsa_key_get_public (&req->slave_key, &slv_pub_key); 1821 GNUNET_CRYPTO_ecdsa_key_get_public (&req->slave_key, &slv_pub_key);
1835 GNUNET_CRYPTO_hash (&slv_pub_key, sizeof (slv_pub_key), &slv_pub_hash); 1822 GNUNET_CRYPTO_hash (&slv_pub_key, sizeof (slv_pub_key), &slv_pub_hash);
1836 GNUNET_CRYPTO_hash (&req->channel_pub_key, sizeof (req->channel_pub_key), &pub_key_hash); 1823 GNUNET_CRYPTO_hash (&req->channel_pub_key, sizeof (req->channel_pub_key), &pub_key_hash);
@@ -1905,7 +1892,7 @@ handle_client_slave_join (void *cls,
1905 GNUNET_CONTAINER_multihashmap_put (slaves, &chn->pub_key_hash, chn, 1892 GNUNET_CONTAINER_multihashmap_put (slaves, &chn->pub_key_hash, chn,
1906 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1893 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1907 chn->store_op = GNUNET_PSYCSTORE_counters_get (store, &chn->pub_key, 1894 chn->store_op = GNUNET_PSYCSTORE_counters_get (store, &chn->pub_key,
1908 &store_recv_slave_counters, slv); 1895 &store_recv_slave_counters, slv);
1909 } 1896 }
1910 else 1897 else
1911 { 1898 {
@@ -1952,8 +1939,9 @@ handle_client_slave_join (void *cls,
1952 } 1939 }
1953 1940
1954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1955 "%p Client connected as slave to channel %s.\n", 1942 "Client %p connected as slave to channel %s.\n",
1956 slv, GNUNET_h2s (&chn->pub_key_hash)); 1943 client,
1944 GNUNET_h2s (&chn->pub_key_hash));
1957 1945
1958 struct ClientList *cli = GNUNET_malloc (sizeof (*cli)); 1946 struct ClientList *cli = GNUNET_malloc (sizeof (*cli));
1959 cli->client = client; 1947 cli->client = client;
@@ -2037,6 +2025,49 @@ handle_client_join_decision (void *cls,
2037} 2025}
2038 2026
2039 2027
2028static void
2029channel_part_cb (void *cls)
2030{
2031 struct GNUNET_SERVICE_Client *client = cls;
2032 struct GNUNET_MQ_Envelope *env;
2033
2034 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_PSYC_PART_ACK);
2035 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
2036 env);
2037}
2038
2039
2040static void
2041handle_client_part_request (void *cls,
2042 const struct GNUNET_MessageHeader *msg)
2043{
2044 struct Client *c = cls;
2045
2046 c->channel->is_disconnecting = GNUNET_YES;
2047 if (GNUNET_YES == c->channel->is_master)
2048 {
2049 struct Master *mst = (struct Master *) c->channel;
2050
2051 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2052 "Got part request from master %p\n",
2053 mst);
2054 GNUNET_assert (NULL != mst->origin);
2055 GNUNET_MULTICAST_origin_stop (mst->origin, channel_part_cb, c->client);
2056 }
2057 else
2058 {
2059 struct Slave *slv = (struct Slave *) c->channel;
2060
2061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2062 "Got part request from slave %p\n",
2063 slv);
2064 GNUNET_assert (NULL != slv->member);
2065 GNUNET_MULTICAST_member_part (slv->member, channel_part_cb, c->client);
2066 }
2067 GNUNET_SERVICE_client_continue (c->client);
2068}
2069
2070
2040/** 2071/**
2041 * Send acknowledgement to a client. 2072 * Send acknowledgement to a client.
2042 * 2073 *
@@ -2096,7 +2127,7 @@ transmit_notify (void *cls, size_t *data_size, void *data)
2096 { 2127 {
2097 GNUNET_SCHEDULER_add_now (&schedule_transmit_message, chn); 2128 GNUNET_SCHEDULER_add_now (&schedule_transmit_message, chn);
2098 } 2129 }
2099 else if (GNUNET_YES == chn->is_disconnected 2130 else if (GNUNET_YES == chn->is_disconnecting
2100 && tmit_msg->last_ptype < GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END) 2131 && tmit_msg->last_ptype < GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END)
2101 { 2132 {
2102 /* FIXME: handle partial message (when still in_transmit) */ 2133 /* FIXME: handle partial message (when still in_transmit) */
@@ -2208,12 +2239,10 @@ transmit_message (struct Channel *chn)
2208static void 2239static void
2209master_queue_message (struct Master *mst, struct TransmitMessage *tmit_msg) 2240master_queue_message (struct Master *mst, struct TransmitMessage *tmit_msg)
2210{ 2241{
2211 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%p master_queue_message()\n", mst);
2212
2213 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == tmit_msg->first_ptype) 2242 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == tmit_msg->first_ptype)
2214 { 2243 {
2215 tmit_msg->id = ++mst->max_message_id; 2244 tmit_msg->id = ++mst->max_message_id;
2216 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2217 "%p master_queue_message: message_id=%" PRIu64 "\n", 2246 "%p master_queue_message: message_id=%" PRIu64 "\n",
2218 mst, tmit_msg->id); 2247 mst, tmit_msg->id);
2219 struct GNUNET_PSYC_MessageMethod *pmeth 2248 struct GNUNET_PSYC_MessageMethod *pmeth
@@ -2225,7 +2254,7 @@ master_queue_message (struct Master *mst, struct TransmitMessage *tmit_msg)
2225 } 2254 }
2226 else if (pmeth->flags & GNUNET_PSYC_MASTER_TRANSMIT_STATE_MODIFY) 2255 else if (pmeth->flags & GNUNET_PSYC_MASTER_TRANSMIT_STATE_MODIFY)
2227 { 2256 {
2228 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2229 "%p master_queue_message: state_delta=%" PRIu64 "\n", 2258 "%p master_queue_message: state_delta=%" PRIu64 "\n",
2230 mst, tmit_msg->id - mst->max_state_message_id); 2259 mst, tmit_msg->id - mst->max_state_message_id);
2231 pmeth->state_delta = GNUNET_htonll (tmit_msg->id 2260 pmeth->state_delta = GNUNET_htonll (tmit_msg->id
@@ -2234,7 +2263,7 @@ master_queue_message (struct Master *mst, struct TransmitMessage *tmit_msg)
2234 } 2263 }
2235 else 2264 else
2236 { 2265 {
2237 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2238 "%p master_queue_message: state not modified\n", mst); 2267 "%p master_queue_message: state not modified\n", mst);
2239 pmeth->state_delta = GNUNET_htonll (GNUNET_PSYC_STATE_NOT_MODIFIED); 2268 pmeth->state_delta = GNUNET_htonll (GNUNET_PSYC_STATE_NOT_MODIFIED);
2240 } 2269 }
@@ -2359,7 +2388,9 @@ handle_client_psyc_message (void *cls,
2359 if (GNUNET_YES != chn->is_ready) 2388 if (GNUNET_YES != chn->is_ready)
2360 { 2389 {
2361 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2390 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2362 "%p Channel is not ready yet, disconnecting client.\n", chn); 2391 "%p Channel is not ready yet, disconnecting client %p.\n",
2392 chn,
2393 client);
2363 GNUNET_break (0); 2394 GNUNET_break (0);
2364 GNUNET_SERVICE_client_drop (client); 2395 GNUNET_SERVICE_client_drop (client);
2365 return; 2396 return;
@@ -2789,9 +2820,9 @@ run (void *cls,
2789GNUNET_SERVICE_MAIN 2820GNUNET_SERVICE_MAIN
2790("psyc", 2821("psyc",
2791 GNUNET_SERVICE_OPTION_NONE, 2822 GNUNET_SERVICE_OPTION_NONE,
2792 run, 2823 &run,
2793 client_notify_connect, 2824 &client_notify_connect,
2794 client_notify_disconnect, 2825 &client_notify_disconnect,
2795 NULL, 2826 NULL,
2796 GNUNET_MQ_hd_fixed_size (client_master_start, 2827 GNUNET_MQ_hd_fixed_size (client_master_start,
2797 GNUNET_MESSAGE_TYPE_PSYC_MASTER_START, 2828 GNUNET_MESSAGE_TYPE_PSYC_MASTER_START,
@@ -2805,6 +2836,10 @@ GNUNET_SERVICE_MAIN
2805 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 2836 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
2806 struct GNUNET_PSYC_JoinDecisionMessage, 2837 struct GNUNET_PSYC_JoinDecisionMessage,
2807 NULL), 2838 NULL),
2839 GNUNET_MQ_hd_fixed_size (client_part_request,
2840 GNUNET_MESSAGE_TYPE_PSYC_PART_REQUEST,
2841 struct GNUNET_MessageHeader,
2842 NULL),
2808 GNUNET_MQ_hd_var_size (client_psyc_message, 2843 GNUNET_MQ_hd_var_size (client_psyc_message,
2809 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 2844 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
2810 struct GNUNET_MessageHeader, 2845 struct GNUNET_MessageHeader,
diff --git a/src/psyc/psyc_api.c b/src/psyc/psyc_api.c
index c93d8b383..d8f4c98bc 100644
--- a/src/psyc/psyc_api.c
+++ b/src/psyc/psyc_api.c
@@ -260,6 +260,10 @@ handle_channel_result (void *cls,
260 GNUNET_OP_result (chn->op, GNUNET_ntohll (res->op_id), 260 GNUNET_OP_result (chn->op, GNUNET_ntohll (res->op_id),
261 GNUNET_ntohll (res->result_code), 261 GNUNET_ntohll (res->result_code),
262 data, data_size, NULL); 262 data, data_size, NULL);
263
264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
265 "handle_channel_result: Received result message with OP ID %" PRIu64 "\n",
266 GNUNET_ntohll (res->op_id));
263} 267}
264 268
265 269
@@ -555,6 +559,9 @@ handle_slave_join_decision (void *cls,
555static void 559static void
556channel_cleanup (struct GNUNET_PSYC_Channel *chn) 560channel_cleanup (struct GNUNET_PSYC_Channel *chn)
557{ 561{
562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
563 "cleaning up channel %p\n",
564 chn);
558 if (NULL != chn->tmit) 565 if (NULL != chn->tmit)
559 { 566 {
560 GNUNET_PSYC_transmit_destroy (chn->tmit); 567 GNUNET_PSYC_transmit_destroy (chn->tmit);
@@ -562,6 +569,7 @@ channel_cleanup (struct GNUNET_PSYC_Channel *chn)
562 } 569 }
563 if (NULL != chn->recv) 570 if (NULL != chn->recv)
564 { 571 {
572
565 GNUNET_PSYC_receive_destroy (chn->recv); 573 GNUNET_PSYC_receive_destroy (chn->recv);
566 chn->recv = NULL; 574 chn->recv = NULL;
567 } 575 }
@@ -585,30 +593,12 @@ channel_cleanup (struct GNUNET_PSYC_Channel *chn)
585 593
586 594
587static void 595static void
588channel_disconnect (struct GNUNET_PSYC_Channel *chn, 596handle_channel_part_ack (void *cls,
589 GNUNET_ContinuationCallback cb, 597 const struct GNUNET_MessageHeader *msg)
590 void *cls)
591{ 598{
592 chn->is_disconnecting = GNUNET_YES; 599 struct GNUNET_PSYC_Channel *chn = cls;
593 chn->disconnect_cb = cb;
594 chn->disconnect_cls = cls;
595 600
596 if (NULL != chn->mq) 601 channel_cleanup (chn);
597 {
598 struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (chn->mq);
599 if (NULL != env)
600 {
601 GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) channel_cleanup, chn);
602 }
603 else
604 {
605 channel_cleanup (chn);
606 }
607 }
608 else
609 {
610 channel_cleanup (chn);
611 }
612} 602}
613 603
614 604
@@ -671,6 +661,10 @@ master_connect (struct GNUNET_PSYC_Master *mst)
671 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, 661 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
672 struct GNUNET_PSYC_JoinRequestMessage, 662 struct GNUNET_PSYC_JoinRequestMessage,
673 mst), 663 mst),
664 GNUNET_MQ_hd_fixed_size (channel_part_ack,
665 GNUNET_MESSAGE_TYPE_PSYC_PART_ACK,
666 struct GNUNET_MessageHeader,
667 chn),
674 GNUNET_MQ_hd_var_size (channel_message, 668 GNUNET_MQ_hd_var_size (channel_message,
675 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 669 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
676 struct GNUNET_PSYC_MessageHeader, 670 struct GNUNET_PSYC_MessageHeader,
@@ -694,8 +688,11 @@ master_connect (struct GNUNET_PSYC_Master *mst)
694 GNUNET_MQ_handler_end () 688 GNUNET_MQ_handler_end ()
695 }; 689 };
696 690
697 chn->mq = GNUNET_CLIENT_connect (chn->cfg, "psyc", 691 chn->mq = GNUNET_CLIENT_connect (chn->cfg,
698 handlers, master_disconnected, mst); 692 "psyc",
693 handlers,
694 &master_disconnected,
695 mst);
699 GNUNET_assert (NULL != chn->mq); 696 GNUNET_assert (NULL != chn->mq);
700 chn->tmit = GNUNET_PSYC_transmit_create (chn->mq); 697 chn->tmit = GNUNET_PSYC_transmit_create (chn->mq);
701 698
@@ -780,10 +777,13 @@ GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *mst,
780 void *stop_cls) 777 void *stop_cls)
781{ 778{
782 struct GNUNET_PSYC_Channel *chn = &mst->chn; 779 struct GNUNET_PSYC_Channel *chn = &mst->chn;
780 struct GNUNET_MQ_Envelope *env;
783 781
784 /* FIXME: send msg to service */ 782 chn->is_disconnecting = GNUNET_YES;
785 783 chn->disconnect_cb = stop_cb;
786 channel_disconnect (chn, stop_cb, stop_cls); 784 chn->disconnect_cls = stop_cls;
785 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_PSYC_PART_REQUEST);
786 GNUNET_MQ_send (chn->mq, env);
787} 787}
788 788
789 789
@@ -931,7 +931,8 @@ slave_reconnect (void *cls)
931 * Reconnect after backoff period. 931 * Reconnect after backoff period.
932 */ 932 */
933static void 933static void
934slave_disconnected (void *cls, enum GNUNET_MQ_Error error) 934slave_disconnected (void *cls,
935 enum GNUNET_MQ_Error error)
935{ 936{
936 struct GNUNET_PSYC_Slave *slv = cls; 937 struct GNUNET_PSYC_Slave *slv = cls;
937 struct GNUNET_PSYC_Channel *chn = &slv->chn; 938 struct GNUNET_PSYC_Channel *chn = &slv->chn;
@@ -950,7 +951,7 @@ slave_disconnected (void *cls, enum GNUNET_MQ_Error error)
950 chn->mq = NULL; 951 chn->mq = NULL;
951 } 952 }
952 chn->reconnect_task = GNUNET_SCHEDULER_add_delayed (chn->reconnect_delay, 953 chn->reconnect_task = GNUNET_SCHEDULER_add_delayed (chn->reconnect_delay,
953 slave_reconnect, 954 &slave_reconnect,
954 slv); 955 slv);
955 chn->reconnect_delay = GNUNET_TIME_STD_BACKOFF (chn->reconnect_delay); 956 chn->reconnect_delay = GNUNET_TIME_STD_BACKOFF (chn->reconnect_delay);
956} 957}
@@ -970,6 +971,10 @@ slave_connect (struct GNUNET_PSYC_Slave *slv)
970 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 971 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
971 struct GNUNET_PSYC_JoinDecisionMessage, 972 struct GNUNET_PSYC_JoinDecisionMessage,
972 slv), 973 slv),
974 GNUNET_MQ_hd_fixed_size (channel_part_ack,
975 GNUNET_MESSAGE_TYPE_PSYC_PART_ACK,
976 struct GNUNET_MessageHeader,
977 chn),
973 GNUNET_MQ_hd_var_size (channel_message, 978 GNUNET_MQ_hd_var_size (channel_message,
974 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 979 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
975 struct GNUNET_PSYC_MessageHeader, 980 struct GNUNET_PSYC_MessageHeader,
@@ -993,9 +998,19 @@ slave_connect (struct GNUNET_PSYC_Slave *slv)
993 GNUNET_MQ_handler_end () 998 GNUNET_MQ_handler_end ()
994 }; 999 };
995 1000
996 chn->mq = GNUNET_CLIENT_connect (chn->cfg, "psyc", 1001 chn->mq = GNUNET_CLIENT_connect (chn->cfg,
997 handlers, slave_disconnected, slv); 1002 "psyc",
998 GNUNET_assert (NULL != chn->mq); 1003 handlers,
1004 &slave_disconnected,
1005 slv);
1006 if (NULL == chn->mq)
1007 {
1008 chn->reconnect_task = GNUNET_SCHEDULER_add_delayed (chn->reconnect_delay,
1009 &slave_reconnect,
1010 slv);
1011 chn->reconnect_delay = GNUNET_TIME_STD_BACKOFF (chn->reconnect_delay);
1012 return;
1013 }
999 chn->tmit = GNUNET_PSYC_transmit_create (chn->mq); 1014 chn->tmit = GNUNET_PSYC_transmit_create (chn->mq);
1000 1015
1001 GNUNET_MQ_send_copy (chn->mq, chn->connect_env); 1016 GNUNET_MQ_send_copy (chn->mq, chn->connect_env);
@@ -1107,10 +1122,13 @@ GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slv,
1107 void *part_cls) 1122 void *part_cls)
1108{ 1123{
1109 struct GNUNET_PSYC_Channel *chn = &slv->chn; 1124 struct GNUNET_PSYC_Channel *chn = &slv->chn;
1125 struct GNUNET_MQ_Envelope *env;
1110 1126
1111 /* FIXME: send msg to service */ 1127 chn->is_disconnecting = GNUNET_YES;
1112 1128 chn->disconnect_cb = part_cb;
1113 channel_disconnect (chn, part_cb, part_cls); 1129 chn->disconnect_cls = part_cls;
1130 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_PSYC_PART_REQUEST);
1131 GNUNET_MQ_send (chn->mq, env);
1114} 1132}
1115 1133
1116 1134
@@ -1233,6 +1251,9 @@ GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *chn,
1233 req->did_join = GNUNET_YES; 1251 req->did_join = GNUNET_YES;
1234 req->op_id = GNUNET_htonll (GNUNET_OP_add (chn->op, result_cb, cls, NULL)); 1252 req->op_id = GNUNET_htonll (GNUNET_OP_add (chn->op, result_cb, cls, NULL));
1235 1253
1254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1255 "GNUNET_PSYC_channel_slave_add, OP ID: %" PRIu64 "\n",
1256 GNUNET_ntohll (req->op_id));
1236 GNUNET_MQ_send (chn->mq, env); 1257 GNUNET_MQ_send (chn->mq, env);
1237} 1258}
1238 1259
@@ -1283,6 +1304,9 @@ GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *chn,
1283 req->did_join = GNUNET_NO; 1304 req->did_join = GNUNET_NO;
1284 req->op_id = GNUNET_htonll (GNUNET_OP_add (chn->op, result_cb, cls, NULL)); 1305 req->op_id = GNUNET_htonll (GNUNET_OP_add (chn->op, result_cb, cls, NULL));
1285 1306
1307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1308 "GNUNET_PSYC_channel_slave_remove, OP ID: %" PRIu64 "\n",
1309 GNUNET_ntohll (req->op_id));
1286 GNUNET_MQ_send (chn->mq, env); 1310 GNUNET_MQ_send (chn->mq, env);
1287} 1311}
1288 1312
@@ -1321,6 +1345,10 @@ channel_history_replay (struct GNUNET_PSYC_Channel *chn,
1321 req->message_limit = GNUNET_htonll (message_limit); 1345 req->message_limit = GNUNET_htonll (message_limit);
1322 req->flags = htonl (flags); 1346 req->flags = htonl (flags);
1323 req->op_id = GNUNET_htonll (hist->op_id); 1347 req->op_id = GNUNET_htonll (hist->op_id);
1348
1349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1350 "channel_history_replay, OP ID: %" PRIu64 "\n",
1351 GNUNET_ntohll (req->op_id));
1324 GNUNET_memcpy (&req[1], method_prefix, method_size); 1352 GNUNET_memcpy (&req[1], method_prefix, method_size);
1325 1353
1326 GNUNET_MQ_send (chn->mq, env); 1354 GNUNET_MQ_send (chn->mq, env);
@@ -1459,6 +1487,11 @@ channel_state_get (struct GNUNET_PSYC_Channel *chn,
1459 struct GNUNET_MQ_Envelope * 1487 struct GNUNET_MQ_Envelope *
1460 env = GNUNET_MQ_msg_extra (req, name_size, type); 1488 env = GNUNET_MQ_msg_extra (req, name_size, type);
1461 req->op_id = GNUNET_htonll (sr->op_id); 1489 req->op_id = GNUNET_htonll (sr->op_id);
1490
1491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1492 "channel_state_get, OP ID: %" PRIu64 "\n",
1493 GNUNET_ntohll (req->op_id));
1494
1462 GNUNET_memcpy (&req[1], name, name_size); 1495 GNUNET_memcpy (&req[1], name, name_size);
1463 1496
1464 GNUNET_MQ_send (chn->mq, env); 1497 GNUNET_MQ_send (chn->mq, env);
diff --git a/src/psyc/test_psyc.c b/src/psyc/test_psyc.c
index 03a1890b1..370befb9d 100644
--- a/src/psyc/test_psyc.c
+++ b/src/psyc/test_psyc.c
@@ -755,15 +755,22 @@ slave_add ()
755 755
756 756
757static void 757static void
758schedule_second_slave_join (void *cls)
759{
760 slave_join (TEST_SLAVE_JOIN_ACCEPT);
761}
762
763
764static void
758first_slave_parted (void *cls) 765first_slave_parted (void *cls)
759{ 766{
760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First slave parted.\n"); 767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First slave parted.\n");
761 slave_join (TEST_SLAVE_JOIN_ACCEPT); 768 GNUNET_SCHEDULER_add_now (&schedule_second_slave_join, NULL);
762} 769}
763 770
764 771
765static void 772static void
766schedule_slave_part (void *cls) 773schedule_first_slave_part (void *cls)
767{ 774{
768 GNUNET_PSYC_slave_part (slv, GNUNET_NO, &first_slave_parted, NULL); 775 GNUNET_PSYC_slave_part (slv, GNUNET_NO, &first_slave_parted, NULL);
769} 776}
@@ -783,7 +790,7 @@ join_decision_cb (void *cls,
783 case TEST_SLAVE_JOIN_REJECT: 790 case TEST_SLAVE_JOIN_REJECT:
784 GNUNET_assert (0 == is_admitted); 791 GNUNET_assert (0 == is_admitted);
785 GNUNET_assert (1 == join_req_count); 792 GNUNET_assert (1 == join_req_count);
786 GNUNET_SCHEDULER_add_now (&schedule_slave_part, NULL); 793 GNUNET_SCHEDULER_add_now (&schedule_first_slave_part, NULL);
787 break; 794 break;
788 795
789 case TEST_SLAVE_JOIN_ACCEPT: 796 case TEST_SLAVE_JOIN_ACCEPT:
@@ -844,11 +851,18 @@ slave_join (int t)
844 struct GNUNET_PSYC_Message * 851 struct GNUNET_PSYC_Message *
845 join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 9); 852 join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 9);
846 853
847 slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key, 854 slv = GNUNET_PSYC_slave_join (cfg,
855 &channel_pub_key,
856 slave_key,
848 GNUNET_PSYC_SLAVE_JOIN_NONE, 857 GNUNET_PSYC_SLAVE_JOIN_NONE,
849 &origin, 0, NULL, 858 &origin,
850 &slave_message_cb, &slave_message_part_cb, 859 0,
851 &slave_connect_cb, &join_decision_cb, NULL, 860 NULL,
861 &slave_message_cb,
862 &slave_message_part_cb,
863 &slave_connect_cb,
864 &join_decision_cb,
865 NULL,
852 join_msg); 866 join_msg);
853 GNUNET_free (join_msg); 867 GNUNET_free (join_msg);
854 slv_chn = GNUNET_PSYC_slave_get_channel (slv); 868 slv_chn = GNUNET_PSYC_slave_get_channel (slv);
diff --git a/src/psyc/test_psyc.conf b/src/psyc/test_psyc.conf
index e69de29bb..e00a614d2 100644
--- a/src/psyc/test_psyc.conf
+++ b/src/psyc/test_psyc.conf
@@ -0,0 +1,16 @@
1@INLINE@ ../../contrib/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/gnunet-test-psyc/
5
6[transport]
7PLUGINS = tcp
8
9[nat]
10DISABLEV6 = YES
11ENABLE_UPNP = NO
12BEHIND_NAT = NO
13ALLOW_NAT = NO
14INTERNAL_ADDRESS = 127.0.0.1
15EXTERNAL_ADDRESS = 127.0.0.1
16
diff --git a/src/psycstore/psycstore_api.c b/src/psycstore/psycstore_api.c
index d79daa357..16f4a1ae9 100644
--- a/src/psycstore/psycstore_api.c
+++ b/src/psycstore/psycstore_api.c
@@ -148,14 +148,14 @@ handle_result_code (void *cls, const struct OperationResult *opres)
148 str, size - sizeof (*opres), (void **) &op)) 148 str, size - sizeof (*opres), (void **) &op))
149 { 149 {
150 LOG (GNUNET_ERROR_TYPE_DEBUG, 150 LOG (GNUNET_ERROR_TYPE_DEBUG,
151 "handle_result_code: Received result message with operation ID: %" PRIu64 "\n", 151 "handle_result_code: Received result message with OP ID: %" PRIu64 "\n",
152 GNUNET_ntohll (opres->op_id)); 152 GNUNET_ntohll (opres->op_id));
153 GNUNET_free (op); 153 GNUNET_free (op);
154 } 154 }
155 else 155 else
156 { 156 {
157 LOG (GNUNET_ERROR_TYPE_DEBUG, 157 LOG (GNUNET_ERROR_TYPE_DEBUG,
158 "handle_result_code: No callback registered for operation with ID %" PRIu64 ".\n", 158 "handle_result_code: No callback registered for OP ID %" PRIu64 ".\n",
159 GNUNET_ntohll (opres->op_id)); 159 GNUNET_ntohll (opres->op_id));
160 } 160 }
161 h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; 161 h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS;
@@ -187,7 +187,7 @@ handle_result_counters (void *cls, const struct CountersResult *cres)
187 else 187 else
188 { 188 {
189 LOG (GNUNET_ERROR_TYPE_DEBUG, 189 LOG (GNUNET_ERROR_TYPE_DEBUG,
190 "handle_result_counters: No callback registered for operation with ID %" PRIu64 ".\n", 190 "handle_result_counters: No callback registered for OP ID %" PRIu64 ".\n",
191 GNUNET_ntohll (cres->op_id)); 191 GNUNET_ntohll (cres->op_id));
192 } 192 }
193 h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; 193 h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS;
@@ -233,7 +233,7 @@ handle_result_fragment (void *cls, const struct FragmentResult *fres)
233 else 233 else
234 { 234 {
235 LOG (GNUNET_ERROR_TYPE_DEBUG, 235 LOG (GNUNET_ERROR_TYPE_DEBUG,
236 "handle_result_fragment: No callback registered for operation with ID %" PRIu64 ".\n", 236 "handle_result_fragment: No callback registered for OP ID %" PRIu64 ".\n",
237 GNUNET_ntohll (fres->op_id)); 237 GNUNET_ntohll (fres->op_id));
238 } 238 }
239 h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; 239 h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS;
@@ -282,7 +282,7 @@ handle_result_state (void *cls, const struct StateResult *sres)
282 else 282 else
283 { 283 {
284 LOG (GNUNET_ERROR_TYPE_DEBUG, 284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "handle_result_state: No callback registered for operation with ID %" PRIu64 ".\n", 285 "handle_result_state: No callback registered for OP ID %" PRIu64 ".\n",
286 GNUNET_ntohll (sres->op_id)); 286 GNUNET_ntohll (sres->op_id));
287 } 287 }
288 h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; 288 h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS;
diff --git a/src/rest/Makefile.am b/src/rest/Makefile.am
index c0feb9122..ebfb98024 100644
--- a/src/rest/Makefile.am
+++ b/src/rest/Makefile.am
@@ -26,6 +26,8 @@ lib_LTLIBRARIES = \
26libexec_PROGRAMS = \ 26libexec_PROGRAMS = \
27 gnunet-rest-server 27 gnunet-rest-server
28 28
29EXTRA_DIST = \
30 rest.conf
29 31
30gnunet_rest_server_SOURCES = \ 32gnunet_rest_server_SOURCES = \
31 gnunet-rest-server.c 33 gnunet-rest-server.c
diff --git a/src/rps/.gitignore b/src/rps/.gitignore
index 0d460e62c..cb14f5b09 100644
--- a/src/rps/.gitignore
+++ b/src/rps/.gitignore
@@ -1,3 +1,15 @@
1gnunet-service-rps 1gnunet-service-rps
2gnunet-rps 2gnunet-rps
3gnunet-rps-profiler 3gnunet-rps-profiler
4test_rps_malicious_1
5test_rps_malicious_2
6test_rps_malicious_3
7test_rps_req_cancel
8test_rps_seed_big
9test_rps_seed_request
10test_rps_single_req
11test_service_rps_custommap
12test_service_rps_sampler_elem
13test_service_rps_view
14test_rps_churn
15test_service_rps_peers
diff --git a/src/rps/Makefile.am b/src/rps/Makefile.am
index e6c8cd929..de3469254 100644
--- a/src/rps/Makefile.am
+++ b/src/rps/Makefile.am
@@ -49,7 +49,6 @@ endif
49gnunet_service_rps_SOURCES = \ 49gnunet_service_rps_SOURCES = \
50 gnunet-service-rps_sampler_elem.h gnunet-service-rps_sampler_elem.c \ 50 gnunet-service-rps_sampler_elem.h gnunet-service-rps_sampler_elem.c \
51 gnunet-service-rps_sampler.h gnunet-service-rps_sampler.c \ 51 gnunet-service-rps_sampler.h gnunet-service-rps_sampler.c \
52 gnunet-service-rps_peers.h gnunet-service-rps_peers.c \
53 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \ 52 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \
54 gnunet-service-rps_view.h gnunet-service-rps_view.c \ 53 gnunet-service-rps_view.h gnunet-service-rps_view.c \
55 rps-test_util.h rps-test_util.c \ 54 rps-test_util.h rps-test_util.c \
@@ -73,7 +72,6 @@ if HAVE_TESTING
73check_PROGRAMS = \ 72check_PROGRAMS = \
74 test_service_rps_view \ 73 test_service_rps_view \
75 test_service_rps_custommap \ 74 test_service_rps_custommap \
76 test_service_rps_peers \
77 test_service_rps_sampler_elem \ 75 test_service_rps_sampler_elem \
78 test_rps_malicious_1 \ 76 test_rps_malicious_1 \
79 test_rps_malicious_2 \ 77 test_rps_malicious_2 \
@@ -81,7 +79,8 @@ check_PROGRAMS = \
81 test_rps_seed_request \ 79 test_rps_seed_request \
82 test_rps_single_req \ 80 test_rps_single_req \
83 test_rps_req_cancel \ 81 test_rps_req_cancel \
84 test_rps_seed_big 82 test_rps_seed_big \
83 test_rps_churn
85endif 84endif
86 85
87ld_rps_test_lib = \ 86ld_rps_test_lib = \
@@ -105,13 +104,6 @@ test_service_rps_view_SOURCES = \
105 test_service_rps_view.c 104 test_service_rps_view.c
106test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la 105test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la
107 106
108test_service_rps_peers_SOURCES = \
109 gnunet-service-rps_peers.h gnunet-service-rps_peers.c \
110 test_service_rps_peers.c
111test_service_rps_peers_LDADD = \
112 $(top_builddir)/src/util/libgnunetutil.la \
113 $(top_builddir)/src/cadet/libgnunetcadet.la
114
115test_service_rps_custommap_SOURCES = \ 107test_service_rps_custommap_SOURCES = \
116 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \ 108 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \
117 test_service_rps_custommap.c 109 test_service_rps_custommap.c
@@ -145,6 +137,9 @@ test_rps_req_cancel_LDADD = $(ld_rps_test_lib)
145test_rps_seed_big_SOURCES = $(rps_test_src) 137test_rps_seed_big_SOURCES = $(rps_test_src)
146test_rps_seed_big_LDADD = $(ld_rps_test_lib) 138test_rps_seed_big_LDADD = $(ld_rps_test_lib)
147 139
140test_rps_churn_SOURCES = $(rps_test_src)
141test_rps_churn_LDADD = $(ld_rps_test_lib)
142
148gnunet_rps_profiler_SOURCES = $(rps_test_src) 143gnunet_rps_profiler_SOURCES = $(rps_test_src)
149gnunet_rps_profiler_LDADD = $(ld_rps_test_lib) 144gnunet_rps_profiler_LDADD = $(ld_rps_test_lib)
150 145
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c
index 0a4543b30..ec70075cf 100644
--- a/src/rps/gnunet-service-rps.c
+++ b/src/rps/gnunet-service-rps.c
@@ -33,7 +33,6 @@
33#include "rps-test_util.h" 33#include "rps-test_util.h"
34#include "gnunet-service-rps_sampler.h" 34#include "gnunet-service-rps_sampler.h"
35#include "gnunet-service-rps_custommap.h" 35#include "gnunet-service-rps_custommap.h"
36#include "gnunet-service-rps_peers.h"
37#include "gnunet-service-rps_view.h" 36#include "gnunet-service-rps_view.h"
38 37
39#include <math.h> 38#include <math.h>
@@ -66,6 +65,1728 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
66static struct GNUNET_PeerIdentity own_identity; 65static struct GNUNET_PeerIdentity own_identity;
67 66
68 67
68
69/***********************************************************************
70 * Old gnunet-service-rps_peers.c
71***********************************************************************/
72
73/**
74 * Set a peer flag of given peer context.
75 */
76#define set_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) |= (mask))
77
78/**
79 * Get peer flag of given peer context.
80 */
81#define check_peer_flag_set(peer_ctx, mask)\
82 ((peer_ctx->peer_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
83
84/**
85 * Unset flag of given peer context.
86 */
87#define unset_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) &= ~(mask))
88
89/**
90 * Set a channel flag of given channel context.
91 */
92#define set_channel_flag(channel_flags, mask) ((*channel_flags) |= (mask))
93
94/**
95 * Get channel flag of given channel context.
96 */
97#define check_channel_flag_set(channel_flags, mask)\
98 ((*channel_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
99
100/**
101 * Unset flag of given channel context.
102 */
103#define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= ~(mask))
104
105
106
107/**
108 * Pending operation on peer consisting of callback and closure
109 *
110 * When an operation cannot be executed right now this struct is used to store
111 * the callback and closure for later execution.
112 */
113struct PeerPendingOp
114{
115 /**
116 * Callback
117 */
118 PeerOp op;
119
120 /**
121 * Closure
122 */
123 void *op_cls;
124};
125
126/**
127 * List containing all messages that are yet to be send
128 *
129 * This is used to keep track of all messages that have not been sent yet. When
130 * a peer is to be removed the pending messages can be removed properly.
131 */
132struct PendingMessage
133{
134 /**
135 * DLL next, prev
136 */
137 struct PendingMessage *next;
138 struct PendingMessage *prev;
139
140 /**
141 * The envelope to the corresponding message
142 */
143 struct GNUNET_MQ_Envelope *ev;
144
145 /**
146 * The corresponding context
147 */
148 struct PeerContext *peer_ctx;
149
150 /**
151 * The message type
152 */
153 const char *type;
154};
155
156/**
157 * Struct used to keep track of other peer's status
158 *
159 * This is stored in a multipeermap.
160 * It contains information such as cadet channels, a message queue for sending,
161 * status about the channels, the pending operations on this peer and some flags
162 * about the status of the peer itself. (live, valid, ...)
163 */
164struct PeerContext
165{
166 /**
167 * Message queue open to client
168 */
169 struct GNUNET_MQ_Handle *mq;
170
171 /**
172 * Channel open to client.
173 */
174 struct GNUNET_CADET_Channel *send_channel;
175
176 /**
177 * Flags to the sending channel
178 */
179 uint32_t *send_channel_flags;
180
181 /**
182 * Channel open from client.
183 */
184 struct GNUNET_CADET_Channel *recv_channel; // unneeded?
185
186 /**
187 * Flags to the receiving channel
188 */
189 uint32_t *recv_channel_flags;
190
191 /**
192 * Array of pending operations on this peer.
193 */
194 struct PeerPendingOp *pending_ops;
195
196 /**
197 * Handle to the callback given to cadet_ntfy_tmt_rdy()
198 *
199 * To be canceled on shutdown.
200 */
201 struct PendingMessage *liveliness_check_pending;
202
203 /**
204 * Number of pending operations.
205 */
206 unsigned int num_pending_ops;
207
208 /**
209 * Identity of the peer
210 */
211 struct GNUNET_PeerIdentity peer_id;
212
213 /**
214 * Flags indicating status of peer
215 */
216 uint32_t peer_flags;
217
218 /**
219 * Last time we received something from that peer.
220 */
221 struct GNUNET_TIME_Absolute last_message_recv;
222
223 /**
224 * Last time we received a keepalive message.
225 */
226 struct GNUNET_TIME_Absolute last_keepalive;
227
228 /**
229 * DLL with all messages that are yet to be sent
230 */
231 struct PendingMessage *pending_messages_head;
232 struct PendingMessage *pending_messages_tail;
233
234 /**
235 * This is pobably followed by 'statistical' data (when we first saw
236 * him, how did we get his ID, how many pushes (in a timeinterval),
237 * ...)
238 */
239};
240
241/**
242 * @brief Closure to #valid_peer_iterator
243 */
244struct PeersIteratorCls
245{
246 /**
247 * Iterator function
248 */
249 PeersIterator iterator;
250
251 /**
252 * Closure to iterator
253 */
254 void *cls;
255};
256
257/**
258 * @brief Hashmap of valid peers.
259 */
260static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers;
261
262/**
263 * @brief Maximum number of valid peers to keep.
264 * TODO read from config
265 */
266static uint32_t num_valid_peers_max = UINT32_MAX;
267
268/**
269 * @brief Filename of the file that stores the valid peers persistently.
270 */
271static char *filename_valid_peers;
272
273/**
274 * Set of all peers to keep track of them.
275 */
276static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
277
278/**
279 * Cadet handle.
280 */
281static struct GNUNET_CADET_Handle *cadet_handle;
282
283
284
285/**
286 * @brief Get the #PeerContext associated with a peer
287 *
288 * @param peer the peer id
289 *
290 * @return the #PeerContext
291 */
292static struct PeerContext *
293get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
294{
295 struct PeerContext *ctx;
296 int ret;
297
298 ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
299 GNUNET_assert (GNUNET_YES == ret);
300 ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
301 GNUNET_assert (NULL != ctx);
302 return ctx;
303}
304
305int
306Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer);
307
308/**
309 * @brief Create a new #PeerContext and insert it into the peer map
310 *
311 * @param peer the peer to create the #PeerContext for
312 *
313 * @return the #PeerContext
314 */
315static struct PeerContext *
316create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
317{
318 struct PeerContext *ctx;
319 int ret;
320
321 GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));
322
323 ctx = GNUNET_new (struct PeerContext);
324 ctx->peer_id = *peer;
325 ctx->send_channel_flags = GNUNET_new (uint32_t);
326 ctx->recv_channel_flags = GNUNET_new (uint32_t);
327 ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
328 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
329 GNUNET_assert (GNUNET_OK == ret);
330 return ctx;
331}
332
333
334/**
335 * @brief Create or get a #PeerContext
336 *
337 * @param peer the peer to get the associated context to
338 *
339 * @return the context
340 */
341static struct PeerContext *
342create_or_get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
343{
344 if (GNUNET_NO == Peers_check_peer_known (peer))
345 {
346 return create_peer_ctx (peer);
347 }
348 return get_peer_ctx (peer);
349}
350
351void
352Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
353
354void
355Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
356
357/**
358 * @brief Check whether we have a connection to this @a peer
359 *
360 * Also sets the #Peers_ONLINE flag accordingly
361 *
362 * @param peer the peer in question
363 *
364 * @return #GNUNET_YES if we are connected
365 * #GNUNET_NO otherwise
366 */
367int
368Peers_check_connected (const struct GNUNET_PeerIdentity *peer)
369{
370 const struct PeerContext *peer_ctx;
371
372 /* If we don't know about this peer we don't know whether it's online */
373 if (GNUNET_NO == Peers_check_peer_known (peer))
374 {
375 return GNUNET_NO;
376 }
377 /* Get the context */
378 peer_ctx = get_peer_ctx (peer);
379 /* If we have no channel to this peer we don't know whether it's online */
380 if ( (NULL == peer_ctx->send_channel) &&
381 (NULL == peer_ctx->recv_channel) )
382 {
383 Peers_unset_peer_flag (peer, Peers_ONLINE);
384 return GNUNET_NO;
385 }
386 /* Otherwise (if we have a channel, we know that it's online */
387 Peers_set_peer_flag (peer, Peers_ONLINE);
388 return GNUNET_YES;
389}
390
391
392/**
393 * @brief The closure to #get_rand_peer_iterator.
394 */
395struct GetRandPeerIteratorCls
396{
397 /**
398 * @brief The index of the peer to return.
399 * Will be decreased until 0.
400 * Then current peer is returned.
401 */
402 uint32_t index;
403
404 /**
405 * @brief Pointer to peer to return.
406 */
407 const struct GNUNET_PeerIdentity *peer;
408};
409
410
411/**
412 * @brief Iterator function for #get_random_peer_from_peermap.
413 *
414 * Implements #GNUNET_CONTAINER_PeerMapIterator.
415 * Decreases the index until the index is null.
416 * Then returns the current peer.
417 *
418 * @param cls the #GetRandPeerIteratorCls containing index and peer
419 * @param peer current peer
420 * @param value unused
421 *
422 * @return #GNUNET_YES if we should continue to
423 * iterate,
424 * #GNUNET_NO if not.
425 */
426static int
427get_rand_peer_iterator (void *cls,
428 const struct GNUNET_PeerIdentity *peer,
429 void *value)
430{
431 struct GetRandPeerIteratorCls *iterator_cls = cls;
432 if (0 >= iterator_cls->index)
433 {
434 iterator_cls->peer = peer;
435 return GNUNET_NO;
436 }
437 iterator_cls->index--;
438 return GNUNET_YES;
439}
440
441
442/**
443 * @brief Get a random peer from @a peer_map
444 *
445 * @param peer_map the peer_map to get the peer from
446 *
447 * @return a random peer
448 */
449static const struct GNUNET_PeerIdentity *
450get_random_peer_from_peermap (const struct
451 GNUNET_CONTAINER_MultiPeerMap *peer_map)
452{
453 struct GetRandPeerIteratorCls *iterator_cls;
454 const struct GNUNET_PeerIdentity *ret;
455
456 iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
457 iterator_cls->index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
458 GNUNET_CONTAINER_multipeermap_size (peer_map));
459 (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
460 get_rand_peer_iterator,
461 iterator_cls);
462 ret = iterator_cls->peer;
463 GNUNET_free (iterator_cls);
464 return ret;
465}
466
467
468/**
469 * @brief Add a given @a peer to valid peers.
470 *
471 * If valid peers are already #num_valid_peers_max, delete a peer previously.
472 *
473 * @param peer the peer that is added to the valid peers.
474 *
475 * @return #GNUNET_YES if no other peer had to be removed
476 * #GNUNET_NO otherwise
477 */
478static int
479add_valid_peer (const struct GNUNET_PeerIdentity *peer)
480{
481 const struct GNUNET_PeerIdentity *rand_peer;
482 int ret;
483
484 ret = GNUNET_YES;
485 while (GNUNET_CONTAINER_multipeermap_size (valid_peers) >= num_valid_peers_max)
486 {
487 rand_peer = get_random_peer_from_peermap (valid_peers);
488 GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
489 ret = GNUNET_NO;
490 }
491 (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
492 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
493 return ret;
494}
495
496
497/**
498 * @brief Set the peer flag to living and
499 * call the pending operations on this peer.
500 *
501 * Also adds peer to #valid_peers.
502 *
503 * @param peer_ctx the #PeerContext of the peer to set live
504 */
505static void
506set_peer_live (struct PeerContext *peer_ctx)
507{
508 struct GNUNET_PeerIdentity *peer;
509 unsigned int i;
510
511 peer = &peer_ctx->peer_id;
512 LOG (GNUNET_ERROR_TYPE_DEBUG,
513 "Peer %s is live and valid, calling %i pending operations on it\n",
514 GNUNET_i2s (peer),
515 peer_ctx->num_pending_ops);
516
517 if (NULL != peer_ctx->liveliness_check_pending)
518 {
519 LOG (GNUNET_ERROR_TYPE_DEBUG,
520 "Removing pending liveliness check for peer %s\n",
521 GNUNET_i2s (&peer_ctx->peer_id));
522 // TODO wait until cadet sets mq->cancel_impl
523 //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
524 GNUNET_free (peer_ctx->liveliness_check_pending);
525 peer_ctx->liveliness_check_pending = NULL;
526 }
527
528 (void) add_valid_peer (peer);
529 set_peer_flag (peer_ctx, Peers_ONLINE);
530
531 /* Call pending operations */
532 for (i = 0; i < peer_ctx->num_pending_ops; i++)
533 {
534 peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
535 }
536 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
537}
538
539static void
540cleanup_destroyed_channel (void *cls,
541 const struct GNUNET_CADET_Channel *channel);
542
543/* Declaration of handlers */
544static void
545handle_peer_check (void *cls,
546 const struct GNUNET_MessageHeader *msg);
547
548static void
549handle_peer_push (void *cls,
550 const struct GNUNET_MessageHeader *msg);
551
552static void
553handle_peer_pull_request (void *cls,
554 const struct GNUNET_MessageHeader *msg);
555
556static int
557check_peer_pull_reply (void *cls,
558 const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
559
560static void
561handle_peer_pull_reply (void *cls,
562 const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
563
564/* End declaration of handlers */
565
566
567/**
568 * @brief Get the channel of a peer. If not existing, create.
569 *
570 * @param peer the peer id
571 * @return the #GNUNET_CADET_Channel used to send data to @a peer
572 */
573struct GNUNET_CADET_Channel *
574get_channel (const struct GNUNET_PeerIdentity *peer)
575{
576 struct PeerContext *peer_ctx;
577 struct GNUNET_HashCode port;
578 /* There exists a copy-paste-clone in run() */
579 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
580 GNUNET_MQ_hd_fixed_size (peer_check,
581 GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE,
582 struct GNUNET_MessageHeader,
583 NULL),
584 GNUNET_MQ_hd_fixed_size (peer_push,
585 GNUNET_MESSAGE_TYPE_RPS_PP_PUSH,
586 struct GNUNET_MessageHeader,
587 NULL),
588 GNUNET_MQ_hd_fixed_size (peer_pull_request,
589 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
590 struct GNUNET_MessageHeader,
591 NULL),
592 GNUNET_MQ_hd_var_size (peer_pull_reply,
593 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY,
594 struct GNUNET_RPS_P2P_PullReplyMessage,
595 NULL),
596 GNUNET_MQ_handler_end ()
597 };
598
599
600 peer_ctx = get_peer_ctx (peer);
601 if (NULL == peer_ctx->send_channel)
602 {
603 LOG (GNUNET_ERROR_TYPE_DEBUG,
604 "Trying to establish channel to peer %s\n",
605 GNUNET_i2s (peer));
606 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS,
607 strlen (GNUNET_APPLICATION_PORT_RPS),
608 &port);
609 peer_ctx->send_channel =
610 GNUNET_CADET_channel_create (cadet_handle,
611 (struct GNUNET_PeerIdentity *) peer, /* context */
612 peer,
613 &port,
614 GNUNET_CADET_OPTION_RELIABLE,
615 NULL, /* WindowSize handler */
616 cleanup_destroyed_channel, /* Disconnect handler */
617 cadet_handlers);
618 }
619 GNUNET_assert (NULL != peer_ctx->send_channel);
620 return peer_ctx->send_channel;
621}
622
623
624/**
625 * Get the message queue (#GNUNET_MQ_Handle) of a specific peer.
626 *
627 * If we already have a message queue open to this client,
628 * simply return it, otherways create one.
629 *
630 * @param peer the peer to get the mq to
631 * @return the #GNUNET_MQ_Handle
632 */
633static struct GNUNET_MQ_Handle *
634get_mq (const struct GNUNET_PeerIdentity *peer)
635{
636 struct PeerContext *peer_ctx;
637
638 peer_ctx = get_peer_ctx (peer);
639
640 if (NULL == peer_ctx->mq)
641 {
642 (void) get_channel (peer);
643 peer_ctx->mq = GNUNET_CADET_get_mq (peer_ctx->send_channel);
644 }
645 return peer_ctx->mq;
646}
647
648
649/**
650 * @brief This is called in response to the first message we sent as a
651 * liveliness check.
652 *
653 * @param cls #PeerContext of peer with pending liveliness check
654 */
655static void
656mq_liveliness_check_successful (void *cls)
657{
658 struct PeerContext *peer_ctx = cls;
659
660 if (NULL != peer_ctx->liveliness_check_pending)
661 {
662 LOG (GNUNET_ERROR_TYPE_DEBUG,
663 "Liveliness check for peer %s was successfull\n",
664 GNUNET_i2s (&peer_ctx->peer_id));
665 GNUNET_free (peer_ctx->liveliness_check_pending);
666 peer_ctx->liveliness_check_pending = NULL;
667 set_peer_live (peer_ctx);
668 }
669}
670
671/**
672 * Issue a check whether peer is live
673 *
674 * @param peer_ctx the context of the peer
675 */
676static void
677check_peer_live (struct PeerContext *peer_ctx)
678{
679 LOG (GNUNET_ERROR_TYPE_DEBUG,
680 "Get informed about peer %s getting live\n",
681 GNUNET_i2s (&peer_ctx->peer_id));
682
683 struct GNUNET_MQ_Handle *mq;
684 struct GNUNET_MQ_Envelope *ev;
685
686 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE);
687 peer_ctx->liveliness_check_pending = GNUNET_new (struct PendingMessage);
688 peer_ctx->liveliness_check_pending->ev = ev;
689 peer_ctx->liveliness_check_pending->peer_ctx = peer_ctx;
690 peer_ctx->liveliness_check_pending->type = "Check liveliness";
691 mq = get_mq (&peer_ctx->peer_id);
692 GNUNET_MQ_notify_sent (ev,
693 mq_liveliness_check_successful,
694 peer_ctx);
695 GNUNET_MQ_send (mq, ev);
696}
697
698/**
699 * @brief Add an envelope to a message passed to mq to list of pending messages
700 *
701 * @param peer peer the message was sent to
702 * @param ev envelope to the message
703 * @param type type of the message to be sent
704 * @return pointer to pending message
705 */
706static struct PendingMessage *
707insert_pending_message (const struct GNUNET_PeerIdentity *peer,
708 struct GNUNET_MQ_Envelope *ev,
709 const char *type)
710{
711 struct PendingMessage *pending_msg;
712 struct PeerContext *peer_ctx;
713
714 peer_ctx = get_peer_ctx (peer);
715 pending_msg = GNUNET_new (struct PendingMessage);
716 pending_msg->ev = ev;
717 pending_msg->peer_ctx = peer_ctx;
718 pending_msg->type = type;
719 GNUNET_CONTAINER_DLL_insert (peer_ctx->pending_messages_head,
720 peer_ctx->pending_messages_tail,
721 pending_msg);
722 return pending_msg;
723}
724
725
726/**
727 * @brief Remove a pending message from the respective DLL
728 *
729 * @param pending_msg the pending message to remove
730 * @param cancel cancel the pending message, too
731 */
732static void
733remove_pending_message (struct PendingMessage *pending_msg, int cancel)
734{
735 struct PeerContext *peer_ctx;
736
737 peer_ctx = pending_msg->peer_ctx;
738 GNUNET_assert (NULL != peer_ctx);
739 GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
740 peer_ctx->pending_messages_tail,
741 pending_msg);
742 // TODO wait for the cadet implementation of message cancellation
743 //if (GNUNET_YES == cancel)
744 //{
745 // GNUNET_MQ_send_cancel (pending_msg->ev);
746 //}
747 GNUNET_free (pending_msg);
748}
749
750
751/**
752 * @brief Check whether function of type #PeerOp was already scheduled
753 *
754 * The array with pending operations will probably never grow really big, so
755 * iterating over it should be ok.
756 *
757 * @param peer the peer to check
758 * @param peer_op the operation (#PeerOp) on the peer
759 *
760 * @return #GNUNET_YES if this operation is scheduled on that peer
761 * #GNUNET_NO otherwise
762 */
763static int
764check_operation_scheduled (const struct GNUNET_PeerIdentity *peer,
765 const PeerOp peer_op)
766{
767 const struct PeerContext *peer_ctx;
768 unsigned int i;
769
770 peer_ctx = get_peer_ctx (peer);
771 for (i = 0; i < peer_ctx->num_pending_ops; i++)
772 if (peer_op == peer_ctx->pending_ops[i].op)
773 return GNUNET_YES;
774 return GNUNET_NO;
775}
776
777int
778Peers_remove_peer (const struct GNUNET_PeerIdentity *peer);
779
780/**
781 * Iterator over hash map entries. Deletes all contexts of peers.
782 *
783 * @param cls closure
784 * @param key current public key
785 * @param value value in the hash map
786 * @return #GNUNET_YES if we should continue to iterate,
787 * #GNUNET_NO if not.
788 */
789static int
790peermap_clear_iterator (void *cls,
791 const struct GNUNET_PeerIdentity *key,
792 void *value)
793{
794 Peers_remove_peer (key);
795 return GNUNET_YES;
796}
797
798
799/**
800 * @brief This is called once a message is sent.
801 *
802 * Removes the pending message
803 *
804 * @param cls type of the message that was sent
805 */
806static void
807mq_notify_sent_cb (void *cls)
808{
809 struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
810 LOG (GNUNET_ERROR_TYPE_DEBUG,
811 "%s was sent.\n",
812 pending_msg->type);
813 /* Do not cancle message */
814 remove_pending_message (pending_msg, GNUNET_NO);
815}
816
817
818/**
819 * @brief Iterator function for #store_valid_peers.
820 *
821 * Implements #GNUNET_CONTAINER_PeerMapIterator.
822 * Writes single peer to disk.
823 *
824 * @param cls the file handle to write to.
825 * @param peer current peer
826 * @param value unused
827 *
828 * @return #GNUNET_YES if we should continue to
829 * iterate,
830 * #GNUNET_NO if not.
831 */
832static int
833store_peer_presistently_iterator (void *cls,
834 const struct GNUNET_PeerIdentity *peer,
835 void *value)
836{
837 const struct GNUNET_DISK_FileHandle *fh = cls;
838 char peer_string[128];
839 int size;
840 ssize_t ret;
841
842 if (NULL == peer)
843 {
844 return GNUNET_YES;
845 }
846 size = GNUNET_snprintf (peer_string,
847 sizeof (peer_string),
848 "%s\n",
849 GNUNET_i2s_full (peer));
850 GNUNET_assert (53 == size);
851 ret = GNUNET_DISK_file_write (fh,
852 peer_string,
853 size);
854 GNUNET_assert (size == ret);
855 return GNUNET_YES;
856}
857
858
859/**
860 * @brief Store the peers currently in #valid_peers to disk.
861 */
862static void
863store_valid_peers ()
864{
865 struct GNUNET_DISK_FileHandle *fh;
866 uint32_t number_written_peers;
867 int ret;
868
869 if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
870 {
871 return;
872 }
873
874 ret = GNUNET_DISK_directory_create_for_file (filename_valid_peers);
875 if (GNUNET_SYSERR == ret)
876 {
877 LOG (GNUNET_ERROR_TYPE_WARNING,
878 "Not able to create directory for file `%s'\n",
879 filename_valid_peers);
880 GNUNET_break (0);
881 }
882 else if (GNUNET_NO == ret)
883 {
884 LOG (GNUNET_ERROR_TYPE_WARNING,
885 "Directory for file `%s' exists but is not writable for us\n",
886 filename_valid_peers);
887 GNUNET_break (0);
888 }
889 fh = GNUNET_DISK_file_open (filename_valid_peers,
890 GNUNET_DISK_OPEN_WRITE |
891 GNUNET_DISK_OPEN_CREATE,
892 GNUNET_DISK_PERM_USER_READ |
893 GNUNET_DISK_PERM_USER_WRITE);
894 if (NULL == fh)
895 {
896 LOG (GNUNET_ERROR_TYPE_WARNING,
897 "Not able to write valid peers to file `%s'\n",
898 filename_valid_peers);
899 return;
900 }
901 LOG (GNUNET_ERROR_TYPE_DEBUG,
902 "Writing %u valid peers to disk\n",
903 GNUNET_CONTAINER_multipeermap_size (valid_peers));
904 number_written_peers =
905 GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
906 store_peer_presistently_iterator,
907 fh);
908 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
909 GNUNET_assert (number_written_peers ==
910 GNUNET_CONTAINER_multipeermap_size (valid_peers));
911}
912
913
914/**
915 * @brief Convert string representation of peer id to peer id.
916 *
917 * Counterpart to #GNUNET_i2s_full.
918 *
919 * @param string_repr The string representation of the peer id
920 *
921 * @return The peer id
922 */
923static const struct GNUNET_PeerIdentity *
924s2i_full (const char *string_repr)
925{
926 struct GNUNET_PeerIdentity *peer;
927 size_t len;
928 int ret;
929
930 peer = GNUNET_new (struct GNUNET_PeerIdentity);
931 len = strlen (string_repr);
932 if (52 > len)
933 {
934 LOG (GNUNET_ERROR_TYPE_WARNING,
935 "Not able to convert string representation of PeerID to PeerID\n"
936 "Sting representation: %s (len %lu) - too short\n",
937 string_repr,
938 len);
939 GNUNET_break (0);
940 }
941 else if (52 < len)
942 {
943 len = 52;
944 }
945 ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr,
946 len,
947 &peer->public_key);
948 if (GNUNET_OK != ret)
949 {
950 LOG (GNUNET_ERROR_TYPE_WARNING,
951 "Not able to convert string representation of PeerID to PeerID\n"
952 "Sting representation: %s\n",
953 string_repr);
954 GNUNET_break (0);
955 }
956 return peer;
957}
958
959
960/**
961 * @brief Restore the peers on disk to #valid_peers.
962 */
963static void
964restore_valid_peers ()
965{
966 off_t file_size;
967 uint32_t num_peers;
968 struct GNUNET_DISK_FileHandle *fh;
969 char *buf;
970 ssize_t size_read;
971 char *iter_buf;
972 char *str_repr;
973 const struct GNUNET_PeerIdentity *peer;
974
975 if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
976 {
977 return;
978 }
979
980 if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers))
981 {
982 return;
983 }
984 fh = GNUNET_DISK_file_open (filename_valid_peers,
985 GNUNET_DISK_OPEN_READ,
986 GNUNET_DISK_PERM_NONE);
987 GNUNET_assert (NULL != fh);
988 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size));
989 num_peers = file_size / 53;
990 buf = GNUNET_malloc (file_size);
991 size_read = GNUNET_DISK_file_read (fh, buf, file_size);
992 GNUNET_assert (size_read == file_size);
993 LOG (GNUNET_ERROR_TYPE_DEBUG,
994 "Restoring %" PRIu32 " peers from file `%s'\n",
995 num_peers,
996 filename_valid_peers);
997 for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53)
998 {
999 str_repr = GNUNET_strndup (iter_buf, 53);
1000 peer = s2i_full (str_repr);
1001 GNUNET_free (str_repr);
1002 add_valid_peer (peer);
1003 LOG (GNUNET_ERROR_TYPE_DEBUG,
1004 "Restored valid peer %s from disk\n",
1005 GNUNET_i2s_full (peer));
1006 }
1007 iter_buf = NULL;
1008 GNUNET_free (buf);
1009 LOG (GNUNET_ERROR_TYPE_DEBUG,
1010 "num_peers: %" PRIu32 ", _size (valid_peers): %u\n",
1011 num_peers,
1012 GNUNET_CONTAINER_multipeermap_size (valid_peers));
1013 if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers))
1014 {
1015 LOG (GNUNET_ERROR_TYPE_WARNING,
1016 "Number of restored peers does not match file size. Have probably duplicates.\n");
1017 }
1018 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
1019 LOG (GNUNET_ERROR_TYPE_DEBUG,
1020 "Restored %u valid peers from disk\n",
1021 GNUNET_CONTAINER_multipeermap_size (valid_peers));
1022}
1023
1024
1025/**
1026 * @brief Initialise storage of peers
1027 *
1028 * @param fn_valid_peers filename of the file used to store valid peer ids
1029 * @param cadet_h cadet handle
1030 * @param disconnect_handler Disconnect handler
1031 * @param own_id own peer identity
1032 */
1033void
1034Peers_initialise (char* fn_valid_peers,
1035 struct GNUNET_CADET_Handle *cadet_h,
1036 GNUNET_CADET_DisconnectEventHandler disconnect_handler,
1037 const struct GNUNET_PeerIdentity *own_id)
1038{
1039 filename_valid_peers = GNUNET_strdup (fn_valid_peers);
1040 cadet_handle = cadet_h;
1041 own_identity = *own_id;
1042 peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
1043 valid_peers = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
1044 restore_valid_peers ();
1045}
1046
1047
1048/**
1049 * @brief Delete storage of peers that was created with #Peers_initialise ()
1050 */
1051void
1052Peers_terminate ()
1053{
1054 if (GNUNET_SYSERR ==
1055 GNUNET_CONTAINER_multipeermap_iterate (peer_map,
1056 peermap_clear_iterator,
1057 NULL))
1058 {
1059 LOG (GNUNET_ERROR_TYPE_WARNING,
1060 "Iteration destroying peers was aborted.\n");
1061 }
1062 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
1063 store_valid_peers ();
1064 GNUNET_free (filename_valid_peers);
1065 GNUNET_CONTAINER_multipeermap_destroy (valid_peers);
1066}
1067
1068
1069/**
1070 * Iterator over #valid_peers hash map entries.
1071 *
1072 * @param cls closure - unused
1073 * @param peer current peer id
1074 * @param value value in the hash map - unused
1075 * @return #GNUNET_YES if we should continue to
1076 * iterate,
1077 * #GNUNET_NO if not.
1078 */
1079static int
1080valid_peer_iterator (void *cls,
1081 const struct GNUNET_PeerIdentity *peer,
1082 void *value)
1083{
1084 struct PeersIteratorCls *it_cls = cls;
1085
1086 return it_cls->iterator (it_cls->cls,
1087 peer);
1088}
1089
1090
1091/**
1092 * @brief Get all currently known, valid peer ids.
1093 *
1094 * @param it function to call on each peer id
1095 * @param it_cls extra argument to @a it
1096 * @return the number of key value pairs processed,
1097 * #GNUNET_SYSERR if it aborted iteration
1098 */
1099int
1100Peers_get_valid_peers (PeersIterator iterator,
1101 void *it_cls)
1102{
1103 struct PeersIteratorCls *cls;
1104 int ret;
1105
1106 cls = GNUNET_new (struct PeersIteratorCls);
1107 cls->iterator = iterator;
1108 cls->cls = it_cls;
1109 ret = GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
1110 valid_peer_iterator,
1111 cls);
1112 GNUNET_free (cls);
1113 return ret;
1114}
1115
1116
1117/**
1118 * @brief Add peer to known peers.
1119 *
1120 * This function is called on new peer_ids from 'external' sources
1121 * (client seed, cadet get_peers(), ...)
1122 *
1123 * @param peer the new #GNUNET_PeerIdentity
1124 *
1125 * @return #GNUNET_YES if peer was inserted
1126 * #GNUNET_NO otherwise (if peer was already known or
1127 * peer was #own_identity)
1128 */
1129int
1130Peers_insert_peer (const struct GNUNET_PeerIdentity *peer)
1131{
1132 if ( (GNUNET_YES == Peers_check_peer_known (peer)) ||
1133 (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity)) )
1134 {
1135 return GNUNET_NO; /* We already know this peer - nothing to do */
1136 }
1137 (void) create_peer_ctx (peer);
1138 return GNUNET_YES;
1139}
1140
1141int
1142Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
1143
1144/**
1145 * @brief Try connecting to a peer to see whether it is online
1146 *
1147 * If not known yet, insert into known peers
1148 *
1149 * @param peer the peer whose liveliness is to be checked
1150 * @return #GNUNET_YES if peer had to be inserted
1151 * #GNUNET_NO otherwise (if peer was already known or
1152 * peer was #own_identity)
1153 */
1154int
1155Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer)
1156{
1157 struct PeerContext *peer_ctx;
1158 int ret;
1159
1160 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity))
1161 {
1162 return GNUNET_NO;
1163 }
1164 ret = Peers_insert_peer (peer);
1165 peer_ctx = get_peer_ctx (peer);
1166 if (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE))
1167 {
1168 check_peer_live (peer_ctx);
1169 }
1170 return ret;
1171}
1172
1173
1174/**
1175 * @brief Check if peer is removable.
1176 *
1177 * Check if
1178 * - a recv channel exists
1179 * - there are pending messages
1180 * - there is no pending pull reply
1181 *
1182 * @param peer the peer in question
1183 * @return #GNUNET_YES if peer is removable
1184 * #GNUNET_NO if peer is NOT removable
1185 * #GNUNET_SYSERR if peer is not known
1186 */
1187int
1188Peers_check_removable (const struct GNUNET_PeerIdentity *peer)
1189{
1190 struct PeerContext *peer_ctx;
1191
1192 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1193 {
1194 return GNUNET_SYSERR;
1195 }
1196
1197 peer_ctx = get_peer_ctx (peer);
1198 if ( (NULL != peer_ctx->recv_channel) ||
1199 (NULL != peer_ctx->pending_messages_head) ||
1200 (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
1201 {
1202 return GNUNET_NO;
1203 }
1204 return GNUNET_YES;
1205}
1206
1207uint32_t *
1208Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1209 enum Peers_ChannelRole role);
1210
1211int
1212Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
1213
1214/**
1215 * @brief Remove peer
1216 *
1217 * @param peer the peer to clean
1218 * @return #GNUNET_YES if peer was removed
1219 * #GNUNET_NO otherwise
1220 */
1221int
1222Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
1223{
1224 struct PeerContext *peer_ctx;
1225 uint32_t *channel_flag;
1226
1227 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1228 {
1229 return GNUNET_NO;
1230 }
1231
1232 peer_ctx = get_peer_ctx (peer);
1233 set_peer_flag (peer_ctx, Peers_TO_DESTROY);
1234 LOG (GNUNET_ERROR_TYPE_DEBUG,
1235 "Going to remove peer %s\n",
1236 GNUNET_i2s (&peer_ctx->peer_id));
1237 Peers_unset_peer_flag (peer, Peers_ONLINE);
1238
1239 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
1240 while (NULL != peer_ctx->pending_messages_head)
1241 {
1242 LOG (GNUNET_ERROR_TYPE_DEBUG,
1243 "Removing unsent %s\n",
1244 peer_ctx->pending_messages_head->type);
1245 /* Cancle pending message, too */
1246 remove_pending_message (peer_ctx->pending_messages_head, GNUNET_YES);
1247 }
1248 /* If we are still waiting for notification whether this peer is live
1249 * cancel the according task */
1250 if (NULL != peer_ctx->liveliness_check_pending)
1251 {
1252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1253 "Removing pending liveliness check for peer %s\n",
1254 GNUNET_i2s (&peer_ctx->peer_id));
1255 // TODO wait until cadet sets mq->cancel_impl
1256 //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
1257 GNUNET_free (peer_ctx->liveliness_check_pending);
1258 peer_ctx->liveliness_check_pending = NULL;
1259 }
1260 channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_SENDING);
1261 if (NULL != peer_ctx->send_channel &&
1262 GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING))
1263 {
1264 LOG (GNUNET_ERROR_TYPE_DEBUG,
1265 "Destroying send channel\n");
1266 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1267 peer_ctx->send_channel = NULL;
1268 }
1269 channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_RECEIVING);
1270 if (NULL != peer_ctx->recv_channel &&
1271 GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING))
1272 {
1273 LOG (GNUNET_ERROR_TYPE_DEBUG,
1274 "Destroying recv channel\n");
1275 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1276 peer_ctx->recv_channel = NULL;
1277 }
1278
1279 GNUNET_free (peer_ctx->send_channel_flags);
1280 GNUNET_free (peer_ctx->recv_channel_flags);
1281
1282 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
1283 {
1284 LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
1285 }
1286 GNUNET_free (peer_ctx);
1287 return GNUNET_YES;
1288}
1289
1290
1291/**
1292 * @brief set flags on a given peer.
1293 *
1294 * @param peer the peer to set flags on
1295 * @param flags the flags
1296 */
1297void
1298Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1299{
1300 struct PeerContext *peer_ctx;
1301
1302 peer_ctx = get_peer_ctx (peer);
1303 set_peer_flag (peer_ctx, flags);
1304}
1305
1306
1307/**
1308 * @brief unset flags on a given peer.
1309 *
1310 * @param peer the peer to unset flags on
1311 * @param flags the flags
1312 */
1313void
1314Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1315{
1316 struct PeerContext *peer_ctx;
1317
1318 peer_ctx = get_peer_ctx (peer);
1319 unset_peer_flag (peer_ctx, flags);
1320}
1321
1322
1323/**
1324 * @brief Check whether flags on a peer are set.
1325 *
1326 * @param peer the peer to check the flag of
1327 * @param flags the flags to check
1328 *
1329 * @return #GNUNET_SYSERR if peer is not known
1330 * #GNUNET_YES if all given flags are set
1331 * #GNUNET_NO otherwise
1332 */
1333int
1334Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1335{
1336 struct PeerContext *peer_ctx;
1337
1338 if (GNUNET_NO == Peers_check_peer_known (peer))
1339 {
1340 return GNUNET_SYSERR;
1341 }
1342 peer_ctx = get_peer_ctx (peer);
1343 return check_peer_flag_set (peer_ctx, flags);
1344}
1345
1346
1347/**
1348 * @brief set flags on a given channel.
1349 *
1350 * @param channel the channel to set flags on
1351 * @param flags the flags
1352 */
1353void
1354Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1355{
1356 set_channel_flag (channel_flags, flags);
1357}
1358
1359
1360/**
1361 * @brief unset flags on a given channel.
1362 *
1363 * @param channel the channel to unset flags on
1364 * @param flags the flags
1365 */
1366void
1367Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1368{
1369 unset_channel_flag (channel_flags, flags);
1370}
1371
1372
1373/**
1374 * @brief Check whether flags on a channel are set.
1375 *
1376 * @param channel the channel to check the flag of
1377 * @param flags the flags to check
1378 *
1379 * @return #GNUNET_YES if all given flags are set
1380 * #GNUNET_NO otherwise
1381 */
1382int
1383Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1384{
1385 return check_channel_flag_set (channel_flags, flags);
1386}
1387
1388/**
1389 * @brief Get the flags for the channel in @a role for @a peer.
1390 *
1391 * @param peer Peer to get the channel flags for.
1392 * @param role Role of channel to get flags for
1393 *
1394 * @return The flags.
1395 */
1396uint32_t *
1397Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1398 enum Peers_ChannelRole role)
1399{
1400 const struct PeerContext *peer_ctx;
1401
1402 peer_ctx = get_peer_ctx (peer);
1403 if (Peers_CHANNEL_ROLE_SENDING == role)
1404 {
1405 return peer_ctx->send_channel_flags;
1406 }
1407 else if (Peers_CHANNEL_ROLE_RECEIVING == role)
1408 {
1409 return peer_ctx->recv_channel_flags;
1410 }
1411 else
1412 {
1413 GNUNET_assert (0);
1414 }
1415}
1416
1417/**
1418 * @brief Check whether we have information about the given peer.
1419 *
1420 * FIXME probably deprecated. Make this the new _online.
1421 *
1422 * @param peer peer in question
1423 *
1424 * @return #GNUNET_YES if peer is known
1425 * #GNUNET_NO if peer is not knwon
1426 */
1427int
1428Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
1429{
1430 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
1431}
1432
1433
1434/**
1435 * @brief Check whether @a peer is actually a peer.
1436 *
1437 * A valid peer is a peer that we know exists eg. we were connected to once.
1438 *
1439 * @param peer peer in question
1440 *
1441 * @return #GNUNET_YES if peer is valid
1442 * #GNUNET_NO if peer is not valid
1443 */
1444int
1445Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer)
1446{
1447 return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer);
1448}
1449
1450
1451/**
1452 * @brief Indicate that we want to send to the other peer
1453 *
1454 * This establishes a sending channel
1455 *
1456 * @param peer the peer to establish channel to
1457 */
1458void
1459Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
1460{
1461 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1462 (void) get_channel (peer);
1463}
1464
1465
1466/**
1467 * @brief Check whether other peer has the intention to send/opened channel
1468 * towars us
1469 *
1470 * @param peer the peer in question
1471 *
1472 * @return #GNUNET_YES if peer has the intention to send
1473 * #GNUNET_NO otherwise
1474 */
1475int
1476Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
1477{
1478 const struct PeerContext *peer_ctx;
1479
1480 peer_ctx = get_peer_ctx (peer);
1481 if (NULL != peer_ctx->recv_channel)
1482 {
1483 return GNUNET_YES;
1484 }
1485 return GNUNET_NO;
1486}
1487
1488
1489/**
1490 * Handle the channel a peer opens to us.
1491 *
1492 * @param cls The closure
1493 * @param channel The channel the peer wants to establish
1494 * @param initiator The peer's peer ID
1495 *
1496 * @return initial channel context for the channel
1497 * (can be NULL -- that's not an error)
1498 */
1499void *
1500Peers_handle_inbound_channel (void *cls,
1501 struct GNUNET_CADET_Channel *channel,
1502 const struct GNUNET_PeerIdentity *initiator)
1503{
1504 struct PeerContext *peer_ctx;
1505
1506 LOG (GNUNET_ERROR_TYPE_DEBUG,
1507 "New channel was established to us (Peer %s).\n",
1508 GNUNET_i2s (initiator));
1509 GNUNET_assert (NULL != channel); /* according to cadet API */
1510 /* Make sure we 'know' about this peer */
1511 peer_ctx = create_or_get_peer_ctx (initiator);
1512 set_peer_live (peer_ctx);
1513 /* We only accept one incoming channel per peer */
1514 if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
1515 {
1516 set_channel_flag (peer_ctx->recv_channel_flags,
1517 Peers_CHANNEL_ESTABLISHED_TWICE);
1518 GNUNET_CADET_channel_destroy (channel);
1519 /* return the channel context */
1520 return &peer_ctx->peer_id;
1521 }
1522 peer_ctx->recv_channel = channel;
1523 return &peer_ctx->peer_id;
1524}
1525
1526
1527/**
1528 * @brief Check whether a sending channel towards the given peer exists
1529 *
1530 * @param peer the peer to check for
1531 *
1532 * @return #GNUNET_YES if a sending channel towards that peer exists
1533 * #GNUNET_NO otherwise
1534 */
1535int
1536Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
1537{
1538 struct PeerContext *peer_ctx;
1539
1540 if (GNUNET_NO == Peers_check_peer_known (peer))
1541 { /* If no such peer exists, there is no channel */
1542 return GNUNET_NO;
1543 }
1544 peer_ctx = get_peer_ctx (peer);
1545 if (NULL == peer_ctx->send_channel)
1546 {
1547 return GNUNET_NO;
1548 }
1549 return GNUNET_YES;
1550}
1551
1552
1553/**
1554 * @brief check whether the given channel is the sending channel of the given
1555 * peer
1556 *
1557 * @param peer the peer in question
1558 * @param channel the channel to check for
1559 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
1560 * #Peers_CHANNEL_ROLE_RECEIVING
1561 *
1562 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
1563 * #GNUNET_NO otherwise
1564 */
1565int
1566Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
1567 const struct GNUNET_CADET_Channel *channel,
1568 enum Peers_ChannelRole role)
1569{
1570 const struct PeerContext *peer_ctx;
1571
1572 if (GNUNET_NO == Peers_check_peer_known (peer))
1573 {
1574 return GNUNET_NO;
1575 }
1576 peer_ctx = get_peer_ctx (peer);
1577 if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
1578 (channel == peer_ctx->send_channel) )
1579 {
1580 return GNUNET_YES;
1581 }
1582 if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
1583 (channel == peer_ctx->recv_channel) )
1584 {
1585 return GNUNET_YES;
1586 }
1587 return GNUNET_NO;
1588}
1589
1590
1591/**
1592 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
1593 * intention to another peer
1594 *
1595 * If there is also no channel to receive messages from that peer, remove it
1596 * from the peermap.
1597 * TODO really?
1598 *
1599 * @peer the peer identity of the peer whose sending channel to destroy
1600 * @return #GNUNET_YES if channel was destroyed
1601 * #GNUNET_NO otherwise
1602 */
1603int
1604Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
1605{
1606 struct PeerContext *peer_ctx;
1607
1608 if (GNUNET_NO == Peers_check_peer_known (peer))
1609 {
1610 return GNUNET_NO;
1611 }
1612 peer_ctx = get_peer_ctx (peer);
1613 if (NULL != peer_ctx->send_channel)
1614 {
1615 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
1616 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1617 peer_ctx->send_channel = NULL;
1618 (void) Peers_check_connected (peer);
1619 return GNUNET_YES;
1620 }
1621 return GNUNET_NO;
1622}
1623
1624/**
1625 * This is called when a channel is destroyed.
1626 *
1627 * @param cls The closure
1628 * @param channel The channel being closed
1629 * @param channel_ctx The context associated with this channel
1630 */
1631void
1632Peers_cleanup_destroyed_channel (void *cls,
1633 const struct GNUNET_CADET_Channel *channel)
1634{
1635 struct GNUNET_PeerIdentity *peer = cls;
1636 struct PeerContext *peer_ctx;
1637
1638 if (GNUNET_NO == Peers_check_peer_known (peer))
1639 {/* We don't want to implicitly create a context that we're about to kill */
1640 LOG (GNUNET_ERROR_TYPE_DEBUG,
1641 "channel (%s) without associated context was destroyed\n",
1642 GNUNET_i2s (peer));
1643 return;
1644 }
1645 peer_ctx = get_peer_ctx (peer);
1646
1647 /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
1648 * flag will be set. In this case simply make sure that the channels are
1649 * cleaned. */
1650 /* FIXME This distinction seems to be redundant */
1651 if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
1652 {/* We initiatad the destruction of this particular peer */
1653 if (channel == peer_ctx->send_channel)
1654 peer_ctx->send_channel = NULL;
1655 else if (channel == peer_ctx->recv_channel)
1656 peer_ctx->recv_channel = NULL;
1657
1658 if (NULL != peer_ctx->send_channel)
1659 {
1660 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1661 peer_ctx->send_channel = NULL;
1662 }
1663 if (NULL != peer_ctx->recv_channel)
1664 {
1665 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1666 peer_ctx->recv_channel = NULL;
1667 }
1668 /* Set the #Peers_ONLINE flag accordingly */
1669 (void) Peers_check_connected (peer);
1670 return;
1671 }
1672
1673 else
1674 { /* We did not initiate the destruction of this peer */
1675 if (channel == peer_ctx->send_channel)
1676 { /* Something (but us) killd the channel - clean up peer */
1677 LOG (GNUNET_ERROR_TYPE_DEBUG,
1678 "send channel (%s) was destroyed - cleaning up\n",
1679 GNUNET_i2s (peer));
1680 peer_ctx->send_channel = NULL;
1681 }
1682 else if (channel == peer_ctx->recv_channel)
1683 { /* Other peer doesn't want to send us messages anymore */
1684 LOG (GNUNET_ERROR_TYPE_DEBUG,
1685 "Peer %s destroyed recv channel - cleaning up channel\n",
1686 GNUNET_i2s (peer));
1687 peer_ctx->recv_channel = NULL;
1688 }
1689 else
1690 {
1691 LOG (GNUNET_ERROR_TYPE_WARNING,
1692 "unknown channel (%s) was destroyed\n",
1693 GNUNET_i2s (peer));
1694 }
1695 }
1696 (void) Peers_check_connected (peer);
1697}
1698
1699/**
1700 * @brief Send a message to another peer.
1701 *
1702 * Keeps track about pending messages so they can be properly removed when the
1703 * peer is destroyed.
1704 *
1705 * @param peer receeiver of the message
1706 * @param ev envelope of the message
1707 * @param type type of the message
1708 */
1709void
1710Peers_send_message (const struct GNUNET_PeerIdentity *peer,
1711 struct GNUNET_MQ_Envelope *ev,
1712 const char *type)
1713{
1714 struct PendingMessage *pending_msg;
1715 struct GNUNET_MQ_Handle *mq;
1716
1717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1718 "Sending message to %s of type %s\n",
1719 GNUNET_i2s (peer),
1720 type);
1721 pending_msg = insert_pending_message (peer, ev, type);
1722 mq = get_mq (peer);
1723 GNUNET_MQ_notify_sent (ev,
1724 mq_notify_sent_cb,
1725 pending_msg);
1726 GNUNET_MQ_send (mq, ev);
1727}
1728
1729/**
1730 * @brief Schedule a operation on given peer
1731 *
1732 * Avoids scheduling an operation twice.
1733 *
1734 * @param peer the peer we want to schedule the operation for once it gets live
1735 *
1736 * @return #GNUNET_YES if the operation was scheduled
1737 * #GNUNET_NO otherwise
1738 */
1739int
1740Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
1741 const PeerOp peer_op)
1742{
1743 struct PeerPendingOp pending_op;
1744 struct PeerContext *peer_ctx;
1745
1746 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity))
1747 {
1748 return GNUNET_NO;
1749 }
1750 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1751
1752 //TODO if LIVE/ONLINE execute immediately
1753
1754 if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
1755 {
1756 peer_ctx = get_peer_ctx (peer);
1757 pending_op.op = peer_op;
1758 pending_op.op_cls = NULL;
1759 GNUNET_array_append (peer_ctx->pending_ops,
1760 peer_ctx->num_pending_ops,
1761 pending_op);
1762 return GNUNET_YES;
1763 }
1764 return GNUNET_NO;
1765}
1766
1767/**
1768 * @brief Get the recv_channel of @a peer.
1769 * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming
1770 * messages.
1771 *
1772 * @param peer The peer to get the recv_channel from.
1773 *
1774 * @return The recv_channel.
1775 */
1776struct GNUNET_CADET_Channel *
1777Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer)
1778{
1779 struct PeerContext *peer_ctx;
1780
1781 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1782 peer_ctx = get_peer_ctx (peer);
1783 return peer_ctx->recv_channel;
1784}
1785/***********************************************************************
1786 * /Old gnunet-service-rps_peers.c
1787***********************************************************************/
1788
1789
69/*********************************************************************** 1790/***********************************************************************
70 * Housekeeping with clients 1791 * Housekeeping with clients
71***********************************************************************/ 1792***********************************************************************/
@@ -847,6 +2568,7 @@ cleanup_destroyed_channel (void *cls,
847{ 2568{
848 struct GNUNET_PeerIdentity *peer = cls; 2569 struct GNUNET_PeerIdentity *peer = cls;
849 uint32_t *channel_flag; 2570 uint32_t *channel_flag;
2571 struct PeerContext *peer_ctx;
850 2572
851 if (GNUNET_NO == Peers_check_peer_known (peer)) 2573 if (GNUNET_NO == Peers_check_peer_known (peer))
852 { /* We don't know a context to that peer */ 2574 { /* We don't know a context to that peer */
@@ -856,6 +2578,15 @@ cleanup_destroyed_channel (void *cls,
856 return; 2578 return;
857 } 2579 }
858 2580
2581 peer_ctx = get_peer_ctx (peer);
2582 if (GNUNET_YES == Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_RECEIVING))
2583 {
2584 set_channel_flag (peer_ctx->recv_channel_flags, Peers_CHANNEL_DESTROING);
2585 } else if (GNUNET_YES == Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_SENDING))
2586 {
2587 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_DESTROING);
2588 }
2589
859 if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY)) 2590 if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY))
860 { /* We are in the middle of removing that peer from our knowledge. In this 2591 { /* We are in the middle of removing that peer from our knowledge. In this
861 case simply make sure that the channels are cleaned. */ 2592 case simply make sure that the channels are cleaned. */
@@ -1121,7 +2852,6 @@ handle_client_request_cancel (void *cls,
1121 (rep_cls->id != ntohl (msg->id)) ) 2852 (rep_cls->id != ntohl (msg->id)) )
1122 rep_cls = rep_cls->next; 2853 rep_cls = rep_cls->next;
1123 GNUNET_assert (rep_cls->id == ntohl (msg->id)); 2854 GNUNET_assert (rep_cls->id == ntohl (msg->id));
1124 RPS_sampler_request_cancel (rep_cls->req_handle);
1125 destroy_reply_cls (rep_cls); 2855 destroy_reply_cls (rep_cls);
1126 GNUNET_SERVICE_client_continue (cli_ctx->client); 2856 GNUNET_SERVICE_client_continue (cli_ctx->client);
1127} 2857}
@@ -1239,24 +2969,24 @@ handle_peer_push (void *cls,
1239 (3 == mal_type) ) 2969 (3 == mal_type) )
1240 { /* Try to maximise representation */ 2970 { /* Try to maximise representation */
1241 tmp_att_peer = GNUNET_new (struct AttackedPeer); 2971 tmp_att_peer = GNUNET_new (struct AttackedPeer);
1242 GNUNET_memcpy (&tmp_att_peer->peer_id, peer, sizeof (struct GNUNET_PeerIdentity)); 2972 tmp_att_peer->peer_id = *peer;
1243 if (NULL == att_peer_set) 2973 if (NULL == att_peer_set)
1244 att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO); 2974 att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
1245 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set, 2975 if (GNUNET_NO ==
1246 peer)) 2976 GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
2977 peer))
1247 { 2978 {
1248 GNUNET_CONTAINER_DLL_insert (att_peers_head, 2979 GNUNET_CONTAINER_DLL_insert (att_peers_head,
1249 att_peers_tail, 2980 att_peers_tail,
1250 tmp_att_peer); 2981 tmp_att_peer);
1251 add_peer_array_to_set (peer, 1, att_peer_set); 2982 add_peer_array_to_set (peer, 1, att_peer_set);
1252 } 2983 }
1253 GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
1254 } 2984 }
1255 2985
1256 2986
1257 else if (2 == mal_type) 2987 else if (2 == mal_type)
1258 { /* We attack one single well-known peer - simply ignore */ 2988 {
1259 GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); 2989 /* We attack one single well-known peer - simply ignore */
1260 } 2990 }
1261 #endif /* ENABLE_MALICIOUS */ 2991 #endif /* ENABLE_MALICIOUS */
1262 2992
@@ -1289,7 +3019,6 @@ handle_peer_pull_request (void *cls,
1289 || 3 == mal_type) 3019 || 3 == mal_type)
1290 { /* Try to maximise representation */ 3020 { /* Try to maximise representation */
1291 send_pull_reply (peer, mal_peers, num_mal_peers); 3021 send_pull_reply (peer, mal_peers, num_mal_peers);
1292 GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
1293 } 3022 }
1294 3023
1295 else if (2 == mal_type) 3024 else if (2 == mal_type)
@@ -1298,7 +3027,6 @@ handle_peer_pull_request (void *cls,
1298 { 3027 {
1299 send_pull_reply (peer, mal_peers, num_mal_peers); 3028 send_pull_reply (peer, mal_peers, num_mal_peers);
1300 } 3029 }
1301 GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
1302 } 3030 }
1303 #endif /* ENABLE_MALICIOUS */ 3031 #endif /* ENABLE_MALICIOUS */
1304 3032
@@ -1360,7 +3088,7 @@ static void
1360handle_peer_pull_reply (void *cls, 3088handle_peer_pull_reply (void *cls,
1361 const struct GNUNET_RPS_P2P_PullReplyMessage *msg) 3089 const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
1362{ 3090{
1363 struct GNUNET_PeerIdentity *peers; 3091 const struct GNUNET_PeerIdentity *peers;
1364 struct GNUNET_PeerIdentity *sender = cls; 3092 struct GNUNET_PeerIdentity *sender = cls;
1365 uint32_t i; 3093 uint32_t i;
1366#ifdef ENABLE_MALICIOUS 3094#ifdef ENABLE_MALICIOUS
@@ -1373,12 +3101,11 @@ handle_peer_pull_reply (void *cls,
1373 // We shouldn't even receive pull replies as we're not sending 3101 // We shouldn't even receive pull replies as we're not sending
1374 if (2 == mal_type) 3102 if (2 == mal_type)
1375 { 3103 {
1376 GNUNET_CADET_receive_done (Peers_get_recv_channel (sender));
1377 } 3104 }
1378 #endif /* ENABLE_MALICIOUS */ 3105 #endif /* ENABLE_MALICIOUS */
1379 3106
1380 /* Do actual logic */ 3107 /* Do actual logic */
1381 peers = (struct GNUNET_PeerIdentity *) &msg[1]; 3108 peers = (const struct GNUNET_PeerIdentity *) &msg[1];
1382 3109
1383 LOG (GNUNET_ERROR_TYPE_DEBUG, 3110 LOG (GNUNET_ERROR_TYPE_DEBUG,
1384 "PULL REPLY received, got following %u peers:\n", 3111 "PULL REPLY received, got following %u peers:\n",
@@ -2132,7 +3859,6 @@ shutdown_task (void *cls)
2132 reply_cls); 3859 reply_cls);
2133 GNUNET_free (reply_cls); 3860 GNUNET_free (reply_cls);
2134 } 3861 }
2135 GNUNET_MQ_destroy (client_ctx->mq);
2136 GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx); 3862 GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx);
2137 GNUNET_free (client_ctx); 3863 GNUNET_free (client_ctx);
2138 } 3864 }
@@ -2150,6 +3876,7 @@ shutdown_task (void *cls)
2150 GNUNET_NSE_disconnect (nse); 3876 GNUNET_NSE_disconnect (nse);
2151 RPS_sampler_destroy (prot_sampler); 3877 RPS_sampler_destroy (prot_sampler);
2152 RPS_sampler_destroy (client_sampler); 3878 RPS_sampler_destroy (client_sampler);
3879 GNUNET_CADET_close_port (cadet_port);
2153 GNUNET_CADET_disconnect (cadet_handle); 3880 GNUNET_CADET_disconnect (cadet_handle);
2154 View_destroy (); 3881 View_destroy ();
2155 CustomPeerMap_destroy (push_map); 3882 CustomPeerMap_destroy (push_map);
@@ -2240,26 +3967,6 @@ run (void *cls,
2240 const struct GNUNET_CONFIGURATION_Handle *c, 3967 const struct GNUNET_CONFIGURATION_Handle *c,
2241 struct GNUNET_SERVICE_Handle *service) 3968 struct GNUNET_SERVICE_Handle *service)
2242{ 3969{
2243 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
2244 GNUNET_MQ_hd_fixed_size (peer_check,
2245 GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE,
2246 struct GNUNET_MessageHeader,
2247 NULL),
2248 GNUNET_MQ_hd_fixed_size (peer_push,
2249 GNUNET_MESSAGE_TYPE_RPS_PP_PUSH,
2250 struct GNUNET_MessageHeader,
2251 NULL),
2252 GNUNET_MQ_hd_fixed_size (peer_pull_request,
2253 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
2254 struct GNUNET_MessageHeader,
2255 NULL),
2256 GNUNET_MQ_hd_var_size (peer_pull_reply,
2257 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY,
2258 struct GNUNET_RPS_P2P_PullReplyMessage,
2259 NULL),
2260 GNUNET_MQ_handler_end ()
2261 };
2262
2263 int size; 3970 int size;
2264 int out_size; 3971 int out_size;
2265 char* fn_valid_peers; 3972 char* fn_valid_peers;
@@ -2349,6 +4056,27 @@ run (void *cls,
2349 4056
2350 4057
2351 /* Initialise cadet */ 4058 /* Initialise cadet */
4059 /* There exists a copy-paste-clone in get_channel() */
4060 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
4061 GNUNET_MQ_hd_fixed_size (peer_check,
4062 GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE,
4063 struct GNUNET_MessageHeader,
4064 NULL),
4065 GNUNET_MQ_hd_fixed_size (peer_push,
4066 GNUNET_MESSAGE_TYPE_RPS_PP_PUSH,
4067 struct GNUNET_MessageHeader,
4068 NULL),
4069 GNUNET_MQ_hd_fixed_size (peer_pull_request,
4070 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
4071 struct GNUNET_MessageHeader,
4072 NULL),
4073 GNUNET_MQ_hd_var_size (peer_pull_reply,
4074 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY,
4075 struct GNUNET_RPS_P2P_PullReplyMessage,
4076 NULL),
4077 GNUNET_MQ_handler_end ()
4078 };
4079
2352 cadet_handle = GNUNET_CADET_connect (cfg); 4080 cadet_handle = GNUNET_CADET_connect (cfg);
2353 GNUNET_assert (NULL != cadet_handle); 4081 GNUNET_assert (NULL != cadet_handle);
2354 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS, 4082 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS,
@@ -2365,7 +4093,7 @@ run (void *cls,
2365 4093
2366 peerinfo_handle = GNUNET_PEERINFO_connect (cfg); 4094 peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
2367 Peers_initialise (fn_valid_peers, cadet_handle, cleanup_destroyed_channel, 4095 Peers_initialise (fn_valid_peers, cadet_handle, cleanup_destroyed_channel,
2368 cadet_handlers, &own_identity); 4096 &own_identity);
2369 GNUNET_free (fn_valid_peers); 4097 GNUNET_free (fn_valid_peers);
2370 4098
2371 /* Initialise sampler */ 4099 /* Initialise sampler */
diff --git a/src/rps/gnunet-service-rps_peers.c b/src/rps/gnunet-service-rps_peers.c
deleted file mode 100644
index 58aa84ccf..000000000
--- a/src/rps/gnunet-service-rps_peers.c
+++ /dev/null
@@ -1,1694 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file rps/gnunet-service-rps_peers.c
23 * @brief utilities for managing (information about) peers
24 * @author Julius Bünger
25 */
26#include "platform.h"
27#include "gnunet_applications.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_cadet_service.h"
30#include <inttypes.h>
31#include "rps.h"
32#include "gnunet-service-rps_peers.h"
33
34
35
36#define LOG(kind, ...) GNUNET_log_from(kind,"rps-peers",__VA_ARGS__)
37
38
39/**
40 * Set a peer flag of given peer context.
41 */
42#define set_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) |= (mask))
43
44/**
45 * Get peer flag of given peer context.
46 */
47#define check_peer_flag_set(peer_ctx, mask)\
48 ((peer_ctx->peer_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
49
50/**
51 * Unset flag of given peer context.
52 */
53#define unset_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) &= ~(mask))
54
55/**
56 * Set a channel flag of given channel context.
57 */
58#define set_channel_flag(channel_flags, mask) ((*channel_flags) |= (mask))
59
60/**
61 * Get channel flag of given channel context.
62 */
63#define check_channel_flag_set(channel_flags, mask)\
64 ((*channel_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
65
66/**
67 * Unset flag of given channel context.
68 */
69#define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= ~(mask))
70
71
72
73/**
74 * Pending operation on peer consisting of callback and closure
75 *
76 * When an operation cannot be executed right now this struct is used to store
77 * the callback and closure for later execution.
78 */
79struct PeerPendingOp
80{
81 /**
82 * Callback
83 */
84 PeerOp op;
85
86 /**
87 * Closure
88 */
89 void *op_cls;
90};
91
92/**
93 * List containing all messages that are yet to be send
94 *
95 * This is used to keep track of all messages that have not been sent yet. When
96 * a peer is to be removed the pending messages can be removed properly.
97 */
98struct PendingMessage
99{
100 /**
101 * DLL next, prev
102 */
103 struct PendingMessage *next;
104 struct PendingMessage *prev;
105
106 /**
107 * The envelope to the corresponding message
108 */
109 struct GNUNET_MQ_Envelope *ev;
110
111 /**
112 * The corresponding context
113 */
114 struct PeerContext *peer_ctx;
115
116 /**
117 * The message type
118 */
119 const char *type;
120};
121
122/**
123 * Struct used to keep track of other peer's status
124 *
125 * This is stored in a multipeermap.
126 * It contains information such as cadet channels, a message queue for sending,
127 * status about the channels, the pending operations on this peer and some flags
128 * about the status of the peer itself. (live, valid, ...)
129 */
130struct PeerContext
131{
132 /**
133 * Message queue open to client
134 */
135 struct GNUNET_MQ_Handle *mq;
136
137 /**
138 * Channel open to client.
139 */
140 struct GNUNET_CADET_Channel *send_channel;
141
142 /**
143 * Flags to the sending channel
144 */
145 uint32_t *send_channel_flags;
146
147 /**
148 * Channel open from client.
149 */
150 struct GNUNET_CADET_Channel *recv_channel; // unneeded?
151
152 /**
153 * Flags to the receiving channel
154 */
155 uint32_t *recv_channel_flags;
156
157 /**
158 * Array of pending operations on this peer.
159 */
160 struct PeerPendingOp *pending_ops;
161
162 /**
163 * Handle to the callback given to cadet_ntfy_tmt_rdy()
164 *
165 * To be canceled on shutdown.
166 */
167 struct PendingMessage *liveliness_check_pending;
168
169 /**
170 * Number of pending operations.
171 */
172 unsigned int num_pending_ops;
173
174 /**
175 * Identity of the peer
176 */
177 struct GNUNET_PeerIdentity peer_id;
178
179 /**
180 * Flags indicating status of peer
181 */
182 uint32_t peer_flags;
183
184 /**
185 * Last time we received something from that peer.
186 */
187 struct GNUNET_TIME_Absolute last_message_recv;
188
189 /**
190 * Last time we received a keepalive message.
191 */
192 struct GNUNET_TIME_Absolute last_keepalive;
193
194 /**
195 * DLL with all messages that are yet to be sent
196 */
197 struct PendingMessage *pending_messages_head;
198 struct PendingMessage *pending_messages_tail;
199
200 /**
201 * This is pobably followed by 'statistical' data (when we first saw
202 * him, how did we get his ID, how many pushes (in a timeinterval),
203 * ...)
204 */
205};
206
207/**
208 * @brief Closure to #valid_peer_iterator
209 */
210struct PeersIteratorCls
211{
212 /**
213 * Iterator function
214 */
215 PeersIterator iterator;
216
217 /**
218 * Closure to iterator
219 */
220 void *cls;
221};
222
223/**
224 * @brief Hashmap of valid peers.
225 */
226static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers;
227
228/**
229 * @brief Maximum number of valid peers to keep.
230 * TODO read from config
231 */
232static uint32_t num_valid_peers_max = UINT32_MAX;
233
234/**
235 * @brief Filename of the file that stores the valid peers persistently.
236 */
237static char *filename_valid_peers;
238
239/**
240 * Set of all peers to keep track of them.
241 */
242static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
243
244/**
245 * Own #GNUNET_PeerIdentity.
246 */
247static const struct GNUNET_PeerIdentity *own_identity;
248
249/**
250 * Cadet handle.
251 */
252static struct GNUNET_CADET_Handle *cadet_handle;
253
254/**
255 * @brief Disconnect handler
256 */
257static GNUNET_CADET_DisconnectEventHandler cleanup_destroyed_channel;
258
259/**
260 * @brief cadet handlers
261 */
262static const struct GNUNET_MQ_MessageHandler *cadet_handlers;
263
264
265
266/**
267 * @brief Get the #PeerContext associated with a peer
268 *
269 * @param peer the peer id
270 *
271 * @return the #PeerContext
272 */
273static struct PeerContext *
274get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
275{
276 struct PeerContext *ctx;
277 int ret;
278
279 ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
280 GNUNET_assert (GNUNET_YES == ret);
281 ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
282 GNUNET_assert (NULL != ctx);
283 return ctx;
284}
285
286
287/**
288 * @brief Create a new #PeerContext and insert it into the peer map
289 *
290 * @param peer the peer to create the #PeerContext for
291 *
292 * @return the #PeerContext
293 */
294static struct PeerContext *
295create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
296{
297 struct PeerContext *ctx;
298 int ret;
299
300 GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));
301
302 ctx = GNUNET_new (struct PeerContext);
303 ctx->peer_id = *peer;
304 ctx->send_channel_flags = GNUNET_new (uint32_t);
305 ctx->recv_channel_flags = GNUNET_new (uint32_t);
306 ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
307 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
308 GNUNET_assert (GNUNET_OK == ret);
309 return ctx;
310}
311
312
313/**
314 * @brief Create or get a #PeerContext
315 *
316 * @param peer the peer to get the associated context to
317 *
318 * @return the context
319 */
320static struct PeerContext *
321create_or_get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
322{
323 if (GNUNET_NO == Peers_check_peer_known (peer))
324 {
325 return create_peer_ctx (peer);
326 }
327 return get_peer_ctx (peer);
328}
329
330
331/**
332 * @brief Check whether we have a connection to this @a peer
333 *
334 * Also sets the #Peers_ONLINE flag accordingly
335 *
336 * @param peer the peer in question
337 *
338 * @return #GNUNET_YES if we are connected
339 * #GNUNET_NO otherwise
340 */
341int
342Peers_check_connected (const struct GNUNET_PeerIdentity *peer)
343{
344 const struct PeerContext *peer_ctx;
345
346 /* If we don't know about this peer we don't know whether it's online */
347 if (GNUNET_NO == Peers_check_peer_known (peer))
348 {
349 return GNUNET_NO;
350 }
351 /* Get the context */
352 peer_ctx = get_peer_ctx (peer);
353 /* If we have no channel to this peer we don't know whether it's online */
354 if ( (NULL == peer_ctx->send_channel) &&
355 (NULL == peer_ctx->recv_channel) )
356 {
357 Peers_unset_peer_flag (peer, Peers_ONLINE);
358 return GNUNET_NO;
359 }
360 /* Otherwise (if we have a channel, we know that it's online */
361 Peers_set_peer_flag (peer, Peers_ONLINE);
362 return GNUNET_YES;
363}
364
365
366/**
367 * @brief The closure to #get_rand_peer_iterator.
368 */
369struct GetRandPeerIteratorCls
370{
371 /**
372 * @brief The index of the peer to return.
373 * Will be decreased until 0.
374 * Then current peer is returned.
375 */
376 uint32_t index;
377
378 /**
379 * @brief Pointer to peer to return.
380 */
381 const struct GNUNET_PeerIdentity *peer;
382};
383
384
385/**
386 * @brief Iterator function for #get_random_peer_from_peermap.
387 *
388 * Implements #GNUNET_CONTAINER_PeerMapIterator.
389 * Decreases the index until the index is null.
390 * Then returns the current peer.
391 *
392 * @param cls the #GetRandPeerIteratorCls containing index and peer
393 * @param peer current peer
394 * @param value unused
395 *
396 * @return #GNUNET_YES if we should continue to
397 * iterate,
398 * #GNUNET_NO if not.
399 */
400static int
401get_rand_peer_iterator (void *cls,
402 const struct GNUNET_PeerIdentity *peer,
403 void *value)
404{
405 struct GetRandPeerIteratorCls *iterator_cls = cls;
406 if (0 >= iterator_cls->index)
407 {
408 iterator_cls->peer = peer;
409 return GNUNET_NO;
410 }
411 iterator_cls->index--;
412 return GNUNET_YES;
413}
414
415
416/**
417 * @brief Get a random peer from @a peer_map
418 *
419 * @param peer_map the peer_map to get the peer from
420 *
421 * @return a random peer
422 */
423static const struct GNUNET_PeerIdentity *
424get_random_peer_from_peermap (const struct
425 GNUNET_CONTAINER_MultiPeerMap *peer_map)
426{
427 struct GetRandPeerIteratorCls *iterator_cls;
428 const struct GNUNET_PeerIdentity *ret;
429
430 iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
431 iterator_cls->index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
432 GNUNET_CONTAINER_multipeermap_size (peer_map));
433 (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
434 get_rand_peer_iterator,
435 iterator_cls);
436 ret = iterator_cls->peer;
437 GNUNET_free (iterator_cls);
438 return ret;
439}
440
441
442/**
443 * @brief Add a given @a peer to valid peers.
444 *
445 * If valid peers are already #num_valid_peers_max, delete a peer previously.
446 *
447 * @param peer the peer that is added to the valid peers.
448 *
449 * @return #GNUNET_YES if no other peer had to be removed
450 * #GNUNET_NO otherwise
451 */
452static int
453add_valid_peer (const struct GNUNET_PeerIdentity *peer)
454{
455 const struct GNUNET_PeerIdentity *rand_peer;
456 int ret;
457
458 ret = GNUNET_YES;
459 while (GNUNET_CONTAINER_multipeermap_size (valid_peers) >= num_valid_peers_max)
460 {
461 rand_peer = get_random_peer_from_peermap (valid_peers);
462 GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
463 ret = GNUNET_NO;
464 }
465 (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
466 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
467 return ret;
468}
469
470
471/**
472 * @brief Set the peer flag to living and
473 * call the pending operations on this peer.
474 *
475 * Also adds peer to #valid_peers.
476 *
477 * @param peer_ctx the #PeerContext of the peer to set live
478 */
479static void
480set_peer_live (struct PeerContext *peer_ctx)
481{
482 struct GNUNET_PeerIdentity *peer;
483 unsigned int i;
484
485 peer = &peer_ctx->peer_id;
486 LOG (GNUNET_ERROR_TYPE_DEBUG,
487 "Peer %s is live and valid, calling %i pending operations on it\n",
488 GNUNET_i2s (peer),
489 peer_ctx->num_pending_ops);
490
491 if (NULL != peer_ctx->liveliness_check_pending)
492 {
493 LOG (GNUNET_ERROR_TYPE_DEBUG,
494 "Removing pending liveliness check for peer %s\n",
495 GNUNET_i2s (&peer_ctx->peer_id));
496 // TODO wait until cadet sets mq->cancel_impl
497 //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
498 GNUNET_free (peer_ctx->liveliness_check_pending);
499 peer_ctx->liveliness_check_pending = NULL;
500 }
501
502 (void) add_valid_peer (peer);
503 set_peer_flag (peer_ctx, Peers_ONLINE);
504
505 /* Call pending operations */
506 for (i = 0; i < peer_ctx->num_pending_ops; i++)
507 {
508 peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
509 }
510 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
511}
512
513
514/**
515 * @brief Get the channel of a peer. If not existing, create.
516 *
517 * @param peer the peer id
518 * @return the #GNUNET_CADET_Channel used to send data to @a peer
519 */
520struct GNUNET_CADET_Channel *
521get_channel (const struct GNUNET_PeerIdentity *peer)
522{
523 struct PeerContext *peer_ctx;
524 struct GNUNET_HashCode port;
525
526 peer_ctx = get_peer_ctx (peer);
527 if (NULL == peer_ctx->send_channel)
528 {
529 LOG (GNUNET_ERROR_TYPE_DEBUG,
530 "Trying to establish channel to peer %s\n",
531 GNUNET_i2s (peer));
532 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS,
533 strlen (GNUNET_APPLICATION_PORT_RPS),
534 &port);
535 peer_ctx->send_channel =
536 GNUNET_CADET_channel_create (cadet_handle,
537 (struct GNUNET_PeerIdentity *) peer, /* context */
538 peer,
539 &port,
540 GNUNET_CADET_OPTION_RELIABLE,
541 NULL, /* WindowSize handler */
542 cleanup_destroyed_channel, /* Disconnect handler */
543 cadet_handlers);
544 }
545 GNUNET_assert (NULL != peer_ctx->send_channel);
546 return peer_ctx->send_channel;
547}
548
549
550/**
551 * Get the message queue (#GNUNET_MQ_Handle) of a specific peer.
552 *
553 * If we already have a message queue open to this client,
554 * simply return it, otherways create one.
555 *
556 * @param peer the peer to get the mq to
557 * @return the #GNUNET_MQ_Handle
558 */
559static struct GNUNET_MQ_Handle *
560get_mq (const struct GNUNET_PeerIdentity *peer)
561{
562 struct PeerContext *peer_ctx;
563
564 peer_ctx = get_peer_ctx (peer);
565
566 if (NULL == peer_ctx->mq)
567 {
568 (void) get_channel (peer);
569 peer_ctx->mq = GNUNET_CADET_get_mq (peer_ctx->send_channel);
570 }
571 return peer_ctx->mq;
572}
573
574
575/**
576 * @brief This is called in response to the first message we sent as a
577 * liveliness check.
578 *
579 * @param cls #PeerContext of peer with pending liveliness check
580 */
581static void
582mq_liveliness_check_successful (void *cls)
583{
584 struct PeerContext *peer_ctx = cls;
585
586 if (NULL != peer_ctx->liveliness_check_pending)
587 {
588 LOG (GNUNET_ERROR_TYPE_DEBUG,
589 "Liveliness check for peer %s was successfull\n",
590 GNUNET_i2s (&peer_ctx->peer_id));
591 GNUNET_free (peer_ctx->liveliness_check_pending);
592 peer_ctx->liveliness_check_pending = NULL;
593 set_peer_live (peer_ctx);
594 }
595}
596
597/**
598 * Issue a check whether peer is live
599 *
600 * @param peer_ctx the context of the peer
601 */
602static void
603check_peer_live (struct PeerContext *peer_ctx)
604{
605 LOG (GNUNET_ERROR_TYPE_DEBUG,
606 "Get informed about peer %s getting live\n",
607 GNUNET_i2s (&peer_ctx->peer_id));
608
609 struct GNUNET_MQ_Handle *mq;
610 struct GNUNET_MQ_Envelope *ev;
611
612 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE);
613 peer_ctx->liveliness_check_pending = GNUNET_new (struct PendingMessage);
614 peer_ctx->liveliness_check_pending->ev = ev;
615 peer_ctx->liveliness_check_pending->peer_ctx = peer_ctx;
616 peer_ctx->liveliness_check_pending->type = "Check liveliness";
617 mq = get_mq (&peer_ctx->peer_id);
618 GNUNET_MQ_notify_sent (ev,
619 mq_liveliness_check_successful,
620 peer_ctx);
621 GNUNET_MQ_send (mq, ev);
622}
623
624/**
625 * @brief Add an envelope to a message passed to mq to list of pending messages
626 *
627 * @param peer peer the message was sent to
628 * @param ev envelope to the message
629 * @param type type of the message to be sent
630 * @return pointer to pending message
631 */
632static struct PendingMessage *
633insert_pending_message (const struct GNUNET_PeerIdentity *peer,
634 struct GNUNET_MQ_Envelope *ev,
635 const char *type)
636{
637 struct PendingMessage *pending_msg;
638 struct PeerContext *peer_ctx;
639
640 peer_ctx = get_peer_ctx (peer);
641 pending_msg = GNUNET_new (struct PendingMessage);
642 pending_msg->ev = ev;
643 pending_msg->peer_ctx = peer_ctx;
644 pending_msg->type = type;
645 GNUNET_CONTAINER_DLL_insert (peer_ctx->pending_messages_head,
646 peer_ctx->pending_messages_tail,
647 pending_msg);
648 return pending_msg;
649}
650
651
652/**
653 * @brief Remove a pending message from the respective DLL
654 *
655 * @param pending_msg the pending message to remove
656 */
657static void
658remove_pending_message (struct PendingMessage *pending_msg)
659{
660 struct PeerContext *peer_ctx;
661
662 peer_ctx = pending_msg->peer_ctx;
663 GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
664 peer_ctx->pending_messages_tail,
665 pending_msg);
666 GNUNET_MQ_send_cancel (peer_ctx->pending_messages_head->ev);
667 GNUNET_free (pending_msg);
668}
669
670
671/**
672 * @brief Check whether function of type #PeerOp was already scheduled
673 *
674 * The array with pending operations will probably never grow really big, so
675 * iterating over it should be ok.
676 *
677 * @param peer the peer to check
678 * @param peer_op the operation (#PeerOp) on the peer
679 *
680 * @return #GNUNET_YES if this operation is scheduled on that peer
681 * #GNUNET_NO otherwise
682 */
683static int
684check_operation_scheduled (const struct GNUNET_PeerIdentity *peer,
685 const PeerOp peer_op)
686{
687 const struct PeerContext *peer_ctx;
688 unsigned int i;
689
690 peer_ctx = get_peer_ctx (peer);
691 for (i = 0; i < peer_ctx->num_pending_ops; i++)
692 if (peer_op == peer_ctx->pending_ops[i].op)
693 return GNUNET_YES;
694 return GNUNET_NO;
695}
696
697
698/**
699 * Iterator over hash map entries. Deletes all contexts of peers.
700 *
701 * @param cls closure
702 * @param key current public key
703 * @param value value in the hash map
704 * @return #GNUNET_YES if we should continue to iterate,
705 * #GNUNET_NO if not.
706 */
707static int
708peermap_clear_iterator (void *cls,
709 const struct GNUNET_PeerIdentity *key,
710 void *value)
711{
712 Peers_remove_peer (key);
713 return GNUNET_YES;
714}
715
716
717/**
718 * @brief This is called once a message is sent.
719 *
720 * Removes the pending message
721 *
722 * @param cls type of the message that was sent
723 */
724static void
725mq_notify_sent_cb (void *cls)
726{
727 struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
728 LOG (GNUNET_ERROR_TYPE_DEBUG,
729 "%s was sent.\n",
730 pending_msg->type);
731 remove_pending_message (pending_msg);
732}
733
734
735/**
736 * @brief Iterator function for #store_valid_peers.
737 *
738 * Implements #GNUNET_CONTAINER_PeerMapIterator.
739 * Writes single peer to disk.
740 *
741 * @param cls the file handle to write to.
742 * @param peer current peer
743 * @param value unused
744 *
745 * @return #GNUNET_YES if we should continue to
746 * iterate,
747 * #GNUNET_NO if not.
748 */
749static int
750store_peer_presistently_iterator (void *cls,
751 const struct GNUNET_PeerIdentity *peer,
752 void *value)
753{
754 const struct GNUNET_DISK_FileHandle *fh = cls;
755 char peer_string[128];
756 int size;
757 ssize_t ret;
758
759 if (NULL == peer)
760 {
761 return GNUNET_YES;
762 }
763 size = GNUNET_snprintf (peer_string,
764 sizeof (peer_string),
765 "%s\n",
766 GNUNET_i2s_full (peer));
767 GNUNET_assert (53 == size);
768 ret = GNUNET_DISK_file_write (fh,
769 peer_string,
770 size);
771 GNUNET_assert (size == ret);
772 return GNUNET_YES;
773}
774
775
776/**
777 * @brief Store the peers currently in #valid_peers to disk.
778 */
779static void
780store_valid_peers ()
781{
782 struct GNUNET_DISK_FileHandle *fh;
783 uint32_t number_written_peers;
784 int ret;
785
786 if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
787 {
788 return;
789 }
790
791 ret = GNUNET_DISK_directory_create_for_file (filename_valid_peers);
792 if (GNUNET_SYSERR == ret)
793 {
794 LOG (GNUNET_ERROR_TYPE_WARNING,
795 "Not able to create directory for file `%s'\n",
796 filename_valid_peers);
797 GNUNET_break (0);
798 }
799 else if (GNUNET_NO == ret)
800 {
801 LOG (GNUNET_ERROR_TYPE_WARNING,
802 "Directory for file `%s' exists but is not writable for us\n",
803 filename_valid_peers);
804 GNUNET_break (0);
805 }
806 fh = GNUNET_DISK_file_open (filename_valid_peers,
807 GNUNET_DISK_OPEN_WRITE |
808 GNUNET_DISK_OPEN_CREATE,
809 GNUNET_DISK_PERM_USER_READ |
810 GNUNET_DISK_PERM_USER_WRITE);
811 if (NULL == fh)
812 {
813 LOG (GNUNET_ERROR_TYPE_WARNING,
814 "Not able to write valid peers to file `%s'\n",
815 filename_valid_peers);
816 return;
817 }
818 LOG (GNUNET_ERROR_TYPE_DEBUG,
819 "Writing %u valid peers to disk\n",
820 GNUNET_CONTAINER_multipeermap_size (valid_peers));
821 number_written_peers =
822 GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
823 store_peer_presistently_iterator,
824 fh);
825 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
826 GNUNET_assert (number_written_peers ==
827 GNUNET_CONTAINER_multipeermap_size (valid_peers));
828}
829
830
831/**
832 * @brief Convert string representation of peer id to peer id.
833 *
834 * Counterpart to #GNUNET_i2s_full.
835 *
836 * @param string_repr The string representation of the peer id
837 *
838 * @return The peer id
839 */
840static const struct GNUNET_PeerIdentity *
841s2i_full (const char *string_repr)
842{
843 struct GNUNET_PeerIdentity *peer;
844 size_t len;
845 int ret;
846
847 peer = GNUNET_new (struct GNUNET_PeerIdentity);
848 len = strlen (string_repr);
849 if (52 > len)
850 {
851 LOG (GNUNET_ERROR_TYPE_WARNING,
852 "Not able to convert string representation of PeerID to PeerID\n"
853 "Sting representation: %s (len %u) - too short\n",
854 string_repr,
855 len);
856 GNUNET_break (0);
857 }
858 else if (52 < len)
859 {
860 len = 52;
861 }
862 ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr,
863 len,
864 &peer->public_key);
865 if (GNUNET_OK != ret)
866 {
867 LOG (GNUNET_ERROR_TYPE_WARNING,
868 "Not able to convert string representation of PeerID to PeerID\n"
869 "Sting representation: %s\n",
870 string_repr);
871 GNUNET_break (0);
872 }
873 return peer;
874}
875
876
877/**
878 * @brief Restore the peers on disk to #valid_peers.
879 */
880static void
881restore_valid_peers ()
882{
883 off_t file_size;
884 uint32_t num_peers;
885 struct GNUNET_DISK_FileHandle *fh;
886 char *buf;
887 ssize_t size_read;
888 char *iter_buf;
889 char *str_repr;
890 const struct GNUNET_PeerIdentity *peer;
891
892 if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
893 {
894 return;
895 }
896
897 if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers))
898 {
899 return;
900 }
901 fh = GNUNET_DISK_file_open (filename_valid_peers,
902 GNUNET_DISK_OPEN_READ,
903 GNUNET_DISK_PERM_NONE);
904 GNUNET_assert (NULL != fh);
905 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size));
906 num_peers = file_size / 53;
907 buf = GNUNET_malloc (file_size);
908 size_read = GNUNET_DISK_file_read (fh, buf, file_size);
909 GNUNET_assert (size_read == file_size);
910 LOG (GNUNET_ERROR_TYPE_DEBUG,
911 "Restoring %" PRIu32 " peers from file `%s'\n",
912 num_peers,
913 filename_valid_peers);
914 for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53)
915 {
916 str_repr = GNUNET_strndup (iter_buf, 53);
917 peer = s2i_full (str_repr);
918 GNUNET_free (str_repr);
919 add_valid_peer (peer);
920 LOG (GNUNET_ERROR_TYPE_DEBUG,
921 "Restored valid peer %s from disk\n",
922 GNUNET_i2s_full (peer));
923 }
924 iter_buf = NULL;
925 GNUNET_free (buf);
926 LOG (GNUNET_ERROR_TYPE_DEBUG,
927 "num_peers: %" PRIu32 ", _size (valid_peers): %u\n",
928 num_peers,
929 GNUNET_CONTAINER_multipeermap_size (valid_peers));
930 if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers))
931 {
932 LOG (GNUNET_ERROR_TYPE_WARNING,
933 "Number of restored peers does not match file size. Have probably duplicates.\n");
934 }
935 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
936 LOG (GNUNET_ERROR_TYPE_DEBUG,
937 "Restored %u valid peers from disk\n",
938 GNUNET_CONTAINER_multipeermap_size (valid_peers));
939}
940
941
942/**
943 * @brief Initialise storage of peers
944 *
945 * @param fn_valid_peers filename of the file used to store valid peer ids
946 * @param cadet_h cadet handle
947 * @param disconnect_handler Disconnect handler
948 * @param c_handlers cadet handlers
949 * @param own_id own peer identity
950 */
951void
952Peers_initialise (char* fn_valid_peers,
953 struct GNUNET_CADET_Handle *cadet_h,
954 GNUNET_CADET_DisconnectEventHandler disconnect_handler,
955 const struct GNUNET_MQ_MessageHandler *c_handlers,
956 const struct GNUNET_PeerIdentity *own_id)
957{
958 filename_valid_peers = GNUNET_strdup (fn_valid_peers);
959 cadet_handle = cadet_h;
960 cleanup_destroyed_channel = disconnect_handler;
961 cadet_handlers = c_handlers;
962 own_identity = own_id;
963 peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
964 valid_peers = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
965 restore_valid_peers ();
966}
967
968
969/**
970 * @brief Delete storage of peers that was created with #Peers_initialise ()
971 */
972void
973Peers_terminate ()
974{
975 if (GNUNET_SYSERR ==
976 GNUNET_CONTAINER_multipeermap_iterate (peer_map,
977 peermap_clear_iterator,
978 NULL))
979 {
980 LOG (GNUNET_ERROR_TYPE_WARNING,
981 "Iteration destroying peers was aborted.\n");
982 }
983 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
984 store_valid_peers ();
985 GNUNET_free (filename_valid_peers);
986 GNUNET_CONTAINER_multipeermap_destroy (valid_peers);
987}
988
989
990/**
991 * Iterator over #valid_peers hash map entries.
992 *
993 * @param cls closure - unused
994 * @param peer current peer id
995 * @param value value in the hash map - unused
996 * @return #GNUNET_YES if we should continue to
997 * iterate,
998 * #GNUNET_NO if not.
999 */
1000static int
1001valid_peer_iterator (void *cls,
1002 const struct GNUNET_PeerIdentity *peer,
1003 void *value)
1004{
1005 struct PeersIteratorCls *it_cls = cls;
1006
1007 return it_cls->iterator (it_cls->cls,
1008 peer);
1009}
1010
1011
1012/**
1013 * @brief Get all currently known, valid peer ids.
1014 *
1015 * @param it function to call on each peer id
1016 * @param it_cls extra argument to @a it
1017 * @return the number of key value pairs processed,
1018 * #GNUNET_SYSERR if it aborted iteration
1019 */
1020int
1021Peers_get_valid_peers (PeersIterator iterator,
1022 void *it_cls)
1023{
1024 struct PeersIteratorCls *cls;
1025 int ret;
1026
1027 cls = GNUNET_new (struct PeersIteratorCls);
1028 cls->iterator = iterator;
1029 cls->cls = it_cls;
1030 ret = GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
1031 valid_peer_iterator,
1032 cls);
1033 GNUNET_free (cls);
1034 return ret;
1035}
1036
1037
1038/**
1039 * @brief Add peer to known peers.
1040 *
1041 * This function is called on new peer_ids from 'external' sources
1042 * (client seed, cadet get_peers(), ...)
1043 *
1044 * @param peer the new #GNUNET_PeerIdentity
1045 *
1046 * @return #GNUNET_YES if peer was inserted
1047 * #GNUNET_NO otherwise (if peer was already known or
1048 * peer was #own_identity)
1049 */
1050int
1051Peers_insert_peer (const struct GNUNET_PeerIdentity *peer)
1052{
1053 if ( (GNUNET_YES == Peers_check_peer_known (peer)) ||
1054 (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity)) )
1055 {
1056 return GNUNET_NO; /* We already know this peer - nothing to do */
1057 }
1058 (void) create_peer_ctx (peer);
1059 return GNUNET_YES;
1060}
1061
1062
1063/**
1064 * @brief Try connecting to a peer to see whether it is online
1065 *
1066 * If not known yet, insert into known peers
1067 *
1068 * @param peer the peer whose liveliness is to be checked
1069 * @return #GNUNET_YES if peer had to be inserted
1070 * #GNUNET_NO otherwise (if peer was already known or
1071 * peer was #own_identity)
1072 */
1073int
1074Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer)
1075{
1076 struct PeerContext *peer_ctx;
1077 int ret;
1078
1079 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1080 {
1081 return GNUNET_NO;
1082 }
1083 ret = Peers_insert_peer (peer);
1084 peer_ctx = get_peer_ctx (peer);
1085 if (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE))
1086 {
1087 check_peer_live (peer_ctx);
1088 }
1089 return ret;
1090}
1091
1092
1093/**
1094 * @brief Check if peer is removable.
1095 *
1096 * Check if
1097 * - a recv channel exists
1098 * - there are pending messages
1099 * - there is no pending pull reply
1100 *
1101 * @param peer the peer in question
1102 * @return #GNUNET_YES if peer is removable
1103 * #GNUNET_NO if peer is NOT removable
1104 * #GNUNET_SYSERR if peer is not known
1105 */
1106int
1107Peers_check_removable (const struct GNUNET_PeerIdentity *peer)
1108{
1109 struct PeerContext *peer_ctx;
1110
1111 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1112 {
1113 return GNUNET_SYSERR;
1114 }
1115
1116 peer_ctx = get_peer_ctx (peer);
1117 if ( (NULL != peer_ctx->recv_channel) ||
1118 (NULL != peer_ctx->pending_messages_head) ||
1119 (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
1120 {
1121 return GNUNET_NO;
1122 }
1123 return GNUNET_YES;
1124}
1125
1126
1127/**
1128 * @brief Remove peer
1129 *
1130 * @param peer the peer to clean
1131 * @return #GNUNET_YES if peer was removed
1132 * #GNUNET_NO otherwise
1133 */
1134int
1135Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
1136{
1137 struct PeerContext *peer_ctx;
1138
1139 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1140 {
1141 return GNUNET_NO;
1142 }
1143
1144 peer_ctx = get_peer_ctx (peer);
1145 set_peer_flag (peer_ctx, Peers_TO_DESTROY);
1146 LOG (GNUNET_ERROR_TYPE_DEBUG,
1147 "Going to remove peer %s\n",
1148 GNUNET_i2s (&peer_ctx->peer_id));
1149 Peers_unset_peer_flag (peer, Peers_ONLINE);
1150
1151 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
1152 while (NULL != peer_ctx->pending_messages_head)
1153 {
1154 LOG (GNUNET_ERROR_TYPE_DEBUG,
1155 "Removing unsent %s\n",
1156 peer_ctx->pending_messages_head->type);
1157 remove_pending_message (peer_ctx->pending_messages_head);
1158 }
1159 /* If we are still waiting for notification whether this peer is live
1160 * cancel the according task */
1161 if (NULL != peer_ctx->liveliness_check_pending)
1162 {
1163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1164 "Removing pending liveliness check for peer %s\n",
1165 GNUNET_i2s (&peer_ctx->peer_id));
1166 // TODO wait until cadet sets mq->cancel_impl
1167 //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
1168 GNUNET_free (peer_ctx->liveliness_check_pending);
1169 peer_ctx->liveliness_check_pending = NULL;
1170 }
1171 if (NULL != peer_ctx->send_channel)
1172 {
1173 LOG (GNUNET_ERROR_TYPE_DEBUG,
1174 "Destroying send channel\n");
1175 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1176 peer_ctx->send_channel = NULL;
1177 }
1178 if (NULL != peer_ctx->recv_channel)
1179 {
1180 LOG (GNUNET_ERROR_TYPE_DEBUG,
1181 "Destroying recv channel\n");
1182 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1183 peer_ctx->recv_channel = NULL;
1184 }
1185 if (NULL != peer_ctx->mq)
1186 {
1187 GNUNET_MQ_destroy (peer_ctx->mq);
1188 peer_ctx->mq = NULL;
1189 }
1190
1191 GNUNET_free (peer_ctx->send_channel_flags);
1192 GNUNET_free (peer_ctx->recv_channel_flags);
1193
1194 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
1195 {
1196 LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
1197 }
1198 GNUNET_free (peer_ctx);
1199 return GNUNET_YES;
1200}
1201
1202
1203/**
1204 * @brief set flags on a given peer.
1205 *
1206 * @param peer the peer to set flags on
1207 * @param flags the flags
1208 */
1209void
1210Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1211{
1212 struct PeerContext *peer_ctx;
1213
1214 peer_ctx = get_peer_ctx (peer);
1215 set_peer_flag (peer_ctx, flags);
1216}
1217
1218
1219/**
1220 * @brief unset flags on a given peer.
1221 *
1222 * @param peer the peer to unset flags on
1223 * @param flags the flags
1224 */
1225void
1226Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1227{
1228 struct PeerContext *peer_ctx;
1229
1230 peer_ctx = get_peer_ctx (peer);
1231 unset_peer_flag (peer_ctx, flags);
1232}
1233
1234
1235/**
1236 * @brief Check whether flags on a peer are set.
1237 *
1238 * @param peer the peer to check the flag of
1239 * @param flags the flags to check
1240 *
1241 * @return #GNUNET_SYSERR if peer is not known
1242 * #GNUNET_YES if all given flags are set
1243 * #GNUNET_NO otherwise
1244 */
1245int
1246Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1247{
1248 struct PeerContext *peer_ctx;
1249
1250 if (GNUNET_NO == Peers_check_peer_known (peer))
1251 {
1252 return GNUNET_SYSERR;
1253 }
1254 peer_ctx = get_peer_ctx (peer);
1255 return check_peer_flag_set (peer_ctx, flags);
1256}
1257
1258
1259/**
1260 * @brief set flags on a given channel.
1261 *
1262 * @param channel the channel to set flags on
1263 * @param flags the flags
1264 */
1265void
1266Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1267{
1268 set_channel_flag (channel_flags, flags);
1269}
1270
1271
1272/**
1273 * @brief unset flags on a given channel.
1274 *
1275 * @param channel the channel to unset flags on
1276 * @param flags the flags
1277 */
1278void
1279Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1280{
1281 unset_channel_flag (channel_flags, flags);
1282}
1283
1284
1285/**
1286 * @brief Check whether flags on a channel are set.
1287 *
1288 * @param channel the channel to check the flag of
1289 * @param flags the flags to check
1290 *
1291 * @return #GNUNET_YES if all given flags are set
1292 * #GNUNET_NO otherwise
1293 */
1294int
1295Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1296{
1297 return check_channel_flag_set (channel_flags, flags);
1298}
1299
1300/**
1301 * @brief Get the flags for the channel in @a role for @a peer.
1302 *
1303 * @param peer Peer to get the channel flags for.
1304 * @param role Role of channel to get flags for
1305 *
1306 * @return The flags.
1307 */
1308uint32_t *
1309Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1310 enum Peers_ChannelRole role)
1311{
1312 const struct PeerContext *peer_ctx;
1313
1314 peer_ctx = get_peer_ctx (peer);
1315 if (Peers_CHANNEL_ROLE_SENDING == role)
1316 {
1317 return peer_ctx->send_channel_flags;
1318 }
1319 else if (Peers_CHANNEL_ROLE_RECEIVING == role)
1320 {
1321 return peer_ctx->recv_channel_flags;
1322 }
1323 else
1324 {
1325 GNUNET_assert (0);
1326 }
1327}
1328
1329/**
1330 * @brief Check whether we have information about the given peer.
1331 *
1332 * FIXME probably deprecated. Make this the new _online.
1333 *
1334 * @param peer peer in question
1335 *
1336 * @return #GNUNET_YES if peer is known
1337 * #GNUNET_NO if peer is not knwon
1338 */
1339int
1340Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
1341{
1342 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
1343}
1344
1345
1346/**
1347 * @brief Check whether @a peer is actually a peer.
1348 *
1349 * A valid peer is a peer that we know exists eg. we were connected to once.
1350 *
1351 * @param peer peer in question
1352 *
1353 * @return #GNUNET_YES if peer is valid
1354 * #GNUNET_NO if peer is not valid
1355 */
1356int
1357Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer)
1358{
1359 return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer);
1360}
1361
1362
1363/**
1364 * @brief Indicate that we want to send to the other peer
1365 *
1366 * This establishes a sending channel
1367 *
1368 * @param peer the peer to establish channel to
1369 */
1370void
1371Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
1372{
1373 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1374 (void) get_channel (peer);
1375}
1376
1377
1378/**
1379 * @brief Check whether other peer has the intention to send/opened channel
1380 * towars us
1381 *
1382 * @param peer the peer in question
1383 *
1384 * @return #GNUNET_YES if peer has the intention to send
1385 * #GNUNET_NO otherwise
1386 */
1387int
1388Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
1389{
1390 const struct PeerContext *peer_ctx;
1391
1392 peer_ctx = get_peer_ctx (peer);
1393 if (NULL != peer_ctx->recv_channel)
1394 {
1395 return GNUNET_YES;
1396 }
1397 return GNUNET_NO;
1398}
1399
1400
1401/**
1402 * Handle the channel a peer opens to us.
1403 *
1404 * @param cls The closure
1405 * @param channel The channel the peer wants to establish
1406 * @param initiator The peer's peer ID
1407 *
1408 * @return initial channel context for the channel
1409 * (can be NULL -- that's not an error)
1410 */
1411void *
1412Peers_handle_inbound_channel (void *cls,
1413 struct GNUNET_CADET_Channel *channel,
1414 const struct GNUNET_PeerIdentity *initiator)
1415{
1416 struct PeerContext *peer_ctx;
1417
1418 LOG (GNUNET_ERROR_TYPE_DEBUG,
1419 "New channel was established to us (Peer %s).\n",
1420 GNUNET_i2s (initiator));
1421 GNUNET_assert (NULL != channel); /* according to cadet API */
1422 /* Make sure we 'know' about this peer */
1423 peer_ctx = create_or_get_peer_ctx (initiator);
1424 set_peer_live (peer_ctx);
1425 /* We only accept one incoming channel per peer */
1426 if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
1427 {
1428 set_channel_flag (peer_ctx->recv_channel_flags,
1429 Peers_CHANNEL_ESTABLISHED_TWICE);
1430 GNUNET_CADET_channel_destroy (channel);
1431 /* return the channel context */
1432 return &peer_ctx->peer_id;
1433 }
1434 peer_ctx->recv_channel = channel;
1435 return &peer_ctx->peer_id;
1436}
1437
1438
1439/**
1440 * @brief Check whether a sending channel towards the given peer exists
1441 *
1442 * @param peer the peer to check for
1443 *
1444 * @return #GNUNET_YES if a sending channel towards that peer exists
1445 * #GNUNET_NO otherwise
1446 */
1447int
1448Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
1449{
1450 struct PeerContext *peer_ctx;
1451
1452 if (GNUNET_NO == Peers_check_peer_known (peer))
1453 { /* If no such peer exists, there is no channel */
1454 return GNUNET_NO;
1455 }
1456 peer_ctx = get_peer_ctx (peer);
1457 if (NULL == peer_ctx->send_channel)
1458 {
1459 return GNUNET_NO;
1460 }
1461 return GNUNET_YES;
1462}
1463
1464
1465/**
1466 * @brief check whether the given channel is the sending channel of the given
1467 * peer
1468 *
1469 * @param peer the peer in question
1470 * @param channel the channel to check for
1471 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
1472 * #Peers_CHANNEL_ROLE_RECEIVING
1473 *
1474 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
1475 * #GNUNET_NO otherwise
1476 */
1477int
1478Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
1479 const struct GNUNET_CADET_Channel *channel,
1480 enum Peers_ChannelRole role)
1481{
1482 const struct PeerContext *peer_ctx;
1483
1484 if (GNUNET_NO == Peers_check_peer_known (peer))
1485 {
1486 return GNUNET_NO;
1487 }
1488 peer_ctx = get_peer_ctx (peer);
1489 if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
1490 (channel == peer_ctx->send_channel) )
1491 {
1492 return GNUNET_YES;
1493 }
1494 if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
1495 (channel == peer_ctx->recv_channel) )
1496 {
1497 return GNUNET_YES;
1498 }
1499 return GNUNET_NO;
1500}
1501
1502
1503/**
1504 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
1505 * intention to another peer
1506 *
1507 * If there is also no channel to receive messages from that peer, remove it
1508 * from the peermap.
1509 * TODO really?
1510 *
1511 * @peer the peer identity of the peer whose sending channel to destroy
1512 * @return #GNUNET_YES if channel was destroyed
1513 * #GNUNET_NO otherwise
1514 */
1515int
1516Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
1517{
1518 struct PeerContext *peer_ctx;
1519
1520 if (GNUNET_NO == Peers_check_peer_known (peer))
1521 {
1522 return GNUNET_NO;
1523 }
1524 peer_ctx = get_peer_ctx (peer);
1525 if (NULL != peer_ctx->send_channel)
1526 {
1527 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
1528 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1529 peer_ctx->send_channel = NULL;
1530 (void) Peers_check_connected (peer);
1531 return GNUNET_YES;
1532 }
1533 return GNUNET_NO;
1534}
1535
1536/**
1537 * This is called when a channel is destroyed.
1538 *
1539 * @param cls The closure
1540 * @param channel The channel being closed
1541 * @param channel_ctx The context associated with this channel
1542 */
1543void
1544Peers_cleanup_destroyed_channel (void *cls,
1545 const struct GNUNET_CADET_Channel *channel)
1546{
1547 struct GNUNET_PeerIdentity *peer = cls;
1548 struct PeerContext *peer_ctx;
1549
1550 if (GNUNET_NO == Peers_check_peer_known (peer))
1551 {/* We don't want to implicitly create a context that we're about to kill */
1552 LOG (GNUNET_ERROR_TYPE_DEBUG,
1553 "channel (%s) without associated context was destroyed\n",
1554 GNUNET_i2s (peer));
1555 return;
1556 }
1557 peer_ctx = get_peer_ctx (peer);
1558
1559 /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
1560 * flag will be set. In this case simply make sure that the channels are
1561 * cleaned. */
1562 /* FIXME This distinction seems to be redundant */
1563 if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
1564 {/* We initiatad the destruction of this particular peer */
1565 if (channel == peer_ctx->send_channel)
1566 peer_ctx->send_channel = NULL;
1567 else if (channel == peer_ctx->recv_channel)
1568 peer_ctx->recv_channel = NULL;
1569
1570 if (NULL != peer_ctx->send_channel)
1571 {
1572 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1573 peer_ctx->send_channel = NULL;
1574 }
1575 if (NULL != peer_ctx->recv_channel)
1576 {
1577 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1578 peer_ctx->recv_channel = NULL;
1579 }
1580 /* Set the #Peers_ONLINE flag accordingly */
1581 (void) Peers_check_connected (peer);
1582 return;
1583 }
1584
1585 else
1586 { /* We did not initiate the destruction of this peer */
1587 if (channel == peer_ctx->send_channel)
1588 { /* Something (but us) killd the channel - clean up peer */
1589 LOG (GNUNET_ERROR_TYPE_DEBUG,
1590 "send channel (%s) was destroyed - cleaning up\n",
1591 GNUNET_i2s (peer));
1592 peer_ctx->send_channel = NULL;
1593 }
1594 else if (channel == peer_ctx->recv_channel)
1595 { /* Other peer doesn't want to send us messages anymore */
1596 LOG (GNUNET_ERROR_TYPE_DEBUG,
1597 "Peer %s destroyed recv channel - cleaning up channel\n",
1598 GNUNET_i2s (peer));
1599 peer_ctx->recv_channel = NULL;
1600 }
1601 else
1602 {
1603 LOG (GNUNET_ERROR_TYPE_WARNING,
1604 "unknown channel (%s) was destroyed\n",
1605 GNUNET_i2s (peer));
1606 }
1607 }
1608 (void) Peers_check_connected (peer);
1609}
1610
1611/**
1612 * @brief Send a message to another peer.
1613 *
1614 * Keeps track about pending messages so they can be properly removed when the
1615 * peer is destroyed.
1616 *
1617 * @param peer receeiver of the message
1618 * @param ev envelope of the message
1619 * @param type type of the message
1620 */
1621void
1622Peers_send_message (const struct GNUNET_PeerIdentity *peer,
1623 struct GNUNET_MQ_Envelope *ev,
1624 const char *type)
1625{
1626 struct PendingMessage *pending_msg;
1627 struct GNUNET_MQ_Handle *mq;
1628
1629 pending_msg = insert_pending_message (peer, ev, type);
1630 mq = get_mq (peer);
1631 GNUNET_MQ_notify_sent (ev,
1632 mq_notify_sent_cb,
1633 pending_msg);
1634 GNUNET_MQ_send (mq, ev);
1635}
1636
1637/**
1638 * @brief Schedule a operation on given peer
1639 *
1640 * Avoids scheduling an operation twice.
1641 *
1642 * @param peer the peer we want to schedule the operation for once it gets live
1643 *
1644 * @return #GNUNET_YES if the operation was scheduled
1645 * #GNUNET_NO otherwise
1646 */
1647int
1648Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
1649 const PeerOp peer_op)
1650{
1651 struct PeerPendingOp pending_op;
1652 struct PeerContext *peer_ctx;
1653
1654 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1655 {
1656 return GNUNET_NO;
1657 }
1658 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1659
1660 //TODO if LIVE/ONLINE execute immediately
1661
1662 if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
1663 {
1664 peer_ctx = get_peer_ctx (peer);
1665 pending_op.op = peer_op;
1666 pending_op.op_cls = NULL;
1667 GNUNET_array_append (peer_ctx->pending_ops,
1668 peer_ctx->num_pending_ops,
1669 pending_op);
1670 return GNUNET_YES;
1671 }
1672 return GNUNET_NO;
1673}
1674
1675/**
1676 * @brief Get the recv_channel of @a peer.
1677 * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming
1678 * messages.
1679 *
1680 * @param peer The peer to get the recv_channel from.
1681 *
1682 * @return The recv_channel.
1683 */
1684struct GNUNET_CADET_Channel *
1685Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer)
1686{
1687 struct PeerContext *peer_ctx;
1688
1689 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1690 peer_ctx = get_peer_ctx (peer);
1691 return peer_ctx->recv_channel;
1692}
1693
1694/* end of gnunet-service-rps_peers.c */
diff --git a/src/rps/gnunet-service-rps_peers.h b/src/rps/gnunet-service-rps_peers.h
deleted file mode 100644
index 15970a7ce..000000000
--- a/src/rps/gnunet-service-rps_peers.h
+++ /dev/null
@@ -1,437 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file rps/gnunet-service-rps_peers.h
23 * @brief utilities for managing (information about) peers
24 * @author Julius Bünger
25 */
26#include "gnunet_util_lib.h"
27#include <inttypes.h>
28#include "gnunet_cadet_service.h"
29
30
31/**
32 * Different flags indicating the status of another peer.
33 */
34enum Peers_PeerFlags
35{
36 /**
37 * If we are waiting for a reply from that peer (sent a pull request).
38 */
39 Peers_PULL_REPLY_PENDING = 0x01,
40
41 /* IN_OTHER_GOSSIP_LIST = 0x02, unneeded? */
42 /* IN_OWN_SAMPLER_LIST = 0x04, unneeded? */
43 /* IN_OWN_GOSSIP_LIST = 0x08, unneeded? */
44
45 /**
46 * We set this bit when we know the peer is online.
47 */
48 Peers_ONLINE = 0x20,
49
50 /**
51 * We set this bit when we are going to destroy the channel to this peer.
52 * When cleanup_channel is called, we know that we wanted to destroy it.
53 * Otherwise the channel to the other peer was destroyed.
54 */
55 Peers_TO_DESTROY = 0x40,
56};
57
58/**
59 * Keep track of the status of a channel.
60 *
61 * This is needed in order to know what to do with a channel when it's
62 * destroyed.
63 */
64enum Peers_ChannelFlags
65{
66 /**
67 * We destroyed the channel because the other peer established a second one.
68 */
69 Peers_CHANNEL_ESTABLISHED_TWICE = 0x1,
70
71 /**
72 * The channel was removed because it was not needed any more. This should be
73 * the sending channel.
74 */
75 Peers_CHANNEL_CLEAN = 0x2,
76};
77
78/**
79 * @brief The role of a channel. Sending or receiving.
80 */
81enum Peers_ChannelRole
82{
83 /**
84 * Channel is used for sending
85 */
86 Peers_CHANNEL_ROLE_SENDING = 0x01,
87
88 /**
89 * Channel is used for receiving
90 */
91 Peers_CHANNEL_ROLE_RECEIVING = 0x02,
92};
93
94/**
95 * @brief Functions of this type can be used to be stored at a peer for later execution.
96 *
97 * @param cls closure
98 * @param peer peer to execute function on
99 */
100typedef void (* PeerOp) (void *cls, const struct GNUNET_PeerIdentity *peer);
101
102/**
103 * @brief Iterator over valid peers.
104 *
105 * @param cls closure
106 * @param peer current public peer id
107 * @return #GNUNET_YES if we should continue to
108 * iterate,
109 * #GNUNET_NO if not.
110 */
111typedef int
112(*PeersIterator) (void *cls,
113 const struct GNUNET_PeerIdentity *peer);
114
115/**
116 * @brief Initialise storage of peers
117 *
118 * @param fn_valid_peers filename of the file used to store valid peer ids
119 * @param cadet_h cadet handle
120 * @param disconnect_handler Disconnect handler
121 * @param c_handlers cadet handlers
122 * @param own_id own peer identity
123 */
124void
125Peers_initialise (char* fn_valid_peers,
126 struct GNUNET_CADET_Handle *cadet_h,
127 GNUNET_CADET_DisconnectEventHandler disconnect_handler,
128 const struct GNUNET_MQ_MessageHandler *c_handlers,
129 const struct GNUNET_PeerIdentity *own_id);
130
131/**
132 * @brief Delete storage of peers that was created with #Peers_initialise ()
133 */
134void
135Peers_terminate ();
136
137
138/**
139 * @brief Get all currently known, valid peer ids.
140 *
141 * @param it function to call on each peer id
142 * @param it_cls extra argument to @a it
143 * @return the number of key value pairs processed,
144 * #GNUNET_SYSERR if it aborted iteration
145 */
146int
147Peers_get_valid_peers (PeersIterator iterator,
148 void *it_cls);
149
150/**
151 * @brief Add peer to known peers.
152 *
153 * This function is called on new peer_ids from 'external' sources
154 * (client seed, cadet get_peers(), ...)
155 *
156 * @param peer the new #GNUNET_PeerIdentity
157 *
158 * @return #GNUNET_YES if peer was inserted
159 * #GNUNET_NO otherwise (if peer was already known or
160 * peer was #own_identity)
161 */
162int
163Peers_insert_peer (const struct GNUNET_PeerIdentity *peer);
164
165/**
166 * @brief Try connecting to a peer to see whether it is online
167 *
168 * If not known yet, insert into known peers
169 *
170 * @param peer the peer whose liveliness is to be checked
171 * @return #GNUNET_YES if peer had to be inserted
172 * #GNUNET_NO otherwise (if peer was already known or
173 * peer was #own_identity)
174 */
175int
176Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer);
177
178/**
179 * @brief Check if peer is removable.
180 *
181 * Check if
182 * - a recv channel exists
183 * - there are pending messages
184 * - there is no pending pull reply
185 *
186 * @param peer the peer in question
187 * @return #GNUNET_YES if peer is removable
188 * #GNUNET_NO if peer is NOT removable
189 * #GNUNET_SYSERR if peer is not known
190 */
191int
192Peers_check_removable (const struct GNUNET_PeerIdentity *peer);
193
194/**
195 * @brief Remove peer
196 *
197 * @param peer the peer to clean
198 * @return #GNUNET_YES if peer was removed
199 * #GNUNET_NO otherwise
200 */
201int
202Peers_remove_peer (const struct GNUNET_PeerIdentity *peer);
203
204/**
205 * @brief set flags on a given peer.
206 *
207 * @param peer the peer to set flags on
208 * @param flags the flags
209 */
210void
211Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
212
213/**
214 * @brief unset flags on a given peer.
215 *
216 * @param peer the peer to unset flags on
217 * @param flags the flags
218 */
219void
220Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
221
222/**
223 * @brief Check whether flags on a peer are set.
224 *
225 * @param peer the peer to check the flag of
226 * @param flags the flags to check
227 *
228 * @return #GNUNET_YES if all given flags are set
229 * ##GNUNET_NO otherwise
230 */
231int
232Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
233
234
235/**
236 * @brief set flags on a given channel.
237 *
238 * @param channel the channel to set flags on
239 * @param flags the flags
240 */
241void
242Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
243
244/**
245 * @brief unset flags on a given channel.
246 *
247 * @param channel the channel to unset flags on
248 * @param flags the flags
249 */
250void
251Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
252
253/**
254 * @brief Check whether flags on a channel are set.
255 *
256 * @param channel the channel to check the flag of
257 * @param flags the flags to check
258 *
259 * @return #GNUNET_YES if all given flags are set
260 * #GNUNET_NO otherwise
261 */
262int
263Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
264
265/**
266 * @brief Get the flags for the channel in @a role for @a peer.
267 *
268 * @param peer Peer to get the channel flags for.
269 * @param role Role of channel to get flags for
270 *
271 * @return The flags.
272 */
273uint32_t *
274Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
275 enum Peers_ChannelRole role);
276
277/**
278 * @brief Check whether we have information about the given peer.
279 *
280 * FIXME probably deprecated. Make this the new _online.
281 *
282 * @param peer peer in question
283 *
284 * @return #GNUNET_YES if peer is known
285 * #GNUNET_NO if peer is not knwon
286 */
287int
288Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer);
289
290/**
291 * @brief Check whether @a peer is actually a peer.
292 *
293 * A valid peer is a peer that we know exists eg. we were connected to once.
294 *
295 * @param peer peer in question
296 *
297 * @return #GNUNET_YES if peer is valid
298 * #GNUNET_NO if peer is not valid
299 */
300int
301Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer);
302
303/**
304 * @brief Indicate that we want to send to the other peer
305 *
306 * This establishes a sending channel
307 *
308 * @param peer the peer to establish channel to
309 */
310void
311Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer);
312
313/**
314 * @brief Check whether other peer has the intention to send/opened channel
315 * towars us
316 *
317 * @param peer the peer in question
318 *
319 * @return #GNUNET_YES if peer has the intention to send
320 * #GNUNET_NO otherwise
321 */
322int
323Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer);
324
325/**
326 * Handle the channel a peer opens to us.
327 *
328 * @param cls The closure
329 * @param channel The channel the peer wants to establish
330 * @param initiator The peer's peer ID
331 *
332 * @return initial channel context for the channel
333 * (can be NULL -- that's not an error)
334 */
335void *
336Peers_handle_inbound_channel (void *cls,
337 struct GNUNET_CADET_Channel *channel,
338 const struct GNUNET_PeerIdentity *initiator);
339
340/**
341 * @brief Check whether a sending channel towards the given peer exists
342 *
343 * @param peer the peer to check for
344 *
345 * @return #GNUNET_YES if a sending channel towards that peer exists
346 * #GNUNET_NO otherwise
347 */
348int
349Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer);
350
351/**
352 * @brief check whether the given channel is the sending channel of the given
353 * peer
354 *
355 * @param peer the peer in question
356 * @param channel the channel to check for
357 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
358 * #Peers_CHANNEL_ROLE_RECEIVING
359 *
360 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
361 * #GNUNET_NO otherwise
362 */
363int
364Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
365 const struct GNUNET_CADET_Channel *channel,
366 enum Peers_ChannelRole role);
367
368/**
369 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
370 * intention to another peer
371 *
372 * If there is also no channel to receive messages from that peer, remove it
373 * from the peermap.
374 *
375 * @peer the peer identity of the peer whose sending channel to destroy
376 * @return #GNUNET_YES if channel was destroyed
377 * #GNUNET_NO otherwise
378 */
379int
380Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer);
381
382/**
383 * This is called when a channel is destroyed.
384 *
385 * Removes peer completely from our knowledge if the send_channel was destroyed
386 * Otherwise simply delete the recv_channel
387 *
388 * @param cls The closure
389 * @param channel The channel being closed
390 * @param channel_ctx The context associated with this channel
391 */
392void
393Peers_cleanup_destroyed_channel (void *cls,
394 const struct GNUNET_CADET_Channel *channel);
395
396/**
397 * @brief Send a message to another peer.
398 *
399 * Keeps track about pending messages so they can be properly removed when the
400 * peer is destroyed.
401 *
402 * @param peer receeiver of the message
403 * @param ev envelope of the message
404 * @param type type of the message
405 */
406void
407Peers_send_message (const struct GNUNET_PeerIdentity *peer,
408 struct GNUNET_MQ_Envelope *ev,
409 const char *type);
410
411/**
412 * @brief Schedule a operation on given peer
413 *
414 * Avoids scheduling an operation twice.
415 *
416 * @param peer the peer we want to schedule the operation for once it gets live
417 *
418 * @return #GNUNET_YES if the operation was scheduled
419 * #GNUNET_NO otherwise
420 */
421int
422Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
423 const PeerOp peer_op);
424
425/**
426 * @brief Get the recv_channel of @a peer.
427 * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming
428 * messages.
429 *
430 * @param peer The peer to get the recv_channel from.
431 *
432 * @return The recv_channel.
433 */
434struct GNUNET_CADET_Channel *
435Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer);
436
437/* end of gnunet-service-rps_peers.h */
diff --git a/src/rps/rps.h b/src/rps/rps.h
index 3037e2190..f5cc2e8d1 100644
--- a/src/rps/rps.h
+++ b/src/rps/rps.h
@@ -175,4 +175,100 @@ struct GNUNET_RPS_CS_ActMaliciousMessage
175}; 175};
176#endif /* ENABLE_MALICIOUS */ 176#endif /* ENABLE_MALICIOUS */
177 177
178
179/***********************************************************************
180 * Defines from old gnunet-service-rps_peers.h
181***********************************************************************/
182
183/**
184 * Different flags indicating the status of another peer.
185 */
186enum Peers_PeerFlags
187{
188 /**
189 * If we are waiting for a reply from that peer (sent a pull request).
190 */
191 Peers_PULL_REPLY_PENDING = 0x01,
192
193 /* IN_OTHER_GOSSIP_LIST = 0x02, unneeded? */
194 /* IN_OWN_SAMPLER_LIST = 0x04, unneeded? */
195 /* IN_OWN_GOSSIP_LIST = 0x08, unneeded? */
196
197 /**
198 * We set this bit when we know the peer is online.
199 */
200 Peers_ONLINE = 0x20,
201
202 /**
203 * We set this bit when we are going to destroy the channel to this peer.
204 * When cleanup_channel is called, we know that we wanted to destroy it.
205 * Otherwise the channel to the other peer was destroyed.
206 */
207 Peers_TO_DESTROY = 0x40,
208};
209
210/**
211 * Keep track of the status of a channel.
212 *
213 * This is needed in order to know what to do with a channel when it's
214 * destroyed.
215 */
216enum Peers_ChannelFlags
217{
218 /**
219 * We destroyed the channel because the other peer established a second one.
220 */
221 Peers_CHANNEL_ESTABLISHED_TWICE = 0x1,
222
223 /**
224 * The channel was removed because it was not needed any more. This should be
225 * the sending channel.
226 */
227 Peers_CHANNEL_CLEAN = 0x2,
228
229 /**
230 * We destroyed the channel because the other peer established a second one.
231 */
232 Peers_CHANNEL_DESTROING = 0x4,
233};
234
235
236/**
237 * @brief The role of a channel. Sending or receiving.
238 */
239enum Peers_ChannelRole
240{
241 /**
242 * Channel is used for sending
243 */
244 Peers_CHANNEL_ROLE_SENDING = 0x01,
245
246 /**
247 * Channel is used for receiving
248 */
249 Peers_CHANNEL_ROLE_RECEIVING = 0x02,
250};
251
252/**
253 * @brief Functions of this type can be used to be stored at a peer for later execution.
254 *
255 * @param cls closure
256 * @param peer peer to execute function on
257 */
258typedef void (* PeerOp) (void *cls, const struct GNUNET_PeerIdentity *peer);
259
260/**
261 * @brief Iterator over valid peers.
262 *
263 * @param cls closure
264 * @param peer current public peer id
265 * @return #GNUNET_YES if we should continue to
266 * iterate,
267 * #GNUNET_NO if not.
268 */
269typedef int
270(*PeersIterator) (void *cls,
271 const struct GNUNET_PeerIdentity *peer);
272
273
178GNUNET_NETWORK_STRUCT_END 274GNUNET_NETWORK_STRUCT_END
diff --git a/src/rps/test_rps.c b/src/rps/test_rps.c
index acd3a165d..0114a19fe 100644
--- a/src/rps/test_rps.c
+++ b/src/rps/test_rps.c
@@ -18,7 +18,7 @@
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20/** 20/**
21 * @file rps/test_rps_multipeer.c 21 * @file rps/test_rps.c
22 * @brief Testcase for the random peer sampling service. Starts 22 * @brief Testcase for the random peer sampling service. Starts
23 * a peergroup with a given number of peers, then waits to 23 * a peergroup with a given number of peers, then waits to
24 * receive size pushes/pulls from each peer. Expects to wait 24 * receive size pushes/pulls from each peer. Expects to wait
@@ -344,6 +344,11 @@ struct SingleTestRun
344 * Number of Requests to make. 344 * Number of Requests to make.
345 */ 345 */
346 uint32_t num_requests; 346 uint32_t num_requests;
347
348 /**
349 * Run with churn
350 */
351 int have_churn;
347} cur_test_run; 352} cur_test_run;
348 353
349/** 354/**
@@ -1023,6 +1028,33 @@ req_cancel_cb (struct RPSPeer *rps_peer)
1023} 1028}
1024 1029
1025/*********************************** 1030/***********************************
1031 * CHURN
1032***********************************/
1033
1034static void
1035churn (void *cls);
1036
1037static void
1038churn_test_cb (struct RPSPeer *rps_peer)
1039{
1040 /* Start churn */
1041 if (GNUNET_YES == cur_test_run.have_churn && NULL == churn_task)
1042 {
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1044 "Starting churn task\n");
1045 churn_task = GNUNET_SCHEDULER_add_delayed (
1046 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1047 churn,
1048 NULL);
1049 } else {
1050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1051 "Not starting churn task\n");
1052 }
1053
1054 schedule_missing_requests (rps_peer);
1055}
1056
1057/***********************************
1026 * PROFILER 1058 * PROFILER
1027***********************************/ 1059***********************************/
1028 1060
@@ -1148,6 +1180,9 @@ churn (void *cls)
1148 double portion_go_online; 1180 double portion_go_online;
1149 double portion_go_offline; 1181 double portion_go_offline;
1150 1182
1183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1184 "Churn function executing\n");
1185
1151 /* Compute the probability for an online peer to go offline 1186 /* Compute the probability for an online peer to go offline
1152 * this round */ 1187 * this round */
1153 portion_online = num_peers_online * 1.0 / num_peers; 1188 portion_online = num_peers_online * 1.0 / num_peers;
@@ -1256,12 +1291,17 @@ static void
1256profiler_cb (struct RPSPeer *rps_peer) 1291profiler_cb (struct RPSPeer *rps_peer)
1257{ 1292{
1258 /* Start churn */ 1293 /* Start churn */
1259 if (NULL == churn_task) 1294 if (GNUNET_YES == cur_test_run.have_churn && NULL == churn_task)
1260 { 1295 {
1296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1297 "Starting churn task\n");
1261 churn_task = GNUNET_SCHEDULER_add_delayed ( 1298 churn_task = GNUNET_SCHEDULER_add_delayed (
1262 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), 1299 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1263 churn, 1300 churn,
1264 NULL); 1301 NULL);
1302 } else {
1303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1304 "Not starting churn task\n");
1265 } 1305 }
1266 1306
1267 /* Only request peer ids at one peer. 1307 /* Only request peer ids at one peer.
@@ -1353,6 +1393,24 @@ run (void *cls,
1353 struct OpListEntry *entry; 1393 struct OpListEntry *entry;
1354 uint32_t num_mal_peers; 1394 uint32_t num_mal_peers;
1355 1395
1396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RUN was called\n");
1397
1398 /* Check whether we timed out */
1399 if (n_peers != num_peers ||
1400 NULL == peers ||
1401 0 == links_succeeded)
1402 {
1403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Going down due to args (eg. timeout)\n");
1404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tn_peers: %u\n", n_peers);
1405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tnum_peers: %" PRIu32 "\n", num_peers);
1406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tpeers: %p\n", peers);
1407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tlinks_succeeded: %u\n", links_succeeded);
1408 GNUNET_SCHEDULER_shutdown ();
1409 return;
1410 }
1411
1412
1413 /* Initialize peers */
1356 testbed_peers = peers; 1414 testbed_peers = peers;
1357 num_peers_online = 0; 1415 num_peers_online = 0;
1358 for (i = 0; i < num_peers; i++) 1416 for (i = 0; i < num_peers; i++)
@@ -1412,6 +1470,7 @@ main (int argc, char *argv[])
1412 cur_test_run.pre_test = NULL; 1470 cur_test_run.pre_test = NULL;
1413 cur_test_run.reply_handle = default_reply_handle; 1471 cur_test_run.reply_handle = default_reply_handle;
1414 cur_test_run.eval_cb = default_eval_cb; 1472 cur_test_run.eval_cb = default_eval_cb;
1473 cur_test_run.have_churn = GNUNET_YES;
1415 churn_task = NULL; 1474 churn_task = NULL;
1416 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); 1475 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30);
1417 1476
@@ -1446,6 +1505,7 @@ main (int argc, char *argv[])
1446 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n"); 1505 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n");
1447 cur_test_run.name = "test-rps-single-req"; 1506 cur_test_run.name = "test-rps-single-req";
1448 cur_test_run.main_test = single_req_cb; 1507 cur_test_run.main_test = single_req_cb;
1508 cur_test_run.have_churn = GNUNET_NO;
1449 } 1509 }
1450 1510
1451 else if (strstr (argv[0], "_delayed_reqs") != NULL) 1511 else if (strstr (argv[0], "_delayed_reqs") != NULL)
@@ -1453,6 +1513,7 @@ main (int argc, char *argv[])
1453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n"); 1513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n");
1454 cur_test_run.name = "test-rps-delayed-reqs"; 1514 cur_test_run.name = "test-rps-delayed-reqs";
1455 cur_test_run.main_test = delay_req_cb; 1515 cur_test_run.main_test = delay_req_cb;
1516 cur_test_run.have_churn = GNUNET_NO;
1456 } 1517 }
1457 1518
1458 else if (strstr (argv[0], "_seed_big") != NULL) 1519 else if (strstr (argv[0], "_seed_big") != NULL)
@@ -1462,6 +1523,7 @@ main (int argc, char *argv[])
1462 cur_test_run.name = "test-rps-seed-big"; 1523 cur_test_run.name = "test-rps-seed-big";
1463 cur_test_run.main_test = seed_big_cb; 1524 cur_test_run.main_test = seed_big_cb;
1464 cur_test_run.eval_cb = no_eval; 1525 cur_test_run.eval_cb = no_eval;
1526 cur_test_run.have_churn = GNUNET_NO;
1465 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); 1527 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1466 } 1528 }
1467 1529
@@ -1470,6 +1532,7 @@ main (int argc, char *argv[])
1470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n"); 1532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n");
1471 cur_test_run.name = "test-rps-single-peer-seed"; 1533 cur_test_run.name = "test-rps-single-peer-seed";
1472 cur_test_run.main_test = single_peer_seed_cb; 1534 cur_test_run.main_test = single_peer_seed_cb;
1535 cur_test_run.have_churn = GNUNET_NO;
1473 } 1536 }
1474 1537
1475 else if (strstr (argv[0], "_seed_request") != NULL) 1538 else if (strstr (argv[0], "_seed_request") != NULL)
@@ -1477,6 +1540,7 @@ main (int argc, char *argv[])
1477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n"); 1540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n");
1478 cur_test_run.name = "test-rps-seed-request"; 1541 cur_test_run.name = "test-rps-seed-request";
1479 cur_test_run.main_test = seed_req_cb; 1542 cur_test_run.main_test = seed_req_cb;
1543 cur_test_run.have_churn = GNUNET_NO;
1480 } 1544 }
1481 1545
1482 else if (strstr (argv[0], "_seed") != NULL) 1546 else if (strstr (argv[0], "_seed") != NULL)
@@ -1485,6 +1549,7 @@ main (int argc, char *argv[])
1485 cur_test_run.name = "test-rps-seed"; 1549 cur_test_run.name = "test-rps-seed";
1486 cur_test_run.main_test = seed_cb; 1550 cur_test_run.main_test = seed_cb;
1487 cur_test_run.eval_cb = no_eval; 1551 cur_test_run.eval_cb = no_eval;
1552 cur_test_run.have_churn = GNUNET_NO;
1488 } 1553 }
1489 1554
1490 else if (strstr (argv[0], "_req_cancel") != NULL) 1555 else if (strstr (argv[0], "_req_cancel") != NULL)
@@ -1494,6 +1559,20 @@ main (int argc, char *argv[])
1494 num_peers = 1; 1559 num_peers = 1;
1495 cur_test_run.main_test = req_cancel_cb; 1560 cur_test_run.main_test = req_cancel_cb;
1496 cur_test_run.eval_cb = no_eval; 1561 cur_test_run.eval_cb = no_eval;
1562 cur_test_run.have_churn = GNUNET_NO;
1563 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1564 }
1565
1566 else if (strstr (argv[0], "_churn") != NULL)
1567 {
1568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test churn\n");
1569 cur_test_run.name = "test-rps-churn";
1570 num_peers = 5;
1571 cur_test_run.init_peer = default_init_peer;
1572 cur_test_run.main_test = churn_test_cb;
1573 cur_test_run.reply_handle = default_reply_handle;
1574 cur_test_run.eval_cb = default_eval_cb;
1575 cur_test_run.have_churn = GNUNET_YES;
1497 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); 1576 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1498 } 1577 }
1499 1578
@@ -1510,6 +1589,7 @@ main (int argc, char *argv[])
1510 cur_test_run.eval_cb = profiler_eval; 1589 cur_test_run.eval_cb = profiler_eval;
1511 cur_test_run.request_interval = 2; 1590 cur_test_run.request_interval = 2;
1512 cur_test_run.num_requests = 5; 1591 cur_test_run.num_requests = 5;
1592 cur_test_run.have_churn = GNUNET_YES;
1513 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90); 1593 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90);
1514 1594
1515 /* 'Clean' directory */ 1595 /* 'Clean' directory */
@@ -1542,4 +1622,4 @@ main (int argc, char *argv[])
1542 return ret_value; 1622 return ret_value;
1543} 1623}
1544 1624
1545/* end of test_rps_multipeer.c */ 1625/* end of test_rps.c */
diff --git a/src/rps/test_rps.conf b/src/rps/test_rps.conf
index 7da91ccf0..fce07c945 100644
--- a/src/rps/test_rps.conf
+++ b/src/rps/test_rps.conf
@@ -24,16 +24,16 @@ INITSIZE = 4
24[testbed] 24[testbed]
25HOSTNAME = localhost 25HOSTNAME = localhost
26 26
27OPERATION_TIMEOUT = 60 s 27# OPERATION_TIMEOUT = 60 s
28 28
29MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 1 29# MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 100
30#OVERLAY_TOPOLOGY = CLIQUE 30OVERLAY_TOPOLOGY = CLIQUE
31OVERLAY_TOPOLOGY = SMALL_WORLD 31#OVERLAY_TOPOLOGY = SMALL_WORLD
32#SCALE_FREE_TOPOLOGY_CAP = 32#SCALE_FREE_TOPOLOGY_CAP =
33 33
34OVERLAY_RANDOM_LINKS = 25 34# OVERLAY_RANDOM_LINKS = 25
35 35
36SETUP_TIMEOUT = 2 m 36# SETUP_TIMEOUT = 2 m
37 37
38[nse] 38[nse]
39WORKBITS = 0 39WORKBITS = 0
@@ -46,7 +46,27 @@ USE_LOCALADDR = YES
46RETURN_LOCAL_ADDRESSES = YES 46RETURN_LOCAL_ADDRESSES = YES
47 47
48[transport] 48[transport]
49PLUGINS = unix 49PLUGINS = udp
50
51[ats]
52# Network specific inbound/outbound quotas
53UNSPECIFIED_QUOTA_IN = unlimited
54UNSPECIFIED_QUOTA_OUT = unlimited
55# LOOPBACK
56LOOPBACK_QUOTA_IN = unlimited
57LOOPBACK_QUOTA_OUT = unlimited
58# LAN
59LAN_QUOTA_IN = unlimited
60LAN_QUOTA_OUT = unlimited
61#WAN
62WAN_QUOTA_OUT = unlimited
63WAN_QUOTA_IN = unlimited
64# WLAN
65WLAN_QUOTA_IN = unlimited
66WLAN_QUOTA_OUT = unlimited
67# BLUETOOTH
68BLUETOOTH_QUOTA_IN = unlimited
69BLUETOOTH_QUOTA_OUT = unlimited
50 70
51[dht] 71[dht]
52DISABLE_TRY_CONNECT = YES 72DISABLE_TRY_CONNECT = YES
@@ -69,6 +89,10 @@ NO_IO = YES
69FORCESTART = NO 89FORCESTART = NO
70AUTOSTART = NO 90AUTOSTART = NO
71 91
92[zonemaster]
93FORCESTART = NO
94AUTOSTART = NO
95
72[namecache] 96[namecache]
73FORCESTART = NO 97FORCESTART = NO
74AUTOSTART = NO 98AUTOSTART = NO
diff --git a/src/rps/test_service_rps_peers.c b/src/rps/test_service_rps_peers.c
deleted file mode 100644
index 9cd677fef..000000000
--- a/src/rps/test_service_rps_peers.c
+++ /dev/null
@@ -1,137 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file rps/test_service_rps_peers.c
22 * @brief testcase for gnunet-service-rps_peers.c
23 */
24#include <platform.h>
25#include "gnunet-service-rps_peers.h"
26
27#define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); Peers_terminate (); return 1; }
28#define CHECK(c) { if (! (c)) ABORT(); }
29
30#define FN_VALID_PEERS "DISABLE"
31
32/**
33 * @brief Dummy implementation of #PeerOp (Operation on peer)
34 *
35 * @param cls closure
36 * @param peer peer
37 */
38void peer_op (void *cls, const struct GNUNET_PeerIdentity *peer)
39{
40 GNUNET_assert (NULL != peer);
41}
42
43/**
44 * @brief Function that is called on a peer for later execution
45 *
46 * @param cls closure
47 * @param peer peer to execute function upon
48 */
49void
50peer_op (void *cls, const struct GNUNET_PeerIdentity *peer);
51
52static int
53check ()
54{
55 struct GNUNET_PeerIdentity k1;
56 struct GNUNET_PeerIdentity own_id;
57
58 memset (&k1, 0, sizeof (k1));
59 memset (&own_id, 1, sizeof (own_id));
60
61 /* Do nothing */
62 Peers_initialise (FN_VALID_PEERS, NULL, NULL, NULL, &own_id);
63 Peers_terminate ();
64
65
66 /* Create peer */
67 Peers_initialise (FN_VALID_PEERS, NULL, NULL, NULL, &own_id);
68 CHECK (GNUNET_YES == Peers_insert_peer (&k1));
69 Peers_terminate ();
70
71
72 /* Create peer */
73 Peers_initialise (FN_VALID_PEERS, NULL, NULL, NULL, &own_id);
74 CHECK (GNUNET_YES == Peers_insert_peer (&k1));
75 CHECK (GNUNET_YES == Peers_remove_peer (&k1));
76 Peers_terminate ();
77
78
79 /* Insertion and Removal */
80 Peers_initialise (FN_VALID_PEERS, NULL, NULL, NULL, &own_id);
81 CHECK (GNUNET_NO == Peers_check_peer_known (&k1));
82
83 CHECK (GNUNET_YES == Peers_insert_peer (&k1));
84 CHECK (GNUNET_NO == Peers_insert_peer (&k1));
85 CHECK (GNUNET_YES == Peers_check_peer_known (&k1));
86
87 CHECK (GNUNET_YES == Peers_remove_peer (&k1));
88 CHECK (GNUNET_NO == Peers_remove_peer (&k1));
89 CHECK (GNUNET_NO == Peers_check_peer_known (&k1));
90
91
92 /* Flags */
93 Peers_insert_peer (&k1);
94
95 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_PULL_REPLY_PENDING));
96 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_ONLINE));
97 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
98
99 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_ONLINE));
100
101 Peers_set_peer_flag (&k1, Peers_ONLINE);
102 CHECK (GNUNET_YES == Peers_check_peer_flag (&k1, Peers_ONLINE));
103 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
104 CHECK (GNUNET_YES == Peers_check_peer_flag (&k1, Peers_ONLINE));
105 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
106
107 /* Check send intention */
108 CHECK (GNUNET_NO == Peers_check_peer_send_intention (&k1));
109
110 /* Check existence of sending channel */
111 CHECK (GNUNET_NO == Peers_check_sending_channel_exists (&k1));
112
113 /* Check role of channels */
114 CHECK (GNUNET_YES == Peers_check_channel_role (&k1,
115 NULL,
116 Peers_CHANNEL_ROLE_SENDING));
117 CHECK (GNUNET_YES == Peers_check_channel_role (&k1,
118 NULL,
119 Peers_CHANNEL_ROLE_RECEIVING));
120
121 CHECK (GNUNET_YES == Peers_schedule_operation (&k1, peer_op));
122
123 Peers_terminate ();
124 return 0;
125}
126
127
128int
129main (int argc, char *argv[])
130{
131 GNUNET_log_setup ("test_service_rps_peers",
132 "WARNING",
133 NULL);
134 return check ();
135}
136
137/* end of test_service_rps_peers.c */
diff --git a/src/set/Makefile.am b/src/set/Makefile.am
index 14667d0ef..df17fa1ab 100644
--- a/src/set/Makefile.am
+++ b/src/set/Makefile.am
@@ -52,7 +52,7 @@ gnunet_set_ibf_profiler_LDADD = \
52gnunet_service_set_SOURCES = \ 52gnunet_service_set_SOURCES = \
53 gnunet-service-set.c gnunet-service-set.h \ 53 gnunet-service-set.c gnunet-service-set.h \
54 gnunet-service-set_union.c gnunet-service-set_union.h \ 54 gnunet-service-set_union.c gnunet-service-set_union.h \
55 gnunet-service-set_intersection.c \ 55 gnunet-service-set_intersection.c gnunet-service-set_intersection.h \
56 ibf.c ibf.h \ 56 ibf.c ibf.h \
57 gnunet-service-set_union_strata_estimator.c gnunet-service-set_union_strata_estimator.h \ 57 gnunet-service-set_union_strata_estimator.c gnunet-service-set_union_strata_estimator.h \
58 gnunet-service-set_protocol.h 58 gnunet-service-set_protocol.h
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c
index 730124495..9586dcf27 100644
--- a/src/set/gnunet-service-set_union.c
+++ b/src/set/gnunet-service-set_union.c
@@ -364,7 +364,7 @@ fail_union_operation (struct Operation *op)
364 struct GNUNET_MQ_Envelope *ev; 364 struct GNUNET_MQ_Envelope *ev;
365 struct GNUNET_SET_ResultMessage *msg; 365 struct GNUNET_SET_ResultMessage *msg;
366 366
367 LOG (GNUNET_ERROR_TYPE_ERROR, 367 LOG (GNUNET_ERROR_TYPE_WARNING,
368 "union operation failed\n"); 368 "union operation failed\n");
369 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); 369 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT);
370 msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); 370 msg->result_status = htons (GNUNET_SET_STATUS_FAILURE);
@@ -1404,7 +1404,7 @@ send_client_done (void *cls)
1404 } 1404 }
1405 1405
1406 if (PHASE_DONE != op->state->phase) { 1406 if (PHASE_DONE != op->state->phase) {
1407 LOG (GNUNET_ERROR_TYPE_ERROR, 1407 LOG (GNUNET_ERROR_TYPE_WARNING,
1408 "union operation failed\n"); 1408 "union operation failed\n");
1409 ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); 1409 ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT);
1410 rm->result_status = htons (GNUNET_SET_STATUS_FAILURE); 1410 rm->result_status = htons (GNUNET_SET_STATUS_FAILURE);
diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c
index dee68fdb8..5b2a8ba9b 100644
--- a/src/social/gnunet-service-social.c
+++ b/src/social/gnunet-service-social.c
@@ -96,7 +96,7 @@ static struct GNUNET_CONTAINER_MultiHashMap *apps_places;
96 * Application subscriptions per place. 96 * Application subscriptions per place.
97 * H(place_pub_key) -> H(app_id) 97 * H(place_pub_key) -> H(app_id)
98 */ 98 */
99static struct GNUNET_CONTAINER_MultiHashMap *places_apps; 99//static struct GNUNET_CONTAINER_MultiHashMap *places_apps;
100 100
101/** 101/**
102 * Connected applications. 102 * Connected applications.
@@ -255,10 +255,10 @@ struct Place
255 uint8_t is_ready; 255 uint8_t is_ready;
256 256
257 /** 257 /**
258 * Is the client disconnected? 258 * Is the client disconnecting?
259 * #GNUNET_YES or #GNUNET_NO 259 * #GNUNET_YES or #GNUNET_NO
260 */ 260 */
261 uint8_t is_disconnected; 261 uint8_t is_disconnecting;
262 262
263 /** 263 /**
264 * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)? 264 * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)?
@@ -348,7 +348,7 @@ struct Guest
348 /** 348 /**
349 * Join request to be transmitted to the master on join. 349 * Join request to be transmitted to the master on join.
350 */ 350 */
351 struct GNUNET_MessageHeader *join_req; 351 struct GNUNET_MessageHeader *join_req; // FIXME: not used!
352 352
353 /** 353 /**
354 * Join decision received from PSYC. 354 * Join decision received from PSYC.
@@ -487,8 +487,6 @@ cleanup_host (struct Host *hst)
487{ 487{
488 struct Place *plc = &hst->place; 488 struct Place *plc = &hst->place;
489 489
490 if (NULL != hst->master)
491 GNUNET_PSYC_master_stop (hst->master, GNUNET_NO, NULL, NULL); // FIXME
492 GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs); 490 GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs);
493 GNUNET_CONTAINER_multihashmap_destroy (hst->relay_msgs); 491 GNUNET_CONTAINER_multihashmap_destroy (hst->relay_msgs);
494 GNUNET_CONTAINER_multihashmap_remove (hosts, &plc->pub_key_hash, plc); 492 GNUNET_CONTAINER_multihashmap_remove (hosts, &plc->pub_key_hash, plc);
@@ -505,7 +503,7 @@ cleanup_guest (struct Guest *gst)
505 struct GNUNET_CONTAINER_MultiHashMap * 503 struct GNUNET_CONTAINER_MultiHashMap *
506 plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, 504 plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
507 &plc->pub_key_hash); 505 &plc->pub_key_hash);
508 GNUNET_assert (NULL != plc_gst); // FIXME 506 GNUNET_assert (NULL != plc_gst);
509 GNUNET_CONTAINER_multihashmap_remove (plc_gst, &plc->ego_pub_hash, gst); 507 GNUNET_CONTAINER_multihashmap_remove (plc_gst, &plc->ego_pub_hash, gst);
510 508
511 if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst)) 509 if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst))
@@ -520,8 +518,6 @@ cleanup_guest (struct Guest *gst)
520 GNUNET_free (gst->join_req); 518 GNUNET_free (gst->join_req);
521 if (NULL != gst->relays) 519 if (NULL != gst->relays)
522 GNUNET_free (gst->relays); 520 GNUNET_free (gst->relays);
523 if (NULL != gst->slave)
524 GNUNET_PSYC_slave_part (gst->slave, GNUNET_NO, NULL, NULL); // FIXME
525 GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, plc); 521 GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, plc);
526} 522}
527 523
@@ -537,8 +533,8 @@ cleanup_place (void *cls)
537 struct Place *plc = cls; 533 struct Place *plc = cls;
538 534
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "%p Cleaning up place %s\n", 536 "cleaning up place %s\n",
541 plc, GNUNET_h2s (&plc->pub_key_hash)); 537 GNUNET_h2s (&plc->pub_key_hash));
542 538
543 (GNUNET_YES == plc->is_host) 539 (GNUNET_YES == plc->is_host)
544 ? cleanup_host ((struct Host *) plc) 540 ? cleanup_host ((struct Host *) plc)
@@ -583,12 +579,19 @@ client_notify_disconnect (void *cls,
583 { 579 {
584 if (cli->client == client) 580 if (cli->client == client)
585 { 581 {
586 GNUNET_CONTAINER_DLL_remove (plc->clients_head, plc->clients_tail, cli); 582 GNUNET_CONTAINER_DLL_remove (plc->clients_head,
583 plc->clients_tail,
584 cli);
587 GNUNET_free (cli); 585 GNUNET_free (cli);
588 break; 586 break;
589 } 587 }
590 cli = cli->next; 588 cli = cli->next;
591 } 589 }
590 if (GNUNET_YES == plc->is_disconnecting)
591 {
592 GNUNET_PSYC_slicer_destroy (plc->slicer);
593 GNUNET_free (plc);
594 }
592} 595}
593 596
594 597
@@ -605,46 +608,55 @@ client_notify_connect (void *cls,
605 struct GNUNET_SERVICE_Client *client, 608 struct GNUNET_SERVICE_Client *client,
606 struct GNUNET_MQ_Handle *mq) 609 struct GNUNET_MQ_Handle *mq)
607{ 610{
608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client); 611 struct Client *c = GNUNET_new (struct Client);
609 612
610 struct Client *c = GNUNET_malloc (sizeof (*c)); 613 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
614 "Client %p connected with queue %p\n",
615 client,
616 mq);
611 c->client = client; 617 c->client = client;
612
613 return c; 618 return c;
614} 619}
615 620
616 621
617/** 622/**
618 * Send message to a client. 623 * Send message to all clients connected to a place and
619 */ 624 * takes care of freeing @env.
620static inline void
621client_send_msg (struct GNUNET_SERVICE_Client *client,
622 const struct GNUNET_MessageHeader *msg)
623{
624 struct GNUNET_MQ_Envelope *
625 env = GNUNET_MQ_msg_copy (msg);
626
627 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
628 env);
629}
630
631
632/**
633 * Send message to all clients connected to a place.
634 */ 625 */
635static void 626static void
636place_send_msg (const struct Place *plc, 627place_send_msg (const struct Place *plc,
637 const struct GNUNET_MessageHeader *msg) 628 struct GNUNET_MQ_Envelope *env)
638{ 629{
630 struct ClientListItem *cli = plc->clients_head;
631
639 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
640 "%p Sending message to clients of place.\n", plc); 633 "%p Sending message to clients of place.\n", plc);
641
642 struct ClientListItem *cli = plc->clients_head;
643 while (NULL != cli) 634 while (NULL != cli)
644 { 635 {
645 client_send_msg (cli->client, msg); 636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
637 "Sending message to client %p\n",
638 cli);
639 GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client),
640 env);
646 cli = cli->next; 641 cli = cli->next;
647 } 642 }
643 GNUNET_MQ_discard (env);
644}
645
646
647static void
648place_send_leave_ack (struct Place *plc)
649{
650 struct GNUNET_MQ_Envelope *env;
651
652 for (struct ClientListItem *cli = plc->clients_head;
653 NULL != cli;
654 cli = cli->next)
655 {
656 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK);
657 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cli->client),
658 env);
659 }
648} 660}
649 661
650 662
@@ -666,23 +678,21 @@ static void
666client_send_result (struct GNUNET_SERVICE_Client *client, uint64_t op_id, 678client_send_result (struct GNUNET_SERVICE_Client *client, uint64_t op_id,
667 int64_t result_code, const void *data, uint16_t data_size) 679 int64_t result_code, const void *data, uint16_t data_size)
668{ 680{
681 struct GNUNET_MQ_Envelope *env;
669 struct GNUNET_OperationResultMessage *res; 682 struct GNUNET_OperationResultMessage *res;
670 683
671 res = GNUNET_malloc (sizeof (*res) + data_size); 684 env = GNUNET_MQ_msg_extra (res,
672 res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE); 685 data_size,
673 res->header.size = htons (sizeof (*res) + data_size); 686 GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE);
674 res->result_code = GNUNET_htonll (result_code); 687 res->result_code = GNUNET_htonll (result_code);
675 res->op_id = op_id; 688 res->op_id = op_id;
676 if (0 < data_size) 689 if (0 < data_size)
677 GNUNET_memcpy (&res[1], data, data_size); 690 GNUNET_memcpy (&res[1], data, data_size);
678
679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
680 "%p Sending result to client for operation #%" PRIu64 ": " 692 "%p Sending result to client for operation #%" PRIu64 ": "
681 "%" PRId64 " (size: %u)\n", 693 "%" PRId64 " (size: %u)\n",
682 client, GNUNET_ntohll (op_id), result_code, data_size); 694 client, GNUNET_ntohll (op_id), result_code, data_size);
683 695 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
684 client_send_msg (client, &res->header);
685 GNUNET_free (res);
686} 696}
687 697
688 698
@@ -690,19 +700,21 @@ static void
690client_send_host_enter_ack (struct GNUNET_SERVICE_Client *client, 700client_send_host_enter_ack (struct GNUNET_SERVICE_Client *client,
691 struct Host *hst, uint32_t result) 701 struct Host *hst, uint32_t result)
692{ 702{
703 struct GNUNET_MQ_Envelope *env;
704 struct HostEnterAck *hack;
693 struct Place *plc = &hst->place; 705 struct Place *plc = &hst->place;
694 706
695 struct HostEnterAck hack; 707 env = GNUNET_MQ_msg (hack,
696 hack.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK); 708 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
697 hack.header.size = htons (sizeof (hack)); 709 hack->result_code = htonl (result);
698 hack.result_code = htonl (result); 710 hack->max_message_id = GNUNET_htonll (plc->max_message_id);
699 hack.max_message_id = GNUNET_htonll (plc->max_message_id); 711 hack->place_pub_key = plc->pub_key;
700 hack.place_pub_key = plc->pub_key;
701 712
702 if (NULL != client) 713 if (NULL != client)
703 client_send_msg (client, &hack.header); 714 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
715 env);
704 else 716 else
705 place_send_msg (plc, &hack.header); 717 place_send_msg (plc, env);
706} 718}
707 719
708 720
@@ -736,7 +748,8 @@ psyc_recv_join_request (void *cls,
736 GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash); 748 GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
737 GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh, 749 GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh,
738 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 750 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
739 place_send_msg (&hst->place, &req->header); 751 place_send_msg (&hst->place,
752 GNUNET_MQ_msg_copy (&req->header));
740} 753}
741 754
742 755
@@ -746,18 +759,29 @@ psyc_recv_join_request (void *cls,
746static void 759static void
747psyc_slave_connected (void *cls, int result, uint64_t max_message_id) 760psyc_slave_connected (void *cls, int result, uint64_t max_message_id)
748{ 761{
762 struct GNUNET_PSYC_CountersResultMessage *res;
763 struct GNUNET_MQ_Envelope *env;
749 struct Guest *gst = cls; 764 struct Guest *gst = cls;
750 struct Place *plc = &gst->place; 765 struct Place *plc = &gst->place;
766
751 plc->max_message_id = max_message_id; 767 plc->max_message_id = max_message_id;
752 plc->is_ready = GNUNET_YES; 768 plc->is_ready = GNUNET_YES;
769 env = GNUNET_MQ_msg (res,
770 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
771 res->result_code =
772 (result != GNUNET_SYSERR) ? htonl (GNUNET_OK) : htonl (GNUNET_SYSERR);
773 res->max_message_id = GNUNET_htonll (plc->max_message_id);
774 place_send_msg (plc, env);
775}
753 776
754 struct GNUNET_PSYC_CountersResultMessage res;
755 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
756 res.header.size = htons (sizeof (res));
757 res.result_code = htonl (result);
758 res.max_message_id = GNUNET_htonll (plc->max_message_id);
759 777
760 place_send_msg (plc, &res.header); 778static void
779slave_parted_after_join_decision (void *cls)
780{
781 struct Guest *gst = cls;
782
783 GNUNET_assert (NULL != gst->join_dcsn);
784 place_send_msg (&gst->place, GNUNET_MQ_msg_copy (&gst->join_dcsn->header));
761} 785}
762 786
763 787
@@ -771,7 +795,21 @@ psyc_recv_join_dcsn (void *cls,
771 const struct GNUNET_PSYC_Message *join_msg) 795 const struct GNUNET_PSYC_Message *join_msg)
772{ 796{
773 struct Guest *gst = cls; 797 struct Guest *gst = cls;
774 place_send_msg (&gst->place, &dcsn->header); 798
799 gst->join_dcsn = GNUNET_malloc (dcsn->header.size);
800 GNUNET_memcpy (gst->join_dcsn,
801 dcsn,
802 dcsn->header.size);
803 if (GNUNET_NO == is_admitted)
804 {
805 GNUNET_PSYC_slave_part (gst->slave,
806 GNUNET_NO,
807 &slave_parted_after_join_decision,
808 gst);
809 gst->slave = NULL;
810 return;
811 }
812 place_send_msg (&gst->place, GNUNET_MQ_msg_copy (&gst->join_dcsn->header));
775} 813}
776 814
777 815
@@ -792,7 +830,7 @@ psyc_recv_message (void *cls,
792 830
793 GNUNET_PSYC_slicer_message (plc->slicer, msg); 831 GNUNET_PSYC_slicer_message (plc->slicer, msg);
794 832
795 place_send_msg (plc, &msg->header); 833 place_send_msg (plc, GNUNET_MQ_msg_copy (&msg->header));
796} 834}
797 835
798 836
@@ -1096,9 +1134,6 @@ place_init (struct Place *plc)
1096static int 1134static int
1097place_add (const struct PlaceEnterRequest *ereq) 1135place_add (const struct PlaceEnterRequest *ereq)
1098{ 1136{
1099 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1100 "Adding place to hashmap:\n");
1101
1102 struct EgoPlacePublicKey ego_place_pub_key = { 1137 struct EgoPlacePublicKey ego_place_pub_key = {
1103 .ego_pub_key = ereq->ego_pub_key, 1138 .ego_pub_key = ereq->ego_pub_key,
1104 .place_pub_key = ereq->place_pub_key, 1139 .place_pub_key = ereq->place_pub_key,
@@ -1173,7 +1208,9 @@ app_place_add (const char *app_id,
1173 return GNUNET_NO; 1208 return GNUNET_NO;
1174 1209
1175 if (GNUNET_SYSERR == place_add (ereq)) 1210 if (GNUNET_SYSERR == place_add (ereq))
1211 {
1176 return GNUNET_SYSERR; 1212 return GNUNET_SYSERR;
1213 }
1177 1214
1178 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (app_places, &ego_place_pub_hash, NULL, 1215 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (app_places, &ego_place_pub_hash, NULL,
1179 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 1216 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
@@ -1181,32 +1218,6 @@ app_place_add (const char *app_id,
1181 GNUNET_break (0); 1218 GNUNET_break (0);
1182 return GNUNET_SYSERR; 1219 return GNUNET_SYSERR;
1183 } 1220 }
1184
1185 struct GNUNET_HashCode place_pub_hash;
1186 GNUNET_CRYPTO_hash (&ereq->place_pub_key, sizeof (ereq->place_pub_key), &place_pub_hash);
1187
1188 struct GNUNET_CONTAINER_MultiHashMap *
1189 place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &place_pub_hash);
1190 if (NULL == place_apps)
1191 {
1192 place_apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1193 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (places_apps, &place_pub_hash, place_apps,
1194 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
1195 {
1196 GNUNET_break (0);
1197 }
1198 }
1199
1200 size_t app_id_size = strlen (app_id) + 1;
1201 void *app_id_value = GNUNET_malloc (app_id_size);
1202 GNUNET_memcpy (app_id_value, app_id, app_id_size);
1203
1204 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (place_apps, &app_id_hash, app_id_value,
1205 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1206 {
1207 GNUNET_break (0);
1208 }
1209
1210 return GNUNET_OK; 1221 return GNUNET_OK;
1211} 1222}
1212 1223
@@ -1223,7 +1234,10 @@ static int
1223app_place_save (const char *app_id, 1234app_place_save (const char *app_id,
1224 const struct PlaceEnterRequest *ereq) 1235 const struct PlaceEnterRequest *ereq)
1225{ 1236{
1226 app_place_add (app_id, ereq); 1237 if (GNUNET_SYSERR == app_place_add (app_id, ereq))
1238 {
1239 GNUNET_assert (0);
1240 }
1227 1241
1228 if (NULL == dir_places) 1242 if (NULL == dir_places)
1229 return GNUNET_SYSERR; 1243 return GNUNET_SYSERR;
@@ -1304,18 +1318,6 @@ app_place_remove (const char *app_id,
1304 if (NULL != app_places) 1318 if (NULL != app_places)
1305 GNUNET_CONTAINER_multihashmap_remove (app_places, &place_pub_hash, NULL); 1319 GNUNET_CONTAINER_multihashmap_remove (app_places, &place_pub_hash, NULL);
1306 1320
1307 struct GNUNET_CONTAINER_MultiHashMap *
1308 place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &place_pub_hash);
1309 if (NULL != place_apps)
1310 {
1311 void *app_id_value = GNUNET_CONTAINER_multihashmap_get (place_apps, &app_id_hash);
1312 if (NULL != app_id_value)
1313 {
1314 GNUNET_CONTAINER_multihashmap_remove (place_apps, &app_id_hash, app_id_value);
1315 GNUNET_free (app_id_value);
1316 }
1317 }
1318
1319 int ret = GNUNET_OK; 1321 int ret = GNUNET_OK;
1320 1322
1321 if (0 != unlink (app_place_filename)) 1323 if (0 != unlink (app_place_filename))
@@ -1407,6 +1409,124 @@ msg_proc_parse (const struct MsgProcRequest *mpreq,
1407} 1409}
1408 1410
1409 1411
1412void
1413app_notify_place (const struct GNUNET_MessageHeader *msg,
1414 struct GNUNET_SERVICE_Client *client)
1415{
1416 struct AppPlaceMessage *amsg;
1417 struct GNUNET_MQ_Envelope *env;
1418 uint16_t msg_size = ntohs (msg->size);
1419
1420 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1421 "%p Sending place notification of type %u to client.\n",
1422 client, ntohs (msg->type));
1423 switch (ntohs (msg->type))
1424 {
1425 case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER:
1426 {
1427 struct HostEnterRequest *hreq = (struct HostEnterRequest *) msg;
1428 if (msg_size < sizeof (struct HostEnterRequest))
1429 return;
1430 env = GNUNET_MQ_msg (amsg,
1431 GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE);
1432 // FIXME: also notify about not entered places
1433 amsg->place_state = GNUNET_SOCIAL_PLACE_STATE_ENTERED;
1434 amsg->is_host = GNUNET_YES;
1435 amsg->ego_pub_key = hreq->ego_pub_key;
1436 amsg->place_pub_key = hreq->place_pub_key;
1437 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1438 env);
1439 break;
1440 }
1441 case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
1442 {
1443 if (msg_size < sizeof (struct GuestEnterRequest))
1444 return;
1445 struct GuestEnterRequest *greq = (struct GuestEnterRequest *) msg;
1446 env = GNUNET_MQ_msg (amsg,
1447 GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE);
1448 // FIXME: also notify about not entered places
1449 amsg->place_state = GNUNET_SOCIAL_PLACE_STATE_ENTERED;
1450 amsg->is_host = GNUNET_NO;
1451 amsg->ego_pub_key = greq->ego_pub_key;
1452 amsg->place_pub_key = greq->place_pub_key;
1453 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1454 env);
1455 break;
1456 }
1457 default:
1458 return;
1459 }
1460}
1461
1462
1463void
1464app_notify_place_end (struct GNUNET_SERVICE_Client *client)
1465{
1466 struct GNUNET_MQ_Envelope *env;
1467
1468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1469 "%p Sending end of place list notification to client\n",
1470 client);
1471 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE_END);
1472 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1473 env);
1474}
1475
1476
1477void
1478app_notify_ego (struct Ego *ego, struct GNUNET_SERVICE_Client *client)
1479{
1480 struct AppEgoMessage *emsg;
1481 struct GNUNET_MQ_Envelope *env;
1482 size_t name_size = strlen (ego->name) + 1;
1483
1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485 "%p Sending ego notification to client: %s\n",
1486 client, ego->name);
1487 env = GNUNET_MQ_msg_extra (emsg,
1488 name_size,
1489 GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO);
1490 GNUNET_CRYPTO_ecdsa_key_get_public (&ego->key, &emsg->ego_pub_key);
1491 GNUNET_memcpy (&emsg[1], ego->name, name_size);
1492 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1493 env);
1494}
1495
1496
1497void
1498app_notify_ego_end (struct GNUNET_SERVICE_Client *client)
1499{
1500 struct GNUNET_MQ_Envelope *env;
1501
1502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1503 "%p Sending end of ego list notification to client\n",
1504 client);
1505 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO_END);
1506 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1507 env);
1508}
1509
1510
1511int
1512app_place_entry_notify (void *cls, const struct GNUNET_HashCode *key, void *value)
1513{
1514 struct GNUNET_MessageHeader *
1515 msg = GNUNET_CONTAINER_multihashmap_get (places, key);
1516 if (NULL != msg)
1517 app_notify_place (msg, cls);
1518 return GNUNET_YES;
1519}
1520
1521
1522int
1523ego_entry (void *cls, const struct GNUNET_HashCode *key, void *value)
1524{
1525 app_notify_ego (value, cls);
1526 return GNUNET_YES;
1527}
1528
1529
1410static int 1530static int
1411check_client_msg_proc_set (void *cls, 1531check_client_msg_proc_set (void *cls,
1412 const struct MsgProcRequest *mpreq) 1532 const struct MsgProcRequest *mpreq)
@@ -1518,9 +1638,8 @@ static void
1518handle_client_host_enter (void *cls, 1638handle_client_host_enter (void *cls,
1519 const struct HostEnterRequest *hr) 1639 const struct HostEnterRequest *hr)
1520{ 1640{
1521 struct Client *c = cls; 1641 struct Client *c = cls;
1522 struct GNUNET_SERVICE_Client *client = c->client; 1642 struct GNUNET_SERVICE_Client *client = c->client;
1523
1524 struct HostEnterRequest * 1643 struct HostEnterRequest *
1525 hreq = (struct HostEnterRequest *) GNUNET_copy_message (&hr->header); 1644 hreq = (struct HostEnterRequest *) GNUNET_copy_message (&hr->header);
1526 1645
@@ -1578,7 +1697,7 @@ handle_client_host_enter (void *cls,
1578 if (ret != GNUNET_SYSERR) 1697 if (ret != GNUNET_SYSERR)
1579 { 1698 {
1580 1699
1581 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1582 "%p Client connected as host to place %s.\n", 1701 "%p Client connected as host to place %s.\n",
1583 hst, GNUNET_h2s (&plc->pub_key_hash)); 1702 hst, GNUNET_h2s (&plc->pub_key_hash));
1584 1703
@@ -1586,6 +1705,7 @@ handle_client_host_enter (void *cls,
1586 cli->client = client; 1705 cli->client = client;
1587 GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli); 1706 GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
1588 c->place = plc; 1707 c->place = plc;
1708 app_notify_place (&hreq->header, client);
1589 } 1709 }
1590 1710
1591 GNUNET_CRYPTO_eddsa_key_clear (&hreq->place_key); 1711 GNUNET_CRYPTO_eddsa_key_clear (&hreq->place_key);
@@ -1622,8 +1742,12 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
1622 struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash); 1742 struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
1623 1743
1624 if (NULL == ego) 1744 if (NULL == ego)
1745 {
1625 return GNUNET_SYSERR; 1746 return GNUNET_SYSERR;
1747 }
1626 1748
1749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1750 "entering as guest\n");
1627 struct GNUNET_HashCode place_pub_hash; 1751 struct GNUNET_HashCode place_pub_hash;
1628 GNUNET_CRYPTO_hash (&greq->place_pub_key, sizeof (greq->place_pub_key), 1752 GNUNET_CRYPTO_hash (&greq->place_pub_key, sizeof (greq->place_pub_key),
1629 &place_pub_hash); 1753 &place_pub_hash);
@@ -1635,9 +1759,16 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
1635 if (NULL != plc_gst) 1759 if (NULL != plc_gst)
1636 gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &ego_pub_hash); 1760 gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &ego_pub_hash);
1637 1761
1638 if (NULL == gst || NULL == gst->slave) 1762 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1763 "plc_gst = %p, gst = %p\n",
1764 plc_gst,
1765 gst);
1766 if (NULL == gst)
1639 { 1767 {
1640 gst = GNUNET_new (struct Guest); 1768 gst = GNUNET_new (struct Guest);
1769 }
1770 if (NULL == gst->slave)
1771 {
1641 gst->origin = greq->origin; 1772 gst->origin = greq->origin;
1642 gst->relay_count = ntohl (greq->relay_count); 1773 gst->relay_count = ntohl (greq->relay_count);
1643 1774
@@ -1710,11 +1841,12 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
1710 plc_gst = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); 1841 plc_gst = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1711 (void) GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst, 1842 (void) GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst,
1712 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1843 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1713 } 1844 (void) GNUNET_CONTAINER_multihashmap_put (plc_gst, &plc->ego_pub_hash, gst,
1714 (void) GNUNET_CONTAINER_multihashmap_put (plc_gst, &plc->ego_pub_hash, gst, 1845 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1715 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1846 (void) GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, gst,
1716 (void) GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, gst,
1717 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1847 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1848
1849 }
1718 gst->slave 1850 gst->slave
1719 = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &plc->ego_key, 1851 = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &plc->ego_key,
1720 gst->join_flags, &gst->origin, 1852 gst->join_flags, &gst->origin,
@@ -1724,6 +1856,9 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
1724 &psyc_recv_join_dcsn, 1856 &psyc_recv_join_dcsn,
1725 gst, join_msg); 1857 gst, join_msg);
1726 plc->channel = GNUNET_PSYC_slave_get_channel (gst->slave); 1858 plc->channel = GNUNET_PSYC_slave_get_channel (gst->slave);
1859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1860 "slave entered channel %p\n",
1861 plc->channel);
1727 ret = GNUNET_YES; 1862 ret = GNUNET_YES;
1728 } 1863 }
1729 1864
@@ -1734,78 +1869,96 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
1734 1869
1735 1870
1736static int 1871static int
1737check_client_guest_enter (void *cls, 1872client_guest_enter (struct Client *c,
1738 const struct GuestEnterRequest *greq) 1873 const struct GuestEnterRequest *greq)
1739{
1740 return GNUNET_OK;
1741}
1742
1743
1744/**
1745 * Handle a connecting client entering a place as guest.
1746 */
1747static void
1748handle_client_guest_enter (void *cls,
1749 const struct GuestEnterRequest *greq)
1750{ 1874{
1751 struct Client *c = cls; 1875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1876 "client_guest_enter\n");
1877 struct GNUNET_PSYC_CountersResultMessage *result_msg;
1878 struct GNUNET_MQ_Envelope *env;
1752 struct GNUNET_SERVICE_Client *client = c->client; 1879 struct GNUNET_SERVICE_Client *client = c->client;
1753
1754 uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq); 1880 uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
1755 const char *app_id = NULL; 1881 const char *app_id = NULL;
1756 uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &greq[1], 1882 uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &greq[1],
1757 remaining, 1, &app_id); 1883 remaining, 1, &app_id);
1758 if (0 == offset)
1759 {
1760 GNUNET_break (0);
1761 GNUNET_SERVICE_client_drop (client);
1762 return;
1763 }
1764
1765 struct Guest *gst = NULL; 1884 struct Guest *gst = NULL;
1766 struct Place *plc = NULL; 1885 struct Place *plc = NULL;
1767 1886
1887 if (0 == offset)
1888 {
1889 return GNUNET_SYSERR;
1890 }
1768 switch (guest_enter (greq, &gst)) 1891 switch (guest_enter (greq, &gst))
1769 { 1892 {
1770 case GNUNET_YES: 1893 case GNUNET_YES:
1894 {
1771 plc = c->place = &gst->place; 1895 plc = c->place = &gst->place;
1896 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1897 "guest entered successfully to local place %s\n",
1898 GNUNET_h2s (&plc->pub_key_hash));
1772 plc->guest = gst; 1899 plc->guest = gst;
1773 app_place_save (app_id, (const struct PlaceEnterRequest *) greq); 1900 app_place_save (app_id, (const struct PlaceEnterRequest *) greq);
1901 app_notify_place (&greq->header, client);
1774 break; 1902 break;
1775 1903 }
1776 case GNUNET_NO: 1904 case GNUNET_NO:
1777 { 1905 {
1778 plc = c->place = &gst->place; 1906 plc = c->place = &gst->place;
1907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1908 "guest re-entered successfully to local place %s\n",
1909 GNUNET_h2s (&plc->pub_key_hash));
1779 plc->guest = gst; 1910 plc->guest = gst;
1780 1911 env = GNUNET_MQ_msg (result_msg,
1781 struct GNUNET_PSYC_CountersResultMessage res; 1912 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
1782 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK); 1913 result_msg->result_code = htonl (GNUNET_OK);
1783 res.header.size = htons (sizeof (res)); 1914 result_msg->max_message_id = GNUNET_htonll (plc->max_message_id);
1784 res.result_code = htonl (GNUNET_OK); 1915 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1785 res.max_message_id = GNUNET_htonll (plc->max_message_id); 1916 env);
1786
1787 client_send_msg (client, &res.header);
1788 if (NULL != gst->join_dcsn) 1917 if (NULL != gst->join_dcsn)
1789 client_send_msg (client, &gst->join_dcsn->header); 1918 {
1790 1919 env = GNUNET_MQ_msg_copy (&gst->join_dcsn->header);
1920 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1921 env);
1922 }
1791 break; 1923 break;
1792 } 1924 }
1793 case GNUNET_SYSERR: 1925 case GNUNET_SYSERR:
1794 GNUNET_break (0); 1926 {
1795 GNUNET_SERVICE_client_drop (client); 1927 return GNUNET_SYSERR;
1796 return; 1928 }
1797 } 1929 }
1798
1799 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1800 "%p Client connected as guest to place %s.\n",
1801 gst, GNUNET_h2s (&plc->pub_key_hash));
1802 1930
1803 struct ClientListItem *cli = GNUNET_new (struct ClientListItem); 1931 struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
1804 cli->client = client; 1932 cli->client = client;
1805 GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli); 1933 GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
1934 return GNUNET_OK;
1935}
1806 1936
1807 c->place = plc; 1937
1808 GNUNET_SERVICE_client_continue (client); 1938static int
1939check_client_guest_enter (void *cls,
1940 const struct GuestEnterRequest *greq)
1941{
1942 return GNUNET_OK;
1943}
1944
1945
1946/**
1947 * Handle a connecting client entering a place as guest.
1948 */
1949static void
1950handle_client_guest_enter (void *cls,
1951 const struct GuestEnterRequest *greq)
1952{
1953 struct Client *c = cls;
1954
1955 if (GNUNET_SYSERR == client_guest_enter (c, greq))
1956 {
1957 GNUNET_break (0);
1958 GNUNET_SERVICE_client_drop (c->client);
1959 return;
1960 }
1961 GNUNET_SERVICE_client_continue (c->client);
1809} 1962}
1810 1963
1811 1964
@@ -1830,7 +1983,7 @@ gns_result_guest_enter (void *cls, uint32_t rd_count,
1830{ 1983{
1831 struct GuestEnterByNameClosure *gcls = cls; 1984 struct GuestEnterByNameClosure *gcls = cls;
1832 struct Client *c = gcls->client; 1985 struct Client *c = gcls->client;
1833 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1834 "%p GNS result: %u records.\n", 1987 "%p GNS result: %u records.\n",
1835 c, rd_count); 1988 c, rd_count);
1836 1989
@@ -1882,7 +2035,7 @@ gns_result_guest_enter (void *cls, uint32_t rd_count,
1882 p += relay_size; 2035 p += relay_size;
1883 GNUNET_memcpy (p, gcls->join_msg, join_msg_size); 2036 GNUNET_memcpy (p, gcls->join_msg, join_msg_size);
1884 2037
1885 handle_client_guest_enter (c, greq); 2038 client_guest_enter (c, greq);
1886 2039
1887 GNUNET_free (gcls->app_id); 2040 GNUNET_free (gcls->app_id);
1888 if (NULL != gcls->password) 2041 if (NULL != gcls->password)
@@ -1960,118 +2113,7 @@ handle_client_guest_enter_by_name (void *cls,
1960 GNUNET_GNSRECORD_TYPE_PLACE, 2113 GNUNET_GNSRECORD_TYPE_PLACE,
1961 GNUNET_GNS_LO_DEFAULT, 2114 GNUNET_GNS_LO_DEFAULT,
1962 &gns_result_guest_enter, gcls); 2115 &gns_result_guest_enter, gcls);
1963} 2116 GNUNET_SERVICE_client_continue (client);
1964
1965
1966void
1967app_notify_place (struct GNUNET_MessageHeader *msg,
1968 struct GNUNET_SERVICE_Client *client)
1969{
1970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1971 "%p Sending place notification of type %u to client.\n",
1972 client, ntohs (msg->type));
1973
1974 uint16_t msg_size = ntohs (msg->size);
1975 struct AppPlaceMessage amsg;
1976 amsg.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE);
1977 amsg.header.size = htons (sizeof (amsg));
1978 // FIXME: also notify about not entered places
1979 amsg.place_state = GNUNET_SOCIAL_PLACE_STATE_ENTERED;
1980
1981 switch (ntohs (msg->type))
1982 {
1983 case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER:
1984 if (msg_size < sizeof (struct HostEnterRequest))
1985 return;
1986 struct HostEnterRequest *hreq = (struct HostEnterRequest *) msg;
1987 amsg.is_host = GNUNET_YES;
1988 amsg.ego_pub_key = hreq->ego_pub_key;
1989 amsg.place_pub_key = hreq->place_pub_key;
1990 break;
1991
1992 case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
1993 if (msg_size < sizeof (struct GuestEnterRequest))
1994 return;
1995 struct GuestEnterRequest *greq = (struct GuestEnterRequest *) msg;
1996 amsg.is_host = GNUNET_NO;
1997 amsg.ego_pub_key = greq->ego_pub_key;
1998 amsg.place_pub_key = greq->place_pub_key;
1999 break;
2000
2001 default:
2002 return;
2003 }
2004
2005 client_send_msg (client, &amsg.header);
2006}
2007
2008
2009void
2010app_notify_place_end (struct GNUNET_SERVICE_Client *client)
2011{
2012 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2013 "%p Sending end of place list notification to client\n",
2014 client);
2015
2016 struct GNUNET_MessageHeader msg;
2017 msg.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE_END);
2018 msg.size = htons (sizeof (msg));
2019
2020 client_send_msg (client, &msg);
2021}
2022
2023
2024void
2025app_notify_ego (struct Ego *ego, struct GNUNET_SERVICE_Client *client)
2026{
2027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2028 "%p Sending ego notification to client: %s\n",
2029 client, ego->name);
2030
2031 size_t name_size = strlen (ego->name) + 1;
2032 struct AppEgoMessage *emsg = GNUNET_malloc (sizeof (*emsg) + name_size);
2033 emsg->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO);
2034 emsg->header.size = htons (sizeof (*emsg) + name_size);
2035
2036 GNUNET_CRYPTO_ecdsa_key_get_public (&ego->key, &emsg->ego_pub_key);
2037 GNUNET_memcpy (&emsg[1], ego->name, name_size);
2038
2039 client_send_msg (client, &emsg->header);
2040 GNUNET_free (emsg);
2041}
2042
2043
2044void
2045app_notify_ego_end (struct GNUNET_SERVICE_Client *client)
2046{
2047 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2048 "%p Sending end of ego list notification to client\n",
2049 client);
2050
2051 struct GNUNET_MessageHeader msg;
2052 msg.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO_END);
2053 msg.size = htons (sizeof (msg));
2054
2055 client_send_msg (client, &msg);
2056}
2057
2058
2059int
2060app_place_entry_notify (void *cls, const struct GNUNET_HashCode *key, void *value)
2061{
2062 struct GNUNET_MessageHeader *
2063 msg = GNUNET_CONTAINER_multihashmap_get (places, key);
2064 if (NULL != msg)
2065 app_notify_place (msg, cls);
2066 return GNUNET_YES;
2067}
2068
2069
2070int
2071ego_entry (void *cls, const struct GNUNET_HashCode *key, void *value)
2072{
2073 app_notify_ego (value, cls);
2074 return GNUNET_YES;
2075} 2117}
2076 2118
2077 2119
@@ -2154,13 +2196,15 @@ handle_client_app_detach (void *cls,
2154} 2196}
2155 2197
2156 2198
2157int 2199static void
2158app_places_entry_remove (void *cls, const struct GNUNET_HashCode *key, void *value) 2200place_leave_cb (void *cls)
2159{ 2201{
2160 struct Place *plc = cls; 2202 struct Place *plc = cls;
2161 const char *app_id = value; 2203
2162 app_place_remove (app_id, &plc->ego_pub_key, &plc->pub_key); 2204 place_send_leave_ack (plc);
2163 return GNUNET_YES; 2205 (GNUNET_YES == plc->is_host)
2206 ? cleanup_host ((struct Host *) plc)
2207 : cleanup_guest ((struct Guest *) plc);
2164} 2208}
2165 2209
2166 2210
@@ -2174,6 +2218,11 @@ handle_client_place_leave (void *cls,
2174 struct Client *c = cls; 2218 struct Client *c = cls;
2175 struct GNUNET_SERVICE_Client *client = c->client; 2219 struct GNUNET_SERVICE_Client *client = c->client;
2176 struct Place *plc = c->place; 2220 struct Place *plc = c->place;
2221
2222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2223 "got leave request from %s for place %s",
2224 plc->is_host? "host" : "slave",
2225 GNUNET_h2s (&plc->pub_key_hash));
2177 if (NULL == plc) 2226 if (NULL == plc)
2178 { 2227 {
2179 GNUNET_break (0); 2228 GNUNET_break (0);
@@ -2181,40 +2230,28 @@ handle_client_place_leave (void *cls,
2181 return; 2230 return;
2182 } 2231 }
2183 2232
2184 /* FIXME: remove all app subscriptions and leave this place */ 2233 if (GNUNET_YES != plc->is_disconnecting)
2185
2186 struct GNUNET_CONTAINER_MultiHashMap *
2187 place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &plc->pub_key_hash);
2188 if (NULL != place_apps)
2189 { 2234 {
2190 GNUNET_CONTAINER_multihashmap_iterate (place_apps, app_places_entry_remove, plc); 2235 plc->is_disconnecting = GNUNET_YES;
2191 } 2236 if (plc->is_host)
2192 2237 {
2193 /* FIXME: disconnect from the network, but keep local connection for history access */ 2238 struct Host *host = plc->host;
2194 2239 GNUNET_assert (NULL != host);
2195 /* Disconnect all clients connected to the place */ 2240 GNUNET_PSYC_master_stop (host->master, GNUNET_NO, &place_leave_cb, plc);
2196 struct ClientListItem *cli = plc->clients_head, *next;
2197 while (NULL != cli)
2198 {
2199 GNUNET_CONTAINER_DLL_remove (plc->clients_head, plc->clients_tail, cli);
2200 GNUNET_SERVICE_client_drop (cli->client);
2201 next = cli->next;
2202 GNUNET_free (cli);
2203 cli = next;
2204 }
2205
2206 if (GNUNET_YES != plc->is_disconnected)
2207 {
2208 plc->is_disconnected = GNUNET_YES;
2209 if (NULL != plc->tmit_msgs_head)
2210 { /* Send pending messages to PSYC before cleanup. */
2211 psyc_transmit_message (plc);
2212 } 2241 }
2213 else 2242 else
2214 { 2243 {
2215 cleanup_place (plc); 2244 struct Guest *guest = plc->guest;
2245 GNUNET_assert (NULL != guest);
2246 GNUNET_PSYC_slave_part (guest->slave, GNUNET_NO, &place_leave_cb, plc);
2216 } 2247 }
2217 } 2248 }
2249 else
2250 {
2251 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2252 "got leave request but place is already leaving\n");
2253 }
2254 GNUNET_SERVICE_client_continue (client);
2218} 2255}
2219 2256
2220 2257
@@ -2273,6 +2310,9 @@ handle_client_join_decision (void *cls,
2273 ? (struct GNUNET_PSYC_Message *) &dcsn[1] 2310 ? (struct GNUNET_PSYC_Message *) &dcsn[1]
2274 : NULL; 2311 : NULL;
2275 2312
2313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2314 "jcls.msg = %p\n",
2315 jcls.msg);
2276 struct GNUNET_HashCode slave_pub_hash; 2316 struct GNUNET_HashCode slave_pub_hash;
2277 GNUNET_CRYPTO_hash (&dcsn->slave_pub_key, sizeof (dcsn->slave_pub_key), 2317 GNUNET_CRYPTO_hash (&dcsn->slave_pub_key, sizeof (dcsn->slave_pub_key),
2278 &slave_pub_hash); 2318 &slave_pub_hash);
@@ -2302,10 +2342,11 @@ handle_client_join_decision (void *cls,
2302static void 2342static void
2303send_message_ack (struct Place *plc, struct GNUNET_SERVICE_Client *client) 2343send_message_ack (struct Place *plc, struct GNUNET_SERVICE_Client *client)
2304{ 2344{
2305 struct GNUNET_MessageHeader res; 2345 struct GNUNET_MQ_Envelope *env;
2306 res.size = htons (sizeof (res)); 2346
2307 res.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK); 2347 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK);
2308 client_send_msg (client, &res); 2348 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
2349 env);
2309} 2350}
2310 2351
2311 2352
@@ -2437,7 +2478,6 @@ psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
2437 { 2478 {
2438 *data_size = 0; 2479 *data_size = 0;
2439 tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg); 2480 tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
2440 plc->is_disconnected = GNUNET_YES;
2441 GNUNET_SERVICE_client_drop (tmit_frag->client); 2481 GNUNET_SERVICE_client_drop (tmit_frag->client);
2442 GNUNET_SCHEDULER_add_now (&cleanup_place, plc); 2482 GNUNET_SCHEDULER_add_now (&cleanup_place, plc);
2443 return ret; 2483 return ret;
@@ -2479,11 +2519,7 @@ psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
2479 { 2519 {
2480 psyc_transmit_message (plc); 2520 psyc_transmit_message (plc);
2481 } 2521 }
2482 else if (GNUNET_YES == plc->is_disconnected) 2522 /* FIXME: handle partial message (when still in_transmit) */
2483 {
2484 /* FIXME: handle partial message (when still in_transmit) */
2485 cleanup_place (plc);
2486 }
2487 } 2523 }
2488 return ret; 2524 return ret;
2489} 2525}
@@ -2597,7 +2633,6 @@ psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
2597 *data_size = 0; 2633 *data_size = 0;
2598 ret = GNUNET_SYSERR; 2634 ret = GNUNET_SYSERR;
2599 tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg); 2635 tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
2600 plc->is_disconnected = GNUNET_YES;
2601 GNUNET_SERVICE_client_drop (tmit_frag->client); 2636 GNUNET_SERVICE_client_drop (tmit_frag->client);
2602 GNUNET_SCHEDULER_add_now (&cleanup_place, plc); 2637 GNUNET_SCHEDULER_add_now (&cleanup_place, plc);
2603 } 2638 }
@@ -2862,26 +2897,26 @@ psyc_transmit_queue_message (struct Place *plc,
2862} 2897}
2863 2898
2864 2899
2865/** 2900///**
2866 * Cancel transmission of current message to PSYC. 2901// * Cancel transmission of current message to PSYC.
2867 * 2902// *
2868 * @param plc Place to send to. 2903// * @param plc Place to send to.
2869 * @param client Client the message originates from. 2904// * @param client Client the message originates from.
2870 */ 2905// */
2871static void 2906//static void
2872psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVICE_Client *client) 2907//psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVICE_Client *client)
2873{ 2908//{
2874 uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL; 2909// uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL;
2875 2910//
2876 struct GNUNET_MessageHeader msg; 2911// struct GNUNET_MessageHeader msg;
2877 msg.size = htons (sizeof (msg)); 2912// msg.size = htons (sizeof (msg));
2878 msg.type = htons (type); 2913// msg.type = htons (type);
2879 2914//
2880 psyc_transmit_queue_message (plc, client, sizeof (msg), &msg, type, type, NULL); 2915// psyc_transmit_queue_message (plc, client, sizeof (msg), &msg, type, type, NULL);
2881 psyc_transmit_message (plc); 2916// psyc_transmit_message (plc);
2882 2917//
2883 /* FIXME: cleanup */ 2918// /* FIXME: cleanup */
2884} 2919//}
2885 2920
2886 2921
2887static int 2922static int
@@ -2902,17 +2937,19 @@ handle_client_psyc_message (void *cls,
2902 struct Client *c = cls; 2937 struct Client *c = cls;
2903 struct GNUNET_SERVICE_Client *client = c->client; 2938 struct GNUNET_SERVICE_Client *client = c->client;
2904 struct Place *plc = c->place; 2939 struct Place *plc = c->place;
2940 int ret;
2941
2905 if (NULL == plc) 2942 if (NULL == plc)
2906 { 2943 {
2944 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2945 "received PSYC message for non-existing client %p\n",
2946 client);
2907 GNUNET_break (0); 2947 GNUNET_break (0);
2908 GNUNET_SERVICE_client_drop (client); 2948 GNUNET_SERVICE_client_drop (client);
2909 return; 2949 return;
2910 } 2950 }
2911
2912 int ret = GNUNET_SYSERR;
2913
2914 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2915 "%p Received message from client.\n", plc); 2952 "%p Received message of type %d from client.\n", plc, ntohs (msg->type));
2916 GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg); 2953 GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg);
2917 2954
2918 if (GNUNET_YES != plc->is_ready) 2955 if (GNUNET_YES != plc->is_ready)
@@ -2933,20 +2970,19 @@ handle_client_psyc_message (void *cls,
2933 "%p Received message with invalid payload size (%u) from client.\n", 2970 "%p Received message with invalid payload size (%u) from client.\n",
2934 plc, psize); 2971 plc, psize);
2935 GNUNET_break (0); 2972 GNUNET_break (0);
2936 psyc_transmit_cancel (plc, client);
2937 GNUNET_SERVICE_client_drop (client); 2973 GNUNET_SERVICE_client_drop (client);
2938 return; 2974 return;
2939 } 2975 }
2940 2976
2941 uint16_t first_ptype = 0, last_ptype = 0; 2977 uint16_t first_ptype = 0;
2942 if (GNUNET_SYSERR 2978 uint16_t last_ptype = 0;
2943 == GNUNET_PSYC_receive_check_parts (psize, (const char *) &msg[1], 2979 if (GNUNET_SYSERR ==
2944 &first_ptype, &last_ptype)) 2980 GNUNET_PSYC_receive_check_parts (psize, (const char *) &msg[1],
2981 &first_ptype, &last_ptype))
2945 { 2982 {
2946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2983 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2947 "%p Received invalid message part from client.\n", plc); 2984 "%p Received invalid message part from client.\n", plc);
2948 GNUNET_break (0); 2985 GNUNET_break (0);
2949 psyc_transmit_cancel (plc, client);
2950 GNUNET_SERVICE_client_drop (client); 2986 GNUNET_SERVICE_client_drop (client);
2951 return; 2987 return;
2952 } 2988 }
@@ -2963,20 +2999,19 @@ handle_client_psyc_message (void *cls,
2963 c->tmit_msg = NULL; 2999 c->tmit_msg = NULL;
2964 ret = psyc_transmit_message (plc); 3000 ret = psyc_transmit_message (plc);
2965 } 3001 }
2966 3002 else
3003 {
3004 ret = GNUNET_SYSERR;
3005 }
2967 if (GNUNET_OK != ret) 3006 if (GNUNET_OK != ret)
2968 { 3007 {
2969 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3008 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2970 "%p Received invalid message part from client.\n", plc); 3009 "%p Received invalid message part from client.\n", plc);
2971 GNUNET_break (0); 3010 GNUNET_break (0);
2972 psyc_transmit_cancel (plc, client);
2973 ret = GNUNET_SYSERR;
2974 }
2975
2976 if (GNUNET_OK == ret)
2977 GNUNET_SERVICE_client_continue (client);
2978 else
2979 GNUNET_SERVICE_client_drop (client); 3011 GNUNET_SERVICE_client_drop (client);
3012 return;
3013 }
3014 GNUNET_SERVICE_client_continue (client);
2980} 3015}
2981 3016
2982 3017
@@ -3006,7 +3041,7 @@ psyc_recv_history_message (void *cls, const struct GNUNET_PSYC_MessageHeader *ms
3006 GNUNET_memcpy (&res[1], msg, size); 3041 GNUNET_memcpy (&res[1], msg, size);
3007 3042
3008 /** @todo FIXME: send only to requesting client */ 3043 /** @todo FIXME: send only to requesting client */
3009 place_send_msg (plc, &res->header); 3044 place_send_msg (plc, GNUNET_MQ_msg_copy (&res->header));
3010 3045
3011 GNUNET_free (res); 3046 GNUNET_free (res);
3012} 3047}
@@ -3108,29 +3143,24 @@ psyc_recv_state_var (void *cls,
3108 uint32_t value_size, 3143 uint32_t value_size,
3109 uint32_t full_value_size) 3144 uint32_t full_value_size)
3110{ 3145{
3146 struct GNUNET_OperationResultMessage *result_msg;
3147 struct GNUNET_MQ_Envelope *env;
3111 struct OperationClosure *opcls = cls; 3148 struct OperationClosure *opcls = cls;
3112 struct Client *c = opcls->client; 3149 struct Client *c = opcls->client;
3113 struct Place *plc = c->place; 3150 struct Place *plc = c->place;
3151 uint16_t size = ntohs (mod->size);
3114 3152
3115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3116 "%p Received state variable %s from PSYC\n", 3154 "%p Received state variable %s from PSYC\n",
3117 plc, name); 3155 plc, name);
3118 3156 env = GNUNET_MQ_msg_extra (result_msg,
3119 uint16_t size = ntohs (mod->size); 3157 size,
3120 3158 GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT);
3121 struct GNUNET_OperationResultMessage * 3159 result_msg->op_id = opcls->op_id;
3122 res = GNUNET_malloc (sizeof (*res) + size); 3160 result_msg->result_code = GNUNET_htonll (GNUNET_OK);
3123 res->header.size = htons (sizeof (*res) + size); 3161 GNUNET_memcpy (&result_msg[1], mod, size);
3124 res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT);
3125 res->op_id = opcls->op_id;
3126 res->result_code = GNUNET_htonll (GNUNET_OK);
3127
3128 GNUNET_memcpy (&res[1], mod, size);
3129
3130 /** @todo FIXME: send only to requesting client */ 3162 /** @todo FIXME: send only to requesting client */
3131 place_send_msg (plc, &res->header); 3163 place_send_msg (plc, env);
3132
3133 GNUNET_free (res);
3134} 3164}
3135 3165
3136 3166
@@ -3184,7 +3214,7 @@ handle_client_state_get (void *cls,
3184 uint16_t size = ntohs (req->header.size); 3214 uint16_t size = ntohs (req->header.size);
3185 const char *name = (const char *) &req[1]; 3215 const char *name = (const char *) &req[1];
3186 3216
3187 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3188 "%p State get #%" PRIu64 ": %s\n", 3218 "%p State get #%" PRIu64 ": %s\n",
3189 plc, GNUNET_ntohll (req->op_id), name); 3219 plc, GNUNET_ntohll (req->op_id), name);
3190 3220
@@ -3382,7 +3412,7 @@ path_basename (const char *path)
3382 if (NULL != basename) 3412 if (NULL != basename)
3383 basename++; 3413 basename++;
3384 3414
3385 if (NULL == basename || '\0' == basename) 3415 if (NULL == basename || '\0' == *basename)
3386 return NULL; 3416 return NULL;
3387 3417
3388 return basename; 3418 return basename;
@@ -3468,7 +3498,10 @@ file_place_load (void *cls, const char *place_filename)
3468 return GNUNET_OK; 3498 return GNUNET_OK;
3469 } 3499 }
3470 3500
3471 app_place_add (plcls->app_id, ereq); 3501 if (GNUNET_SYSERR == app_place_add (plcls->app_id, ereq))
3502 {
3503 GNUNET_assert (0);
3504 }
3472 GNUNET_free (ereq); 3505 GNUNET_free (ereq);
3473 return GNUNET_OK; 3506 return GNUNET_OK;
3474} 3507}
@@ -3523,6 +3556,10 @@ identity_recv_ego (void *cls, struct GNUNET_IDENTITY_Ego *id_ego,
3523 if (NULL == id_ego) // end of initial list of egos 3556 if (NULL == id_ego) // end of initial list of egos
3524 return; 3557 return;
3525 3558
3559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3560 "social service received ego %s\n",
3561 name);
3562
3526 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key; 3563 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
3527 GNUNET_IDENTITY_ego_get_public_key (id_ego, &ego_pub_key); 3564 GNUNET_IDENTITY_ego_get_public_key (id_ego, &ego_pub_key);
3528 3565
@@ -3571,6 +3608,9 @@ run (void *cls,
3571 const struct GNUNET_CONFIGURATION_Handle *c, 3608 const struct GNUNET_CONFIGURATION_Handle *c,
3572 struct GNUNET_SERVICE_Handle *svc) 3609 struct GNUNET_SERVICE_Handle *svc)
3573{ 3610{
3611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3612 "starting social service\n");
3613
3574 cfg = c; 3614 cfg = c;
3575 service = svc; 3615 service = svc;
3576 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer); 3616 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
@@ -3583,7 +3623,7 @@ run (void *cls,
3583 apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); 3623 apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
3584 places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); 3624 places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
3585 apps_places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); 3625 apps_places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
3586 places_apps = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); 3626 //places_apps = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
3587 3627
3588 id = GNUNET_IDENTITY_connect (cfg, &identity_recv_ego, NULL); 3628 id = GNUNET_IDENTITY_connect (cfg, &identity_recv_ego, NULL);
3589 gns = GNUNET_GNS_connect (cfg); 3629 gns = GNUNET_GNS_connect (cfg);
diff --git a/src/social/gnunet-social.c b/src/social/gnunet-social.c
index de680b11c..12c5bf2e1 100644
--- a/src/social/gnunet-social.c
+++ b/src/social/gnunet-social.c
@@ -283,7 +283,7 @@ exit_fail ()
283static void 283static void
284host_left (void *cls) 284host_left (void *cls)
285{ 285{
286 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 286 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
287 "The host has left the place.\n"); 287 "The host has left the place.\n");
288 exit_success (); 288 exit_success ();
289} 289}
@@ -309,7 +309,7 @@ host_leave ()
309static void 309static void
310guest_left (void *cls) 310guest_left (void *cls)
311{ 311{
312 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 312 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
313 "Guest has left the place.\n"); 313 "Guest has left the place.\n");
314} 314}
315 315
@@ -518,7 +518,7 @@ look_var (void *cls,
518 uint32_t value_size, 518 uint32_t value_size,
519 uint32_t full_value_size) 519 uint32_t full_value_size)
520{ 520{
521 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 521 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
522 "Received var: %s\n%.*s\n", 522 "Received var: %s\n%.*s\n",
523 name, value_size, (const char *) value); 523 name, value_size, (const char *) value);
524} 524}
@@ -558,7 +558,7 @@ slicer_recv_method (void *cls,
558 const char *method_name) 558 const char *method_name)
559{ 559{
560 method_received = method_name; 560 method_received = method_name;
561 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 561 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
562 "Received method for message ID %" PRIu64 ":\n" 562 "Received method for message ID %" PRIu64 ":\n"
563 "%s (flags: %x)\n", 563 "%s (flags: %x)\n",
564 message_id, method_name, ntohl (meth->flags)); 564 message_id, method_name, ntohl (meth->flags));
@@ -584,7 +584,7 @@ slicer_recv_modifier (void *cls,
584 uint16_t full_value_size) 584 uint16_t full_value_size)
585{ 585{
586#if 0 586#if 0
587 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 587 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
588 "Received modifier for message ID %" PRIu64 ":\n" 588 "Received modifier for message ID %" PRIu64 ":\n"
589 "%c%s: %.*s (size: %u)\n", 589 "%c%s: %.*s (size: %u)\n",
590 message_id, oper, name, value_size, (const char *) value, value_size); 590 message_id, oper, name, value_size, (const char *) value, value_size);
@@ -608,7 +608,7 @@ slicer_recv_data (void *cls,
608 uint16_t data_size) 608 uint16_t data_size)
609{ 609{
610#if 0 610#if 0
611 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 611 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
612 "Received data for message ID %" PRIu64 ":\n" 612 "Received data for message ID %" PRIu64 ":\n"
613 "%.*s\n", 613 "%.*s\n",
614 message_id, data_size, (const char *) data); 614 message_id, data_size, (const char *) data);
@@ -631,7 +631,7 @@ slicer_recv_eom (void *cls,
631 uint8_t is_cancelled) 631 uint8_t is_cancelled)
632{ 632{
633 printf(".\n"); 633 printf(".\n");
634 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 634 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
635 "Received end of message ID %" PRIu64 635 "Received end of message ID %" PRIu64
636 ", cancelled: %u\n", 636 ", cancelled: %u\n",
637 message_id, is_cancelled); 637 message_id, is_cancelled);
@@ -668,7 +668,7 @@ guest_recv_entry_decision (void *cls,
668 int is_admitted, 668 int is_admitted,
669 const struct GNUNET_PSYC_Message *entry_msg) 669 const struct GNUNET_PSYC_Message *entry_msg)
670{ 670{
671 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 671 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
672 "Guest received entry decision %d\n", 672 "Guest received entry decision %d\n",
673 is_admitted); 673 is_admitted);
674 674
@@ -683,7 +683,7 @@ guest_recv_entry_decision (void *cls,
683 GNUNET_PSYC_message_parse (pmsg, &method_name, env, &data, &data_size); 683 GNUNET_PSYC_message_parse (pmsg, &method_name, env, &data, &data_size);
684 GNUNET_free (pmsg); 684 GNUNET_free (pmsg);
685 685
686 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 686 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
687 "%s\n%.*s\n", 687 "%s\n%.*s\n",
688 method_name, data_size, (const char *) data); 688 method_name, data_size, (const char *) data);
689 } 689 }
@@ -704,7 +704,7 @@ guest_recv_local_enter (void *cls, int result,
704 uint64_t max_message_id) 704 uint64_t max_message_id)
705{ 705{
706 char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key); 706 char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key);
707 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 707 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
708 "Guest entered local place: %s, max_message_id: %" PRIu64 "\n", 708 "Guest entered local place: %s, max_message_id: %" PRIu64 "\n",
709 pub_str, max_message_id); 709 pub_str, max_message_id);
710 GNUNET_free (pub_str); 710 GNUNET_free (pub_str);
@@ -802,7 +802,7 @@ host_answer_door (void *cls,
802 char * 802 char *
803 nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key); 803 nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
804 804
805 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 805 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
806 "Entry request: %s\n", nym_str); 806 "Entry request: %s\n", nym_str);
807 GNUNET_free (nym_str); 807 GNUNET_free (nym_str);
808 808
@@ -840,7 +840,7 @@ host_farewell (void *cls,
840 char * 840 char *
841 nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key); 841 nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
842 842
843 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 843 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
844 "Farewell: %s\n", nym_str); 844 "Farewell: %s\n", nym_str);
845 GNUNET_free (nym_str); 845 GNUNET_free (nym_str);
846} 846}
@@ -856,7 +856,7 @@ host_entered (void *cls, int result,
856{ 856{
857 place_pub_key = *pub_key; 857 place_pub_key = *pub_key;
858 char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key); 858 char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key);
859 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 859 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
860 "Host entered: %s, max_message_id: %" PRIu64 "\n", 860 "Host entered: %s, max_message_id: %" PRIu64 "\n",
861 pub_str, max_message_id); 861 pub_str, max_message_id);
862 GNUNET_free (pub_str); 862 GNUNET_free (pub_str);
diff --git a/src/social/social_api.c b/src/social/social_api.c
index d57d16cfb..89843831b 100644
--- a/src/social/social_api.c
+++ b/src/social/social_api.c
@@ -183,6 +183,7 @@ struct GNUNET_SOCIAL_Place
183 */ 183 */
184 struct GNUNET_PSYC_Slicer *slicer; 184 struct GNUNET_PSYC_Slicer *slicer;
185 185
186 // FIXME: do we need is_disconnecing like on the psyc and multicast APIs?
186 /** 187 /**
187 * Function called after disconnected from the service. 188 * Function called after disconnected from the service.
188 */ 189 */
@@ -371,6 +372,68 @@ struct ZoneAddNymHandle
371}; 372};
372 373
373 374
375/*** CLEANUP / DISCONNECT ***/
376
377
378static void
379host_cleanup (struct GNUNET_SOCIAL_Host *hst)
380{
381 if (NULL != hst->slicer)
382 {
383 GNUNET_PSYC_slicer_destroy (hst->slicer);
384 hst->slicer = NULL;
385 }
386 GNUNET_free (hst);
387}
388
389
390static void
391guest_cleanup (struct GNUNET_SOCIAL_Guest *gst)
392{
393 GNUNET_free (gst);
394}
395
396
397static void
398place_cleanup (struct GNUNET_SOCIAL_Place *plc)
399{
400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
401 "cleaning up place %p\n",
402 plc);
403 if (NULL != plc->tmit)
404 {
405 GNUNET_PSYC_transmit_destroy (plc->tmit);
406 plc->tmit = NULL;
407 }
408 if (NULL != plc->connect_env)
409 {
410 GNUNET_MQ_discard (plc->connect_env);
411 plc->connect_env = NULL;
412 }
413 if (NULL != plc->mq)
414 {
415 GNUNET_MQ_destroy (plc->mq);
416 plc->mq = NULL;
417 }
418 if (NULL != plc->disconnect_cb)
419 {
420 plc->disconnect_cb (plc->disconnect_cls);
421 plc->disconnect_cb = NULL;
422 }
423
424 (GNUNET_YES == plc->is_host)
425 ? host_cleanup ((struct GNUNET_SOCIAL_Host *) plc)
426 : guest_cleanup ((struct GNUNET_SOCIAL_Guest *) plc);
427}
428
429
430static void
431place_disconnect (struct GNUNET_SOCIAL_Place *plc)
432{
433 place_cleanup (plc);
434}
435
436
374/*** NYM ***/ 437/*** NYM ***/
375 438
376static struct GNUNET_SOCIAL_Nym * 439static struct GNUNET_SOCIAL_Nym *
@@ -428,7 +491,7 @@ host_recv_notice_place_leave_method (void *cls,
428 491
429 struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&msg->slave_pub_key); 492 struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&msg->slave_pub_key);
430 493
431 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
432 "Host received method for message ID %" PRIu64 " from nym %s: %s\n", 495 "Host received method for message ID %" PRIu64 " from nym %s: %s\n",
433 message_id, GNUNET_h2s (&nym->pub_key_hash), method_name); 496 message_id, GNUNET_h2s (&nym->pub_key_hash), method_name);
434 497
@@ -436,7 +499,7 @@ host_recv_notice_place_leave_method (void *cls,
436 hst->notice_place_leave_env = GNUNET_PSYC_env_create (); 499 hst->notice_place_leave_env = GNUNET_PSYC_env_create ();
437 500
438 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key); 501 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key);
439 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
440 "_notice_place_leave: got method from nym %s (%s).\n", 503 "_notice_place_leave: got method from nym %s (%s).\n",
441 GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str); 504 GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str);
442 GNUNET_free (str); 505 GNUNET_free (str);
@@ -458,7 +521,7 @@ host_recv_notice_place_leave_modifier (void *cls,
458 if (NULL == hst->notice_place_leave_env) 521 if (NULL == hst->notice_place_leave_env)
459 return; 522 return;
460 523
461 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
462 "Host received modifier for _notice_place_leave message with ID %" PRIu64 ":\n" 525 "Host received modifier for _notice_place_leave message with ID %" PRIu64 ":\n"
463 "%c%s: %.*s\n", 526 "%c%s: %.*s\n",
464 message_id, oper, name, value_size, (const char *) value); 527 message_id, oper, name, value_size, (const char *) value);
@@ -485,7 +548,7 @@ host_recv_notice_place_leave_eom (void *cls,
485 return; 548 return;
486 549
487 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key); 550 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key);
488 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
489 "_notice_place_leave: got EOM from nym %s (%s).\n", 552 "_notice_place_leave: got EOM from nym %s (%s).\n",
490 GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str); 553 GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str);
491 GNUNET_free (str); 554 GNUNET_free (str);
@@ -1015,100 +1078,24 @@ handle_app_place_end (void *cls,
1015} 1078}
1016 1079
1017 1080
1018/*** CLEANUP / DISCONNECT ***/ 1081/**
1019 1082 * Handler for a #GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK message received
1020 1083 * from the social service.
1021static void 1084 *
1022host_cleanup (struct GNUNET_SOCIAL_Host *hst) 1085 * @param cls the place of type `struct GNUNET_SOCIAL_Place`
1023{ 1086 * @param msg the message received from the service
1024 if (NULL != hst->slicer) 1087 */
1025 {
1026 GNUNET_PSYC_slicer_destroy (hst->slicer);
1027 hst->slicer = NULL;
1028 }
1029 GNUNET_free (hst);
1030}
1031
1032
1033static void 1088static void
1034guest_cleanup (struct GNUNET_SOCIAL_Guest *gst) 1089handle_place_leave_ack (void *cls,
1090 const struct GNUNET_MessageHeader *msg)
1035{ 1091{
1036 GNUNET_free (gst); 1092 struct GNUNET_SOCIAL_Place *plc = cls;
1037}
1038
1039 1093
1040static void
1041place_cleanup (struct GNUNET_SOCIAL_Place *plc)
1042{
1043 struct GNUNET_HashCode place_pub_hash;
1044 GNUNET_CRYPTO_hash (&plc->pub_key, sizeof (plc->pub_key), &place_pub_hash);
1045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1046 "%s place cleanup: %s\n", 1095 "%s left place %p\n",
1047 GNUNET_YES == plc->is_host ? "host" : "guest", 1096 plc->is_host ? "host" : "guest",
1048 GNUNET_h2s (&place_pub_hash)); 1097 plc);
1049 1098 place_disconnect (plc);
1050 if (NULL != plc->tmit)
1051 {
1052 GNUNET_PSYC_transmit_destroy (plc->tmit);
1053 plc->tmit = NULL;
1054 }
1055 if (NULL != plc->connect_env)
1056 {
1057 GNUNET_MQ_discard (plc->connect_env);
1058 plc->connect_env = NULL;
1059 }
1060 if (NULL != plc->mq)
1061 {
1062 GNUNET_MQ_destroy (plc->mq);
1063 plc->mq = NULL;
1064 }
1065 if (NULL != plc->disconnect_cb)
1066 {
1067 plc->disconnect_cb (plc->disconnect_cls);
1068 plc->disconnect_cb = NULL;
1069 }
1070
1071 (GNUNET_YES == plc->is_host)
1072 ? host_cleanup ((struct GNUNET_SOCIAL_Host *) plc)
1073 : guest_cleanup ((struct GNUNET_SOCIAL_Guest *) plc);
1074}
1075
1076
1077void
1078place_disconnect (struct GNUNET_SOCIAL_Place *plc,
1079 GNUNET_ContinuationCallback cb,
1080 void *cls)
1081{
1082 plc->disconnect_cb = cb;
1083 plc->disconnect_cls = cls;
1084
1085 if (NULL != plc->mq)
1086 {
1087 struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (plc->mq);
1088 if (NULL != env)
1089 {
1090 GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) place_cleanup, plc);
1091 }
1092 else
1093 {
1094 place_cleanup (plc);
1095 }
1096 }
1097 else
1098 {
1099 place_cleanup (plc);
1100 }
1101}
1102
1103
1104void
1105place_leave (struct GNUNET_SOCIAL_Place *plc)
1106{
1107 struct GNUNET_MessageHeader *msg;
1108 struct GNUNET_MQ_Envelope *
1109 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE);
1110
1111 GNUNET_MQ_send (plc->mq, env);
1112} 1099}
1113 1100
1114 1101
@@ -1168,6 +1155,10 @@ host_connect (struct GNUNET_SOCIAL_Host *hst)
1168 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK, 1155 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK,
1169 struct HostEnterAck, 1156 struct HostEnterAck,
1170 hst), 1157 hst),
1158 GNUNET_MQ_hd_fixed_size (place_leave_ack,
1159 GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK,
1160 struct GNUNET_MessageHeader,
1161 plc),
1171 GNUNET_MQ_hd_var_size (host_enter_request, 1162 GNUNET_MQ_hd_var_size (host_enter_request,
1172 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, 1163 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
1173 struct GNUNET_PSYC_JoinRequestMessage, 1164 struct GNUNET_PSYC_JoinRequestMessage,
@@ -1516,6 +1507,9 @@ GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst,
1516 void *notify_data_cls, 1507 void *notify_data_cls,
1517 enum GNUNET_SOCIAL_AnnounceFlags flags) 1508 enum GNUNET_SOCIAL_AnnounceFlags flags)
1518{ 1509{
1510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1511 "PSYC_transmit_message for host, method: %s\n",
1512 method_name);
1519 if (GNUNET_OK == 1513 if (GNUNET_OK ==
1520 GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env, 1514 GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env,
1521 NULL, notify_data, notify_data_cls, flags)) 1515 NULL, notify_data, notify_data_cls, flags))
@@ -1580,7 +1574,11 @@ GNUNET_SOCIAL_host_disconnect (struct GNUNET_SOCIAL_Host *hst,
1580 GNUNET_ContinuationCallback disconnect_cb, 1574 GNUNET_ContinuationCallback disconnect_cb,
1581 void *cls) 1575 void *cls)
1582{ 1576{
1583 place_disconnect (&hst->plc, disconnect_cb, cls); 1577 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1578
1579 plc->disconnect_cb = disconnect_cb;
1580 plc->disconnect_cls = cls;
1581 place_disconnect (plc);
1584} 1582}
1585 1583
1586 1584
@@ -1607,10 +1605,15 @@ GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst,
1607 GNUNET_ContinuationCallback disconnect_cb, 1605 GNUNET_ContinuationCallback disconnect_cb,
1608 void *cls) 1606 void *cls)
1609{ 1607{
1608 struct GNUNET_MQ_Envelope *envelope;
1609
1610 GNUNET_SOCIAL_host_announce (hst, "_notice_place_closing", env, NULL, NULL, 1610 GNUNET_SOCIAL_host_announce (hst, "_notice_place_closing", env, NULL, NULL,
1611 GNUNET_SOCIAL_ANNOUNCE_NONE); 1611 GNUNET_SOCIAL_ANNOUNCE_NONE);
1612 place_leave (&hst->plc); 1612 hst->plc.disconnect_cb = disconnect_cb;
1613 GNUNET_SOCIAL_host_disconnect (hst, disconnect_cb, cls); 1613 hst->plc.disconnect_cls = cls;
1614 envelope = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE);
1615 GNUNET_MQ_send (hst->plc.mq,
1616 envelope);
1614} 1617}
1615 1618
1616 1619
@@ -1670,6 +1673,10 @@ guest_connect (struct GNUNET_SOCIAL_Guest *gst)
1670 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK, 1673 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK,
1671 struct GNUNET_PSYC_CountersResultMessage, 1674 struct GNUNET_PSYC_CountersResultMessage,
1672 gst), 1675 gst),
1676 GNUNET_MQ_hd_fixed_size (place_leave_ack,
1677 GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK,
1678 struct GNUNET_MessageHeader,
1679 plc),
1673 GNUNET_MQ_hd_var_size (guest_enter_decision, 1680 GNUNET_MQ_hd_var_size (guest_enter_decision,
1674 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 1681 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
1675 struct GNUNET_PSYC_JoinDecisionMessage, 1682 struct GNUNET_PSYC_JoinDecisionMessage,
@@ -1896,6 +1903,64 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app,
1896} 1903}
1897 1904
1898 1905
1906struct ReconnectContext
1907{
1908 struct GNUNET_SOCIAL_Guest *guest;
1909 int *result;
1910 int64_t *max_message_id;
1911 GNUNET_SOCIAL_GuestEnterCallback enter_cb;
1912 void *enter_cls;
1913};
1914
1915
1916static void
1917guest_enter_reconnect_cb (void *cls,
1918 int result,
1919 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
1920 uint64_t max_message_id)
1921{
1922 struct ReconnectContext *reconnect_ctx = cls;
1923
1924 GNUNET_assert (NULL != reconnect_ctx);
1925 reconnect_ctx->result = GNUNET_new (int);
1926 *(reconnect_ctx->result) = result;
1927 reconnect_ctx->max_message_id = GNUNET_new (int64_t);
1928 *(reconnect_ctx->max_message_id) = max_message_id;
1929}
1930
1931
1932static void
1933guest_entry_dcsn_reconnect_cb (void *cls,
1934 int is_admitted,
1935 const struct GNUNET_PSYC_Message *entry_resp)
1936{
1937 struct ReconnectContext *reconnect_ctx = cls;
1938 struct GNUNET_SOCIAL_Guest *gst = reconnect_ctx->guest;
1939
1940 GNUNET_assert (NULL != reconnect_ctx);
1941 GNUNET_assert (NULL != reconnect_ctx->result);
1942 GNUNET_assert (NULL != reconnect_ctx->max_message_id);
1943 if (GNUNET_YES != is_admitted)
1944 {
1945 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1946 "Guest was rejected after calling "
1947 "GNUNET_SOCIAL_guest_enter_reconnect ()\n");
1948 }
1949 else if (NULL != reconnect_ctx->enter_cb)
1950 {
1951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1952 "guest reconnected!\n");
1953 reconnect_ctx->enter_cb (reconnect_ctx->enter_cls,
1954 *(reconnect_ctx->result),
1955 &gst->plc.pub_key,
1956 *(reconnect_ctx->max_message_id));
1957 }
1958 GNUNET_free (reconnect_ctx->result);
1959 GNUNET_free (reconnect_ctx->max_message_id);
1960 GNUNET_free (reconnect_ctx);
1961}
1962
1963
1899/** 1964/**
1900 * Reconnect to an already entered place as guest. 1965 * Reconnect to an already entered place as guest.
1901 * 1966 *
@@ -1906,8 +1971,8 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app,
1906 * Flags for the entry. 1971 * Flags for the entry.
1907 * @param slicer 1972 * @param slicer
1908 * Slicer to use for processing incoming requests from guests. 1973 * Slicer to use for processing incoming requests from guests.
1909 * @param local_enter_cb 1974 * @param enter_cb
1910 * Called upon connection established to the social service. 1975 * Called upon re-entering is complete.
1911 * @param entry_decision_cb 1976 * @param entry_decision_cb
1912 * Called upon receiving entry decision. 1977 * Called upon receiving entry decision.
1913 * 1978 *
@@ -1917,11 +1982,12 @@ struct GNUNET_SOCIAL_Guest *
1917GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn, 1982GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn,
1918 enum GNUNET_PSYC_SlaveJoinFlags flags, 1983 enum GNUNET_PSYC_SlaveJoinFlags flags,
1919 struct GNUNET_PSYC_Slicer *slicer, 1984 struct GNUNET_PSYC_Slicer *slicer,
1920 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, 1985 GNUNET_SOCIAL_GuestEnterCallback enter_cb,
1921 void *cls) 1986 void *cls)
1922{ 1987{
1923 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); 1988 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
1924 struct GNUNET_SOCIAL_Place *plc = &gst->plc; 1989 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1990 struct ReconnectContext *reconnect_ctx;
1925 1991
1926 uint16_t app_id_size = strlen (gconn->app->id) + 1; 1992 uint16_t app_id_size = strlen (gconn->app->id) + 1;
1927 struct GuestEnterRequest *greq; 1993 struct GuestEnterRequest *greq;
@@ -1940,10 +2006,15 @@ GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn
1940 plc->pub_key = gconn->plc_msg.place_pub_key; 2006 plc->pub_key = gconn->plc_msg.place_pub_key;
1941 plc->ego_pub_key = gconn->plc_msg.ego_pub_key; 2007 plc->ego_pub_key = gconn->plc_msg.ego_pub_key;
1942 2008
1943 plc->op = GNUNET_OP_create (); 2009 reconnect_ctx = GNUNET_new (struct ReconnectContext);
2010 reconnect_ctx->guest = gst;
2011 reconnect_ctx->enter_cb = enter_cb;
2012 reconnect_ctx->enter_cls = cls;
1944 2013
1945 gst->enter_cb = local_enter_cb; 2014 plc->op = GNUNET_OP_create ();
1946 gst->cb_cls = cls; 2015 gst->enter_cb = &guest_enter_reconnect_cb;
2016 gst->entry_dcsn_cb = &guest_entry_dcsn_reconnect_cb;
2017 gst->cb_cls = reconnect_ctx;
1947 2018
1948 guest_connect (gst); 2019 guest_connect (gst);
1949 return gst; 2020 return gst;
@@ -2028,7 +2099,11 @@ GNUNET_SOCIAL_guest_disconnect (struct GNUNET_SOCIAL_Guest *gst,
2028 GNUNET_ContinuationCallback disconnect_cb, 2099 GNUNET_ContinuationCallback disconnect_cb,
2029 void *cls) 2100 void *cls)
2030{ 2101{
2031 place_disconnect (&gst->plc, disconnect_cb, cls); 2102 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
2103
2104 plc->disconnect_cb = disconnect_cb;
2105 plc->disconnect_cls = cls;
2106 place_disconnect (plc);
2032} 2107}
2033 2108
2034 2109
@@ -2054,10 +2129,15 @@ GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst,
2054 GNUNET_ContinuationCallback disconnect_cb, 2129 GNUNET_ContinuationCallback disconnect_cb,
2055 void *cls) 2130 void *cls)
2056{ 2131{
2132 struct GNUNET_MQ_Envelope *envelope;
2133
2057 GNUNET_SOCIAL_guest_talk (gst, "_notice_place_leave", env, NULL, NULL, 2134 GNUNET_SOCIAL_guest_talk (gst, "_notice_place_leave", env, NULL, NULL,
2058 GNUNET_SOCIAL_TALK_NONE); 2135 GNUNET_SOCIAL_TALK_NONE);
2059 place_leave (&gst->plc); 2136 gst->plc.disconnect_cb = disconnect_cb;
2060 GNUNET_SOCIAL_guest_disconnect (gst, disconnect_cb, cls); 2137 gst->plc.disconnect_cls = cls;
2138 envelope = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE);
2139 GNUNET_MQ_send (gst->plc.mq,
2140 envelope);
2061} 2141}
2062 2142
2063 2143
diff --git a/src/social/test_social.c b/src/social/test_social.c
index 64ef10125..4d95cf005 100644
--- a/src/social/test_social.c
+++ b/src/social/test_social.c
@@ -129,22 +129,22 @@ enum
129 TEST_HOST_ANSWER_DOOR_REFUSE = 4, 129 TEST_HOST_ANSWER_DOOR_REFUSE = 4,
130 TEST_GUEST_RECV_ENTRY_DCSN_REFUSE = 5, 130 TEST_GUEST_RECV_ENTRY_DCSN_REFUSE = 5,
131 TEST_HOST_ANSWER_DOOR_ADMIT = 6, 131 TEST_HOST_ANSWER_DOOR_ADMIT = 6,
132 TEST_GUEST_RECV_ENTRY_DCSN_ADMIT = 9, 132 TEST_GUEST_RECV_ENTRY_DCSN_ADMIT = 7,
133 TEST_HOST_ANNOUNCE = 10, 133 TEST_HOST_ANNOUNCE = 8,
134 TEST_HOST_ANNOUNCE_END = 11, 134 TEST_HOST_ANNOUNCE_END = 9,
135 TEST_GUEST_TALK = 12, 135 TEST_GUEST_TALK = 10,
136 TEST_HOST_ANNOUNCE2 = 13, 136 TEST_HOST_ANNOUNCE2 = 11,
137 TEST_HOST_ANNOUNCE2_END = 14, 137 TEST_HOST_ANNOUNCE2_END = 12,
138 TEST_GUEST_HISTORY_REPLAY = 15, 138 TEST_GUEST_HISTORY_REPLAY = 13,
139 TEST_GUEST_HISTORY_REPLAY_LATEST = 16, 139 TEST_GUEST_HISTORY_REPLAY_LATEST = 14,
140 TEST_GUEST_LOOK_AT = 17, 140 TEST_GUEST_LOOK_AT = 15,
141 TEST_GUEST_LOOK_FOR = 18, 141 TEST_GUEST_LOOK_FOR = 16,
142 TEST_GUEST_LEAVE = 18, 142 TEST_GUEST_LEAVE = 17,
143 TEST_ZONE_ADD_PLACE = 20, 143 TEST_ZONE_ADD_PLACE = 18,
144 TEST_GUEST_ENTER_BY_NAME = 21, 144 TEST_GUEST_ENTER_BY_NAME = 19,
145 TEST_RECONNECT = 22, 145 TEST_RECONNECT = 20,
146 TEST_GUEST_LEAVE2 = 23, 146 TEST_GUEST_LEAVE2 = 21,
147 TEST_HOST_LEAVE = 24, 147 TEST_HOST_LEAVE = 22,
148} test; 148} test;
149 149
150 150
@@ -180,10 +180,28 @@ host_announce2 ();
180 180
181 181
182/** 182/**
183 * Clean up all resources used. 183 * Terminate the test case (failure).
184 *
185 * @param cls NULL
186 */
187static void
188end_badly (void *cls)
189{
190 end_badly_task = NULL;
191 GNUNET_SCHEDULER_shutdown ();
192 res = 2;
193 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
194 "Test FAILED.\n");
195}
196
197
198/**
199 * Terminate the test case (failure).
200 *
201 * @param cls NULL
184 */ 202 */
185static void 203static void
186cleanup () 204end_shutdown (void *cls)
187{ 205{
188 if (NULL != id) 206 if (NULL != id)
189 { 207 {
@@ -202,7 +220,11 @@ cleanup ()
202 GNUNET_PSYC_slicer_destroy (host_slicer); 220 GNUNET_PSYC_slicer_destroy (host_slicer);
203 host_slicer = NULL; 221 host_slicer = NULL;
204 } 222 }
205 223 if (NULL != end_badly_task)
224 {
225 GNUNET_SCHEDULER_cancel (end_badly_task);
226 end_badly_task = NULL;
227 }
206 if (NULL != gst) 228 if (NULL != gst)
207 { 229 {
208 GNUNET_SOCIAL_guest_leave (gst, NULL, NULL, NULL); 230 GNUNET_SOCIAL_guest_leave (gst, NULL, NULL, NULL);
@@ -216,21 +238,6 @@ cleanup ()
216 hst_plc = NULL; 238 hst_plc = NULL;
217 } 239 }
218 GNUNET_SOCIAL_app_disconnect (app, NULL, NULL); 240 GNUNET_SOCIAL_app_disconnect (app, NULL, NULL);
219 GNUNET_SCHEDULER_shutdown ();
220}
221
222
223/**
224 * Terminate the test case (failure).
225 *
226 * @param cls NULL
227 */
228static void
229end_badly (void *cls)
230{
231 res = 1;
232 cleanup ();
233 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test FAILED.\n");
234} 241}
235 242
236 243
@@ -242,9 +249,9 @@ end_badly (void *cls)
242static void 249static void
243end_normally (void *cls) 250end_normally (void *cls)
244{ 251{
252 GNUNET_SCHEDULER_shutdown ();
245 res = 0; 253 res = 0;
246 cleanup (); 254 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Test PASSED.\n");
247 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test PASSED.\n");
248} 255}
249 256
250 257
@@ -254,7 +261,7 @@ end_normally (void *cls)
254static void 261static void
255end () 262end ()
256{ 263{
257 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 264 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
258 "Test #%u: Ending tests.\n", test); 265 "Test #%u: Ending tests.\n", test);
259 266
260 if (end_badly_task != NULL) 267 if (end_badly_task != NULL)
@@ -271,7 +278,7 @@ transmit_resume (void *cls)
271{ 278{
272 struct TransmitClosure *tmit = cls; 279 struct TransmitClosure *tmit = cls;
273 280
274 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 281 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
275 "Test #%u: Transmission resumed.\n", test); 282 "Test #%u: Transmission resumed.\n", test);
276 if (NULL != tmit->host_ann) 283 if (NULL != tmit->host_ann)
277 GNUNET_SOCIAL_host_announce_resume (tmit->host_ann); 284 GNUNET_SOCIAL_host_announce_resume (tmit->host_ann);
@@ -296,7 +303,7 @@ notify_data (void *cls, uint16_t *data_size, void *data)
296 } 303 }
297 304
298 uint16_t size = strlen (tmit->data[tmit->n]); 305 uint16_t size = strlen (tmit->data[tmit->n]);
299 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 306 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
300 "Test #%u: Transmit notify data: %u bytes available, " 307 "Test #%u: Transmit notify data: %u bytes available, "
301 "processing fragment %u/%u (size %u).\n", 308 "processing fragment %u/%u (size %u).\n",
302 test, *data_size, tmit->n + 1, tmit->data_count, size); 309 test, *data_size, tmit->n + 1, tmit->data_count, size);
@@ -309,7 +316,7 @@ notify_data (void *cls, uint16_t *data_size, void *data)
309 316
310 if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n]) 317 if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n])
311 { 318 {
312 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 319 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
313 "Test #%u: Transmission paused.\n", test); 320 "Test #%u: Transmission paused.\n", test);
314 tmit->paused = GNUNET_YES; 321 tmit->paused = GNUNET_YES;
315 GNUNET_SCHEDULER_add_delayed ( 322 GNUNET_SCHEDULER_add_delayed (
@@ -331,7 +338,7 @@ notify_data (void *cls, uint16_t *data_size, void *data)
331static void 338static void
332host_left () 339host_left ()
333{ 340{
334 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 341 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
335 "Test #%u: The host has left the place.\n", test); 342 "Test #%u: The host has left the place.\n", test);
336 end (); 343 end ();
337} 344}
@@ -352,7 +359,7 @@ host_farewell2 (void *cls,
352 const struct GNUNET_SOCIAL_Nym *nym, 359 const struct GNUNET_SOCIAL_Nym *nym,
353 struct GNUNET_PSYC_Environment *env) 360 struct GNUNET_PSYC_Environment *env)
354{ 361{
355 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 362 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
356 "Nym left the place again.\n"); 363 "Nym left the place again.\n");
357 GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL); 364 GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL);
358} 365}
@@ -365,13 +372,14 @@ host_reconnected (void *cls, int result,
365{ 372{
366 place_pub_key = *home_pub_key; 373 place_pub_key = *home_pub_key;
367 GNUNET_CRYPTO_hash (&place_pub_key, sizeof (place_pub_key), &place_pub_hash); 374 GNUNET_CRYPTO_hash (&place_pub_key, sizeof (place_pub_key), &place_pub_hash);
368 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 375 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
369 "Test #%u: Host reconnected to place %s\n", 376 "Test #%u: Host reconnected to place %s\n",
370 test, GNUNET_h2s (&place_pub_hash)); 377 test, GNUNET_h2s (&place_pub_hash));
371 378
372 is_host_reconnected = GNUNET_YES; 379 is_host_reconnected = GNUNET_YES;
373 if (GNUNET_YES == is_guest_reconnected) 380 if (GNUNET_YES == is_guest_reconnected)
374 { 381 {
382 GNUNET_assert (NULL != gst);
375 GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL); 383 GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL);
376 } 384 }
377} 385}
@@ -382,7 +390,7 @@ guest_reconnected (void *cls, int result,
382 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, 390 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
383 uint64_t max_message_id) 391 uint64_t max_message_id)
384{ 392{
385 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 393 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
386 "Test #%u: Guest reconnected to place: %d\n", 394 "Test #%u: Guest reconnected to place: %d\n",
387 test, result); 395 test, result);
388 GNUNET_assert (0 <= result); 396 GNUNET_assert (0 <= result);
@@ -390,6 +398,7 @@ guest_reconnected (void *cls, int result,
390 is_guest_reconnected = GNUNET_YES; 398 is_guest_reconnected = GNUNET_YES;
391 if (GNUNET_YES == is_host_reconnected) 399 if (GNUNET_YES == is_host_reconnected)
392 { 400 {
401 GNUNET_assert (NULL != gst);
393 GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL); 402 GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL);
394 } 403 }
395} 404}
@@ -398,7 +407,7 @@ guest_reconnected (void *cls, int result,
398static void 407static void
399app_connected (void *cls) 408app_connected (void *cls)
400{ 409{
401 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 410 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
402 "Test #%u: App connected: %p\n", test, cls); 411 "Test #%u: App connected: %p\n", test, cls);
403} 412}
404 413
@@ -411,21 +420,28 @@ app_recv_host (void *cls,
411 enum GNUNET_SOCIAL_AppPlaceState place_state) 420 enum GNUNET_SOCIAL_AppPlaceState place_state)
412{ 421{
413 struct GNUNET_HashCode host_pub_hash; 422 struct GNUNET_HashCode host_pub_hash;
414 GNUNET_CRYPTO_hash (host_pub_key, sizeof (*host_pub_key), &host_pub_hash);
415 423
416 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 424 GNUNET_CRYPTO_hash (host_pub_key,
425 sizeof (*host_pub_key),
426 &host_pub_hash);
427
428 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
417 "Test #%u: Got app host place notification: %s\n", 429 "Test #%u: Got app host place notification: %s\n",
418 test, GNUNET_h2s (&host_pub_hash)); 430 test,
431 GNUNET_h2s (&host_pub_hash));
419 432
420 if (test == TEST_RECONNECT) 433 if (test == TEST_RECONNECT)
421 { 434 {
422 if (0 == memcmp (&place_pub_key, host_pub_key, sizeof (*host_pub_key))) 435 if (0 == memcmp (&place_pub_key, host_pub_key, sizeof (*host_pub_key)))
423 { 436 {
424 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 437 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
425 "Test #%u: Reconnecting to host place: %s\n", 438 "Test #%u: Reconnecting to host place: %s\n",
426 test, GNUNET_h2s (&host_pub_hash)); 439 test, GNUNET_h2s (&host_pub_hash));
427 hst = GNUNET_SOCIAL_host_enter_reconnect (hconn, host_slicer, host_reconnected, 440 hst = GNUNET_SOCIAL_host_enter_reconnect (hconn, host_slicer,
428 host_answer_door, host_farewell2, NULL); 441 &host_reconnected,
442 &host_answer_door,
443 &host_farewell2,
444 NULL);
429 } 445 }
430 } 446 }
431} 447}
@@ -439,21 +455,30 @@ app_recv_guest (void *cls,
439 enum GNUNET_SOCIAL_AppPlaceState place_state) 455 enum GNUNET_SOCIAL_AppPlaceState place_state)
440{ 456{
441 struct GNUNET_HashCode guest_pub_hash; 457 struct GNUNET_HashCode guest_pub_hash;
442 GNUNET_CRYPTO_hash (guest_pub_key, sizeof (*guest_pub_key), &guest_pub_hash);
443 458
444 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 459 GNUNET_CRYPTO_hash (guest_pub_key,
460 sizeof (*guest_pub_key),
461 &guest_pub_hash);
462
463 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
445 "Test #%u: Got app guest place notification: %s\n", 464 "Test #%u: Got app guest place notification: %s\n",
446 test, GNUNET_h2s (&guest_pub_hash)); 465 test, GNUNET_h2s (&guest_pub_hash));
447 466
448 if (test == TEST_RECONNECT) 467 if (test == TEST_RECONNECT)
449 { 468 {
450 if (0 == memcmp (&place_pub_key, guest_pub_key, sizeof (*guest_pub_key))) 469 if (0 == memcmp (&place_pub_key,
470 guest_pub_key,
471 sizeof (*guest_pub_key)))
451 { 472 {
452 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 473 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
453 "Test #%u: Reconnecting to guest place: %s\n", 474 "Test #%u: Reconnecting to guest place: %s\n",
454 test, GNUNET_h2s (&guest_pub_hash)); 475 test, GNUNET_h2s (&guest_pub_hash));
455 gst = GNUNET_SOCIAL_guest_enter_reconnect (gconn, GNUNET_PSYC_SLAVE_JOIN_NONE, 476 gst = GNUNET_SOCIAL_guest_enter_reconnect (gconn,
456 guest_slicer, guest_reconnected, NULL); 477 GNUNET_PSYC_SLAVE_JOIN_NONE,
478 guest_slicer,
479 &guest_reconnected,
480 NULL);
481 GNUNET_assert (NULL != gst);
457 } 482 }
458 } 483 }
459} 484}
@@ -478,7 +503,7 @@ app_recv_ego (void *cls,
478 const char *name) 503 const char *name)
479{ 504{
480 char *ego_pub_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (ego_pub_key); 505 char *ego_pub_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (ego_pub_key);
481 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 506 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
482 "Test #%u: Got app ego notification: %p %s %s\n", 507 "Test #%u: Got app ego notification: %p %s %s\n",
483 test, ego, name, ego_pub_str); 508 test, ego, name, ego_pub_str);
484 GNUNET_free (ego_pub_str); 509 GNUNET_free (ego_pub_str);
@@ -487,15 +512,30 @@ app_recv_ego (void *cls,
487 { 512 {
488 host_ego = ego; 513 host_ego = ego;
489 host_pub_key = ego_pub_key; 514 host_pub_key = ego_pub_key;
490 GNUNET_assert (TEST_IDENTITIES_CREATE == test); 515 if (TEST_IDENTITIES_CREATE == test)
491 enter_if_ready (); 516 {
517 enter_if_ready ();
518 }
519 else
520 {
521 GNUNET_assert (TEST_RECONNECT == test);
522 }
492 } 523 }
493 else if (NULL != strstr (name, guest_name)) 524 else if (NULL != strstr (name, guest_name))
494 { 525 {
495 guest_ego = ego; 526 guest_ego = ego;
496 guest_pub_key = ego_pub_key; 527 guest_pub_key = ego_pub_key;
497 GNUNET_assert (TEST_IDENTITIES_CREATE == test); 528 if (TEST_IDENTITIES_CREATE == test)
498 enter_if_ready (); 529 {
530 enter_if_ready ();
531 }
532 else
533 {
534 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
535 "test = %d\n",
536 test);
537 GNUNET_assert (TEST_RECONNECT == test);
538 }
499 } 539 }
500} 540}
501 541
@@ -504,7 +544,6 @@ static void
504schedule_reconnect (void *cls) 544schedule_reconnect (void *cls)
505{ 545{
506 test = TEST_RECONNECT; 546 test = TEST_RECONNECT;
507
508 GNUNET_SOCIAL_host_disconnect (hst, NULL, NULL); 547 GNUNET_SOCIAL_host_disconnect (hst, NULL, NULL);
509 GNUNET_SOCIAL_guest_disconnect (gst, NULL, NULL); 548 GNUNET_SOCIAL_guest_disconnect (gst, NULL, NULL);
510 hst = NULL; 549 hst = NULL;
@@ -512,10 +551,10 @@ schedule_reconnect (void *cls)
512 551
513 GNUNET_SOCIAL_app_disconnect (app, NULL, NULL); 552 GNUNET_SOCIAL_app_disconnect (app, NULL, NULL);
514 app = GNUNET_SOCIAL_app_connect (cfg, app_id, 553 app = GNUNET_SOCIAL_app_connect (cfg, app_id,
515 app_recv_ego, 554 &app_recv_ego,
516 app_recv_host, 555 &app_recv_host,
517 app_recv_guest, 556 &app_recv_guest,
518 app_connected, 557 &app_connected,
519 NULL); 558 NULL);
520} 559}
521 560
@@ -524,7 +563,7 @@ static void
524host_recv_zone_add_place_result (void *cls, int64_t result, 563host_recv_zone_add_place_result (void *cls, int64_t result,
525 const void *data, uint16_t data_size) 564 const void *data, uint16_t data_size)
526{ 565{
527 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 566 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
528 "Test #%u: Zone add place result: %" PRId64 " (%.*s).\n", 567 "Test #%u: Zone add place result: %" PRId64 " (%.*s).\n",
529 test, result, data_size, (const char *) data); 568 test, result, data_size, (const char *) data);
530 GNUNET_assert (GNUNET_YES == result); 569 GNUNET_assert (GNUNET_YES == result);
@@ -538,7 +577,7 @@ static void
538zone_add_place () 577zone_add_place ()
539{ 578{
540 test = TEST_ZONE_ADD_PLACE; 579 test = TEST_ZONE_ADD_PLACE;
541 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 580 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
542 "Test #%u: Adding place to zone.\n", test); 581 "Test #%u: Adding place to zone.\n", test);
543 582
544 GNUNET_SOCIAL_zone_add_place (app, host_ego, "home", "let.me*in!", 583 GNUNET_SOCIAL_zone_add_place (app, host_ego, "home", "let.me*in!",
@@ -557,7 +596,7 @@ host_farewell (void *cls,
557 nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym); 596 nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym);
558 597
559 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key); 598 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
560 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 599 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
561 "Test #%u: Farewell: nym %s (%s) has left the place.\n", 600 "Test #%u: Farewell: nym %s (%s) has left the place.\n",
562 test, GNUNET_h2s (GNUNET_SOCIAL_nym_get_pub_key_hash (nym)), str); 601 test, GNUNET_h2s (GNUNET_SOCIAL_nym_get_pub_key_hash (nym)), str);
563 GNUNET_free (str); 602 GNUNET_free (str);
@@ -578,13 +617,13 @@ host_farewell (void *cls,
578static void 617static void
579guest_left (void *cls) 618guest_left (void *cls)
580{ 619{
581 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 620 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
582 "Test #%u: The guest has left the place.\n", test); 621 "Test #%u: The guest has left the place.\n", test);
583} 622}
584 623
585 624
586static void 625static void
587guest_leave() 626guest_leave ()
588{ 627{
589 if (test < TEST_RECONNECT) 628 if (test < TEST_RECONNECT)
590 test = TEST_GUEST_LEAVE; 629 test = TEST_GUEST_LEAVE;
@@ -615,11 +654,11 @@ guest_look_for_result (void *cls,
615 uint16_t data_size) 654 uint16_t data_size)
616{ 655{
617 struct ResultClosure *rcls = cls; 656 struct ResultClosure *rcls = cls;
618 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 657 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
619 "Test #%u: guest_look_for_result: %" PRId64 "\n", 658 "Test #%u: guest_look_for_result: %" PRId64 "\n",
620 test, result_code); 659 test, result_code);
621 GNUNET_assert (GNUNET_OK == result_code); 660 GNUNET_assert (GNUNET_OK == result_code);
622 GNUNET_assert (3 == rcls->n); 661 GNUNET_assert (6 == rcls->n);
623 GNUNET_free (rcls); 662 GNUNET_free (rcls);
624 GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL); 663 GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL);
625} 664}
@@ -635,7 +674,7 @@ guest_look_for_var (void *cls,
635{ 674{
636 struct ResultClosure *rcls = cls; 675 struct ResultClosure *rcls = cls;
637 rcls->n++; 676 rcls->n++;
638 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 677 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
639 "Test #%u: guest_look_for_var: %s\n%.*s\n", 678 "Test #%u: guest_look_for_var: %s\n%.*s\n",
640 test, name, value_size, (const char *) value); 679 test, name, value_size, (const char *) value);
641} 680}
@@ -656,7 +695,7 @@ guest_look_at_result (void *cls, int64_t result_code,
656{ 695{
657 struct ResultClosure *rcls = cls; 696 struct ResultClosure *rcls = cls;
658 697
659 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 698 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
660 "Test #%u: guest_look_at_result: %" PRId64 "\n", 699 "Test #%u: guest_look_at_result: %" PRId64 "\n",
661 test, result_code); 700 test, result_code);
662 GNUNET_assert (GNUNET_OK == result_code); 701 GNUNET_assert (GNUNET_OK == result_code);
@@ -677,7 +716,7 @@ guest_look_at_var (void *cls,
677 struct ResultClosure *rcls = cls; 716 struct ResultClosure *rcls = cls;
678 rcls->n++; 717 rcls->n++;
679 718
680 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 719 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
681 "Test #%u: guest_look_at_var: %s\n%.*s\n", 720 "Test #%u: guest_look_at_var: %s\n%.*s\n",
682 test ,name, value_size, (const char *) value); 721 test ,name, value_size, (const char *) value);
683} 722}
@@ -696,7 +735,7 @@ static void
696guest_recv_history_replay_latest_result (void *cls, int64_t result, 735guest_recv_history_replay_latest_result (void *cls, int64_t result,
697 const void *data, uint16_t data_size) 736 const void *data, uint16_t data_size)
698{ 737{
699 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 738 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
700 "Test #%u: Guest received latest history replay result " 739 "Test #%u: Guest received latest history replay result "
701 "(%" PRIu32 " messages, %" PRId64 " fragments):\n" 740 "(%" PRIu32 " messages, %" PRId64 " fragments):\n"
702 "%.*s\n", 741 "%.*s\n",
@@ -725,7 +764,7 @@ static void
725guest_recv_history_replay_result (void *cls, int64_t result, 764guest_recv_history_replay_result (void *cls, int64_t result,
726 const void *data, uint16_t data_size) 765 const void *data, uint16_t data_size)
727{ 766{
728 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 767 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
729 "Test #%u: Guest received history replay result: %" PRId64 "\n" 768 "Test #%u: Guest received history replay result: %" PRId64 "\n"
730 "%.*s\n", 769 "%.*s\n",
731 test, result, data_size, (const char *) data); 770 test, result, data_size, (const char *) data);
@@ -756,7 +795,7 @@ guest_recv_method (void *cls,
756 uint64_t message_id, 795 uint64_t message_id,
757 const char *method_name) 796 const char *method_name)
758{ 797{
759 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 798 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
760 "Test #%u: Guest received method for message ID %" PRIu64 ":\n" 799 "Test #%u: Guest received method for message ID %" PRIu64 ":\n"
761 "%s (flags: %x)\n", 800 "%s (flags: %x)\n",
762 test, message_id, method_name, ntohl (meth->flags)); 801 test, message_id, method_name, ntohl (meth->flags));
@@ -775,7 +814,7 @@ guest_recv_modifier (void *cls,
775 uint16_t value_size, 814 uint16_t value_size,
776 uint16_t full_value_size) 815 uint16_t full_value_size)
777{ 816{
778 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 817 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
779 "Test #%u: Guest received modifier for message ID %" PRIu64 ":\n" 818 "Test #%u: Guest received modifier for message ID %" PRIu64 ":\n"
780 "%c%s: %.*s (size: %u)\n", 819 "%c%s: %.*s (size: %u)\n",
781 test, message_id, oper, name, value_size, (const char *) value, value_size); 820 test, message_id, oper, name, value_size, (const char *) value, value_size);
@@ -793,7 +832,7 @@ guest_recv_mod_foo_bar (void *cls,
793 uint16_t value_size, 832 uint16_t value_size,
794 uint16_t full_value_size) 833 uint16_t full_value_size)
795{ 834{
796 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 835 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
797 "Test #%u: Guest received modifier matching _foo_bar for message ID %" PRIu64 ":\n" 836 "Test #%u: Guest received modifier matching _foo_bar for message ID %" PRIu64 ":\n"
798 "%c%s: %.*s (size: %u)\n", 837 "%c%s: %.*s (size: %u)\n",
799 test, message_id, oper, name, value_size, (const char *) value, value_size); 838 test, message_id, oper, name, value_size, (const char *) value, value_size);
@@ -811,7 +850,7 @@ guest_recv_data (void *cls,
811 const void *data, 850 const void *data,
812 uint16_t data_size) 851 uint16_t data_size)
813{ 852{
814 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 853 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
815 "Test #%u: Guest received data for message ID %" PRIu64 ":\n" 854 "Test #%u: Guest received data for message ID %" PRIu64 ":\n"
816 "%.*s\n", 855 "%.*s\n",
817 test, message_id, data_size, (const char *) data); 856 test, message_id, data_size, (const char *) data);
@@ -826,7 +865,7 @@ guest_recv_eom (void *cls,
826 uint64_t message_id, 865 uint64_t message_id,
827 uint8_t is_cancelled) 866 uint8_t is_cancelled)
828{ 867{
829 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 868 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
830 "Test #%u: Guest received end of message ID %" PRIu64 869 "Test #%u: Guest received end of message ID %" PRIu64
831 ", cancelled: %u\n", 870 ", cancelled: %u\n",
832 test, message_id, is_cancelled); 871 test, message_id, is_cancelled);
@@ -868,7 +907,7 @@ host_recv_method (void *cls,
868 uint64_t message_id, 907 uint64_t message_id,
869 const char *method_name) 908 const char *method_name)
870{ 909{
871 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 910 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
872 "Test #%u: Host received method for message ID %" PRIu64 ":\n" 911 "Test #%u: Host received method for message ID %" PRIu64 ":\n"
873 "%s\n", 912 "%s\n",
874 test, message_id, method_name); 913 test, message_id, method_name);
@@ -887,7 +926,7 @@ host_recv_modifier (void *cls,
887 uint16_t value_size, 926 uint16_t value_size,
888 uint16_t full_value_size) 927 uint16_t full_value_size)
889{ 928{
890 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 929 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
891 "Test #%u: Host received modifier for message ID %" PRIu64 ":\n" 930 "Test #%u: Host received modifier for message ID %" PRIu64 ":\n"
892 "%c%s: %.*s\n", 931 "%c%s: %.*s\n",
893 test, message_id, oper, name, value_size, (const char *) value); 932 test, message_id, oper, name, value_size, (const char *) value);
@@ -902,7 +941,7 @@ host_recv_data (void *cls,
902 const void *data, 941 const void *data,
903 uint16_t data_size) 942 uint16_t data_size)
904{ 943{
905 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 944 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
906 "Test #%u: Host received data for message ID %" PRIu64 ":\n" 945 "Test #%u: Host received data for message ID %" PRIu64 ":\n"
907 "%.*s\n", 946 "%.*s\n",
908 test, message_id, data_size, (const char *) data); 947 test, message_id, data_size, (const char *) data);
@@ -916,7 +955,7 @@ host_recv_eom (void *cls,
916 uint64_t message_id, 955 uint64_t message_id,
917 uint8_t is_cancelled) 956 uint8_t is_cancelled)
918{ 957{
919 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 958 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
920 "Test #%u: Host received end of message ID %" PRIu64 959 "Test #%u: Host received end of message ID %" PRIu64
921 ", cancelled: %u\n", 960 ", cancelled: %u\n",
922 test, message_id, is_cancelled); 961 test, message_id, is_cancelled);
@@ -981,7 +1020,7 @@ host_announce ()
981{ 1020{
982 test = TEST_HOST_ANNOUNCE; 1021 test = TEST_HOST_ANNOUNCE;
983 1022
984 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1023 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
985 "Test #%u: Host announcement.\n", test); 1024 "Test #%u: Host announcement.\n", test);
986 1025
987 tmit = (struct TransmitClosure) {}; 1026 tmit = (struct TransmitClosure) {};
@@ -1015,7 +1054,7 @@ host_announce2 ()
1015 1054
1016 test = TEST_HOST_ANNOUNCE2; 1055 test = TEST_HOST_ANNOUNCE2;
1017 1056
1018 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1057 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1019 "Test #%u: Host announcement 2.\n", test); 1058 "Test #%u: Host announcement 2.\n", test);
1020 1059
1021 tmit = (struct TransmitClosure) {}; 1060 tmit = (struct TransmitClosure) {};
@@ -1025,7 +1064,7 @@ host_announce2 ()
1025 GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, 1064 GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN,
1026 "_foo2_bar", DATA2ARG ("FOO BAR")); 1065 "_foo2_bar", DATA2ARG ("FOO BAR"));
1027 GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, 1066 GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN,
1028 "_foo2_bar", DATA2ARG ("FOO BAR BAZ")); 1067 "_foo2_bar_baz", DATA2ARG ("FOO BAR BAZ"));
1029 tmit.data[0] = "AAA BBB CCC "; 1068 tmit.data[0] = "AAA BBB CCC ";
1030 tmit.data[1] = "ABC DEF GHI JKL.\n"; 1069 tmit.data[1] = "ABC DEF GHI JKL.\n";
1031 tmit.data[2] = "TESTING ONE TWO THREE.\n"; 1070 tmit.data[2] = "TESTING ONE TWO THREE.\n";
@@ -1043,7 +1082,7 @@ guest_recv_entry_decision (void *cls,
1043 int is_admitted, 1082 int is_admitted,
1044 const struct GNUNET_PSYC_Message *entry_msg) 1083 const struct GNUNET_PSYC_Message *entry_msg)
1045{ 1084{
1046 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1085 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1047 "Test #%u: Guest received entry decision (try %u): %d.\n", 1086 "Test #%u: Guest received entry decision (try %u): %d.\n",
1048 test, join_req_count, is_admitted); 1087 test, join_req_count, is_admitted);
1049 1088
@@ -1068,7 +1107,8 @@ guest_recv_entry_decision (void *cls,
1068 { 1107 {
1069 case TEST_GUEST_RECV_ENTRY_DCSN_REFUSE: 1108 case TEST_GUEST_RECV_ENTRY_DCSN_REFUSE:
1070 GNUNET_assert (GNUNET_NO == is_admitted); 1109 GNUNET_assert (GNUNET_NO == is_admitted);
1071 guest_enter (); 1110 test = TEST_HOST_ANSWER_DOOR_ADMIT;
1111 GNUNET_SOCIAL_guest_disconnect (gst, &guest_enter, NULL);
1072 break; 1112 break;
1073 1113
1074 case TEST_GUEST_RECV_ENTRY_DCSN_ADMIT: 1114 case TEST_GUEST_RECV_ENTRY_DCSN_ADMIT:
@@ -1097,7 +1137,7 @@ host_answer_door (void *cls,
1097{ 1137{
1098 join_req_count++; 1138 join_req_count++;
1099 1139
1100 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1140 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1101 "Test #%u: Host received entry request from guest (try %u).\n", 1141 "Test #%u: Host received entry request from guest (try %u).\n",
1102 (uint8_t) test, join_req_count); 1142 (uint8_t) test, join_req_count);
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1118,7 +1158,7 @@ host_answer_door (void *cls,
1118 // fall through 1158 // fall through
1119 1159
1120 case TEST_GUEST_ENTER_BY_NAME: 1160 case TEST_GUEST_ENTER_BY_NAME:
1121 join_resp = GNUNET_PSYC_message_create ("_notice_place_admit", env, 1161 join_resp = GNUNET_PSYC_message_create ("_notice_place_admit", env,
1122 DATA2ARG ("Welcome, nym!")); 1162 DATA2ARG ("Welcome, nym!"));
1123 GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, join_resp); 1163 GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, join_resp);
1124 break; 1164 break;
@@ -1135,18 +1175,18 @@ guest_recv_local_enter (void *cls, int result,
1135 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, 1175 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
1136 uint64_t max_message_id) 1176 uint64_t max_message_id)
1137{ 1177{
1138 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1178 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1139 "Test #%u: Guest entered to local place: %d\n", 1179 "Test #%u: Guest entered local place: %d\n",
1140 test, result); 1180 test, result);
1141 GNUNET_assert (0 <= result); 1181 GNUNET_assert (GNUNET_OK == result);
1142} 1182}
1143 1183
1144 1184
1145static void 1185static void
1146guest_enter () 1186guest_enter ()
1147{ 1187{
1148 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1188 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1149 "Test #%u: Entering to place as guest.\n", test); 1189 "Test #%u: Entering place as guest.\n", test);
1150 1190
1151 struct GuestEnterMessage *emsg = &guest_enter_msg; 1191 struct GuestEnterMessage *emsg = &guest_enter_msg;
1152 1192
@@ -1177,8 +1217,8 @@ static void
1177guest_enter_by_name () 1217guest_enter_by_name ()
1178{ 1218{
1179 test = TEST_GUEST_ENTER_BY_NAME; 1219 test = TEST_GUEST_ENTER_BY_NAME;
1180 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1220 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1181 "Test #%u: Entering to place by name as guest.\n", test); 1221 "Test #%u: Entering place by name as guest.\n", test);
1182 1222
1183 struct GuestEnterMessage *emsg = &guest_enter_msg; 1223 struct GuestEnterMessage *emsg = &guest_enter_msg;
1184 1224
@@ -1222,7 +1262,7 @@ guest_init ()
1222 guest_recv_data, guest_recv_eom, NULL); 1262 guest_recv_data, guest_recv_eom, NULL);
1223 GNUNET_PSYC_slicer_modifier_add (guest_slicer, "_foo_bar", 1263 GNUNET_PSYC_slicer_modifier_add (guest_slicer, "_foo_bar",
1224 guest_recv_mod_foo_bar, &mod_foo_bar_rcls); 1264 guest_recv_mod_foo_bar, &mod_foo_bar_rcls);
1225 test = TEST_HOST_ANSWER_DOOR_ADMIT; 1265 test = TEST_HOST_ANSWER_DOOR_REFUSE;
1226 1266
1227 GNUNET_SOCIAL_zone_add_nym (app, guest_ego, "host", host_pub_key, 1267 GNUNET_SOCIAL_zone_add_nym (app, guest_ego, "host", host_pub_key,
1228 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES), 1268 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES),
@@ -1270,8 +1310,8 @@ host_entered (void *cls, int result,
1270{ 1310{
1271 place_pub_key = *home_pub_key; 1311 place_pub_key = *home_pub_key;
1272 GNUNET_CRYPTO_hash (&place_pub_key, sizeof (place_pub_key), &place_pub_hash); 1312 GNUNET_CRYPTO_hash (&place_pub_key, sizeof (place_pub_key), &place_pub_hash);
1273 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1313 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1274 "Test #%u: Host entered to place %s\n", 1314 "Test #%u: Host entered place %s\n",
1275 test, GNUNET_h2s (&place_pub_hash)); 1315 test, GNUNET_h2s (&place_pub_hash));
1276 guest_enter (); 1316 guest_enter ();
1277} 1317}
@@ -1285,8 +1325,8 @@ host_enter ()
1285 host_recv_method, host_recv_modifier, 1325 host_recv_method, host_recv_modifier,
1286 host_recv_data, host_recv_eom, NULL); 1326 host_recv_data, host_recv_eom, NULL);
1287 1327
1288 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1328 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1289 "Test #%u: Entering to place as host.\n", test); 1329 "Test #%u: Entering place as host.\n", test);
1290 test = TEST_HOST_ENTER; 1330 test = TEST_HOST_ENTER;
1291 hst = GNUNET_SOCIAL_host_enter (app, host_ego, 1331 hst = GNUNET_SOCIAL_host_enter (app, host_ego,
1292 GNUNET_PSYC_CHANNEL_PRIVATE, 1332 GNUNET_PSYC_CHANNEL_PRIVATE,
@@ -1306,6 +1346,8 @@ start_app_if_ready ()
1306 { 1346 {
1307 return; 1347 return;
1308 } 1348 }
1349 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1350 "starting app...\n");
1309 app = GNUNET_SOCIAL_app_connect (cfg, 1351 app = GNUNET_SOCIAL_app_connect (cfg,
1310 app_id, 1352 app_id,
1311 app_recv_ego, 1353 app_recv_ego,
@@ -1324,17 +1366,17 @@ identity_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego,
1324 { 1366 {
1325 if (ego == identity_host_ego) 1367 if (ego == identity_host_ego)
1326 { 1368 {
1327 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1369 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1328 "Host ego deleted\n"); 1370 "Host ego deleted\n");
1329 } 1371 }
1330 else if (ego == identity_guest_ego) 1372 else if (ego == identity_guest_ego)
1331 { 1373 {
1332 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1374 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1333 "Guest ego deleted\n"); 1375 "Guest ego deleted\n");
1334 } 1376 }
1335 else if (0 == strcmp (name, host_name)) 1377 else if (0 == strcmp (name, host_name))
1336 { 1378 {
1337 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1379 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1338 "Created ego %s\n", 1380 "Created ego %s\n",
1339 name); 1381 name);
1340 identity_host_ego = ego; 1382 identity_host_ego = ego;
@@ -1342,7 +1384,7 @@ identity_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego,
1342 } 1384 }
1343 else if (0 == strcmp (name, guest_name)) 1385 else if (0 == strcmp (name, guest_name))
1344 { 1386 {
1345 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1387 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1346 "Created guest ego %s\n", 1388 "Created guest ego %s\n",
1347 name); 1389 name);
1348 identity_guest_ego = ego; 1390 identity_guest_ego = ego;
@@ -1370,9 +1412,11 @@ run (void *cls,
1370#endif 1412#endif
1371{ 1413{
1372 cfg = c; 1414 cfg = c;
1415 res = 1;
1373 end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 1416 end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
1374 &end_badly, NULL); 1417 &end_badly, NULL);
1375 1418 GNUNET_SCHEDULER_add_shutdown (&end_shutdown,
1419 NULL);
1376 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer); 1420 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
1377 1421
1378 id = GNUNET_IDENTITY_connect (cfg, &identity_ego_cb, NULL); 1422 id = GNUNET_IDENTITY_connect (cfg, &identity_ego_cb, NULL);
diff --git a/src/social/test_social.conf b/src/social/test_social.conf
index e69de29bb..7cf858b1c 100644
--- a/src/social/test_social.conf
+++ b/src/social/test_social.conf
@@ -0,0 +1,19 @@
1@INLINE@ ../../contrib/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = /tmp/gnunet-test-social/
5
6[social]
7FORCESTART = YES
8
9[transport]
10PLUGINS = tcp
11
12[nat]
13DISABLEV6 = YES
14ENABLE_UPNP = NO
15BEHIND_NAT = NO
16ALLOW_NAT = NO
17INTERNAL_ADDRESS = 127.0.0.1
18EXTERNAL_ADDRESS = 127.0.0.1
19
diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c
index 0cb136b99..87e966a01 100644
--- a/src/statistics/gnunet-service-statistics.c
+++ b/src/statistics/gnunet-service-statistics.c
@@ -998,7 +998,9 @@ client_disconnect_cb (void *cls,
998 * 998 *
999 * @param cls NULL 999 * @param cls NULL
1000 * @param message the message found on disk 1000 * @param message the message found on disk
1001 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing 1001 * @return #GNUNET_OK on success,
1002 * #GNUNET_NO to stop further processing (no error)
1003 * #GNUNET_SYSERR to stop further processing with error
1002 */ 1004 */
1003static int 1005static int
1004inject_message (void *cls, 1006inject_message (void *cls,
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 94b981eee..e858e44b4 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -45,7 +45,7 @@ gnunet_service_testbed_SOURCES = \
45 gnunet-service-testbed_oc.c \ 45 gnunet-service-testbed_oc.c \
46 gnunet-service-testbed_cpustatus.c \ 46 gnunet-service-testbed_cpustatus.c \
47 gnunet-service-testbed_meminfo.c gnunet-service-testbed_meminfo.h \ 47 gnunet-service-testbed_meminfo.c gnunet-service-testbed_meminfo.h \
48 gnunet-service-testbed_barriers.c \ 48 gnunet-service-testbed_barriers.c gnunet-service-testbed_barriers.h \
49 gnunet-service-testbed_connectionpool.c gnunet-service-testbed_connectionpool.h 49 gnunet-service-testbed_connectionpool.c gnunet-service-testbed_connectionpool.h
50gnunet_service_testbed_LDADD = $(XLIB) \ 50gnunet_service_testbed_LDADD = $(XLIB) \
51 $(top_builddir)/src/util/libgnunetutil.la \ 51 $(top_builddir)/src/util/libgnunetutil.la \
diff --git a/src/testbed/gnunet-daemon-testbed-underlay.c b/src/testbed/gnunet-daemon-testbed-underlay.c
index 0b6c44710..3605e0384 100644
--- a/src/testbed/gnunet-daemon-testbed-underlay.c
+++ b/src/testbed/gnunet-daemon-testbed-underlay.c
@@ -165,7 +165,8 @@ check_access (void *cls, const struct GNUNET_PeerIdentity * pid)
165 165
166 166
167static int 167static int
168get_identity (unsigned int offset, struct GNUNET_PeerIdentity *id) 168get_identity (unsigned int offset,
169 struct GNUNET_PeerIdentity *id)
169{ 170{
170 struct GNUNET_CRYPTO_EddsaPrivateKey private_key; 171 struct GNUNET_CRYPTO_EddsaPrivateKey private_key;
171 172
@@ -174,7 +175,8 @@ get_identity (unsigned int offset, struct GNUNET_PeerIdentity *id)
174 GNUNET_memcpy (&private_key, 175 GNUNET_memcpy (&private_key,
175 hostkeys_data + (offset * GNUNET_TESTING_HOSTKEYFILESIZE), 176 hostkeys_data + (offset * GNUNET_TESTING_HOSTKEYFILESIZE),
176 GNUNET_TESTING_HOSTKEYFILESIZE); 177 GNUNET_TESTING_HOSTKEYFILESIZE);
177 GNUNET_CRYPTO_eddsa_key_get_public (&private_key, &id->public_key); 178 GNUNET_CRYPTO_eddsa_key_get_public (&private_key,
179 &id->public_key);
178 return GNUNET_OK; 180 return GNUNET_OK;
179} 181}
180 182
diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c
index 392f257dd..9601e7567 100644
--- a/src/testbed/gnunet-helper-testbed.c
+++ b/src/testbed/gnunet-helper-testbed.c
@@ -292,8 +292,9 @@ child_death_task (void *cls)
292 * 292 *
293 * @param cls identification of the client 293 * @param cls identification of the client
294 * @param message the actual message 294 * @param message the actual message
295 * 295 * @return #GNUNET_OK on success,
296 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing 296 * #GNUNET_NO to stop further processing (no error)
297 * #GNUNET_SYSERR to stop further processing with error
297 */ 298 */
298static int 299static int
299tokenizer_cb (void *cls, 300tokenizer_cb (void *cls,
@@ -359,7 +360,7 @@ tokenizer_cb (void *cls,
359 cfg = GNUNET_CONFIGURATION_create (); 360 cfg = GNUNET_CONFIGURATION_create ();
360 if (GNUNET_OK != 361 if (GNUNET_OK !=
361 GNUNET_CONFIGURATION_deserialize (cfg, 362 GNUNET_CONFIGURATION_deserialize (cfg,
362 config, 363 config,
363 ul_config_size, 364 ul_config_size,
364 NULL)) 365 NULL))
365 { 366 {
diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c
index 09849797c..11c45a0f5 100644
--- a/src/testbed/gnunet-service-testbed_oc.c
+++ b/src/testbed/gnunet-service-testbed_oc.c
@@ -261,7 +261,7 @@ struct OverlayConnectContext
261 enum OverlayConnectContextType type; 261 enum OverlayConnectContextType type;
262 262
263 /** 263 /**
264 * The id of the second peer which is has to connect to the first peer 264 * The id of the second peer which has to connect to the first peer
265 */ 265 */
266 uint32_t other_peer_id; 266 uint32_t other_peer_id;
267}; 267};
@@ -930,10 +930,10 @@ send_hello (void *cls)
930 other_peer_str); 930 other_peer_str);
931 GNUNET_free (other_peer_str); 931 GNUNET_free (other_peer_str);
932 lp2c->ohh = 932 lp2c->ohh =
933 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg, 933 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
934 occ->hello, 934 occ->hello,
935 &occ_hello_sent_cb, 935 &occ_hello_sent_cb,
936 occ); 936 occ);
937 if (NULL == lp2c->ohh) 937 if (NULL == lp2c->ohh)
938 { 938 {
939 GNUNET_break (0); 939 GNUNET_break (0);
@@ -1001,6 +1001,11 @@ p2_transport_connect (struct OverlayConnectContext *occ)
1001{ 1001{
1002 struct Peer *peer2; 1002 struct Peer *peer2;
1003 1003
1004 /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the
1005 HELLO! */
1006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1007 "Connecting to transport of peer %s to obtain HELLO\n",
1008 GNUNET_i2s (&occ->other_peer_identity));
1004 GNUNET_assert (NULL == occ->emsg); 1009 GNUNET_assert (NULL == occ->emsg);
1005 GNUNET_assert (NULL != occ->hello); 1010 GNUNET_assert (NULL != occ->hello);
1006 GNUNET_assert (NULL == occ->ghh); 1011 GNUNET_assert (NULL == occ->ghh);
diff --git a/src/testbed/gnunet-testbed-profiler.c b/src/testbed/gnunet-testbed-profiler.c
index 9829bbf0d..0fa6d8172 100644
--- a/src/testbed/gnunet-testbed-profiler.c
+++ b/src/testbed/gnunet-testbed-profiler.c
@@ -175,9 +175,7 @@ controller_event_cb (void *cls,
175 { 175 {
176 printf ("\nAborting due to very high failure rate\n"); 176 printf ("\nAborting due to very high failure rate\n");
177 print_overlay_links_summary (); 177 print_overlay_links_summary ();
178 if (NULL != abort_task) 178 GNUNET_SCHEDULER_shutdown ();
179 GNUNET_SCHEDULER_cancel (abort_task);
180 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
181 return; 179 return;
182 } 180 }
183 } 181 }
@@ -260,11 +258,12 @@ run (void *cls, char *const *args, const char *cfgfile,
260 event_mask = 0; 258 event_mask = 0;
261 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); 259 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
262 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); 260 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
263 GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, controller_event_cb, 261 GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask,
264 NULL, &test_run, NULL); 262 &controller_event_cb, NULL,
263 &test_run, NULL);
265 abort_task = 264 abort_task =
266 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_abort, 265 GNUNET_SCHEDULER_add_shutdown (&do_abort,
267 NULL); 266 NULL);
268} 267}
269 268
270 269
@@ -310,6 +309,8 @@ main (int argc, char *const *argv)
310 const char *binaryHelp = "gnunet-testbed-profiler [OPTIONS]"; 309 const char *binaryHelp = "gnunet-testbed-profiler [OPTIONS]";
311 int ret; 310 int ret;
312 311
312 unsetenv ("XDG_DATA_HOME");
313 unsetenv ("XDG_CONFIG_HOME");
313 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 314 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
314 return 2; 315 return 2;
315 result = GNUNET_SYSERR; 316 result = GNUNET_SYSERR;
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index d65da6bb6..e8c1f5d4a 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -295,7 +295,7 @@ noinst_LTLIBRARIES = \
295 libgnunet_plugin_transport_template.la 295 libgnunet_plugin_transport_template.la
296 296
297libgnunet_plugin_transport_tcp_la_SOURCES = \ 297libgnunet_plugin_transport_tcp_la_SOURCES = \
298 plugin_transport_tcp.c 298 plugin_transport_tcp.c
299libgnunet_plugin_transport_tcp_la_LIBADD = \ 299libgnunet_plugin_transport_tcp_la_LIBADD = \
300 $(top_builddir)/src/hello/libgnunethello.la \ 300 $(top_builddir)/src/hello/libgnunethello.la \
301 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 301 $(top_builddir)/src/statistics/libgnunetstatistics.la \
@@ -1330,7 +1330,6 @@ test_transport_api_monitor_peers_peer2.conf\
1330test_transport_api_monitor_validation_peer1.conf\ 1330test_transport_api_monitor_validation_peer1.conf\
1331test_transport_api_monitor_validation_peer2.conf\ 1331test_transport_api_monitor_validation_peer2.conf\
1332test_transport_defaults.conf\ 1332test_transport_defaults.conf\
1333test_transport_startonly.conf\
1334test_transport_api_disconnect_tcp_peer1.conf\ 1333test_transport_api_disconnect_tcp_peer1.conf\
1335test_transport_api_disconnect_tcp_peer2.conf\ 1334test_transport_api_disconnect_tcp_peer2.conf\
1336test_transport_api_timeout_http_peer1.conf\ 1335test_transport_api_timeout_http_peer1.conf\
@@ -1350,4 +1349,8 @@ test_transport_api_http_reverse_peer2.conf \
1350perf_tcp_peer1.conf \ 1349perf_tcp_peer1.conf \
1351perf_tcp_peer2.conf \ 1350perf_tcp_peer2.conf \
1352test_transport_api_slow_ats_peer1.conf \ 1351test_transport_api_slow_ats_peer1.conf \
1353test_transport_api_slow_ats_peer2.conf 1352test_transport_api_slow_ats_peer2.conf \
1353 tcp_connection_legacy.c \
1354 tcp_server_mst_legacy.c \
1355 tcp_server_legacy.c \
1356 tcp_service_legacy.c
diff --git a/src/transport/gnunet-helper-transport-wlan-dummy.c b/src/transport/gnunet-helper-transport-wlan-dummy.c
index 63ed9c4b7..f02d8bdd7 100644
--- a/src/transport/gnunet-helper-transport-wlan-dummy.c
+++ b/src/transport/gnunet-helper-transport-wlan-dummy.c
@@ -121,6 +121,9 @@ send_mac_to_plugin (char *buffer, struct GNUNET_TRANSPORT_WLAN_MacAddress *mac)
121 * 121 *
122 * @param cls the 'struct SendBuffer' to copy the converted message to 122 * @param cls the 'struct SendBuffer' to copy the converted message to
123 * @param hdr inbound message from the FIFO 123 * @param hdr inbound message from the FIFO
124 * @return #GNUNET_OK on success,
125 * #GNUNET_NO to stop further processing (no error)
126 * #GNUNET_SYSERR to stop further processing with error
124 */ 127 */
125static int 128static int
126stdin_send (void *cls, 129stdin_send (void *cls,
@@ -167,6 +170,9 @@ stdin_send (void *cls,
167 * 170 *
168 * @param cls the 'struct SendBuffer' to copy to 171 * @param cls the 'struct SendBuffer' to copy to
169 * @param hdr the message we received to copy to the buffer 172 * @param hdr the message we received to copy to the buffer
173 * @return #GNUNET_OK on success,
174 * #GNUNET_NO to stop further processing (no error)
175 * #GNUNET_SYSERR to stop further processing with error
170 */ 176 */
171static int 177static int
172file_in_send (void *cls, 178file_in_send (void *cls,
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 6b354df98..124260c41 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -688,6 +688,8 @@ handle_client_hello (void *cls,
688{ 688{
689 struct TransportClient *tc = cls; 689 struct TransportClient *tc = cls;
690 690
691 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
692 "Received HELLO message\n");
691 GST_validation_handle_hello (message); 693 GST_validation_handle_hello (message);
692 GNUNET_SERVICE_client_continue (tc->client); 694 GNUNET_SERVICE_client_continue (tc->client);
693} 695}
@@ -2802,7 +2804,7 @@ run (void *cls,
2802 GNUNET_assert (NULL != GST_my_private_key); 2804 GNUNET_assert (NULL != GST_my_private_key);
2803 2805
2804 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 2806 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2805 "My identity is `%4s'\n", 2807 "My identity is `%s'\n",
2806 GNUNET_i2s_full (&GST_my_identity)); 2808 GNUNET_i2s_full (&GST_my_identity));
2807 2809
2808 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 2810 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c
index 27c3c7041..cd5aeb5e2 100644
--- a/src/transport/gnunet-service-transport_validation.c
+++ b/src/transport/gnunet-service-transport_validation.c
@@ -1347,6 +1347,9 @@ GST_validation_handle_address (const struct GNUNET_HELLO_Address *address)
1347 if (NULL == papi) 1347 if (NULL == papi)
1348 { 1348 {
1349 /* This plugin is currently unvailable ... ignore */ 1349 /* This plugin is currently unvailable ... ignore */
1350 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1351 "No plugin available for %s\n",
1352 address->transport_name);
1350 return; 1353 return;
1351 } 1354 }
1352 ve = find_validation_entry (address); 1355 ve = find_validation_entry (address);
@@ -1358,6 +1361,13 @@ GST_validation_handle_address (const struct GNUNET_HELLO_Address *address)
1358 GNUNET_i2s (&ve->address->peer)); 1361 GNUNET_i2s (&ve->address->peer));
1359 ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve); 1362 ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve);
1360 } 1363 }
1364 else
1365 {
1366 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1367 "Validation already running for address `%s' of %s\n",
1368 GST_plugins_a2s (ve->address),
1369 GNUNET_i2s (&ve->address->peer));
1370 }
1361} 1371}
1362 1372
1363 1373
@@ -1657,6 +1667,9 @@ GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello)
1657 sizeof (struct GNUNET_PeerIdentity))) 1667 sizeof (struct GNUNET_PeerIdentity)))
1658 { 1668 {
1659 /* got our own HELLO, how boring */ 1669 /* got our own HELLO, how boring */
1670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1671 "Validation received our own HELLO (%s), ignoring\n",
1672 GNUNET_i2s (&pid));
1660 return GNUNET_OK; 1673 return GNUNET_OK;
1661 } 1674 }
1662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c
index d9fade44f..6a9c1b0ba 100644
--- a/src/transport/plugin_transport_http_server.c
+++ b/src/transport/plugin_transport_http_server.c
@@ -1651,7 +1651,7 @@ server_send_callback (void *cls,
1651 * 1651 *
1652 * @param cls current session as closure 1652 * @param cls current session as closure
1653 * @param message the message to be forwarded to transport service 1653 * @param message the message to be forwarded to transport service
1654 * @return #GNUNET_OK 1654 * @return #GNUNET_OK (all OK)
1655 */ 1655 */
1656static int 1656static int
1657server_receive_mst_cb (void *cls, 1657server_receive_mst_cb (void *cls,
diff --git a/src/util/client.c b/src/util/client.c
index 3d74bff33..e5bf7e176 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -261,14 +261,27 @@ transmit_ready (void *cls)
261 pos = (const char *) cstate->msg; 261 pos = (const char *) cstate->msg;
262 len = ntohs (cstate->msg->size); 262 len = ntohs (cstate->msg->size);
263 GNUNET_assert (cstate->msg_off < len); 263 GNUNET_assert (cstate->msg_off < len);
264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
265 "client: message of type %u trying to send with socket %p (MQ: %p\n",
266 ntohs(cstate->msg->type),
267 cstate->sock,
268 cstate->mq);
269
264 RETRY: 270 RETRY:
265 ret = GNUNET_NETWORK_socket_send (cstate->sock, 271 ret = GNUNET_NETWORK_socket_send (cstate->sock,
266 &pos[cstate->msg_off], 272 &pos[cstate->msg_off],
267 len - cstate->msg_off); 273 len - cstate->msg_off);
268 if (-1 == ret) 274 if (-1 == ret)
269 { 275 {
270 if (EINTR == errno) 276 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
277 "client: error during sending message of type %u\n",
278 ntohs(cstate->msg->type));
279 if (EINTR == errno){
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
281 "client: retrying message of type %u\n",
282 ntohs(cstate->msg->type));
271 goto RETRY; 283 goto RETRY;
284 }
272 GNUNET_MQ_inject_error (cstate->mq, 285 GNUNET_MQ_inject_error (cstate->mq,
273 GNUNET_MQ_ERROR_WRITE); 286 GNUNET_MQ_ERROR_WRITE);
274 return; 287 return;
@@ -277,6 +290,9 @@ transmit_ready (void *cls)
277 cstate->msg_off += ret; 290 cstate->msg_off += ret;
278 if (cstate->msg_off < len) 291 if (cstate->msg_off < len)
279 { 292 {
293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
294 "client: rescheduling message of type %u\n",
295 ntohs(cstate->msg->type));
280 cstate->send_task 296 cstate->send_task
281 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 297 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
282 cstate->sock, 298 cstate->sock,
@@ -286,6 +302,9 @@ transmit_ready (void *cls)
286 GNUNET_MQ_impl_send_in_flight (cstate->mq); 302 GNUNET_MQ_impl_send_in_flight (cstate->mq);
287 return; 303 return;
288 } 304 }
305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
306 "client: sending message of type %u successful\n",
307 ntohs(cstate->msg->type));
289 cstate->msg = NULL; 308 cstate->msg = NULL;
290 GNUNET_MQ_impl_send_continue (cstate->mq); 309 GNUNET_MQ_impl_send_continue (cstate->mq);
291} 310}
@@ -297,7 +316,9 @@ transmit_ready (void *cls)
297 * 316 *
298 * @param cls the `struct ClientState` 317 * @param cls the `struct ClientState`
299 * @param msg message we received. 318 * @param msg message we received.
300 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing 319 * @return #GNUNET_OK on success,
320 * #GNUNET_NO to stop further processing due to disconnect (no error)
321 * #GNUNET_SYSERR to stop further processing due to error
301 */ 322 */
302static int 323static int
303recv_message (void *cls, 324recv_message (void *cls,
@@ -306,7 +327,7 @@ recv_message (void *cls,
306 struct ClientState *cstate = cls; 327 struct ClientState *cstate = cls;
307 328
308 if (GNUNET_YES == cstate->in_destroy) 329 if (GNUNET_YES == cstate->in_destroy)
309 return GNUNET_SYSERR; 330 return GNUNET_NO;
310 LOG (GNUNET_ERROR_TYPE_DEBUG, 331 LOG (GNUNET_ERROR_TYPE_DEBUG,
311 "Received message of type %u and size %u from %s\n", 332 "Received message of type %u and size %u from %s\n",
312 ntohs (msg->type), 333 ntohs (msg->type),
@@ -315,7 +336,7 @@ recv_message (void *cls,
315 GNUNET_MQ_inject_message (cstate->mq, 336 GNUNET_MQ_inject_message (cstate->mq,
316 msg); 337 msg);
317 if (GNUNET_YES == cstate->in_destroy) 338 if (GNUNET_YES == cstate->in_destroy)
318 return GNUNET_SYSERR; 339 return GNUNET_NO;
319 return GNUNET_OK; 340 return GNUNET_OK;
320} 341}
321 342
@@ -371,8 +392,12 @@ connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
371 GNUNET_SCHEDULER_cancel (cstate->recv_task); 392 GNUNET_SCHEDULER_cancel (cstate->recv_task);
372 if (NULL != cstate->retry_task) 393 if (NULL != cstate->retry_task)
373 GNUNET_SCHEDULER_cancel (cstate->retry_task); 394 GNUNET_SCHEDULER_cancel (cstate->retry_task);
374 if (NULL != cstate->sock) 395 if (NULL != cstate->sock){
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
397 "client: destroying socket: %p\n",
398 cstate->sock);
375 GNUNET_NETWORK_socket_close (cstate->sock); 399 GNUNET_NETWORK_socket_close (cstate->sock);
400 }
376 cancel_aps (cstate); 401 cancel_aps (cstate);
377 GNUNET_free (cstate->service_name); 402 GNUNET_free (cstate->service_name);
378 GNUNET_free_non_null (cstate->hostname); 403 GNUNET_free_non_null (cstate->hostname);
@@ -794,8 +819,12 @@ connection_client_send_impl (struct GNUNET_MQ_Handle *mq,
794 GNUNET_assert (NULL == cstate->send_task); 819 GNUNET_assert (NULL == cstate->send_task);
795 cstate->msg = msg; 820 cstate->msg = msg;
796 cstate->msg_off = 0; 821 cstate->msg_off = 0;
797 if (NULL == cstate->sock) 822 if (NULL == cstate->sock){
823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
824 "client: message of type %u waiting for socket\n",
825 ntohs(msg->type));
798 return; /* still waiting for connection */ 826 return; /* still waiting for connection */
827 }
799 cstate->send_task 828 cstate->send_task
800 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 829 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
801 cstate->sock, 830 cstate->sock,
diff --git a/src/util/mq.c b/src/util/mq.c
index 90b2aa968..8d71359ac 100644
--- a/src/util/mq.c
+++ b/src/util/mq.c
@@ -357,6 +357,12 @@ GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
357 } 357 }
358 GNUNET_assert (NULL == mq->envelope_head); 358 GNUNET_assert (NULL == mq->envelope_head);
359 mq->current_envelope = ev; 359 mq->current_envelope = ev;
360
361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
362 "mq: sending message of type %u, queue empty (MQ: %p)\n",
363 ntohs(ev->mh->type),
364 mq);
365
360 mq->send_impl (mq, 366 mq->send_impl (mq,
361 ev->mh, 367 ev->mh,
362 mq->impl_state); 368 mq->impl_state);
@@ -452,6 +458,11 @@ impl_send_continue (void *cls)
452 GNUNET_CONTAINER_DLL_remove (mq->envelope_head, 458 GNUNET_CONTAINER_DLL_remove (mq->envelope_head,
453 mq->envelope_tail, 459 mq->envelope_tail,
454 mq->current_envelope); 460 mq->current_envelope);
461
462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
463 "mq: sending message of type %u from queue\n",
464 ntohs(mq->current_envelope->mh->type));
465
455 mq->send_impl (mq, 466 mq->send_impl (mq,
456 mq->current_envelope->mh, 467 mq->current_envelope->mh,
457 mq->impl_state); 468 mq->impl_state);
@@ -840,6 +851,9 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq)
840 ev); 851 ev);
841 GNUNET_assert (0 < mq->queue_length); 852 GNUNET_assert (0 < mq->queue_length);
842 mq->queue_length--; 853 mq->queue_length--;
854 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
855 "MQ destroy drops message of type %u\n",
856 ntohs (ev->mh->type));
843 GNUNET_MQ_discard (ev); 857 GNUNET_MQ_discard (ev);
844 } 858 }
845 if (NULL != mq->current_envelope) 859 if (NULL != mq->current_envelope)
@@ -847,6 +861,9 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq)
847 /* we can only discard envelopes that 861 /* we can only discard envelopes that
848 * are not queued! */ 862 * are not queued! */
849 mq->current_envelope->parent_queue = NULL; 863 mq->current_envelope->parent_queue = NULL;
864 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
865 "MQ destroy drops current message of type %u\n",
866 ntohs (mq->current_envelope->mh->type));
850 GNUNET_MQ_discard (mq->current_envelope); 867 GNUNET_MQ_discard (mq->current_envelope);
851 mq->current_envelope = NULL; 868 mq->current_envelope = NULL;
852 GNUNET_assert (0 < mq->queue_length); 869 GNUNET_assert (0 < mq->queue_length);
@@ -928,6 +945,11 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev)
928 GNUNET_CONTAINER_DLL_remove (mq->envelope_head, 945 GNUNET_CONTAINER_DLL_remove (mq->envelope_head,
929 mq->envelope_tail, 946 mq->envelope_tail,
930 mq->current_envelope); 947 mq->current_envelope);
948
949 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
950 "mq: sending canceled message of type %u queue\n",
951 ntohs(ev->mh->type));
952
931 mq->send_impl (mq, 953 mq->send_impl (mq,
932 mq->current_envelope->mh, 954 mq->current_envelope->mh,
933 mq->impl_state); 955 mq->impl_state);
diff --git a/src/util/mst.c b/src/util/mst.c
index 0d90c5d10..5e472965f 100644
--- a/src/util/mst.c
+++ b/src/util/mst.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2010, 2016 GNUnet e.V. 3 Copyright (C) 2010, 2016, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -126,6 +126,7 @@ GNUNET_MST_from_buffer (struct GNUNET_MessageStreamTokenizer *mst,
126 int need_align; 126 int need_align;
127 unsigned long offset; 127 unsigned long offset;
128 int ret; 128 int ret;
129 int cbret;
129 130
130 GNUNET_assert (mst->off <= mst->pos); 131 GNUNET_assert (mst->off <= mst->pos);
131 GNUNET_assert (mst->pos <= mst->curr_buf); 132 GNUNET_assert (mst->pos <= mst->curr_buf);
@@ -229,9 +230,17 @@ do_align:
229 if (one_shot == GNUNET_YES) 230 if (one_shot == GNUNET_YES)
230 one_shot = GNUNET_SYSERR; 231 one_shot = GNUNET_SYSERR;
231 mst->off += want; 232 mst->off += want;
232 if (GNUNET_SYSERR == mst->cb (mst->cb_cls, 233 if (GNUNET_OK !=
233 hdr)) 234 (cbret = mst->cb (mst->cb_cls,
235 hdr)))
236 {
237 if (GNUNET_SYSERR == cbret)
238 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
239 "Failure processing message of type %u and size %u\n",
240 ntohs (hdr->type),
241 ntohs (hdr->size));
234 return GNUNET_SYSERR; 242 return GNUNET_SYSERR;
243 }
235 if (mst->off == mst->pos) 244 if (mst->off == mst->pos)
236 { 245 {
237 /* reset to beginning of buffer, it's free right now! */ 246 /* reset to beginning of buffer, it's free right now! */
@@ -271,9 +280,17 @@ do_align:
271 } 280 }
272 if (one_shot == GNUNET_YES) 281 if (one_shot == GNUNET_YES)
273 one_shot = GNUNET_SYSERR; 282 one_shot = GNUNET_SYSERR;
274 if (GNUNET_SYSERR == mst->cb (mst->cb_cls, 283 if (GNUNET_OK !=
275 hdr)) 284 (cbret = mst->cb (mst->cb_cls,
285 hdr)))
286 {
287 if (GNUNET_SYSERR == cbret)
288 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
289 "Failure processing message of type %u and size %u\n",
290 ntohs (hdr->type),
291 ntohs (hdr->size));
276 return GNUNET_SYSERR; 292 return GNUNET_SYSERR;
293 }
277 buf += want; 294 buf += want;
278 size -= want; 295 size -= want;
279 } 296 }
diff --git a/src/util/network.c b/src/util/network.c
index 942288613..cf5ef3e00 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -1223,7 +1223,7 @@ GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1223 * @return POSIX file descriptor 1223 * @return POSIX file descriptor
1224 */ 1224 */
1225int 1225int
1226GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc) 1226GNUNET_NETWORK_get_fd (const struct GNUNET_NETWORK_Handle *desc)
1227{ 1227{
1228 return desc->fd; 1228 return desc->fd;
1229} 1229}
@@ -1236,7 +1236,7 @@ GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1236 * @return sockaddr 1236 * @return sockaddr
1237 */ 1237 */
1238struct sockaddr* 1238struct sockaddr*
1239GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc) 1239GNUNET_NETWORK_get_addr (const struct GNUNET_NETWORK_Handle *desc)
1240{ 1240{
1241 return desc->addr; 1241 return desc->addr;
1242} 1242}
@@ -1249,7 +1249,7 @@ GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1249 * @return socklen_t for sockaddr 1249 * @return socklen_t for sockaddr
1250 */ 1250 */
1251socklen_t 1251socklen_t
1252GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc) 1252GNUNET_NETWORK_get_addrlen (const struct GNUNET_NETWORK_Handle *desc)
1253{ 1253{
1254 return desc->addrlen; 1254 return desc->addrlen;
1255} 1255}
diff --git a/src/util/program.c b/src/util/program.c
index 92a9750f3..233792387 100644
--- a/src/util/program.c
+++ b/src/util/program.c
@@ -69,6 +69,16 @@ struct CommandContext
69 69
70 70
71/** 71/**
72 * task run when the scheduler shuts down
73 */
74static void
75shutdown_task (void *cls)
76{
77 GNUNET_SPEEDUP_stop_ ();
78}
79
80
81/**
72 * Initial task called by the scheduler for each 82 * Initial task called by the scheduler for each
73 * program. Runs the program-specific main task. 83 * program. Runs the program-specific main task.
74 */ 84 */
@@ -78,6 +88,7 @@ program_main (void *cls)
78 struct CommandContext *cc = cls; 88 struct CommandContext *cc = cls;
79 89
80 GNUNET_SPEEDUP_start_(cc->cfg); 90 GNUNET_SPEEDUP_start_(cc->cfg);
91 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
81 GNUNET_RESOLVER_connect (cc->cfg); 92 GNUNET_RESOLVER_connect (cc->cfg);
82 cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg); 93 cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg);
83} 94}
@@ -306,7 +317,6 @@ GNUNET_PROGRAM_run2 (int argc, char *const *argv, const char *binaryName,
306 } 317 }
307 ret = GNUNET_OK; 318 ret = GNUNET_OK;
308 cleanup: 319 cleanup:
309 GNUNET_SPEEDUP_stop_ ();
310 GNUNET_CONFIGURATION_destroy (cfg); 320 GNUNET_CONFIGURATION_destroy (cfg);
311 GNUNET_free_non_null (cc.cfgfile); 321 GNUNET_free_non_null (cc.cfgfile);
312 GNUNET_free (cfg_fn); 322 GNUNET_free (cfg_fn);
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 540a60557..b96e4e6c4 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -89,12 +89,6 @@ struct GNUNET_SCHEDULER_Handle
89 * @deprecated 89 * @deprecated
90 */ 90 */
91 struct GNUNET_NETWORK_FDSet *ws; 91 struct GNUNET_NETWORK_FDSet *ws;
92
93 /**
94 * Driver we used for the event loop.
95 */
96 const struct GNUNET_SCHEDULER_Driver *driver;
97
98}; 92};
99 93
100 94
@@ -124,36 +118,40 @@ struct GNUNET_SCHEDULER_Task
124 void *callback_cls; 118 void *callback_cls;
125 119
126 /** 120 /**
127 * Handle to the scheduler's state. 121 * Information about which FDs are ready for this task (and why).
128 */ 122 */
129 const struct GNUNET_SCHEDULER_Handle *sh; 123 struct GNUNET_SCHEDULER_FdInfo *fds;
130 124
131 /** 125 /**
132 * Set of file descriptors this task is waiting 126 * Storage location used for @e fds if we want to avoid
133 * for for reading. Once ready, this is updated 127 * a separate malloc() call in the common case that this
134 * to reflect the set of file descriptors ready 128 * task is only about a single FD.
135 * for operation.
136 */ 129 */
137 struct GNUNET_NETWORK_FDSet *read_set; 130 struct GNUNET_SCHEDULER_FdInfo fdx;
138 131
139 /** 132 /**
140 * Set of file descriptors this task is waiting for for writing. 133 * Size of the @e fds array.
141 * Once ready, this is updated to reflect the set of file
142 * descriptors ready for operation.
143 */ 134 */
144 struct GNUNET_NETWORK_FDSet *write_set; 135 unsigned int fds_len;
145 136
146 /** 137 /**
147 * Information about which FDs are ready for this task (and why). 138 * if this task is related to multiple FDs this array contains
139 * all FdInfo structs that were marked as ready by calling
140 * #GNUNET_SCHEDULER_task_ready
148 */ 141 */
149 const struct GNUNET_SCHEDULER_FdInfo *fds; 142 struct GNUNET_SCHEDULER_FdInfo *ready_fds;
150 143
151 /** 144 /**
152 * Storage location used for @e fds if we want to avoid 145 * Size of the @e ready_fds array
153 * a separate malloc() call in the common case that this
154 * task is only about a single FD.
155 */ 146 */
156 struct GNUNET_SCHEDULER_FdInfo fdx; 147 unsigned int ready_fds_len;
148
149 /**
150 * Do we own the network and file handles referenced by the FdInfo
151 * structs in the fds array. This will only be GNUNET_YES if the
152 * task was created by the #GNUNET_SCHEDULER_add_select function.
153 */
154 int own_handles;
157 155
158 /** 156 /**
159 * Absolute timeout value for the task, or 157 * Absolute timeout value for the task, or
@@ -169,11 +167,6 @@ struct GNUNET_SCHEDULER_Task
169#endif 167#endif
170 168
171 /** 169 /**
172 * Size of the @e fds array.
173 */
174 unsigned int fds_len;
175
176 /**
177 * Why is the task ready? Set after task is added to ready queue. 170 * Why is the task ready? Set after task is added to ready queue.
178 * Initially set to zero. All reasons that have already been 171 * Initially set to zero. All reasons that have already been
179 * satisfied (i.e. read or write ready) will be set over time. 172 * satisfied (i.e. read or write ready) will be set over time.
@@ -224,11 +217,72 @@ struct GNUNET_SCHEDULER_Task
224 int num_backtrace_strings; 217 int num_backtrace_strings;
225#endif 218#endif
226 219
220};
221
222
223/**
224 * A struct representing an event the select driver is waiting for
225 */
226struct Scheduled
227{
228 struct Scheduled *prev;
229
230 struct Scheduled *next;
231
232 /**
233 * the task, the event is related to
234 */
235 struct GNUNET_SCHEDULER_Task *task;
236
237 /**
238 * information about the network socket / file descriptor where
239 * the event is expected to occur
240 */
241 struct GNUNET_SCHEDULER_FdInfo *fdi;
242
243 /**
244 * the event types (multiple event types can be ORed) the select
245 * driver is expected to wait for
246 */
247 enum GNUNET_SCHEDULER_EventType et;
248};
249
250
251/**
252 * Driver context used by GNUNET_SCHEDULER_run
253 */
254struct DriverContext
255{
256 /**
257 * the head of a DLL containing information about the events the
258 * select driver is waiting for
259 */
260 struct Scheduled *scheduled_head;
227 261
262 /**
263 * the tail of a DLL containing information about the events the
264 * select driver is waiting for
265 */
266 struct Scheduled *scheduled_tail;
267
268 /**
269 * the time until the select driver will wake up again (after
270 * calling select)
271 */
272 struct GNUNET_TIME_Relative timeout;
228}; 273};
229 274
230 275
231/** 276/**
277 * The driver used for the event loop. Will be handed over to
278 * the scheduler in #GNUNET_SCHEDULER_run_from_driver(), peristed
279 * there in this variable for later use in functions like
280 * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and
281 * #GNUNET_SCHEDULER_cancel().
282 */
283static const struct GNUNET_SCHEDULER_Driver *scheduler_driver;
284
285/**
232 * Head of list of tasks waiting for an event. 286 * Head of list of tasks waiting for an event.
233 */ 287 */
234static struct GNUNET_SCHEDULER_Task *pending_head; 288static struct GNUNET_SCHEDULER_Task *pending_head;
@@ -330,6 +384,11 @@ static struct GNUNET_SCHEDULER_TaskContext tc;
330 */ 384 */
331static void *scheduler_select_cls; 385static void *scheduler_select_cls;
332 386
387/**
388 * Scheduler handle used for the driver functions
389 */
390static struct GNUNET_SCHEDULER_Handle sh;
391
333 392
334/** 393/**
335 * Sets the select function to use in the scheduler (scheduler_select). 394 * Sets the select function to use in the scheduler (scheduler_select).
@@ -364,115 +423,44 @@ check_priority (enum GNUNET_SCHEDULER_Priority p)
364 423
365 424
366/** 425/**
367 * Update all sets and timeout for select. 426 * chooses the nearest timeout from all pending tasks, to be used
368 * 427 * to tell the driver the next wakeup time (using its set_wakeup
369 * @param rs read-set, set to all FDs we would like to read (updated) 428 * callback)
370 * @param ws write-set, set to all FDs we would like to write (updated)
371 * @param timeout next timeout (updated)
372 */ 429 */
373static void 430struct GNUNET_TIME_Absolute
374update_sets (struct GNUNET_NETWORK_FDSet *rs, 431get_timeout ()
375 struct GNUNET_NETWORK_FDSet *ws,
376 struct GNUNET_TIME_Relative *timeout)
377{ 432{
378 struct GNUNET_SCHEDULER_Task *pos; 433 struct GNUNET_SCHEDULER_Task *pos;
379 struct GNUNET_TIME_Absolute now; 434 struct GNUNET_TIME_Absolute now;
380 struct GNUNET_TIME_Relative to; 435 struct GNUNET_TIME_Absolute timeout;
381 436
382 now = GNUNET_TIME_absolute_get ();
383 pos = pending_timeout_head; 437 pos = pending_timeout_head;
438 now = GNUNET_TIME_absolute_get ();
439 timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
384 if (NULL != pos) 440 if (NULL != pos)
385 { 441 {
386 to = GNUNET_TIME_absolute_get_difference (now, pos->timeout);
387 if (timeout->rel_value_us > to.rel_value_us)
388 *timeout = to;
389 if (0 != pos->reason) 442 if (0 != pos->reason)
390 *timeout = GNUNET_TIME_UNIT_ZERO; 443 {
444 timeout = now;
445 }
446 else
447 {
448 timeout = pos->timeout;
449 }
391 } 450 }
392 for (pos = pending_head; NULL != pos; pos = pos->next) 451 for (pos = pending_head; NULL != pos; pos = pos->next)
393 { 452 {
394 if (pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) 453 if (0 != pos->reason)
395 { 454 {
396 to = GNUNET_TIME_absolute_get_difference (now, pos->timeout); 455 timeout = now;
397 if (timeout->rel_value_us > to.rel_value_us) 456 }
398 *timeout = to; 457 else if ((pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
458 (timeout.abs_value_us > pos->timeout.abs_value_us))
459 {
460 timeout = pos->timeout;
399 } 461 }
400 if (-1 != pos->read_fd)
401 GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd);
402 if (-1 != pos->write_fd)
403 GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd);
404 if (NULL != pos->read_set)
405 GNUNET_NETWORK_fdset_add (rs, pos->read_set);
406 if (NULL != pos->write_set)
407 GNUNET_NETWORK_fdset_add (ws, pos->write_set);
408 if (0 != pos->reason)
409 *timeout = GNUNET_TIME_UNIT_ZERO;
410 }
411}
412
413
414/**
415 * Check if the ready set overlaps with the set we want to have ready.
416 * If so, update the want set (set all FDs that are ready). If not,
417 * return #GNUNET_NO.
418 *
419 * @param ready set that is ready
420 * @param want set that we want to be ready
421 * @return #GNUNET_YES if there was some overlap
422 */
423static int
424set_overlaps (const struct GNUNET_NETWORK_FDSet *ready,
425 struct GNUNET_NETWORK_FDSet *want)
426{
427 if ((NULL == want) || (NULL == ready))
428 return GNUNET_NO;
429 if (GNUNET_NETWORK_fdset_overlap (ready, want))
430 {
431 /* copy all over (yes, there maybe unrelated bits,
432 * but this should not hurt well-written clients) */
433 GNUNET_NETWORK_fdset_copy (want, ready);
434 return GNUNET_YES;
435 } 462 }
436 return GNUNET_NO; 463 return timeout;
437}
438
439
440/**
441 * Check if the given task is eligible to run now.
442 * Also set the reason why it is eligible.
443 *
444 * @param task task to check if it is ready
445 * @param now the current time
446 * @param rs set of FDs ready for reading
447 * @param ws set of FDs ready for writing
448 * @return #GNUNET_YES if we can run it, #GNUNET_NO if not.
449 */
450static int
451is_ready (struct GNUNET_SCHEDULER_Task *task,
452 struct GNUNET_TIME_Absolute now,
453 const struct GNUNET_NETWORK_FDSet *rs,
454 const struct GNUNET_NETWORK_FDSet *ws)
455{
456 enum GNUNET_SCHEDULER_Reason reason;
457
458 reason = task->reason;
459 if (now.abs_value_us >= task->timeout.abs_value_us)
460 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
461 if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
462 (((task->read_fd != -1) &&
463 (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, task->read_fd))) ||
464 (set_overlaps (rs, task->read_set))))
465 reason |= GNUNET_SCHEDULER_REASON_READ_READY;
466 if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
467 (((task->write_fd != -1) &&
468 (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, task->write_fd)))
469 || (set_overlaps (ws, task->write_set))))
470 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY;
471 if (0 == reason)
472 return GNUNET_NO; /* not ready */
473 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE;
474 task->reason = reason;
475 return GNUNET_YES;
476} 464}
477 465
478 466
@@ -495,51 +483,6 @@ queue_ready_task (struct GNUNET_SCHEDULER_Task *task)
495 483
496 484
497/** 485/**
498 * Check which tasks are ready and move them
499 * to the respective ready queue.
500 *
501 * @param rs FDs ready for reading
502 * @param ws FDs ready for writing
503 */
504static void
505check_ready (const struct GNUNET_NETWORK_FDSet *rs,
506 const struct GNUNET_NETWORK_FDSet *ws)
507{
508 struct GNUNET_SCHEDULER_Task *pos;
509 struct GNUNET_SCHEDULER_Task *next;
510 struct GNUNET_TIME_Absolute now;
511
512 now = GNUNET_TIME_absolute_get ();
513 while (NULL != (pos = pending_timeout_head))
514 {
515 if (now.abs_value_us >= pos->timeout.abs_value_us)
516 pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
517 if (0 == pos->reason)
518 break;
519 GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
520 pending_timeout_tail,
521 pos);
522 if (pending_timeout_last == pos)
523 pending_timeout_last = NULL;
524 queue_ready_task (pos);
525 }
526 pos = pending_head;
527 while (NULL != pos)
528 {
529 next = pos->next;
530 if (GNUNET_YES == is_ready (pos, now, rs, ws))
531 {
532 GNUNET_CONTAINER_DLL_remove (pending_head,
533 pending_tail,
534 pos);
535 queue_ready_task (pos);
536 }
537 pos = next;
538 }
539}
540
541
542/**
543 * Request the shutdown of a scheduler. Marks all tasks 486 * Request the shutdown of a scheduler. Marks all tasks
544 * awaiting shutdown as ready. Note that tasks 487 * awaiting shutdown as ready. Note that tasks
545 * scheduled with #GNUNET_SCHEDULER_add_shutdown() AFTER this call 488 * scheduled with #GNUNET_SCHEDULER_add_shutdown() AFTER this call
@@ -562,25 +505,6 @@ GNUNET_SCHEDULER_shutdown ()
562 505
563 506
564/** 507/**
565 * Destroy a task (release associated resources)
566 *
567 * @param t task to destroy
568 */
569static void
570destroy_task (struct GNUNET_SCHEDULER_Task *t)
571{
572 if (NULL != t->read_set)
573 GNUNET_NETWORK_fdset_destroy (t->read_set);
574 if (NULL != t->write_set)
575 GNUNET_NETWORK_fdset_destroy (t->write_set);
576#if EXECINFO
577 GNUNET_free (t->backtrace_strings);
578#endif
579 GNUNET_free (t);
580}
581
582
583/**
584 * Output stack trace of task @a t. 508 * Output stack trace of task @a t.
585 * 509 *
586 * @param t task to dump stack trace of 510 * @param t task to dump stack trace of
@@ -592,88 +516,59 @@ dump_backtrace (struct GNUNET_SCHEDULER_Task *t)
592 unsigned int i; 516 unsigned int i;
593 517
594 for (i = 0; i < t->num_backtrace_strings; i++) 518 for (i = 0; i < t->num_backtrace_strings; i++)
595 LOG (GNUNET_ERROR_TYPE_DEBUG, 519 LOG (GNUNET_ERROR_TYPE_WARNING,
596 "Task %p trace %u: %s\n", 520 "Task %p trace %u: %s\n",
597 t, 521 t,
598 i, 522 i,
599 t->backtrace_strings[i]); 523 t->backtrace_strings[i]);
600#endif 524#endif
601} 525}
602 526
603 527
604/** 528/**
605 * Run at least one task in the highest-priority queue that is not 529 * Destroy a task (release associated resources)
606 * empty. Keep running tasks until we are either no longer running
607 * "URGENT" tasks or until we have at least one "pending" task (which
608 * may become ready, hence we should select on it). Naturally, if
609 * there are no more ready tasks, we also return.
610 * 530 *
611 * @param rs FDs ready for reading 531 * @param t task to destroy
612 * @param ws FDs ready for writing
613 */ 532 */
614static void 533static void
615run_ready (struct GNUNET_NETWORK_FDSet *rs, 534destroy_task (struct GNUNET_SCHEDULER_Task *t)
616 struct GNUNET_NETWORK_FDSet *ws)
617{ 535{
618 enum GNUNET_SCHEDULER_Priority p; 536 unsigned int i;
619 struct GNUNET_SCHEDULER_Task *pos;
620 537
621 max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; 538 LOG (GNUNET_ERROR_TYPE_DEBUG,
622 do 539 "destroying task %p\n",
540 t);
541
542 if (GNUNET_YES == t->own_handles)
623 { 543 {
624 if (0 == ready_count) 544 for (i = 0; i != t->fds_len; ++i)
625 return;
626 GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]);
627 /* yes, p>0 is correct, 0 is "KEEP" which should
628 * always be an empty queue (see assertion)! */
629 for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--)
630 {
631 pos = ready_head[p];
632 if (NULL != pos)
633 break;
634 }
635 GNUNET_assert (NULL != pos); /* ready_count wrong? */
636 GNUNET_CONTAINER_DLL_remove (ready_head[p],
637 ready_tail[p],
638 pos);
639 ready_count--;
640 current_priority = pos->priority;
641 current_lifeness = pos->lifeness;
642 active_task = pos;
643#if PROFILE_DELAYS
644 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
645 DELAY_THRESHOLD.rel_value_us)
646 { 545 {
647 LOG (GNUNET_ERROR_TYPE_DEBUG, 546 const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
648 "Task %p took %s to be scheduled\n", 547 const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
649 pos, 548 if (fd)
650 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), 549 {
651 GNUNET_YES)); 550 GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fd);
551 }
552 if (fh)
553 {
554 // FIXME: on WIN32 this is not enough! A function
555 // GNUNET_DISK_file_free_memory_only would be nice
556 GNUNET_free ((void *) fh);
557 }
652 } 558 }
653#endif
654 tc.reason = pos->reason;
655 tc.read_ready = (NULL == pos->read_set) ? rs : pos->read_set;
656 if ((-1 != pos->read_fd) &&
657 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)))
658 GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd);
659 tc.write_ready = (NULL == pos->write_set) ? ws : pos->write_set;
660 if ((-1 != pos->write_fd) &&
661 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)))
662 GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd);
663 if ((0 != (tc.reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
664 (-1 != pos->write_fd) &&
665 (!GNUNET_NETWORK_fdset_test_native (ws, pos->write_fd)))
666 GNUNET_assert (0); // added to ready in previous select loop!
667 LOG (GNUNET_ERROR_TYPE_DEBUG,
668 "Running task: %p\n",
669 pos);
670 pos->callback (pos->callback_cls);
671 dump_backtrace (pos);
672 active_task = NULL;
673 destroy_task (pos);
674 tasks_run++;
675 } 559 }
676 while ((NULL == pending_head) || (p >= max_priority_added)); 560 if (t->fds_len > 1)
561 {
562 GNUNET_array_grow (t->fds, t->fds_len, 0);
563 }
564 if (t->ready_fds_len > 0)
565 {
566 GNUNET_array_grow (t->ready_fds, t->ready_fds_len, 0);
567 }
568#if EXECINFO
569 GNUNET_free (t->backtrace_strings);
570#endif
571 GNUNET_free (t);
677} 572}
678 573
679 574
@@ -700,22 +595,22 @@ sighandler_pipe ()
700#endif 595#endif
701 596
702 597
703/** 598///**
704 * Wait for a short time. 599// * Wait for a short time.
705 * Sleeps for @a ms ms (as that should be long enough for virtually all 600// * Sleeps for @a ms ms (as that should be long enough for virtually all
706 * modern systems to context switch and allow another process to do 601// * modern systems to context switch and allow another process to do
707 * some 'real' work). 602// * some 'real' work).
708 * 603// *
709 * @param ms how many ms to wait 604// * @param ms how many ms to wait
710 */ 605// */
711static void 606//static void
712short_wait (unsigned int ms) 607//short_wait (unsigned int ms)
713{ 608//{
714 struct GNUNET_TIME_Relative timeout; 609// struct GNUNET_TIME_Relative timeout;
715 610//
716 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms); 611// timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms);
717 (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); 612// (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
718} 613//}
719 614
720 615
721/** 616/**
@@ -737,35 +632,31 @@ sighandler_shutdown ()
737} 632}
738 633
739 634
740/** 635void
741 * Check if the system is still alive. Trigger shutdown if we 636shutdown_if_no_lifeness ()
742 * have tasks, but none of them give us lifeness.
743 *
744 * @return #GNUNET_OK to continue the main loop,
745 * #GNUNET_NO to exit
746 */
747static int
748check_lifeness ()
749{ 637{
750 struct GNUNET_SCHEDULER_Task *t; 638 struct GNUNET_SCHEDULER_Task *t;
751 639
752 if (ready_count > 0) 640 if (ready_count > 0)
753 return GNUNET_OK; 641 return;
754 for (t = pending_head; NULL != t; t = t->next) 642 for (t = pending_head; NULL != t; t = t->next)
755 if (t->lifeness == GNUNET_YES) 643 if (GNUNET_YES == t->lifeness)
756 return GNUNET_OK; 644 return;
757 for (t = shutdown_head; NULL != t; t = t->next) 645 for (t = shutdown_head; NULL != t; t = t->next)
758 if (t->lifeness == GNUNET_YES) 646 if (GNUNET_YES == t->lifeness)
759 return GNUNET_OK; 647 return;
760 for (t = pending_timeout_head; NULL != t; t = t->next) 648 for (t = pending_timeout_head; NULL != t; t = t->next)
761 if (t->lifeness == GNUNET_YES) 649 if (GNUNET_YES == t->lifeness)
762 return GNUNET_OK; 650 return;
763 if (NULL != shutdown_head) 651 /* No lifeness! Cancel all pending tasks the driver knows about and shutdown */
652 t = pending_head;
653 while (NULL != t)
764 { 654 {
765 GNUNET_SCHEDULER_shutdown (); 655 struct GNUNET_SCHEDULER_Task *next = t->next;
766 return GNUNET_OK; 656 GNUNET_SCHEDULER_cancel (t);
657 t = next;
767 } 658 }
768 return GNUNET_NO; 659 GNUNET_SCHEDULER_shutdown ();
769} 660}
770 661
771 662
@@ -787,204 +678,17 @@ void
787GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, 678GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task,
788 void *task_cls) 679 void *task_cls)
789{ 680{
790 GNUNET_SCHEDULER_run_with_optional_signals(GNUNET_YES, task, task_cls); 681 struct GNUNET_SCHEDULER_Driver *driver;
791} 682 struct DriverContext context = {.scheduled_head = NULL,
792 683 .scheduled_tail = NULL,
793void 684 .timeout = GNUNET_TIME_UNIT_FOREVER_REL};
794GNUNET_SCHEDULER_run_with_optional_signals (int install_signals, 685
795 GNUNET_SCHEDULER_TaskCallback task, 686 driver = GNUNET_SCHEDULER_driver_select ();
796 void *task_cls) 687 driver->cls = &context;
797{ 688
798 struct GNUNET_NETWORK_FDSet *rs; 689 GNUNET_SCHEDULER_run_with_driver (driver, task, task_cls);
799 struct GNUNET_NETWORK_FDSet *ws; 690
800 struct GNUNET_TIME_Relative timeout; 691 GNUNET_free (driver);
801 int ret;
802 struct GNUNET_SIGNAL_Context *shc_int;
803 struct GNUNET_SIGNAL_Context *shc_term;
804#if (SIGTERM != GNUNET_TERM_SIG)
805 struct GNUNET_SIGNAL_Context *shc_gterm;
806#endif
807
808#ifndef MINGW
809 struct GNUNET_SIGNAL_Context *shc_quit;
810 struct GNUNET_SIGNAL_Context *shc_hup;
811 struct GNUNET_SIGNAL_Context *shc_pipe;
812#endif
813 unsigned long long last_tr;
814 unsigned int busy_wait_warning;
815 const struct GNUNET_DISK_FileHandle *pr;
816 char c;
817
818 GNUNET_assert (NULL == active_task);
819 rs = GNUNET_NETWORK_fdset_create ();
820 ws = GNUNET_NETWORK_fdset_create ();
821 GNUNET_assert (NULL == shutdown_pipe_handle);
822 shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO,
823 GNUNET_NO,
824 GNUNET_NO,
825 GNUNET_NO);
826 GNUNET_assert (NULL != shutdown_pipe_handle);
827 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
828 GNUNET_DISK_PIPE_END_READ);
829 GNUNET_assert (NULL != pr);
830 my_pid = getpid ();
831
832 if (GNUNET_YES == install_signals)
833 {
834 LOG (GNUNET_ERROR_TYPE_DEBUG,
835 "Registering signal handlers\n");
836 shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
837 &sighandler_shutdown);
838 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
839 &sighandler_shutdown);
840#if (SIGTERM != GNUNET_TERM_SIG)
841 shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG,
842 &sighandler_shutdown);
843#endif
844#ifndef MINGW
845 shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
846 &sighandler_pipe);
847 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
848 &sighandler_shutdown);
849 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
850 &sighandler_shutdown);
851#endif
852 }
853
854 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
855 current_lifeness = GNUNET_YES;
856 GNUNET_SCHEDULER_add_with_reason_and_priority (task,
857 task_cls,
858 GNUNET_SCHEDULER_REASON_STARTUP,
859 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
860 active_task = (void *) (long) -1; /* force passing of sanity check */
861 GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO,
862 &GNUNET_OS_install_parent_control_handler,
863 NULL);
864 active_task = NULL;
865 last_tr = 0;
866 busy_wait_warning = 0;
867 while (GNUNET_OK == check_lifeness ())
868 {
869 GNUNET_NETWORK_fdset_zero (rs);
870 GNUNET_NETWORK_fdset_zero (ws);
871 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
872 update_sets (rs, ws, &timeout);
873 GNUNET_NETWORK_fdset_handle_set (rs, pr);
874 if (ready_count > 0)
875 {
876 /* no blocking, more work already ready! */
877 timeout = GNUNET_TIME_UNIT_ZERO;
878 }
879 if (NULL == scheduler_select)
880 ret = GNUNET_NETWORK_socket_select (rs,
881 ws,
882 NULL,
883 timeout);
884 else
885 ret = scheduler_select (scheduler_select_cls,
886 rs,
887 ws,
888 NULL,
889 timeout);
890 if (ret == GNUNET_SYSERR)
891 {
892 if (errno == EINTR)
893 continue;
894
895 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "select");
896#ifndef MINGW
897#if USE_LSOF
898 char lsof[512];
899
900 snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid ());
901 (void) close (1);
902 (void) dup2 (2, 1);
903 if (0 != system (lsof))
904 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
905 "system");
906#endif
907#endif
908#if DEBUG_FDS
909 struct GNUNET_SCHEDULER_Task *t;
910
911 for (t = pending_head; NULL != t; t = t->next)
912 {
913 if (-1 != t->read_fd)
914 {
915 int flags = fcntl (t->read_fd, F_GETFD);
916 if ((flags == -1) && (errno == EBADF))
917 {
918 LOG (GNUNET_ERROR_TYPE_ERROR,
919 "Got invalid file descriptor %d!\n",
920 t->read_fd);
921 dump_backtrace (t);
922 }
923 }
924 if (-1 != t->write_fd)
925 {
926 int flags = fcntl (t->write_fd, F_GETFD);
927 if ((flags == -1) && (errno == EBADF))
928 {
929 LOG (GNUNET_ERROR_TYPE_ERROR,
930 "Got invalid file descriptor %d!\n",
931 t->write_fd);
932 dump_backtrace (t);
933 }
934 }
935 }
936#endif
937 GNUNET_assert (0);
938 break;
939 }
940
941 if ( (0 == ret) &&
942 (0 == timeout.rel_value_us) &&
943 (busy_wait_warning > 16) )
944 {
945 LOG (GNUNET_ERROR_TYPE_WARNING,
946 "Looks like we're busy waiting...\n");
947 short_wait (100); /* mitigate */
948 }
949 check_ready (rs, ws);
950 run_ready (rs, ws);
951 if (GNUNET_NETWORK_fdset_handle_isset (rs, pr))
952 {
953 /* consume the signal */
954 GNUNET_DISK_file_read (pr, &c, sizeof (c));
955 /* mark all active tasks as ready due to shutdown */
956 GNUNET_SCHEDULER_shutdown ();
957 }
958 if (last_tr == tasks_run)
959 {
960 short_wait (1);
961 busy_wait_warning++;
962 }
963 else
964 {
965 last_tr = tasks_run;
966 busy_wait_warning = 0;
967 }
968 }
969
970 if (GNUNET_YES == install_signals)
971 {
972 GNUNET_SIGNAL_handler_uninstall (shc_int);
973 GNUNET_SIGNAL_handler_uninstall (shc_term);
974#if (SIGTERM != GNUNET_TERM_SIG)
975 GNUNET_SIGNAL_handler_uninstall (shc_gterm);
976#endif
977#ifndef MINGW
978 GNUNET_SIGNAL_handler_uninstall (shc_pipe);
979 GNUNET_SIGNAL_handler_uninstall (shc_quit);
980 GNUNET_SIGNAL_handler_uninstall (shc_hup);
981#endif
982 }
983
984 GNUNET_DISK_pipe_close (shutdown_pipe_handle);
985 shutdown_pipe_handle = NULL;
986 GNUNET_NETWORK_fdset_destroy (rs);
987 GNUNET_NETWORK_fdset_destroy (ws);
988} 692}
989 693
990 694
@@ -1029,9 +733,164 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p)
1029} 733}
1030 734
1031 735
736void
737init_fd_info (struct GNUNET_SCHEDULER_Task *t,
738 const struct GNUNET_NETWORK_Handle *const *read_nh,
739 unsigned int read_nh_len,
740 const struct GNUNET_NETWORK_Handle *const *write_nh,
741 unsigned int write_nh_len,
742 const struct GNUNET_DISK_FileHandle *const *read_fh,
743 unsigned int read_fh_len,
744 const struct GNUNET_DISK_FileHandle *const *write_fh,
745 unsigned int write_fh_len)
746{
747 // FIXME: if we have exactly two network handles / exactly two file handles
748 // and they are equal, we can make one FdInfo with both
749 // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
750 struct GNUNET_SCHEDULER_FdInfo *fdi;
751
752 t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
753 if (1 == t->fds_len)
754 {
755 fdi = &t->fdx;
756 t->fds = fdi;
757 if (1 == read_nh_len)
758 {
759 fdi->fd = *read_nh;
760 GNUNET_assert (NULL != fdi->fd);
761 fdi->et = GNUNET_SCHEDULER_ET_IN;
762 fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
763 t->read_fd = fdi->sock;
764 t->write_fd = -1;
765 }
766 else if (1 == write_nh_len)
767 {
768 fdi->fd = *write_nh;
769 GNUNET_assert (NULL != fdi->fd);
770 fdi->et = GNUNET_SCHEDULER_ET_OUT;
771 fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
772 t->read_fd = -1;
773 t->write_fd = fdi->sock;
774 }
775 else if (1 == read_fh_len)
776 {
777 fdi->fh = *read_fh;
778 GNUNET_assert (NULL != fdi->fh);
779 fdi->et = GNUNET_SCHEDULER_ET_IN;
780 fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
781 t->read_fd = fdi->sock;
782 t->write_fd = -1;
783 }
784 else
785 {
786 fdi->fh = *write_fh;
787 GNUNET_assert (NULL != fdi->fh);
788 fdi->et = GNUNET_SCHEDULER_ET_OUT;
789 fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
790 t->read_fd = -1;
791 t->write_fd = fdi->sock;
792 }
793 }
794 else
795 {
796 fdi = GNUNET_new_array (t->fds_len, struct GNUNET_SCHEDULER_FdInfo);
797 t->fds = fdi;
798 t->read_fd = -1;
799 t->write_fd = -1;
800 unsigned int i;
801 for (i = 0; i != read_nh_len; ++i)
802 {
803 fdi->fd = read_nh[i];
804 GNUNET_assert (NULL != fdi->fd);
805 fdi->et = GNUNET_SCHEDULER_ET_IN;
806 fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
807 ++fdi;
808 }
809 for (i = 0; i != write_nh_len; ++i)
810 {
811 fdi->fd = write_nh[i];
812 GNUNET_assert (NULL != fdi->fd);
813 fdi->et = GNUNET_SCHEDULER_ET_OUT;
814 fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
815 ++fdi;
816 }
817 for (i = 0; i != read_fh_len; ++i)
818 {
819 fdi->fh = read_fh[i];
820 GNUNET_assert (NULL != fdi->fh);
821 fdi->et = GNUNET_SCHEDULER_ET_IN;
822 fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
823 ++fdi;
824 }
825 for (i = 0; i != write_fh_len; ++i)
826 {
827 fdi->fh = write_fh[i];
828 GNUNET_assert (NULL != fdi->fh);
829 fdi->et = GNUNET_SCHEDULER_ET_OUT;
830 fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
831 ++fdi;
832 }
833 }
834}
835
836
837/**
838 * calls the given function @a func on each FdInfo related to @a t.
839 * Optionally updates the event type field in each FdInfo after calling
840 * @a func.
841 *
842 * @param t the task
843 * @param driver_func the function to call with each FdInfo contained in
844 * in @a t
845 * @param if_not_ready only call @a driver_func on FdInfos that are not
846 * ready
847 * @param et the event type to be set in each FdInfo after calling
848 * @a driver_func on it, or -1 if no updating not desired.
849 */
850void driver_add_multiple (struct GNUNET_SCHEDULER_Task *t,
851 enum GNUNET_SCHEDULER_EventType et)
852{
853 struct GNUNET_SCHEDULER_FdInfo *fdi;
854 int success = GNUNET_YES;
855
856 for (int i = 0; i != t->fds_len; ++i)
857 {
858 fdi = &t->fds[i];
859 success = scheduler_driver->add (scheduler_driver->cls, t, fdi) && success;
860 if (et != -1)
861 {
862 fdi->et = et;
863 }
864 }
865 if (GNUNET_YES != success)
866 {
867 LOG (GNUNET_ERROR_TYPE_ERROR,
868 "driver could not add task\n");
869 }
870}
871
872
873void
874shutdown_cb (void *cls)
875{
876 char c;
877 const struct GNUNET_DISK_FileHandle *pr;
878
879 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
880 GNUNET_DISK_PIPE_END_READ);
881 GNUNET_assert (! GNUNET_DISK_handle_invalid (pr));
882 /* consume the signal */
883 GNUNET_DISK_file_read (pr, &c, sizeof (c));
884 /* mark all active tasks as ready due to shutdown */
885 GNUNET_SCHEDULER_shutdown ();
886}
887
888
1032/** 889/**
1033 * Cancel the task with the specified identifier. 890 * Cancel the task with the specified identifier.
1034 * The task must not yet have run. 891 * The task must not yet have run. Only allowed to be called as long as the
892 * scheduler is running (#GNUNET_SCHEDULER_run or
893 * #GNUNET_SCHEDULER_run_with_driver has been called and has not returned yet).
1035 * 894 *
1036 * @param task id of the task to cancel 895 * @param task id of the task to cancel
1037 * @return original closure of the task 896 * @return original closure of the task
@@ -1040,34 +899,50 @@ void *
1040GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) 899GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task)
1041{ 900{
1042 enum GNUNET_SCHEDULER_Priority p; 901 enum GNUNET_SCHEDULER_Priority p;
902 int is_fd_task;
1043 void *ret; 903 void *ret;
1044 904
905 LOG (GNUNET_ERROR_TYPE_DEBUG,
906 "canceling task %p\n",
907 task);
908
909 /* scheduler must be running */
910 GNUNET_assert (NULL != scheduler_driver);
1045 GNUNET_assert ( (NULL != active_task) || 911 GNUNET_assert ( (NULL != active_task) ||
1046 (GNUNET_NO == task->lifeness) ); 912 (GNUNET_NO == task->lifeness) );
1047 if (! task->in_ready_list) 913 is_fd_task = (NULL != task->fds);
914 if (is_fd_task)
1048 { 915 {
1049 if ( (-1 == task->read_fd) && 916 int del_result = scheduler_driver->del (scheduler_driver->cls, task);
1050 (-1 == task->write_fd) && 917 if (GNUNET_OK != del_result)
1051 (NULL == task->read_set) &&
1052 (NULL == task->write_set) )
1053 { 918 {
1054 if (GNUNET_YES == task->on_shutdown) 919 LOG (GNUNET_ERROR_TYPE_ERROR,
1055 GNUNET_CONTAINER_DLL_remove (shutdown_head, 920 "driver could not delete task\n");
1056 shutdown_tail, 921 GNUNET_assert (0);
1057 task);
1058 else
1059 GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
1060 pending_timeout_tail,
1061 task);
1062 if (task == pending_timeout_last)
1063 pending_timeout_last = NULL;
1064 } 922 }
1065 else 923 }
924 if (! task->in_ready_list)
925 {
926 if (is_fd_task)
1066 { 927 {
1067 GNUNET_CONTAINER_DLL_remove (pending_head, 928 GNUNET_CONTAINER_DLL_remove (pending_head,
1068 pending_tail, 929 pending_tail,
1069 task); 930 task);
1070 } 931 }
932 else if (GNUNET_YES == task->on_shutdown)
933 {
934 GNUNET_CONTAINER_DLL_remove (shutdown_head,
935 shutdown_tail,
936 task);
937 }
938 else
939 {
940 GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
941 pending_timeout_tail,
942 task);
943 if (pending_timeout_last == task)
944 pending_timeout_last = NULL;
945 }
1071 } 946 }
1072 else 947 else
1073 { 948 {
@@ -1078,9 +953,6 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task)
1078 ready_count--; 953 ready_count--;
1079 } 954 }
1080 ret = task->callback_cls; 955 ret = task->callback_cls;
1081 LOG (GNUNET_ERROR_TYPE_DEBUG,
1082 "Canceling task %p\n",
1083 task);
1084 destroy_task (task); 956 destroy_task (task);
1085 return ret; 957 return ret;
1086} 958}
@@ -1101,7 +973,7 @@ init_backtrace (struct GNUNET_SCHEDULER_Task *t)
1101 = backtrace (backtrace_array, MAX_TRACE_DEPTH); 973 = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1102 t->backtrace_strings = 974 t->backtrace_strings =
1103 backtrace_symbols (backtrace_array, 975 backtrace_symbols (backtrace_array,
1104 t->num_backtrace_strings); 976 t->num_backtrace_strings);
1105 dump_backtrace (t); 977 dump_backtrace (t);
1106#endif 978#endif
1107} 979}
@@ -1218,7 +1090,7 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at,
1218 pending_timeout_last = t; 1090 pending_timeout_last = t;
1219 1091
1220 LOG (GNUNET_ERROR_TYPE_DEBUG, 1092 LOG (GNUNET_ERROR_TYPE_DEBUG,
1221 "Adding task: %p\n", 1093 "Adding task %p\n",
1222 t); 1094 t);
1223 init_backtrace (t); 1095 init_backtrace (t);
1224 return t; 1096 return t;
@@ -1238,8 +1110,8 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at,
1238 */ 1110 */
1239struct GNUNET_SCHEDULER_Task * 1111struct GNUNET_SCHEDULER_Task *
1240GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, 1112GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay,
1241 enum GNUNET_SCHEDULER_Priority priority, 1113 enum GNUNET_SCHEDULER_Priority priority,
1242 GNUNET_SCHEDULER_TaskCallback task, 1114 GNUNET_SCHEDULER_TaskCallback task,
1243 void *task_cls) 1115 void *task_cls)
1244{ 1116{
1245 return GNUNET_SCHEDULER_add_at_with_priority (GNUNET_TIME_relative_to_absolute (delay), 1117 return GNUNET_SCHEDULER_add_at_with_priority (GNUNET_TIME_relative_to_absolute (delay),
@@ -1307,12 +1179,12 @@ GNUNET_SCHEDULER_add_at (struct GNUNET_TIME_Absolute at,
1307struct GNUNET_SCHEDULER_Task * 1179struct GNUNET_SCHEDULER_Task *
1308GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, 1180GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
1309 GNUNET_SCHEDULER_TaskCallback task, 1181 GNUNET_SCHEDULER_TaskCallback task,
1310 void *task_cls) 1182 void *task_cls)
1311{ 1183{
1312 return GNUNET_SCHEDULER_add_delayed_with_priority (delay, 1184 return GNUNET_SCHEDULER_add_delayed_with_priority (delay,
1313 GNUNET_SCHEDULER_PRIORITY_DEFAULT, 1185 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1314 task, 1186 task,
1315 task_cls); 1187 task_cls);
1316} 1188}
1317 1189
1318 1190
@@ -1333,11 +1205,11 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
1333 */ 1205 */
1334struct GNUNET_SCHEDULER_Task * 1206struct GNUNET_SCHEDULER_Task *
1335GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, 1207GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task,
1336 void *task_cls) 1208 void *task_cls)
1337{ 1209{
1338 return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, 1210 return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO,
1339 task, 1211 task,
1340 task_cls); 1212 task_cls);
1341} 1213}
1342 1214
1343 1215
@@ -1353,7 +1225,7 @@ GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task,
1353 */ 1225 */
1354struct GNUNET_SCHEDULER_Task * 1226struct GNUNET_SCHEDULER_Task *
1355GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, 1227GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task,
1356 void *task_cls) 1228 void *task_cls)
1357{ 1229{
1358 struct GNUNET_SCHEDULER_Task *t; 1230 struct GNUNET_SCHEDULER_Task *t;
1359 1231
@@ -1370,12 +1242,12 @@ GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task,
1370 t->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; 1242 t->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1371 t->priority = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN; 1243 t->priority = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN;
1372 t->on_shutdown = GNUNET_YES; 1244 t->on_shutdown = GNUNET_YES;
1373 t->lifeness = GNUNET_YES; 1245 t->lifeness = GNUNET_NO;
1374 GNUNET_CONTAINER_DLL_insert (shutdown_head, 1246 GNUNET_CONTAINER_DLL_insert (shutdown_head,
1375 shutdown_tail, 1247 shutdown_tail,
1376 t); 1248 t);
1377 LOG (GNUNET_ERROR_TYPE_DEBUG, 1249 LOG (GNUNET_ERROR_TYPE_DEBUG,
1378 "Adding task: %p\n", 1250 "Adding shutdown task %p\n",
1379 t); 1251 t);
1380 init_backtrace (t); 1252 init_backtrace (t);
1381 return t; 1253 return t;
@@ -1409,6 +1281,33 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
1409} 1281}
1410 1282
1411 1283
1284#if DEBUG_FDS
1285/**
1286 * check a raw file descriptor and abort if it is bad (for debugging purposes)
1287 *
1288 * @param t the task related to the file descriptor
1289 * @param raw_fd the raw file descriptor to check
1290 */
1291void
1292check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1293{
1294 if (-1 != raw_fd)
1295 {
1296 int flags = fcntl (raw_fd, F_GETFD);
1297
1298 if ((flags == -1) && (errno == EBADF))
1299 {
1300 LOG (GNUNET_ERROR_TYPE_ERROR,
1301 "Got invalid file descriptor %d!\n",
1302 raw_fd);
1303 init_backtrace (t);
1304 GNUNET_assert (0);
1305 }
1306 }
1307}
1308#endif
1309
1310
1412/** 1311/**
1413 * Schedule a new task to be run with a specified delay or when any of 1312 * Schedule a new task to be run with a specified delay or when any of
1414 * the specified file descriptor sets is ready. The delay can be used 1313 * the specified file descriptor sets is ready. The delay can be used
@@ -1437,9 +1336,11 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
1437#ifndef MINGW 1336#ifndef MINGW
1438static struct GNUNET_SCHEDULER_Task * 1337static struct GNUNET_SCHEDULER_Task *
1439add_without_sets (struct GNUNET_TIME_Relative delay, 1338add_without_sets (struct GNUNET_TIME_Relative delay,
1440 enum GNUNET_SCHEDULER_Priority priority, 1339 enum GNUNET_SCHEDULER_Priority priority,
1441 int rfd, 1340 const struct GNUNET_NETWORK_Handle *read_nh,
1442 int wfd, 1341 const struct GNUNET_NETWORK_Handle *write_nh,
1342 const struct GNUNET_DISK_FileHandle *read_fh,
1343 const struct GNUNET_DISK_FileHandle *write_fh,
1443 GNUNET_SCHEDULER_TaskCallback task, 1344 GNUNET_SCHEDULER_TaskCallback task,
1444 void *task_cls) 1345 void *task_cls)
1445{ 1346{
@@ -1448,39 +1349,23 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
1448 GNUNET_assert (NULL != active_task); 1349 GNUNET_assert (NULL != active_task);
1449 GNUNET_assert (NULL != task); 1350 GNUNET_assert (NULL != task);
1450 t = GNUNET_new (struct GNUNET_SCHEDULER_Task); 1351 t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1352 init_fd_info (t,
1353 &read_nh,
1354 read_nh ? 1 : 0,
1355 &write_nh,
1356 write_nh ? 1 : 0,
1357 &read_fh,
1358 read_fh ? 1 : 0,
1359 &write_fh,
1360 write_fh ? 1 : 0);
1451 t->callback = task; 1361 t->callback = task;
1452 t->callback_cls = task_cls; 1362 t->callback_cls = task_cls;
1453#if DEBUG_FDS 1363#if DEBUG_FDS
1454 if (-1 != rfd) 1364 check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1455 { 1365 check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1456 int flags = fcntl (rfd, F_GETFD); 1366 check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1457 1367 check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1458 if ((flags == -1) && (errno == EBADF))
1459 {
1460 LOG (GNUNET_ERROR_TYPE_ERROR,
1461 "Got invalid file descriptor %d!\n",
1462 rfd);
1463 init_backtrace (t);
1464 GNUNET_assert (0);
1465 }
1466 }
1467 if (-1 != wfd)
1468 {
1469 int flags = fcntl (wfd, F_GETFD);
1470
1471 if (flags == -1 && errno == EBADF)
1472 {
1473 LOG (GNUNET_ERROR_TYPE_ERROR,
1474 "Got invalid file descriptor %d!\n",
1475 wfd);
1476 init_backtrace (t);
1477 GNUNET_assert (0);
1478 }
1479 }
1480#endif 1368#endif
1481 t->read_fd = rfd;
1482 GNUNET_assert (wfd >= -1);
1483 t->write_fd = wfd;
1484#if PROFILE_DELAYS 1369#if PROFILE_DELAYS
1485 t->start_time = GNUNET_TIME_absolute_get (); 1370 t->start_time = GNUNET_TIME_absolute_get ();
1486#endif 1371#endif
@@ -1490,11 +1375,9 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
1490 GNUNET_CONTAINER_DLL_insert (pending_head, 1375 GNUNET_CONTAINER_DLL_insert (pending_head,
1491 pending_tail, 1376 pending_tail,
1492 t); 1377 t);
1378 driver_add_multiple (t, GNUNET_SCHEDULER_ET_NONE);
1493 max_priority_added = GNUNET_MAX (max_priority_added, 1379 max_priority_added = GNUNET_MAX (max_priority_added,
1494 t->priority); 1380 t->priority);
1495 LOG (GNUNET_ERROR_TYPE_DEBUG,
1496 "Adding task %p\n",
1497 t);
1498 init_backtrace (t); 1381 init_backtrace (t);
1499 return t; 1382 return t;
1500} 1383}
@@ -1507,6 +1390,9 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
1507 * used as a timeout on the socket being ready. The task will be 1390 * used as a timeout on the socket being ready. The task will be
1508 * scheduled for execution once either the delay has expired or the 1391 * scheduled for execution once either the delay has expired or the
1509 * socket operation is ready. It will be run with the DEFAULT priority. 1392 * socket operation is ready. It will be run with the DEFAULT priority.
1393 * Only allowed to be called as long as the scheduler is running
1394 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1395 * called and has not returned yet).
1510 * 1396 *
1511 * @param delay when should this operation time out? 1397 * @param delay when should this operation time out?
1512 * @param rfd read file-descriptor 1398 * @param rfd read file-descriptor
@@ -1522,8 +1408,8 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
1522 void *task_cls) 1408 void *task_cls)
1523{ 1409{
1524 return GNUNET_SCHEDULER_add_read_net_with_priority (delay, 1410 return GNUNET_SCHEDULER_add_read_net_with_priority (delay,
1525 GNUNET_SCHEDULER_PRIORITY_DEFAULT, 1411 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1526 rfd, task, task_cls); 1412 rfd, task, task_cls);
1527} 1413}
1528 1414
1529 1415
@@ -1534,6 +1420,9 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
1534 * socket being ready. The task will be scheduled for execution once 1420 * socket being ready. The task will be scheduled for execution once
1535 * either the delay has expired or the socket operation is ready. It 1421 * either the delay has expired or the socket operation is ready. It
1536 * will be run with the DEFAULT priority. 1422 * will be run with the DEFAULT priority.
1423 * Only allowed to be called as long as the scheduler is running
1424 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1425 * called and has not returned yet).
1537 * 1426 *
1538 * @param delay when should this operation time out? 1427 * @param delay when should this operation time out?
1539 * @param priority priority to use for the task 1428 * @param priority priority to use for the task
@@ -1545,9 +1434,9 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
1545 */ 1434 */
1546struct GNUNET_SCHEDULER_Task * 1435struct GNUNET_SCHEDULER_Task *
1547GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, 1436GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
1548 enum GNUNET_SCHEDULER_Priority priority, 1437 enum GNUNET_SCHEDULER_Priority priority,
1549 struct GNUNET_NETWORK_Handle *rfd, 1438 struct GNUNET_NETWORK_Handle *rfd,
1550 GNUNET_SCHEDULER_TaskCallback task, 1439 GNUNET_SCHEDULER_TaskCallback task,
1551 void *task_cls) 1440 void *task_cls)
1552{ 1441{
1553 return GNUNET_SCHEDULER_add_net_with_priority (delay, priority, 1442 return GNUNET_SCHEDULER_add_net_with_priority (delay, priority,
@@ -1565,6 +1454,9 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
1565 * scheduled for execution once either the delay has expired or the 1454 * scheduled for execution once either the delay has expired or the
1566 * socket operation is ready. It will be run with the priority of 1455 * socket operation is ready. It will be run with the priority of
1567 * the calling task. 1456 * the calling task.
1457 * Only allowed to be called as long as the scheduler is running
1458 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1459 * called and has not returned yet).
1568 * 1460 *
1569 * @param delay when should this operation time out? 1461 * @param delay when should this operation time out?
1570 * @param wfd write file-descriptor 1462 * @param wfd write file-descriptor
@@ -1592,6 +1484,9 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
1592 * used as a timeout on the socket being ready. The task will be 1484 * used as a timeout on the socket being ready. The task will be
1593 * scheduled for execution once either the delay has expired or the 1485 * scheduled for execution once either the delay has expired or the
1594 * socket operation is ready. 1486 * socket operation is ready.
1487 * Only allowed to be called as long as the scheduler is running
1488 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1489 * called and has not returned yet).
1595 * 1490 *
1596 * @param delay when should this operation time out? 1491 * @param delay when should this operation time out?
1597 * @param priority priority of the task 1492 * @param priority priority of the task
@@ -1612,6 +1507,9 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay,
1612 GNUNET_SCHEDULER_TaskCallback task, 1507 GNUNET_SCHEDULER_TaskCallback task,
1613 void *task_cls) 1508 void *task_cls)
1614{ 1509{
1510 /* scheduler must be running */
1511 GNUNET_assert (NULL != scheduler_driver);
1512
1615#if MINGW 1513#if MINGW
1616 struct GNUNET_NETWORK_FDSet *s; 1514 struct GNUNET_NETWORK_FDSet *s;
1617 struct GNUNET_SCHEDULER_Task * ret; 1515 struct GNUNET_SCHEDULER_Task * ret;
@@ -1627,10 +1525,13 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay,
1627 GNUNET_NETWORK_fdset_destroy (s); 1525 GNUNET_NETWORK_fdset_destroy (s);
1628 return ret; 1526 return ret;
1629#else 1527#else
1528 GNUNET_assert (on_read || on_write);
1630 GNUNET_assert (GNUNET_NETWORK_get_fd (fd) >= 0); 1529 GNUNET_assert (GNUNET_NETWORK_get_fd (fd) >= 0);
1631 return add_without_sets (delay, priority, 1530 return add_without_sets (delay, priority,
1632 on_read ? GNUNET_NETWORK_get_fd (fd) : -1, 1531 on_read ? fd : NULL,
1633 on_write ? GNUNET_NETWORK_get_fd (fd) : -1, 1532 on_write ? fd : NULL,
1533 NULL,
1534 NULL,
1634 task, task_cls); 1535 task, task_cls);
1635#endif 1536#endif
1636} 1537}
@@ -1642,6 +1543,9 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay,
1642 * used as a timeout on the socket being ready. The task will be 1543 * used as a timeout on the socket being ready. The task will be
1643 * scheduled for execution once either the delay has expired or the 1544 * scheduled for execution once either the delay has expired or the
1644 * socket operation is ready. It will be run with the DEFAULT priority. 1545 * socket operation is ready. It will be run with the DEFAULT priority.
1546 * Only allowed to be called as long as the scheduler is running
1547 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1548 * called and has not returned yet).
1645 * 1549 *
1646 * @param delay when should this operation time out? 1550 * @param delay when should this operation time out?
1647 * @param rfd read file-descriptor 1551 * @param rfd read file-descriptor
@@ -1668,6 +1572,9 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
1668 * used as a timeout on the socket being ready. The task will be 1572 * used as a timeout on the socket being ready. The task will be
1669 * scheduled for execution once either the delay has expired or the 1573 * scheduled for execution once either the delay has expired or the
1670 * socket operation is ready. It will be run with the DEFAULT priority. 1574 * socket operation is ready. It will be run with the DEFAULT priority.
1575 * Only allowed to be called as long as the scheduler is running
1576 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1577 * called and has not returned yet).
1671 * 1578 *
1672 * @param delay when should this operation time out? 1579 * @param delay when should this operation time out?
1673 * @param wfd write file-descriptor 1580 * @param wfd write file-descriptor
@@ -1694,6 +1601,9 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
1694 * used as a timeout on the socket being ready. The task will be 1601 * used as a timeout on the socket being ready. The task will be
1695 * scheduled for execution once either the delay has expired or the 1602 * scheduled for execution once either the delay has expired or the
1696 * socket operation is ready. 1603 * socket operation is ready.
1604 * Only allowed to be called as long as the scheduler is running
1605 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1606 * called and has not returned yet).
1697 * 1607 *
1698 * @param delay when should this operation time out? 1608 * @param delay when should this operation time out?
1699 * @param priority priority of the task 1609 * @param priority priority of the task
@@ -1712,6 +1622,9 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
1712 int on_read, int on_write, 1622 int on_read, int on_write,
1713 GNUNET_SCHEDULER_TaskCallback task, void *task_cls) 1623 GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
1714{ 1624{
1625 /* scheduler must be running */
1626 GNUNET_assert (NULL != scheduler_driver);
1627
1715#if MINGW 1628#if MINGW
1716 struct GNUNET_NETWORK_FDSet *s; 1629 struct GNUNET_NETWORK_FDSet *s;
1717 struct GNUNET_SCHEDULER_Task * ret; 1630 struct GNUNET_SCHEDULER_Task * ret;
@@ -1727,19 +1640,70 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
1727 GNUNET_NETWORK_fdset_destroy (s); 1640 GNUNET_NETWORK_fdset_destroy (s);
1728 return ret; 1641 return ret;
1729#else 1642#else
1730 int real_fd; 1643 GNUNET_assert (on_read || on_write);
1731 1644 GNUNET_assert (fd->fd >= 0);
1732 GNUNET_DISK_internal_file_handle_ (fd, &real_fd, sizeof (int)); 1645 return add_without_sets (delay, priority,
1733 GNUNET_assert (real_fd >= 0); 1646 NULL,
1734 return add_without_sets ( 1647 NULL,
1735 delay, priority, 1648 on_read ? fd : NULL,
1736 on_read ? real_fd : -1, 1649 on_write ? fd : NULL,
1737 on_write ? real_fd : -1, 1650 task, task_cls);
1738 task, task_cls);
1739#endif 1651#endif
1740} 1652}
1741 1653
1742 1654
1655void
1656extract_handles (struct GNUNET_SCHEDULER_Task *t,
1657 const struct GNUNET_NETWORK_FDSet *fdset,
1658 const struct GNUNET_NETWORK_Handle ***ntarget,
1659 unsigned int *extracted_nhandles,
1660 const struct GNUNET_DISK_FileHandle ***ftarget,
1661 unsigned int *extracted_fhandles)
1662{
1663 // FIXME: this implementation only works for unix, for WIN32 the file handles
1664 // in fdset must be handled separately
1665 const struct GNUNET_NETWORK_Handle **nhandles;
1666 const struct GNUNET_DISK_FileHandle **fhandles;
1667 unsigned int nhandles_len, fhandles_len;
1668 int sock;
1669
1670 nhandles = NULL;
1671 fhandles = NULL;
1672 nhandles_len = 0;
1673 fhandles_len = 0;
1674 for (sock = 0; sock != fdset->nsds; ++sock)
1675 {
1676 if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1677 {
1678 struct GNUNET_NETWORK_Handle *nhandle;
1679 struct GNUNET_DISK_FileHandle *fhandle;
1680
1681 nhandle = GNUNET_NETWORK_socket_box_native (sock);
1682 if (NULL != nhandle)
1683 {
1684 GNUNET_array_append (nhandles, nhandles_len, nhandle);
1685 }
1686 else
1687 {
1688 fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1689 if (NULL != fhandle)
1690 {
1691 GNUNET_array_append (fhandles, fhandles_len, fhandle);
1692 }
1693 else
1694 {
1695 GNUNET_assert (0);
1696 }
1697 }
1698 }
1699 }
1700 *ntarget = nhandles_len > 0 ? nhandles : NULL;
1701 *ftarget = fhandles_len > 0 ? fhandles : NULL;
1702 *extracted_nhandles = nhandles_len;
1703 *extracted_fhandles = fhandles_len;
1704}
1705
1706
1743/** 1707/**
1744 * Schedule a new task to be run with a specified delay or when any of 1708 * Schedule a new task to be run with a specified delay or when any of
1745 * the specified file descriptor sets is ready. The delay can be used 1709 * the specified file descriptor sets is ready. The delay can be used
@@ -1755,6 +1719,9 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
1755 * || any-rs-ready 1719 * || any-rs-ready
1756 * || any-ws-ready) ) 1720 * || any-ws-ready) )
1757 * </code> 1721 * </code>
1722 * Only allowed to be called as long as the scheduler is running
1723 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1724 * called and has not returned yet).
1758 * 1725 *
1759 * @param prio how important is this task? 1726 * @param prio how important is this task?
1760 * @param delay how long should we wait? 1727 * @param delay how long should we wait?
@@ -1774,13 +1741,20 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1774 void *task_cls) 1741 void *task_cls)
1775{ 1742{
1776 struct GNUNET_SCHEDULER_Task *t; 1743 struct GNUNET_SCHEDULER_Task *t;
1777 1744 const struct GNUNET_NETWORK_Handle **read_nhandles;
1778 if ( (NULL == rs) && 1745 const struct GNUNET_NETWORK_Handle **write_nhandles;
1779 (NULL == ws) ) 1746 const struct GNUNET_DISK_FileHandle **read_fhandles;
1747 const struct GNUNET_DISK_FileHandle **write_fhandles;
1748 unsigned int read_nhandles_len, write_nhandles_len,
1749 read_fhandles_len, write_fhandles_len;
1750
1751 if (((NULL == rs) && (NULL == ws)) || ((0 == rs->nsds) && (0 == ws->nsds)))
1780 return GNUNET_SCHEDULER_add_delayed_with_priority (delay, 1752 return GNUNET_SCHEDULER_add_delayed_with_priority (delay,
1781 prio, 1753 prio,
1782 task, 1754 task,
1783 task_cls); 1755 task_cls);
1756 /* scheduler must be running */
1757 GNUNET_assert (NULL != scheduler_driver);
1784 GNUNET_assert (NULL != active_task); 1758 GNUNET_assert (NULL != active_task);
1785 GNUNET_assert (NULL != task); 1759 GNUNET_assert (NULL != task);
1786 t = GNUNET_new (struct GNUNET_SCHEDULER_Task); 1760 t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
@@ -1788,16 +1762,48 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1788 t->callback_cls = task_cls; 1762 t->callback_cls = task_cls;
1789 t->read_fd = -1; 1763 t->read_fd = -1;
1790 t->write_fd = -1; 1764 t->write_fd = -1;
1765 t->own_handles = GNUNET_YES;
1766 read_nhandles = NULL;
1767 write_nhandles = NULL;
1768 read_fhandles = NULL;
1769 write_fhandles = NULL;
1770 read_nhandles_len = 0;
1771 write_nhandles_len = 0;
1772 read_fhandles_len = 0;
1773 write_fhandles_len = 0;
1791 if (NULL != rs) 1774 if (NULL != rs)
1792 { 1775 {
1793 t->read_set = GNUNET_NETWORK_fdset_create (); 1776 extract_handles (t,
1794 GNUNET_NETWORK_fdset_copy (t->read_set, rs); 1777 rs,
1778 &read_nhandles,
1779 &read_nhandles_len,
1780 &read_fhandles,
1781 &read_fhandles_len);
1795 } 1782 }
1796 if (NULL != ws) 1783 if (NULL != ws)
1797 { 1784 {
1798 t->write_set = GNUNET_NETWORK_fdset_create (); 1785 extract_handles (t,
1799 GNUNET_NETWORK_fdset_copy (t->write_set, ws); 1786 ws,
1787 &write_nhandles,
1788 &write_nhandles_len,
1789 &write_fhandles,
1790 &write_fhandles_len);
1800 } 1791 }
1792 init_fd_info (t,
1793 read_nhandles,
1794 read_nhandles_len,
1795 write_nhandles,
1796 write_nhandles_len,
1797 read_fhandles,
1798 read_fhandles_len,
1799 write_fhandles,
1800 write_fhandles_len);
1801 /* free the arrays of pointers to network / file handles, the actual
1802 * handles will be freed in destroy_task */
1803 GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1804 GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1805 GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1806 GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1801#if PROFILE_DELAYS 1807#if PROFILE_DELAYS
1802 t->start_time = GNUNET_TIME_absolute_get (); 1808 t->start_time = GNUNET_TIME_absolute_get ();
1803#endif 1809#endif
@@ -1810,8 +1816,9 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1810 GNUNET_CONTAINER_DLL_insert (pending_head, 1816 GNUNET_CONTAINER_DLL_insert (pending_head,
1811 pending_tail, 1817 pending_tail,
1812 t); 1818 t);
1819 driver_add_multiple (t, GNUNET_SCHEDULER_ET_NONE);
1813 max_priority_added = GNUNET_MAX (max_priority_added, 1820 max_priority_added = GNUNET_MAX (max_priority_added,
1814 t->priority); 1821 t->priority);
1815 LOG (GNUNET_ERROR_TYPE_DEBUG, 1822 LOG (GNUNET_ERROR_TYPE_DEBUG,
1816 "Adding task %p\n", 1823 "Adding task %p\n",
1817 t); 1824 t);
@@ -1822,17 +1829,18 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1822 1829
1823/** 1830/**
1824 * Function used by event-loop implementations to signal the scheduler 1831 * Function used by event-loop implementations to signal the scheduler
1825 * that a particular @a task is ready due to an event of type @a et. 1832 * that a particular @a task is ready due to an event specified in the
1833 * et field of @a fdi.
1826 * 1834 *
1827 * This function will then queue the task to notify the application 1835 * This function will then queue the task to notify the application
1828 * that the task is ready (with the respective priority). 1836 * that the task is ready (with the respective priority).
1829 * 1837 *
1830 * @param task the task that is ready, NULL for wake up calls 1838 * @param task the task that is ready
1831 * @param et information about why the task is ready 1839 * @param fdi information about the related FD
1832 */ 1840 */
1833void 1841void
1834GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, 1842GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1835 enum GNUNET_SCHEDULER_EventType et) 1843 struct GNUNET_SCHEDULER_FdInfo *fdi)
1836{ 1844{
1837 enum GNUNET_SCHEDULER_Reason reason; 1845 enum GNUNET_SCHEDULER_Reason reason;
1838 struct GNUNET_TIME_Absolute now; 1846 struct GNUNET_TIME_Absolute now;
@@ -1842,17 +1850,20 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1842 if (now.abs_value_us >= task->timeout.abs_value_us) 1850 if (now.abs_value_us >= task->timeout.abs_value_us)
1843 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; 1851 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
1844 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) && 1852 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1845 (0 != (GNUNET_SCHEDULER_ET_IN & et)) ) 1853 (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) )
1846 reason |= GNUNET_SCHEDULER_REASON_READ_READY; 1854 reason |= GNUNET_SCHEDULER_REASON_READ_READY;
1847 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && 1855 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1848 (0 != (GNUNET_SCHEDULER_ET_OUT & et)) ) 1856 (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) )
1849 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; 1857 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY;
1850 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; 1858 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE;
1851 task->reason = reason; 1859 task->reason = reason;
1852 task->fds = &task->fdx; 1860 if (GNUNET_NO == task->in_ready_list)
1853 task->fdx.et = et; 1861 {
1854 task->fds_len = 1; 1862 GNUNET_CONTAINER_DLL_remove (pending_head,
1855 queue_ready_task (task); 1863 pending_tail,
1864 task);
1865 queue_ready_task (task);
1866 }
1856} 1867}
1857 1868
1858 1869
@@ -1862,15 +1873,16 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1862 * there are tasks left to run just to give other tasks a chance as 1873 * there are tasks left to run just to give other tasks a chance as
1863 * well. If we return #GNUNET_YES, the driver should call this 1874 * well. If we return #GNUNET_YES, the driver should call this
1864 * function again as soon as possible, while if we return #GNUNET_NO 1875 * function again as soon as possible, while if we return #GNUNET_NO
1865 * it must block until the operating system has more work as the 1876 * it must block until either the operating system has more work (the
1866 * scheduler has no more work to do right now. 1877 * scheduler has no more work to do right now) or the timeout set by
1878 * the scheduler (using the set_wakeup callback) is reached.
1867 * 1879 *
1868 * @param sh scheduler handle that was given to the `loop` 1880 * @param sh scheduler handle that was given to the `loop`
1869 * @return #GNUNET_OK if there are more tasks that are ready, 1881 * @return #GNUNET_OK if there are more tasks that are ready,
1870 * and thus we would like to run more (yield to avoid 1882 * and thus we would like to run more (yield to avoid
1871 * blocking other activities for too long) 1883 * blocking other activities for too long)
1872 * #GNUNET_NO if we are done running tasks (yield to block) 1884 * #GNUNET_NO if we are done running tasks (yield to block)
1873 * #GNUNET_SYSERR on error 1885 * #GNUNET_SYSERR on error, e.g. no tasks were ready
1874 */ 1886 */
1875int 1887int
1876GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) 1888GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
@@ -1894,9 +1906,27 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1894 pending_timeout_last = NULL; 1906 pending_timeout_last = NULL;
1895 queue_ready_task (pos); 1907 queue_ready_task (pos);
1896 } 1908 }
1909 pos = pending_head;
1910 while (NULL != pos)
1911 {
1912 struct GNUNET_SCHEDULER_Task *next = pos->next;
1913 if (now.abs_value_us >= pos->timeout.abs_value_us)
1914 {
1915 pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
1916 GNUNET_CONTAINER_DLL_remove (pending_head,
1917 pending_tail,
1918 pos);
1919 queue_ready_task (pos);
1920 }
1921 pos = next;
1922 }
1897 1923
1898 if (0 == ready_count) 1924 if (0 == ready_count)
1899 return GNUNET_NO; 1925 {
1926 LOG (GNUNET_ERROR_TYPE_ERROR,
1927 "GNUNET_SCHEDULER_run_from_driver was called, but no tasks are ready!\n");
1928 return GNUNET_SYSERR;
1929 }
1900 1930
1901 /* find out which task priority level we are going to 1931 /* find out which task priority level we are going to
1902 process this time */ 1932 process this time */
@@ -1916,49 +1946,74 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1916 while (NULL != (pos = ready_head[p])) 1946 while (NULL != (pos = ready_head[p]))
1917 { 1947 {
1918 GNUNET_CONTAINER_DLL_remove (ready_head[p], 1948 GNUNET_CONTAINER_DLL_remove (ready_head[p],
1919 ready_tail[p], 1949 ready_tail[p],
1920 pos); 1950 pos);
1921 ready_count--; 1951 ready_count--;
1922 current_priority = pos->priority; 1952 current_priority = pos->priority;
1923 current_lifeness = pos->lifeness; 1953 current_lifeness = pos->lifeness;
1924 active_task = pos; 1954 active_task = pos;
1925#if PROFILE_DELAYS 1955#if PROFILE_DELAYS
1926 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > 1956 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
1927 DELAY_THRESHOLD.rel_value_us) 1957 DELAY_THRESHOLD.rel_value_us)
1928 { 1958 {
1929 LOG (GNUNET_ERROR_TYPE_DEBUG, 1959 LOG (GNUNET_ERROR_TYPE_DEBUG,
1930 "Task %p took %s to be scheduled\n", 1960 "Task %p took %s to be scheduled\n",
1931 pos, 1961 pos,
1932 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), 1962 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time),
1933 GNUNET_YES)); 1963 GNUNET_YES));
1934 } 1964 }
1935#endif 1965#endif
1936 tc.reason = pos->reason; 1966 tc.reason = pos->reason;
1937 GNUNET_NETWORK_fdset_zero (sh->rs); 1967 GNUNET_NETWORK_fdset_zero (sh->rs);
1938 GNUNET_NETWORK_fdset_zero (sh->ws); 1968 GNUNET_NETWORK_fdset_zero (sh->ws);
1969 // FIXME: do we have to remove FdInfos from fds if they are not ready?
1939 tc.fds_len = pos->fds_len; 1970 tc.fds_len = pos->fds_len;
1940 tc.fds = pos->fds; 1971 tc.fds = pos->fds;
1941 tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set; 1972 for (int i = 0; i != pos->fds_len; ++i)
1942 if ( (-1 != pos->read_fd) && 1973 {
1943 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) 1974 struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
1944 GNUNET_NETWORK_fdset_set_native (sh->rs, 1975 if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
1945 pos->read_fd); 1976 {
1946 tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set; 1977 GNUNET_NETWORK_fdset_set_native (sh->rs,
1947 if ((-1 != pos->write_fd) && 1978 fdi->sock);
1948 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) 1979 }
1949 GNUNET_NETWORK_fdset_set_native (sh->ws, 1980 if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
1950 pos->write_fd); 1981 {
1982 GNUNET_NETWORK_fdset_set_native (sh->ws,
1983 fdi->sock);
1984 }
1985 }
1986 tc.read_ready = sh->rs;
1987 tc.write_ready = sh->ws;
1951 LOG (GNUNET_ERROR_TYPE_DEBUG, 1988 LOG (GNUNET_ERROR_TYPE_DEBUG,
1952 "Running task: %p\n", 1989 "Running task %p\n",
1953 pos); 1990 pos);
1991 GNUNET_assert (NULL != pos->callback);
1954 pos->callback (pos->callback_cls); 1992 pos->callback (pos->callback_cls);
1993 if (NULL != pos->fds)
1994 {
1995 int del_result = scheduler_driver->del (scheduler_driver->cls, pos);
1996 if (GNUNET_OK != del_result)
1997 {
1998 LOG (GNUNET_ERROR_TYPE_ERROR,
1999 "driver could not delete task\n");
2000 GNUNET_assert (0);
2001 }
2002 }
1955 active_task = NULL; 2003 active_task = NULL;
1956 dump_backtrace (pos); 2004 dump_backtrace (pos);
1957 destroy_task (pos); 2005 destroy_task (pos);
1958 tasks_run++; 2006 tasks_run++;
1959 } 2007 }
2008 shutdown_if_no_lifeness ();
1960 if (0 == ready_count) 2009 if (0 == ready_count)
2010 {
2011 scheduler_driver->set_wakeup (scheduler_driver->cls,
2012 get_timeout ());
1961 return GNUNET_NO; 2013 return GNUNET_NO;
2014 }
2015 scheduler_driver->set_wakeup (scheduler_driver->cls,
2016 GNUNET_TIME_absolute_get ());
1962 return GNUNET_OK; 2017 return GNUNET_OK;
1963} 2018}
1964 2019
@@ -1981,8 +2036,8 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1981 */ 2036 */
1982int 2037int
1983GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, 2038GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
1984 GNUNET_SCHEDULER_TaskCallback task, 2039 GNUNET_SCHEDULER_TaskCallback task,
1985 void *task_cls) 2040 void *task_cls)
1986{ 2041{
1987 int ret; 2042 int ret;
1988 struct GNUNET_SIGNAL_Context *shc_int; 2043 struct GNUNET_SIGNAL_Context *shc_int;
@@ -1997,7 +2052,6 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
1997#endif 2052#endif
1998 struct GNUNET_SCHEDULER_Task tsk; 2053 struct GNUNET_SCHEDULER_Task tsk;
1999 const struct GNUNET_DISK_FileHandle *pr; 2054 const struct GNUNET_DISK_FileHandle *pr;
2000 struct GNUNET_SCHEDULER_Handle sh;
2001 2055
2002 /* general set-up */ 2056 /* general set-up */
2003 GNUNET_assert (NULL == active_task); 2057 GNUNET_assert (NULL == active_task);
@@ -2009,54 +2063,56 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
2009 GNUNET_assert (NULL != shutdown_pipe_handle); 2063 GNUNET_assert (NULL != shutdown_pipe_handle);
2010 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, 2064 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
2011 GNUNET_DISK_PIPE_END_READ); 2065 GNUNET_DISK_PIPE_END_READ);
2012 GNUNET_assert (NULL != pr);
2013 my_pid = getpid (); 2066 my_pid = getpid ();
2067 scheduler_driver = driver;
2014 2068
2015 /* install signal handlers */ 2069 /* install signal handlers */
2016 LOG (GNUNET_ERROR_TYPE_DEBUG, 2070 LOG (GNUNET_ERROR_TYPE_DEBUG,
2017 "Registering signal handlers\n"); 2071 "Registering signal handlers\n");
2018 shc_int = GNUNET_SIGNAL_handler_install (SIGINT, 2072 shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2019 &sighandler_shutdown); 2073 &sighandler_shutdown);
2020 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, 2074 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2021 &sighandler_shutdown); 2075 &sighandler_shutdown);
2022#if (SIGTERM != GNUNET_TERM_SIG) 2076#if (SIGTERM != GNUNET_TERM_SIG)
2023 shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, 2077 shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG,
2024 &sighandler_shutdown); 2078 &sighandler_shutdown);
2025#endif 2079#endif
2026#ifndef MINGW 2080#ifndef MINGW
2027 shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, 2081 shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2028 &sighandler_pipe); 2082 &sighandler_pipe);
2029 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, 2083 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2030 &sighandler_shutdown); 2084 &sighandler_shutdown);
2031 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, 2085 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2032 &sighandler_shutdown); 2086 &sighandler_shutdown);
2033#endif 2087#endif
2034 2088
2035 /* Setup initial tasks */ 2089 /* Setup initial tasks */
2036 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; 2090 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
2037 current_lifeness = GNUNET_YES; 2091 current_lifeness = GNUNET_NO;
2038 memset (&tsk, 2092 memset (&tsk,
2039 0, 2093 0,
2040 sizeof (tsk)); 2094 sizeof (tsk));
2041 active_task = &tsk; 2095 active_task = &tsk;
2042 tsk.sh = &sh; 2096 GNUNET_SCHEDULER_add_now (&GNUNET_OS_install_parent_control_handler,
2097 NULL);
2098 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
2099 pr,
2100 &shutdown_cb,
2101 NULL);
2102 current_lifeness = GNUNET_YES;
2043 GNUNET_SCHEDULER_add_with_reason_and_priority (task, 2103 GNUNET_SCHEDULER_add_with_reason_and_priority (task,
2044 task_cls, 2104 task_cls,
2045 GNUNET_SCHEDULER_REASON_STARTUP, 2105 GNUNET_SCHEDULER_REASON_STARTUP,
2046 GNUNET_SCHEDULER_PRIORITY_DEFAULT); 2106 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
2047 GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO,
2048 &GNUNET_OS_install_parent_control_handler,
2049 NULL);
2050 active_task = NULL; 2107 active_task = NULL;
2051 driver->set_wakeup (driver->cls, 2108 scheduler_driver->set_wakeup (scheduler_driver->cls,
2052 GNUNET_TIME_absolute_get ()); 2109 get_timeout ());
2053
2054 /* begin main event loop */ 2110 /* begin main event loop */
2055 sh.rs = GNUNET_NETWORK_fdset_create (); 2111 sh.rs = GNUNET_NETWORK_fdset_create ();
2056 sh.ws = GNUNET_NETWORK_fdset_create (); 2112 sh.ws = GNUNET_NETWORK_fdset_create ();
2057 sh.driver = driver; 2113 GNUNET_NETWORK_fdset_handle_set (sh.rs, pr);
2058 ret = driver->loop (driver->cls, 2114 ret = driver->loop (driver->cls,
2059 &sh); 2115 &sh);
2060 GNUNET_NETWORK_fdset_destroy (sh.rs); 2116 GNUNET_NETWORK_fdset_destroy (sh.rs);
2061 GNUNET_NETWORK_fdset_destroy (sh.ws); 2117 GNUNET_NETWORK_fdset_destroy (sh.ws);
2062 2118
@@ -2073,20 +2129,215 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
2073#endif 2129#endif
2074 GNUNET_DISK_pipe_close (shutdown_pipe_handle); 2130 GNUNET_DISK_pipe_close (shutdown_pipe_handle);
2075 shutdown_pipe_handle = NULL; 2131 shutdown_pipe_handle = NULL;
2132 scheduler_driver = NULL;
2076 return ret; 2133 return ret;
2077} 2134}
2078 2135
2079 2136
2137int
2138select_add (void *cls,
2139 struct GNUNET_SCHEDULER_Task *task,
2140 struct GNUNET_SCHEDULER_FdInfo *fdi)
2141{
2142 struct DriverContext *context = cls;
2143 GNUNET_assert (NULL != context);
2144 GNUNET_assert (NULL != task);
2145 GNUNET_assert (NULL != fdi);
2146 GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2147 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2148
2149 if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2150 {
2151 /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2152 return GNUNET_SYSERR;
2153 }
2154
2155 struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2156 scheduled->task = task;
2157 scheduled->fdi = fdi;
2158 scheduled->et = fdi->et;
2159
2160 GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2161 context->scheduled_tail,
2162 scheduled);
2163 return GNUNET_OK;
2164}
2165
2166
2167int
2168select_del (void *cls,
2169 struct GNUNET_SCHEDULER_Task *task)
2170{
2171 struct DriverContext *context;
2172 struct Scheduled *pos;
2173 int ret;
2174
2175 GNUNET_assert (NULL != cls);
2176
2177 context = cls;
2178 ret = GNUNET_SYSERR;
2179 pos = context->scheduled_head;
2180 while (NULL != pos)
2181 {
2182 struct Scheduled *next = pos->next;
2183 if (pos->task == task)
2184 {
2185 GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2186 context->scheduled_tail,
2187 pos);
2188 GNUNET_free (pos);
2189 ret = GNUNET_OK;
2190 }
2191 pos = next;
2192 }
2193 return ret;
2194}
2195
2196
2197int
2198select_loop (void *cls,
2199 struct GNUNET_SCHEDULER_Handle *sh)
2200{
2201 struct GNUNET_NETWORK_FDSet *rs;
2202 struct GNUNET_NETWORK_FDSet *ws;
2203 struct DriverContext *context;
2204 int select_result;
2205 int tasks_ready;
2206
2207 context = cls;
2208 GNUNET_assert (NULL != context);
2209 rs = GNUNET_NETWORK_fdset_create ();
2210 ws = GNUNET_NETWORK_fdset_create ();
2211 tasks_ready = GNUNET_NO;
2212 while (NULL != context->scheduled_head ||
2213 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != context->timeout.rel_value_us)
2214 {
2215 LOG (GNUNET_ERROR_TYPE_DEBUG,
2216 "select timeout = %s\n",
2217 GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO));
2218
2219 GNUNET_NETWORK_fdset_zero (rs);
2220 GNUNET_NETWORK_fdset_zero (ws);
2221 struct Scheduled *pos;
2222 for (pos = context->scheduled_head; NULL != pos; pos = pos->next)
2223 {
2224 if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2225 {
2226 GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2227 }
2228 if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2229 {
2230 GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2231 }
2232 }
2233 if (NULL == scheduler_select)
2234 {
2235 select_result = GNUNET_NETWORK_socket_select (rs,
2236 ws,
2237 NULL,
2238 context->timeout);
2239 }
2240 else
2241 {
2242 select_result = scheduler_select (scheduler_select_cls,
2243 rs,
2244 ws,
2245 NULL,
2246 context->timeout);
2247 }
2248 if (select_result == GNUNET_SYSERR)
2249 {
2250 if (errno == EINTR)
2251 continue;
2252
2253 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "select");
2254#ifndef MINGW
2255#if USE_LSOF
2256 char lsof[512];
2257
2258 snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid ());
2259 (void) close (1);
2260 (void) dup2 (2, 1);
2261 if (0 != system (lsof))
2262 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
2263 "system");
2264#endif
2265#endif
2266#if DEBUG_FDS
2267 struct Scheduled *s;
2268 for (s = context->scheduled_head; NULL != s; s = s->next)
2269 {
2270 int flags = fcntl (s->fdi->sock, F_GETFD);
2271 if ((flags == -1) && (errno == EBADF))
2272 {
2273 LOG (GNUNET_ERROR_TYPE_ERROR,
2274 "Got invalid file descriptor %d!\n",
2275 s->fdi->sock);
2276 }
2277 }
2278#endif
2279 GNUNET_assert (0);
2280 GNUNET_NETWORK_fdset_destroy (rs);
2281 GNUNET_NETWORK_fdset_destroy (ws);
2282 return GNUNET_SYSERR;
2283 }
2284 for (pos = context->scheduled_head; NULL != pos; pos = pos->next)
2285 {
2286 int is_ready = GNUNET_NO;
2287 if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et) &&
2288 GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, pos->fdi->sock))
2289 {
2290 pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2291 is_ready = GNUNET_YES;
2292 }
2293 if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et) &&
2294 GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, pos->fdi->sock))
2295 {
2296 pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2297 is_ready = GNUNET_YES;
2298 }
2299 if (GNUNET_YES == is_ready)
2300 {
2301 GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi);
2302 }
2303 }
2304 tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh);
2305 GNUNET_assert (GNUNET_SYSERR != tasks_ready);
2306 }
2307 GNUNET_NETWORK_fdset_destroy (rs);
2308 GNUNET_NETWORK_fdset_destroy (ws);
2309 return GNUNET_OK;
2310}
2311
2312
2313void
2314select_set_wakeup(void *cls,
2315 struct GNUNET_TIME_Absolute dt)
2316{
2317 struct DriverContext *context = cls;
2318 GNUNET_assert (NULL != context);
2319
2320 context->timeout = GNUNET_TIME_absolute_get_remaining (dt);
2321}
2322
2323
2080/** 2324/**
2081 * Obtain the driver for using select() as the event loop. 2325 * Obtain the driver for using select() as the event loop.
2082 * 2326 *
2083 * @return NULL on error 2327 * @return NULL on error
2084 */ 2328 */
2085const struct GNUNET_SCHEDULER_Driver * 2329struct GNUNET_SCHEDULER_Driver *
2086GNUNET_SCHEDULER_driver_select () 2330GNUNET_SCHEDULER_driver_select ()
2087{ 2331{
2088 GNUNET_break (0); // not implemented 2332 struct GNUNET_SCHEDULER_Driver *select_driver;
2089 return NULL; 2333 select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2334
2335 select_driver->loop = &select_loop;
2336 select_driver->add = &select_add;
2337 select_driver->del = &select_del;
2338 select_driver->set_wakeup = &select_set_wakeup;
2339
2340 return select_driver;
2090} 2341}
2091 2342
2092 2343
diff --git a/src/util/service.c b/src/util/service.c
index fcdf45a51..b4eb33caa 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -1932,6 +1932,11 @@ do_send (void *cls)
1932 size_t left; 1932 size_t left;
1933 const char *buf; 1933 const char *buf;
1934 1934
1935 LOG (GNUNET_ERROR_TYPE_DEBUG,
1936 "service: sending message with type %u",
1937 ntohs(client->msg->type));
1938
1939
1935 client->send_task = NULL; 1940 client->send_task = NULL;
1936 buf = (const char *) client->msg; 1941 buf = (const char *) client->msg;
1937 left = ntohs (client->msg->size) - client->msg_pos; 1942 left = ntohs (client->msg->size) - client->msg_pos;
@@ -1941,6 +1946,8 @@ do_send (void *cls)
1941 GNUNET_assert (ret <= (ssize_t) left); 1946 GNUNET_assert (ret <= (ssize_t) left);
1942 if (0 == ret) 1947 if (0 == ret)
1943 { 1948 {
1949 LOG (GNUNET_ERROR_TYPE_DEBUG,
1950 "no data send");
1944 GNUNET_MQ_inject_error (client->mq, 1951 GNUNET_MQ_inject_error (client->mq,
1945 GNUNET_MQ_ERROR_WRITE); 1952 GNUNET_MQ_ERROR_WRITE);
1946 return; 1953 return;
@@ -1958,6 +1965,9 @@ do_send (void *cls)
1958 if (EPIPE != errno) 1965 if (EPIPE != errno)
1959 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 1966 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1960 "send"); 1967 "send");
1968 LOG (GNUNET_ERROR_TYPE_DEBUG,
1969 "socket send returned with error code %i",
1970 errno);
1961 GNUNET_MQ_inject_error (client->mq, 1971 GNUNET_MQ_inject_error (client->mq,
1962 GNUNET_MQ_ERROR_WRITE); 1972 GNUNET_MQ_ERROR_WRITE);
1963 return; 1973 return;
@@ -2402,7 +2412,7 @@ resume_client_receive (void *cls)
2402 GNUNET_YES); 2412 GNUNET_YES);
2403 if (GNUNET_SYSERR == ret) 2413 if (GNUNET_SYSERR == ret)
2404 { 2414 {
2405 if (NULL != c->drop_task) 2415 if (NULL == c->drop_task)
2406 GNUNET_SERVICE_client_drop (c); 2416 GNUNET_SERVICE_client_drop (c);
2407 return; 2417 return;
2408 } 2418 }
@@ -2431,6 +2441,7 @@ resume_client_receive (void *cls)
2431void 2441void
2432GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c) 2442GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
2433{ 2443{
2444 GNUNET_assert (NULL == c->drop_task);
2434 GNUNET_assert (GNUNET_YES == c->needs_continue); 2445 GNUNET_assert (GNUNET_YES == c->needs_continue);
2435 GNUNET_assert (NULL == c->recv_task); 2446 GNUNET_assert (NULL == c->recv_task);
2436 c->needs_continue = GNUNET_NO; 2447 c->needs_continue = GNUNET_NO;
@@ -2513,6 +2524,24 @@ GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
2513{ 2524{
2514 struct GNUNET_SERVICE_Handle *sh = c->sh; 2525 struct GNUNET_SERVICE_Handle *sh = c->sh;
2515 2526
2527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2528 "Client dropped: %p (MQ: %p)\n",
2529 c,
2530 c->mq);
2531
2532#if EXECINFO
2533 void *backtrace_array[MAX_TRACE_DEPTH];
2534 int num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH);
2535 char **backtrace_strings =
2536 backtrace_symbols (backtrace_array,
2537 t->num_backtrace_strings);
2538 for (unsigned int i = 0; i < num_backtrace_strings; i++)
2539 LOG (GNUNET_ERROR_TYPE_DEBUG,
2540 "client drop trace %u: %s\n",
2541 i,
2542 backtrace_strings[i]);
2543#endif
2544
2516 if (NULL != c->drop_task) 2545 if (NULL != c->drop_task)
2517 { 2546 {
2518 /* asked to drop twice! */ 2547 /* asked to drop twice! */
diff --git a/src/util/time.c b/src/util/time.c
index 19100ac36..5ffb19ec1 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -693,7 +693,7 @@ GNUNET_TIME_year_to_time (unsigned int year)
693 } 693 }
694 t.tm_year = year - 1900; 694 t.tm_year = year - 1900;
695 t.tm_mday = 1; 695 t.tm_mday = 1;
696 t.tm_mon = 1; 696 t.tm_mon = 0;
697 t.tm_wday = 1; 697 t.tm_wday = 1;
698 t.tm_yday = 1; 698 t.tm_yday = 1;
699 tp = mktime (&t); 699 tp = mktime (&t);
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index d9daaa7e2..bdc638176 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -2218,6 +2218,9 @@ route_packet (struct DestinationEntry *destination,
2218 * 2218 *
2219 * @param cls closure, NULL 2219 * @param cls closure, NULL
2220 * @param message message we got from the client (VPN channel interface) 2220 * @param message message we got from the client (VPN channel interface)
2221 * @return #GNUNET_OK on success,
2222 * #GNUNET_NO to stop further processing (no error)
2223 * #GNUNET_SYSERR to stop further processing with error
2221 */ 2224 */
2222static int 2225static int
2223message_token (void *cls, 2226message_token (void *cls,