diff options
author | Gabor X Toth <*@tg-x.net> | 2013-09-16 16:46:43 +0000 |
---|---|---|
committer | Gabor X Toth <*@tg-x.net> | 2013-09-16 16:46:43 +0000 |
commit | 4839fff11f31cac9af0cfbe1d67b6961d5f1b88f (patch) | |
tree | 2ccae35bf637e1bec185656f8c25b2693d0a29d4 /src/psyc | |
parent | 2745a5145a07c6effa7075391fb9ea74288ec83a (diff) | |
download | gnunet-4839fff11f31cac9af0cfbe1d67b6961d5f1b88f.tar.gz gnunet-4839fff11f31cac9af0cfbe1d67b6961d5f1b88f.zip |
psyc service skeleton
Diffstat (limited to 'src/psyc')
-rw-r--r-- | src/psyc/Makefile.am | 71 | ||||
-rw-r--r-- | src/psyc/gnunet-service-psyc.c | 115 | ||||
-rw-r--r-- | src/psyc/psyc.conf.in | 7 | ||||
-rw-r--r-- | src/psyc/psyc.h | 38 | ||||
-rw-r--r-- | src/psyc/psyc_api.c | 452 | ||||
-rw-r--r-- | src/psyc/test_psyc.c | 144 | ||||
-rw-r--r-- | src/psyc/test_psyc.conf | 11 |
7 files changed, 838 insertions, 0 deletions
diff --git a/src/psyc/Makefile.am b/src/psyc/Makefile.am new file mode 100644 index 000000000..b65f9ec7a --- /dev/null +++ b/src/psyc/Makefile.am | |||
@@ -0,0 +1,71 @@ | |||
1 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
2 | |||
3 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
4 | |||
5 | libexecdir= $(pkglibdir)/libexec/ | ||
6 | |||
7 | pkgcfg_DATA = \ | ||
8 | psyc.conf | ||
9 | |||
10 | |||
11 | if MINGW | ||
12 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
13 | endif | ||
14 | |||
15 | if USE_COVERAGE | ||
16 | AM_CFLAGS = --coverage -O0 | ||
17 | XLIB = -lgcov | ||
18 | endif | ||
19 | |||
20 | lib_LTLIBRARIES = libgnunetpsyc.la | ||
21 | |||
22 | libgnunetpsyc_la_SOURCES = \ | ||
23 | psyc_api.c \ | ||
24 | psyc.h | ||
25 | libgnunetpsyc_la_LIBADD = \ | ||
26 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
27 | $(GN_LIBINTL) $(XLIB) | ||
28 | libgnunetpsyc_la_LDFLAGS = \ | ||
29 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
30 | -version-info 0:0:0 | ||
31 | libgnunetpsyc_la_DEPENDENCIES = \ | ||
32 | $(top_builddir)/src/util/libgnunetutil.la | ||
33 | |||
34 | bin_PROGRAMS = | ||
35 | |||
36 | libexec_PROGRAMS = \ | ||
37 | gnunet-service-psyc | ||
38 | |||
39 | gnunet_service_psyc_SOURCES = \ | ||
40 | gnunet-service-psyc.c | ||
41 | gnunet_service_psyc_LDADD = \ | ||
42 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
43 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
44 | $(GN_LIBINTL) | ||
45 | gnunet_service_psyc_DEPENDENCIES = \ | ||
46 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
47 | $(top_builddir)/src/util/libgnunetutil.la | ||
48 | |||
49 | |||
50 | if HAVE_TESTING | ||
51 | check_PROGRAMS = \ | ||
52 | test_psyc | ||
53 | endif | ||
54 | |||
55 | if ENABLE_TEST_RUN | ||
56 | TESTS = $(check_PROGRAMS) | ||
57 | endif | ||
58 | |||
59 | test_psyc_SOURCES = \ | ||
60 | test_psyc.c | ||
61 | test_psyc_LDADD = \ | ||
62 | libgnunetpsyc.la \ | ||
63 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
64 | $(top_builddir)/src/util/libgnunetutil.la | ||
65 | test_psyc_DEPENDENCIES = \ | ||
66 | libgnunetpsyc.la \ | ||
67 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
68 | $(top_builddir)/src/util/libgnunetutil.la | ||
69 | |||
70 | EXTRA_DIST = \ | ||
71 | test_psyc.conf | ||
diff --git a/src/psyc/gnunet-service-psyc.c b/src/psyc/gnunet-service-psyc.c new file mode 100644 index 000000000..528b76e59 --- /dev/null +++ b/src/psyc/gnunet-service-psyc.c | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | * Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file psyc/gnunet-service-psyc.c | ||
23 | * @brief PSYC service | ||
24 | * @author Gabor X Toth | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_constants.h" | ||
30 | #include "gnunet_protocols.h" | ||
31 | #include "gnunet_statistics_service.h" | ||
32 | #include "gnunet_psyc_service.h" | ||
33 | #include "psyc.h" | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Handle to our current configuration. | ||
38 | */ | ||
39 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
40 | |||
41 | /** | ||
42 | * Handle to the statistics service. | ||
43 | */ | ||
44 | static struct GNUNET_STATISTICS_Handle *stats; | ||
45 | |||
46 | /** | ||
47 | * Notification context, simplifies client broadcasts. | ||
48 | */ | ||
49 | static struct GNUNET_SERVER_NotificationContext *nc; | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Task run during shutdown. | ||
54 | * | ||
55 | * @param cls unused | ||
56 | * @param tc unused | ||
57 | */ | ||
58 | static void | ||
59 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
60 | { | ||
61 | if (NULL != nc) | ||
62 | { | ||
63 | GNUNET_SERVER_notification_context_destroy (nc); | ||
64 | nc = NULL; | ||
65 | } | ||
66 | if (NULL != stats) | ||
67 | { | ||
68 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
69 | stats = NULL; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | |||
74 | /** | ||
75 | * Initialize the PSYC service. | ||
76 | * | ||
77 | * @param cls Closure. | ||
78 | * @param server The initialized server. | ||
79 | * @param c Configuration to use. | ||
80 | */ | ||
81 | static void | ||
82 | run (void *cls, struct GNUNET_SERVER_Handle *server, | ||
83 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
84 | { | ||
85 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { | ||
86 | { NULL, NULL, 0, 0 } | ||
87 | }; | ||
88 | |||
89 | cfg = c; | ||
90 | |||
91 | stats = GNUNET_STATISTICS_create ("psyc", cfg); | ||
92 | GNUNET_SERVER_add_handlers (server, handlers); | ||
93 | nc = GNUNET_SERVER_notification_context_create (server, 1); | ||
94 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, | ||
95 | NULL); | ||
96 | } | ||
97 | |||
98 | |||
99 | /** | ||
100 | * The main function for the service. | ||
101 | * | ||
102 | * @param argc number of arguments from the command line | ||
103 | * @param argv command line arguments | ||
104 | * @return 0 ok, 1 on error | ||
105 | */ | ||
106 | int | ||
107 | main (int argc, char *const *argv) | ||
108 | { | ||
109 | return (GNUNET_OK == | ||
110 | GNUNET_SERVICE_run (argc, argv, "psyc", | ||
111 | GNUNET_SERVICE_OPTION_NONE, | ||
112 | &run, NULL)) ? 0 : 1; | ||
113 | } | ||
114 | |||
115 | /* end of gnunet-service-psycstore.c */ | ||
diff --git a/src/psyc/psyc.conf.in b/src/psyc/psyc.conf.in new file mode 100644 index 000000000..5a1eebf61 --- /dev/null +++ b/src/psyc/psyc.conf.in | |||
@@ -0,0 +1,7 @@ | |||
1 | [psyc] | ||
2 | AUTOSTART = YES | ||
3 | HOME = $SERVICEHOME | ||
4 | BINARY = gnunet-service-psyc | ||
5 | UNIXPATH = /tmp/gnunet-service-psyc.sock | ||
6 | UNIX_MATCH_UID = NO | ||
7 | UNIX_MATCH_GID = YES | ||
diff --git a/src/psyc/psyc.h b/src/psyc/psyc.h new file mode 100644 index 000000000..c82c10ffa --- /dev/null +++ b/src/psyc/psyc.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | * Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file psyc/psyc.h | ||
23 | * @brief Common type definitions for the PSYC service and API. | ||
24 | * @author Gabor X Toth | ||
25 | */ | ||
26 | |||
27 | #ifndef GNUNET_PSYC_H | ||
28 | #define GNUNET_PSYC_H | ||
29 | |||
30 | #include "gnunet_common.h" | ||
31 | |||
32 | GNUNET_NETWORK_STRUCT_BEGIN | ||
33 | |||
34 | |||
35 | |||
36 | GNUNET_NETWORK_STRUCT_END | ||
37 | |||
38 | #endif | ||
diff --git a/src/psyc/psyc_api.c b/src/psyc/psyc_api.c new file mode 100644 index 000000000..8d07f5f79 --- /dev/null +++ b/src/psyc/psyc_api.c | |||
@@ -0,0 +1,452 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | * Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file psyc/psyc_api.c | ||
23 | * @brief PSYC service; high-level access to the PSYC protocol | ||
24 | * note that clients of this API are NOT expected to | ||
25 | * understand the PSYC message format, only the semantics! | ||
26 | * Parsing (and serializing) the PSYC stream format is done | ||
27 | * within the implementation of the libgnunetpsyc library, | ||
28 | * and this API deliberately exposes as little as possible | ||
29 | * of the actual data stream format to the application! | ||
30 | * @author Gabor X Toth | ||
31 | */ | ||
32 | |||
33 | #include "platform.h" | ||
34 | #include "gnunet_util_lib.h" | ||
35 | #include "gnunet_env_lib.h" | ||
36 | #include "gnunet_psyc_service.h" | ||
37 | #include "psyc.h" | ||
38 | |||
39 | /** | ||
40 | * Handle that identifies a join request. | ||
41 | * | ||
42 | * Used to match calls to #GNUNET_PSYC_JoinCallback to the | ||
43 | * corresponding calls to GNUNET_PSYC_join_decision(). | ||
44 | */ | ||
45 | struct GNUNET_PSYC_JoinHandle; | ||
46 | |||
47 | |||
48 | /** | ||
49 | * Handle for the master of a PSYC channel. | ||
50 | */ | ||
51 | struct GNUNET_PSYC_Master; | ||
52 | |||
53 | |||
54 | /** | ||
55 | * Handle for a pending PSYC transmission operation. | ||
56 | */ | ||
57 | struct GNUNET_PSYC_MasterTransmitHandle; | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Handle for a PSYC channel slave. | ||
62 | */ | ||
63 | struct GNUNET_PSYC_Slave; | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Handle for a pending PSYC transmission operation. | ||
68 | */ | ||
69 | struct GNUNET_PSYC_SlaveTransmitHandle; | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Handle to access PSYC channel operations for both the master and slaves. | ||
74 | */ | ||
75 | struct GNUNET_PSYC_Channel; | ||
76 | |||
77 | |||
78 | /** | ||
79 | * Handle to a story telling operation. | ||
80 | */ | ||
81 | struct GNUNET_PSYC_Story; | ||
82 | |||
83 | |||
84 | struct GNUNET_PSYC_StateQuery; | ||
85 | |||
86 | |||
87 | /** | ||
88 | * Function to call with the decision made for a join request. | ||
89 | * | ||
90 | * Must be called once and only once in response to an invocation of the | ||
91 | * #GNUNET_PSYC_JoinCallback. | ||
92 | * | ||
93 | * @param jh Join request handle. | ||
94 | * @param is_admitted #GNUNET_YES if joining is approved, | ||
95 | * #GNUNET_NO if it is disapproved. | ||
96 | * @param relay_count Number of relays given. | ||
97 | * @param relays Array of suggested peers that might be useful relays to use | ||
98 | * when joining the multicast group (essentially a list of peers that | ||
99 | * are already part of the multicast group and might thus be willing | ||
100 | * to help with routing). If empty, only this local peer (which must | ||
101 | * be the multicast origin) is a good candidate for building the | ||
102 | * multicast tree. Note that it is unnecessary to specify our own | ||
103 | * peer identity in this array. | ||
104 | * @param method_name Method name for the message transmitted with the response. | ||
105 | * @param env Environment containing transient variables for the message, or NULL. | ||
106 | * @param data Data of the message. | ||
107 | * @param data_size Size of @a data. | ||
108 | */ | ||
109 | void | ||
110 | GNUNET_PSYC_join_decision (struct GNUNET_PSYC_JoinHandle *jh, | ||
111 | int is_admitted, | ||
112 | unsigned int relay_count, | ||
113 | const struct GNUNET_PeerIdentity *relays, | ||
114 | const char *method_name, | ||
115 | const struct GNUNET_ENV_Environment *env, | ||
116 | const void *data, | ||
117 | size_t data_size); | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Start a PSYC master channel. | ||
122 | * | ||
123 | * Will start a multicast group identified by the given ECC key. Messages | ||
124 | * received from group members will be given to the respective handler methods. | ||
125 | * If a new member wants to join a group, the "join" method handler will be | ||
126 | * invoked; the join handler must then generate a "join" message to approve the | ||
127 | * joining of the new member. The channel can also change group membership | ||
128 | * without explicit requests. Note that PSYC doesn't itself "understand" join | ||
129 | * or part messages, the respective methods must call other PSYC functions to | ||
130 | * inform PSYC about the meaning of the respective events. | ||
131 | * | ||
132 | * @param cfg Configuration to use (to connect to PSYC service). | ||
133 | * @param channel_key ECC key that will be used to sign messages for this | ||
134 | * PSYC session. The public key is used to identify the PSYC channel. | ||
135 | * Note that end-users will usually not use the private key directly, but | ||
136 | * rather look it up in GADS for places managed by other users, or select | ||
137 | * a file with the private key(s) when setting up their own channels | ||
138 | * FIXME: we'll likely want to use NOT the p521 curve here, but a cheaper | ||
139 | * one in the future. | ||
140 | * @param policy Channel policy specifying join and history restrictions. | ||
141 | * Used to automate join decisions. | ||
142 | * @param method Function to invoke on messages received from slaves. | ||
143 | * @param join_cb Function to invoke when a peer wants to join. | ||
144 | * @param cls Closure for @a method and @a join_cb. | ||
145 | * @return Handle for the channel master, NULL on error. | ||
146 | */ | ||
147 | struct GNUNET_PSYC_Master * | ||
148 | GNUNET_PSYC_master_start (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
149 | const struct GNUNET_CRYPTO_EccPrivateKey *channel_key, | ||
150 | enum GNUNET_PSYC_Policy policy, | ||
151 | GNUNET_PSYC_Method method, | ||
152 | GNUNET_PSYC_JoinCallback join_cb, | ||
153 | void *cls); | ||
154 | |||
155 | |||
156 | /** | ||
157 | * Send a message to call a method to all members in the PSYC channel. | ||
158 | * | ||
159 | * @param master Handle to the PSYC channel. | ||
160 | * @param method_name Which method should be invoked. | ||
161 | * @param env Environment containing state operations and transient variables | ||
162 | * for the message, or NULL. | ||
163 | * @param notify Function to call to obtain the arguments. | ||
164 | * @param notify_cls Closure for @a notify. | ||
165 | * @param flags Flags for the message being transmitted. | ||
166 | * @return Transmission handle, NULL on error (i.e. more than one request queued). | ||
167 | */ | ||
168 | struct GNUNET_PSYC_MasterTransmitHandle * | ||
169 | GNUNET_PSYC_master_transmit (struct GNUNET_PSYC_Master *master, | ||
170 | const char *method_name, | ||
171 | const struct GNUNET_ENV_Environment *env, | ||
172 | GNUNET_PSYC_MasterTransmitNotify notify, | ||
173 | void *notify_cls, | ||
174 | enum GNUNET_PSYC_MasterTransmitFlags flags); | ||
175 | |||
176 | |||
177 | /** | ||
178 | * Abort transmission request to channel. | ||
179 | * | ||
180 | * @param th Handle of the request that is being aborted. | ||
181 | */ | ||
182 | void | ||
183 | GNUNET_PSYC_master_transmit_cancel (struct GNUNET_PSYC_MasterTransmitHandle *th); | ||
184 | |||
185 | |||
186 | /** | ||
187 | * Stop a PSYC master channel. | ||
188 | * | ||
189 | * @param master PSYC channel master to stop. | ||
190 | */ | ||
191 | void | ||
192 | GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *master); | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Join a PSYC channel. | ||
197 | * | ||
198 | * The entity joining is always the local peer. The user must immediately use | ||
199 | * the GNUNET_PSYC_slave_to_master() functions to transmit a @e join_msg to the | ||
200 | * channel; if the join request succeeds, the channel state (and @e recent | ||
201 | * method calls) will be replayed to the joining member. There is no explicit | ||
202 | * notification on failure (as the channel may simply take days to approve, | ||
203 | * and disapproval is simply being ignored). | ||
204 | * | ||
205 | * @param cfg Configuration to use. | ||
206 | * @param channel_key ECC public key that identifies the channel we wish to join. | ||
207 | * @param slave_key ECC private-public key pair that identifies the slave, and | ||
208 | * used by multicast to sign the join request and subsequent unicast | ||
209 | * requests sent to the master. | ||
210 | * @param origin Peer identity of the origin. | ||
211 | * @param relay_count Number of peers in the @a relays array. | ||
212 | * @param relays Peer identities of members of the multicast group, which serve | ||
213 | * as relays and used to join the group at. | ||
214 | * @param method Function to invoke on messages received from the channel, | ||
215 | * typically at least contains functions for @e join and @e part. | ||
216 | * @param join_cb Function to invoke when a peer wants to join. | ||
217 | * @param cls Closure for @a method_cb and @a join_cb. | ||
218 | * @param method_name Method name for the join request. | ||
219 | * @param env Environment containing transient variables for the request, or NULL. | ||
220 | * @param data Payload for the join message. | ||
221 | * @param data_size Number of bytes in @a data. | ||
222 | * @return Handle for the slave, NULL on error. | ||
223 | */ | ||
224 | struct GNUNET_PSYC_Slave * | ||
225 | GNUNET_PSYC_slave_join (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
226 | const struct GNUNET_CRYPTO_EccPublicSignKey *channel_key, | ||
227 | const struct GNUNET_CRYPTO_EccPrivateKey *slave_key, | ||
228 | const struct GNUNET_PeerIdentity *origin, | ||
229 | size_t relay_count, | ||
230 | const struct GNUNET_PeerIdentity *relays, | ||
231 | GNUNET_PSYC_Method method, | ||
232 | GNUNET_PSYC_JoinCallback join_cb, | ||
233 | void *cls, | ||
234 | const char *method_name, | ||
235 | const struct GNUNET_ENV_Environment *env, | ||
236 | const void *data, | ||
237 | size_t data_size); | ||
238 | |||
239 | |||
240 | /** | ||
241 | * Part a PSYC channel. | ||
242 | * | ||
243 | * Will terminate the connection to the PSYC service. Polite clients should | ||
244 | * first explicitly send a @e part request (via GNUNET_PSYC_slave_to_master()). | ||
245 | * | ||
246 | * @param slave Slave handle. | ||
247 | */ | ||
248 | void | ||
249 | GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slave); | ||
250 | |||
251 | |||
252 | /** | ||
253 | * Request a message to be sent to the channel master. | ||
254 | * | ||
255 | * @param slave Slave handle. | ||
256 | * @param method_name Which (PSYC) method should be invoked (on host). | ||
257 | * @param env Environment containing transient variables for the message, or NULL. | ||
258 | * @param notify Function to call when we are allowed to transmit (to get data). | ||
259 | * @param notify_cls Closure for @a notify. | ||
260 | * @param flags Flags for the message being transmitted. | ||
261 | * @return Transmission handle, NULL on error (i.e. more than one request queued). | ||
262 | */ | ||
263 | struct GNUNET_PSYC_SlaveTransmitHandle * | ||
264 | GNUNET_PSYC_slave_transmit (struct GNUNET_PSYC_Slave *slave, | ||
265 | const char *method_name, | ||
266 | const struct GNUNET_ENV_Environment *env, | ||
267 | GNUNET_PSYC_SlaveTransmitNotify notify, | ||
268 | void *notify_cls, | ||
269 | enum GNUNET_PSYC_SlaveTransmitFlags flags); | ||
270 | |||
271 | |||
272 | /** | ||
273 | * Abort transmission request to master. | ||
274 | * | ||
275 | * @param th Handle of the request that is being aborted. | ||
276 | */ | ||
277 | void | ||
278 | GNUNET_PSYC_slave_transmit_cancel (struct GNUNET_PSYC_SlaveTransmitHandle *th); | ||
279 | |||
280 | |||
281 | /** | ||
282 | * Convert a channel @a master to a @e channel handle to access the @e channel APIs. | ||
283 | * | ||
284 | * @param master Channel master handle. | ||
285 | * @return Channel handle, valid for as long as @a master is valid. | ||
286 | */ | ||
287 | struct GNUNET_PSYC_Channel * | ||
288 | GNUNET_PSYC_master_get_channel (struct GNUNET_PSYC_Master *master); | ||
289 | |||
290 | |||
291 | /** | ||
292 | * Convert @a slave to a @e channel handle to access the @e channel APIs. | ||
293 | * | ||
294 | * @param slave Slave handle. | ||
295 | * @return Channel handle, valid for as long as @a slave is valid. | ||
296 | */ | ||
297 | struct GNUNET_PSYC_Channel * | ||
298 | GNUNET_PSYC_slave_get_channel (struct GNUNET_PSYC_Slave *slave); | ||
299 | |||
300 | |||
301 | /** | ||
302 | * Add a slave to the channel's membership list. | ||
303 | * | ||
304 | * Note that this will NOT generate any PSYC traffic, it will merely update the | ||
305 | * local database to modify how we react to <em>membership test</em> queries. | ||
306 | * The channel master still needs to explicitly transmit a @e join message to | ||
307 | * notify other channel members and they then also must still call this function | ||
308 | * in their respective methods handling the @e join message. This way, how @e | ||
309 | * join and @e part operations are exactly implemented is still up to the | ||
310 | * application; for example, there might be a @e part_all method to kick out | ||
311 | * everyone. | ||
312 | * | ||
313 | * Note that channel slaves are explicitly trusted to execute such methods | ||
314 | * correctly; not doing so correctly will result in either denying other slaves | ||
315 | * access or offering access to channel data to non-members. | ||
316 | * | ||
317 | * @param channel Channel handle. | ||
318 | * @param slave_key Identity of channel slave to add. | ||
319 | * @param announced_at ID of the message that announced the membership change. | ||
320 | * @param effective_since Addition of slave is in effect since this message ID. | ||
321 | */ | ||
322 | void | ||
323 | GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *channel, | ||
324 | const struct GNUNET_CRYPTO_EccPublicSignKey *slave_key, | ||
325 | uint64_t announced_at, | ||
326 | uint64_t effective_since); | ||
327 | |||
328 | |||
329 | /** | ||
330 | * Remove a slave from the channel's membership list. | ||
331 | * | ||
332 | * Note that this will NOT generate any PSYC traffic, it will merely update the | ||
333 | * local database to modify how we react to <em>membership test</em> queries. | ||
334 | * The channel master still needs to explicitly transmit a @e part message to | ||
335 | * notify other channel members and they then also must still call this function | ||
336 | * in their respective methods handling the @e part message. This way, how | ||
337 | * @e join and @e part operations are exactly implemented is still up to the | ||
338 | * application; for example, there might be a @e part_all message to kick out | ||
339 | * everyone. | ||
340 | * | ||
341 | * Note that channel members are explicitly trusted to perform these | ||
342 | * operations correctly; not doing so correctly will result in either | ||
343 | * denying members access or offering access to channel data to | ||
344 | * non-members. | ||
345 | * | ||
346 | * @param channel Channel handle. | ||
347 | * @param slave_key Identity of channel slave to remove. | ||
348 | * @param announced_at ID of the message that announced the membership change. | ||
349 | */ | ||
350 | void | ||
351 | GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *channel, | ||
352 | const struct GNUNET_CRYPTO_EccPublicSignKey *slave_key, | ||
353 | uint64_t announced_at); | ||
354 | |||
355 | |||
356 | /** | ||
357 | * Request to be told the message history of the channel. | ||
358 | * | ||
359 | * Historic messages (but NOT the state at the time) will be replayed (given to | ||
360 | * the normal method handlers) if available and if access is permitted. | ||
361 | * | ||
362 | * To get the latest message, use 0 for both the start and end message ID. | ||
363 | * | ||
364 | * @param channel Which channel should be replayed? | ||
365 | * @param start_message_id Earliest interesting point in history. | ||
366 | * @param end_message_id Last (exclusive) interesting point in history. | ||
367 | * @param method Function to invoke on messages received from the story. | ||
368 | * @param finish_cb Function to call when the requested story has been fully | ||
369 | * told (counting message IDs might not suffice, as some messages | ||
370 | * might be secret and thus the listener would not know the story is | ||
371 | * finished without being told explicitly); once this function | ||
372 | * has been called, the client must not call | ||
373 | * GNUNET_PSYC_channel_story_tell_cancel() anymore. | ||
374 | * @param cls Closure for the callbacks. | ||
375 | * @return Handle to cancel story telling operation. | ||
376 | */ | ||
377 | struct GNUNET_PSYC_Story * | ||
378 | GNUNET_PSYC_channel_story_tell (struct GNUNET_PSYC_Channel *channel, | ||
379 | uint64_t start_message_id, | ||
380 | uint64_t end_message_id, | ||
381 | GNUNET_PSYC_Method method, | ||
382 | GNUNET_PSYC_FinishCallback *finish_cb, | ||
383 | void *cls); | ||
384 | |||
385 | |||
386 | /** | ||
387 | * Abort story telling. | ||
388 | * | ||
389 | * This function must not be called from within method handlers (as given to | ||
390 | * GNUNET_PSYC_slave_join()) of the slave. | ||
391 | * | ||
392 | * @param story Story telling operation to stop. | ||
393 | */ | ||
394 | void | ||
395 | GNUNET_PSYC_channel_story_tell_cancel (struct GNUNET_PSYC_Story *story); | ||
396 | |||
397 | |||
398 | /** | ||
399 | * Retrieve the best matching channel state variable. | ||
400 | * | ||
401 | * If the requested variable name is not present in the state, the nearest | ||
402 | * less-specific name is matched; for example, requesting "_a_b" will match "_a" | ||
403 | * if "_a_b" does not exist. | ||
404 | * | ||
405 | * @param channel Channel handle. | ||
406 | * @param full_name Full name of the requested variable, the actual variable | ||
407 | * returned might have a shorter name.. | ||
408 | * @param cb Function called once when a matching state variable is found. | ||
409 | * Not called if there's no matching state variable. | ||
410 | * @param cb_cls Closure for the callbacks. | ||
411 | * @return Handle that can be used to cancel the query operation. | ||
412 | */ | ||
413 | struct GNUNET_PSYC_StateQuery * | ||
414 | GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel, | ||
415 | const char *full_name, | ||
416 | GNUNET_PSYC_StateCallback cb, | ||
417 | void *cb_cls); | ||
418 | |||
419 | |||
420 | /** | ||
421 | * Return all channel state variables whose name matches a given prefix. | ||
422 | * | ||
423 | * A name matches if it starts with the given @a name_prefix, thus requesting the | ||
424 | * empty prefix ("") will match all values; requesting "_a_b" will also return | ||
425 | * values stored under "_a_b_c". | ||
426 | * | ||
427 | * The @a state_cb is invoked on all matching state variables asynchronously, as | ||
428 | * the state is stored in and retrieved from the PSYCstore, | ||
429 | * | ||
430 | * @param channel Channel handle. | ||
431 | * @param name_prefix Prefix of the state variable name to match. | ||
432 | * @param cb Function to call with the matching state variables. | ||
433 | * @param cb_cls Closure for the callbacks. | ||
434 | * @return Handle that can be used to cancel the query operation. | ||
435 | */ | ||
436 | struct GNUNET_PSYC_StateQuery * | ||
437 | GNUNET_PSYC_channel_state_get_prefix (struct GNUNET_PSYC_Channel *channel, | ||
438 | const char *name_prefix, | ||
439 | GNUNET_PSYC_StateCallback cb, | ||
440 | void *cb_cls); | ||
441 | |||
442 | |||
443 | /** | ||
444 | * Cancel a state query operation. | ||
445 | * | ||
446 | * @param query Handle for the operation to cancel. | ||
447 | */ | ||
448 | void | ||
449 | GNUNET_PSYC_channel_state_get_cancel (struct GNUNET_PSYC_StateQuery *query); | ||
450 | |||
451 | |||
452 | /* end of psyc_api.c */ | ||
diff --git a/src/psyc/test_psyc.c b/src/psyc/test_psyc.c new file mode 100644 index 000000000..b37b3ceb1 --- /dev/null +++ b/src/psyc/test_psyc.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | * Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file psycstore/test_psycstore.c | ||
23 | * @brief Test for the PSYCstore service. | ||
24 | * @author Gabor X Toth | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_common.h" | ||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "gnunet_psycstore_service.h" | ||
32 | #include "gnunet_testing_lib.h" | ||
33 | |||
34 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
35 | |||
36 | #define DEBUG_SERVICE 0 | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Return value from 'main'. | ||
41 | */ | ||
42 | static int res; | ||
43 | |||
44 | /** | ||
45 | * Handle for task for timeout termination. | ||
46 | */ | ||
47 | static GNUNET_SCHEDULER_TaskIdentifier end_badly_task; | ||
48 | |||
49 | |||
50 | /** | ||
51 | * Clean up all resources used. | ||
52 | */ | ||
53 | static void | ||
54 | cleanup () | ||
55 | { | ||
56 | GNUNET_SCHEDULER_shutdown (); | ||
57 | } | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Terminate the testcase (failure). | ||
62 | * | ||
63 | * @param cls NULL | ||
64 | * @param tc scheduler context | ||
65 | */ | ||
66 | static void | ||
67 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
68 | { | ||
69 | res = 1; | ||
70 | cleanup (); | ||
71 | } | ||
72 | |||
73 | |||
74 | /** | ||
75 | * Terminate the testcase (success). | ||
76 | * | ||
77 | * @param cls NULL | ||
78 | * @param tc scheduler context | ||
79 | */ | ||
80 | static void | ||
81 | end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
82 | { | ||
83 | res = 0; | ||
84 | cleanup (); | ||
85 | } | ||
86 | |||
87 | |||
88 | /** | ||
89 | * Finish the testcase (successfully). | ||
90 | */ | ||
91 | static void | ||
92 | end () | ||
93 | { | ||
94 | if (end_badly_task != GNUNET_SCHEDULER_NO_TASK) | ||
95 | { | ||
96 | GNUNET_SCHEDULER_cancel (end_badly_task); | ||
97 | end_badly_task = GNUNET_SCHEDULER_NO_TASK; | ||
98 | } | ||
99 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | ||
100 | &end_normally, NULL); | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * Main function of the test, run from scheduler. | ||
105 | * | ||
106 | * @param cls NULL | ||
107 | * @param cfg configuration we use (also to connect to PSYCstore service) | ||
108 | * @param peer handle to access more of the peer (not used) | ||
109 | */ | ||
110 | static void | ||
111 | #if DEBUG_SERVICE | ||
112 | run (void *cls, char *const *args, const char *cfgfile, | ||
113 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
114 | #else | ||
115 | run (void *cls, | ||
116 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
117 | struct GNUNET_TESTING_Peer *peer) | ||
118 | #endif | ||
119 | { | ||
120 | end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); | ||
121 | } | ||
122 | |||
123 | |||
124 | int | ||
125 | main (int argc, char *argv[]) | ||
126 | { | ||
127 | res = 1; | ||
128 | #if DEBUG_SERVICE | ||
129 | const struct GNUNET_GETOPT_CommandLineOption opts[] = { | ||
130 | GNUNET_GETOPT_OPTION_END | ||
131 | }; | ||
132 | if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psyc", | ||
133 | "test-psyc [options]", | ||
134 | opts, &run, NULL)) | ||
135 | return 1; | ||
136 | #else | ||
137 | if (0 != GNUNET_TESTING_service_run ("test-psyc", "psyc", | ||
138 | "test_psyc.conf", &run, NULL)) | ||
139 | return 1; | ||
140 | #endif | ||
141 | return res; | ||
142 | } | ||
143 | |||
144 | /* end of test_psyc.c */ | ||
diff --git a/src/psyc/test_psyc.conf b/src/psyc/test_psyc.conf new file mode 100644 index 000000000..b5d3fd3fc --- /dev/null +++ b/src/psyc/test_psyc.conf | |||
@@ -0,0 +1,11 @@ | |||
1 | [arm] | ||
2 | UNIXPATH = /tmp/test-gnunet-service-arm.sock | ||
3 | DEFAULTSERVICES = psyc | ||
4 | |||
5 | [psyc] | ||
6 | AUTOSTART = YES | ||
7 | HOME = $SERVICEHOME | ||
8 | BINARY = gnunet-service-psyc | ||
9 | UNIXPATH = /tmp/test-gnunet-service-psyc.sock | ||
10 | UNIX_MATCH_UID = NO | ||
11 | UNIX_MATCH_GID = YES | ||