diff options
author | Florian Dold <florian.dold@gmail.com> | 2012-11-21 20:56:49 +0000 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2012-11-21 20:56:49 +0000 |
commit | 6b1559589726297aa372048b4e388d2e1473a6f6 (patch) | |
tree | e4edfd3bc5865905de4db27229427ac998484824 /src/consensus | |
parent | 84d88f3ddc67f50c4493a20f33883c9242fd0d57 (diff) | |
download | gnunet-6b1559589726297aa372048b4e388d2e1473a6f6.tar.gz gnunet-6b1559589726297aa372048b4e388d2e1473a6f6.zip |
started implementing consensus api and service
Diffstat (limited to 'src/consensus')
-rw-r--r-- | src/consensus/Makefile.am | 35 | ||||
-rw-r--r-- | src/consensus/consensus.h | 95 | ||||
-rw-r--r-- | src/consensus/consensus_api.c | 502 | ||||
-rw-r--r-- | src/consensus/gnunet-service-consensus.cc | 74 | ||||
-rw-r--r-- | src/consensus/test_consensus.conf | 15 | ||||
-rw-r--r-- | src/consensus/test_consensus_api.c | 73 |
6 files changed, 779 insertions, 15 deletions
diff --git a/src/consensus/Makefile.am b/src/consensus/Makefile.am index 5929a4d97..4eb06ceea 100644 --- a/src/consensus/Makefile.am +++ b/src/consensus/Makefile.am | |||
@@ -21,6 +21,9 @@ bin_PROGRAMS = \ | |||
21 | libexec_PROGRAMS = \ | 21 | libexec_PROGRAMS = \ |
22 | gnunet-service-consensus | 22 | gnunet-service-consensus |
23 | 23 | ||
24 | lib_LTLIBRARIES = \ | ||
25 | libgnunetconsensus.la | ||
26 | |||
24 | gnunet_consensus_SOURCES = \ | 27 | gnunet_consensus_SOURCES = \ |
25 | gnunet-consensus.c | 28 | gnunet-consensus.c |
26 | gnunet_consensus_LDADD = \ | 29 | gnunet_consensus_LDADD = \ |
@@ -33,16 +36,28 @@ gnunet_service_consensus_LDADD = \ | |||
33 | $(top_builddir)/src/util/libgnunetutil.la \ | 36 | $(top_builddir)/src/util/libgnunetutil.la \ |
34 | $(GN_LIBINTL) | 37 | $(GN_LIBINTL) |
35 | 38 | ||
39 | libgnunetconsensus_la_SOURCES = \ | ||
40 | consensus_api.c | ||
41 | libgnunetconsensus_la_LIBADD = \ | ||
42 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
43 | $(LTLIBINTL) | ||
44 | libgnunetconsensus_la_LDFLAGS = \ | ||
45 | $(GN_LIB_LDFLAGS) | ||
46 | |||
47 | check_PROGRAMS = \ | ||
48 | test_consensus_api | ||
36 | 49 | ||
37 | #check_PROGRAMS = \ | 50 | if ENABLE_TEST_RUN |
38 | # test_consensus_api | 51 | TESTS = $(check_PROGRAMS) |
52 | endif | ||
53 | |||
54 | test_consensus_api_SOURCES = \ | ||
55 | test_consensus_api.c | ||
56 | test_consensus_api_LDADD = \ | ||
57 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
58 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
59 | $(top_builddir)/src/consensus/libgnunetconsensus.la | ||
39 | 60 | ||
40 | #if ENABLE_TEST_RUN | ||
41 | #TESTS = $(check_PROGRAMS) | ||
42 | #endif | ||
43 | # | ||
44 | #test_consensus_api_SOURCES = \ | ||
45 | # test_consensus_api.c | ||
46 | #test_consensus_api_LDADD = \ | ||
47 | # $(top_builddir)/src/util/libgnunetutil.la | ||
48 | 61 | ||
62 | EXTRA_DIST = \ | ||
63 | test_consensus.conf | ||
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h new file mode 100644 index 000000000..3f1efe340 --- /dev/null +++ b/src/consensus/consensus.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 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 2, 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 | * @author Florian Dold | ||
23 | * @file consensus/consensus.h | ||
24 | * @brief | ||
25 | */ | ||
26 | #ifndef NSE_H | ||
27 | #define NSE_H | ||
28 | |||
29 | #include "gnunet_common.h" | ||
30 | |||
31 | GNUNET_NETWORK_STRUCT_BEGIN | ||
32 | |||
33 | struct GNUNET_CONSENSUS_JoinMessage | ||
34 | { | ||
35 | /** | ||
36 | * Type: GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN | ||
37 | */ | ||
38 | struct GNUNET_MessageHeader header; | ||
39 | |||
40 | struct GNUNET_HashCode session_id; | ||
41 | |||
42 | uint16_t num_peers; | ||
43 | |||
44 | /* GNUNET_PeerIdentity[num_peers] */ | ||
45 | }; | ||
46 | |||
47 | |||
48 | struct GNUNET_CONSENSUS_ConcludeMessage | ||
49 | { | ||
50 | /** | ||
51 | * Type: GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE | ||
52 | */ | ||
53 | struct GNUNET_MessageHeader header; | ||
54 | |||
55 | struct GNUNET_TIME_RelativeNBO timeout; | ||
56 | }; | ||
57 | |||
58 | |||
59 | struct GNUNET_CONSENSUS_ConcludeDoneMessage | ||
60 | { | ||
61 | /** | ||
62 | * Type: GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE | ||
63 | */ | ||
64 | struct GNUNET_MessageHeader header; | ||
65 | |||
66 | uint16_t num_peers; | ||
67 | |||
68 | /** PeerIdentity[num_peers] */ | ||
69 | }; | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Message with an element | ||
74 | */ | ||
75 | struct GNUNET_CONSENSUS_ElementMessage | ||
76 | { | ||
77 | |||
78 | /** | ||
79 | * Type: | ||
80 | * Either GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT | ||
81 | * or GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT_ELEMENT | ||
82 | */ | ||
83 | struct GNUNET_MessageHeader header; | ||
84 | |||
85 | /** | ||
86 | * Type: GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_NEW_ELEMENT | ||
87 | */ | ||
88 | uint16_t element_type; | ||
89 | |||
90 | /* rest: element data */ | ||
91 | }; | ||
92 | |||
93 | GNUNET_NETWORK_STRUCT_END | ||
94 | |||
95 | #endif | ||
diff --git a/src/consensus/consensus_api.c b/src/consensus/consensus_api.c new file mode 100644 index 000000000..0d7e6c8e4 --- /dev/null +++ b/src/consensus/consensus_api.c | |||
@@ -0,0 +1,502 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 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 consensus/consensus_api.c | ||
23 | * @brief | ||
24 | * @author Florian Dold | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_protocols.h" | ||
28 | #include "gnunet_client_lib.h" | ||
29 | #include "gnunet_consensus_service.h" | ||
30 | #include "consensus.h" | ||
31 | |||
32 | |||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "consensus-api",__VA_ARGS__) | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Handle for the service. | ||
38 | */ | ||
39 | struct GNUNET_CONSENSUS_Handle | ||
40 | { | ||
41 | /** | ||
42 | * Configuration to use. | ||
43 | */ | ||
44 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
45 | |||
46 | /** | ||
47 | * Socket (if available). | ||
48 | */ | ||
49 | struct GNUNET_CLIENT_Connection *client; | ||
50 | |||
51 | /** | ||
52 | * Callback for new elements. Not called for elements added locally. | ||
53 | */ | ||
54 | GNUNET_CONSENSUS_NewElementCallback new_element_cb; | ||
55 | |||
56 | /** | ||
57 | * Closure for new_element_cb | ||
58 | */ | ||
59 | void *new_element_cls; | ||
60 | |||
61 | /** | ||
62 | * Session identifier for the consensus session. | ||
63 | */ | ||
64 | struct GNUNET_HashCode session_id; | ||
65 | |||
66 | /** | ||
67 | * Number of peers in the consensus. Optionally includes the local peer. | ||
68 | */ | ||
69 | int num_peers; | ||
70 | |||
71 | /** | ||
72 | * Peer identities of peers in the consensus. Optionally includes the local peer. | ||
73 | */ | ||
74 | struct GNUNET_PeerIdentity *peers; | ||
75 | |||
76 | /** | ||
77 | * Currently active transmit request. | ||
78 | */ | ||
79 | struct GNUNET_CLIENT_TransmitHandle *th; | ||
80 | |||
81 | /** | ||
82 | * GNUNES_YES iff the join message has been sent to the service. | ||
83 | */ | ||
84 | int joined; | ||
85 | |||
86 | /** | ||
87 | * Called when the current insertion operation finishes. | ||
88 | * NULL if there is no insert operation active. | ||
89 | */ | ||
90 | GNUNET_CONSENSUS_InsertDoneCallback idc; | ||
91 | |||
92 | /** | ||
93 | * Closure for the insert done callback. | ||
94 | */ | ||
95 | void *idc_cls; | ||
96 | |||
97 | /** | ||
98 | * An element that was requested to be inserted. | ||
99 | */ | ||
100 | struct GNUNET_CONSENSUS_Element *insert_element; | ||
101 | |||
102 | /** | ||
103 | * Called when the conclude operation finishes or fails. | ||
104 | */ | ||
105 | GNUNET_CONSENSUS_ConcludeCallback conclude_cb; | ||
106 | |||
107 | /** | ||
108 | * Closure for the conclude callback. | ||
109 | */ | ||
110 | void *conclude_cls; | ||
111 | |||
112 | /** | ||
113 | * Deadline for the conclude operation. | ||
114 | */ | ||
115 | struct GNUNET_TIME_Absolute conclude_deadline; | ||
116 | }; | ||
117 | |||
118 | |||
119 | static void | ||
120 | handle_new_element(struct GNUNET_CONSENSUS_Handle *consensus, | ||
121 | struct GNUNET_CONSENSUS_ElementMessage *msg) | ||
122 | { | ||
123 | struct GNUNET_CONSENSUS_Element element; | ||
124 | element.type = msg->element_type; | ||
125 | element.size = msg->header.size - sizeof (struct GNUNET_CONSENSUS_ElementMessage); | ||
126 | element.data = &msg[1]; | ||
127 | consensus->new_element_cb(consensus->new_element_cls, &element); | ||
128 | } | ||
129 | |||
130 | static void | ||
131 | handle_conclude_done(struct GNUNET_CONSENSUS_Handle *consensus, | ||
132 | struct GNUNET_CONSENSUS_ConcludeDoneMessage *msg) | ||
133 | { | ||
134 | GNUNET_assert (NULL != consensus->conclude_cb); | ||
135 | consensus->conclude_cb(consensus->conclude_cls, | ||
136 | msg->num_peers, | ||
137 | (struct GNUNET_PeerIdentity *) &msg[1]); | ||
138 | consensus->conclude_cb = NULL; | ||
139 | } | ||
140 | |||
141 | |||
142 | |||
143 | /** | ||
144 | * Type of a function to call when we receive a message | ||
145 | * from the service. | ||
146 | * | ||
147 | * @param cls closure | ||
148 | * @param msg message received, NULL on timeout or fatal error | ||
149 | */ | ||
150 | static void | ||
151 | message_handler (void *cls, const struct GNUNET_MessageHeader *msg) | ||
152 | { | ||
153 | struct GNUNET_CONSENSUS_Handle *consensus = cls; | ||
154 | GNUNET_CONSENSUS_InsertDoneCallback idc; | ||
155 | void *idc_cls; | ||
156 | |||
157 | if (msg == NULL) | ||
158 | { | ||
159 | /* Error, timeout, death */ | ||
160 | GNUNET_CLIENT_disconnect (consensus->client); | ||
161 | consensus->client = NULL; | ||
162 | consensus->new_element_cb(NULL, NULL); | ||
163 | if (NULL != consensus->idc) | ||
164 | { | ||
165 | consensus->idc(consensus->idc_cls, GNUNET_NO); | ||
166 | consensus->idc = NULL; | ||
167 | consensus->idc_cls = NULL; | ||
168 | } | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | switch (ntohs(msg->type)) | ||
173 | { | ||
174 | case GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT_ACK: | ||
175 | idc = consensus->idc; | ||
176 | consensus->idc = NULL; | ||
177 | idc_cls = consensus->idc_cls; | ||
178 | consensus->idc_cls = NULL; | ||
179 | idc(idc_cls, GNUNET_YES); | ||
180 | break; | ||
181 | case GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT: | ||
182 | handle_new_element(consensus, (struct GNUNET_CONSENSUS_ElementMessage *) msg); | ||
183 | break; | ||
184 | case GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE: | ||
185 | handle_conclude_done(consensus, (struct GNUNET_CONSENSUS_ConcludeDoneMessage *) msg); | ||
186 | break; | ||
187 | default: | ||
188 | LOG(GNUNET_ERROR_TYPE_WARNING, "did not understand message type sent by service, ignoring"); | ||
189 | } | ||
190 | GNUNET_CLIENT_receive (consensus->client, &message_handler, consensus, | ||
191 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
192 | } | ||
193 | |||
194 | |||
195 | |||
196 | |||
197 | /** | ||
198 | * Function called to notify a client about the connection | ||
199 | * begin ready to queue more data. "buf" will be | ||
200 | * NULL and "size" zero if the connection was closed for | ||
201 | * writing in the meantime. | ||
202 | * | ||
203 | * @param cls closure | ||
204 | * @param size number of bytes available in buf | ||
205 | * @param buf where the callee should write the message | ||
206 | * @return number of bytes written to buf | ||
207 | */ | ||
208 | static size_t | ||
209 | transmit_insert (void *cls, size_t size, void *buf) | ||
210 | { | ||
211 | struct GNUNET_CONSENSUS_ElementMessage *msg; | ||
212 | struct GNUNET_CONSENSUS_Handle *consensus; | ||
213 | int msize; | ||
214 | |||
215 | GNUNET_assert (NULL != buf); | ||
216 | |||
217 | consensus = cls; | ||
218 | |||
219 | GNUNET_assert (NULL != consensus->insert_element); | ||
220 | |||
221 | consensus->th = NULL; | ||
222 | |||
223 | |||
224 | msg = buf; | ||
225 | |||
226 | msize = sizeof (struct GNUNET_CONSENSUS_ElementMessage) + | ||
227 | consensus->insert_element->size; | ||
228 | |||
229 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT); | ||
230 | msg->header.size = htons (msize); | ||
231 | memcpy(&msg[1], | ||
232 | consensus->insert_element->data, | ||
233 | consensus->insert_element->size); | ||
234 | |||
235 | return msize; | ||
236 | } | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Function called to notify a client about the connection | ||
241 | * begin ready to queue more data. "buf" will be | ||
242 | * NULL and "size" zero if the connection was closed for | ||
243 | * writing in the meantime. | ||
244 | * | ||
245 | * @param cls closure | ||
246 | * @param size number of bytes available in buf | ||
247 | * @param buf where the callee should write the message | ||
248 | * @return number of bytes written to buf | ||
249 | */ | ||
250 | static size_t | ||
251 | transmit_join (void *cls, size_t size, void *buf) | ||
252 | { | ||
253 | struct GNUNET_CONSENSUS_JoinMessage *msg; | ||
254 | struct GNUNET_CONSENSUS_Handle *consensus; | ||
255 | int msize; | ||
256 | |||
257 | LOG(GNUNET_ERROR_TYPE_DEBUG, "transmitting CLIENT_JOIN to service\n"); | ||
258 | |||
259 | GNUNET_assert (NULL != buf); | ||
260 | |||
261 | consensus = cls; | ||
262 | consensus->th = NULL; | ||
263 | consensus->joined = 1; | ||
264 | |||
265 | msg = buf; | ||
266 | |||
267 | msize = sizeof (struct GNUNET_CONSENSUS_JoinMessage) + | ||
268 | consensus->num_peers * sizeof (struct GNUNET_PeerIdentity); | ||
269 | |||
270 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN); | ||
271 | msg->header.size = htons (msize); | ||
272 | msg->session_id = consensus->session_id; | ||
273 | msg->num_peers = htons (consensus->num_peers); | ||
274 | memcpy(&msg[1], | ||
275 | consensus->peers, | ||
276 | consensus->num_peers * sizeof (struct GNUNET_PeerIdentity)); | ||
277 | |||
278 | if (consensus->insert_element != NULL) | ||
279 | { | ||
280 | consensus->th = | ||
281 | GNUNET_CLIENT_notify_transmit_ready (consensus->client, | ||
282 | msize, | ||
283 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
284 | GNUNET_NO, &transmit_insert, consensus); | ||
285 | } | ||
286 | |||
287 | |||
288 | GNUNET_CLIENT_receive (consensus->client, &message_handler, consensus, | ||
289 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
290 | |||
291 | return msize; | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Function called to notify a client about the connection | ||
297 | * begin ready to queue more data. "buf" will be | ||
298 | * NULL and "size" zero if the connection was closed for | ||
299 | * writing in the meantime. | ||
300 | * | ||
301 | * @param cls closure | ||
302 | * @param size number of bytes available in buf | ||
303 | * @param buf where the callee should write the message | ||
304 | * @return number of bytes written to buf | ||
305 | */ | ||
306 | static size_t | ||
307 | transmit_conclude (void *cls, size_t size, void *buf) | ||
308 | { | ||
309 | struct GNUNET_CONSENSUS_ConcludeMessage *msg; | ||
310 | struct GNUNET_CONSENSUS_Handle *consensus; | ||
311 | int msize; | ||
312 | |||
313 | GNUNET_assert (NULL != buf); | ||
314 | |||
315 | consensus = cls; | ||
316 | consensus->th = NULL; | ||
317 | |||
318 | msg = buf; | ||
319 | |||
320 | msize = sizeof (struct GNUNET_CONSENSUS_ConcludeMessage); | ||
321 | |||
322 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE); | ||
323 | msg->header.size = htons (msize); | ||
324 | msg->timeout = | ||
325 | GNUNET_TIME_relative_hton(GNUNET_TIME_absolute_get_remaining(consensus->conclude_deadline)); | ||
326 | |||
327 | return msize; | ||
328 | } | ||
329 | |||
330 | |||
331 | |||
332 | |||
333 | /** | ||
334 | * Create a consensus session. | ||
335 | * | ||
336 | * @param cfg | ||
337 | * @param num_peers | ||
338 | * @param peers array of peers participating in this consensus session | ||
339 | * Inclusion of the local peer is optional. | ||
340 | * @param session_id session identifier | ||
341 | * Allows a group of peers to have more than consensus session. | ||
342 | * @param num_initial_elements number of entries in the 'initial_elements' array | ||
343 | * @param initial_elements our elements for the consensus (each of 'element_size' | ||
344 | * @param new_element callback, called when a new element is added to the set by | ||
345 | * another peer | ||
346 | * @param new_element_cls closure for new_element | ||
347 | * @return handle to use, NULL on error | ||
348 | */ | ||
349 | struct GNUNET_CONSENSUS_Handle * | ||
350 | GNUNET_CONSENSUS_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
351 | unsigned int num_peers, | ||
352 | const struct GNUNET_PeerIdentity *peers, | ||
353 | const struct GNUNET_HashCode *session_id, | ||
354 | /* | ||
355 | unsigned int num_initial_elements, | ||
356 | const struct GNUNET_CONSENSUS_Element **initial_elements, | ||
357 | */ | ||
358 | GNUNET_CONSENSUS_NewElementCallback new_element, | ||
359 | void *new_element_cls) | ||
360 | { | ||
361 | struct GNUNET_CONSENSUS_Handle *consensus; | ||
362 | size_t join_message_size; | ||
363 | |||
364 | |||
365 | consensus = GNUNET_malloc (sizeof (struct GNUNET_CONSENSUS_Handle)); | ||
366 | consensus->cfg = cfg; | ||
367 | consensus->new_element_cb = new_element; | ||
368 | consensus->new_element_cls = new_element_cls; | ||
369 | consensus->num_peers = num_peers; | ||
370 | consensus->session_id = *session_id; | ||
371 | |||
372 | |||
373 | |||
374 | if (0 == num_peers) | ||
375 | { | ||
376 | consensus->peers = NULL; | ||
377 | } | ||
378 | else if (num_peers > 0) | ||
379 | { | ||
380 | |||
381 | consensus->peers = GNUNET_memdup (peers, num_peers * sizeof (struct GNUNET_PeerIdentity)); | ||
382 | } | ||
383 | else | ||
384 | { | ||
385 | GNUNET_break (0); | ||
386 | } | ||
387 | |||
388 | |||
389 | consensus->client = GNUNET_CLIENT_connect ("consensus", cfg); | ||
390 | |||
391 | GNUNET_assert (consensus->client != NULL); | ||
392 | |||
393 | join_message_size = (sizeof (struct GNUNET_CONSENSUS_JoinMessage)) + | ||
394 | (num_peers * sizeof (struct GNUNET_PeerIdentity)); | ||
395 | |||
396 | consensus->th = | ||
397 | GNUNET_CLIENT_notify_transmit_ready (consensus->client, | ||
398 | join_message_size, | ||
399 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
400 | GNUNET_NO, &transmit_join, consensus); | ||
401 | |||
402 | |||
403 | GNUNET_assert (consensus->th != NULL); | ||
404 | |||
405 | return consensus; | ||
406 | } | ||
407 | |||
408 | |||
409 | |||
410 | /** | ||
411 | * Insert an element in the set being reconsiled. Must not be called after | ||
412 | * "GNUNET_CONSENSUS_conclude". | ||
413 | * | ||
414 | * @param consensus handle for the consensus session | ||
415 | * @param element the element to be inserted | ||
416 | * @param idc function called when we are done with this element and it | ||
417 | * is thus allowed to call GNUNET_CONSENSUS_insert again | ||
418 | * @param idc_cls closure for 'idc' | ||
419 | */ | ||
420 | void | ||
421 | GNUNET_CONSENSUS_insert (struct GNUNET_CONSENSUS_Handle *consensus, | ||
422 | const struct GNUNET_CONSENSUS_Element *element, | ||
423 | GNUNET_CONSENSUS_InsertDoneCallback idc, | ||
424 | void *idc_cls) | ||
425 | { | ||
426 | |||
427 | GNUNET_assert (NULL == consensus->idc); | ||
428 | GNUNET_assert (NULL == consensus->insert_element); | ||
429 | |||
430 | consensus->idc = idc; | ||
431 | consensus->idc_cls = idc_cls; | ||
432 | consensus->insert_element = GNUNET_memdup(element, sizeof (struct GNUNET_CONSENSUS_Element) + element->size); | ||
433 | |||
434 | if (consensus->joined == 0) | ||
435 | { | ||
436 | GNUNET_assert (NULL != consensus->th); | ||
437 | return; | ||
438 | } | ||
439 | |||
440 | GNUNET_assert (NULL == consensus->th); | ||
441 | |||
442 | consensus->th = | ||
443 | GNUNET_CLIENT_notify_transmit_ready (consensus->client, | ||
444 | element->size + sizeof (struct GNUNET_CONSENSUS_ElementMessage), | ||
445 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
446 | GNUNET_NO, &transmit_insert, consensus); | ||
447 | } | ||
448 | |||
449 | |||
450 | /** | ||
451 | * We are finished inserting new elements into the consensus; | ||
452 | * try to conclude the consensus within a given time window. | ||
453 | * | ||
454 | * @param consensus consensus session | ||
455 | * @param timeout timeout after which the conculde callback | ||
456 | * must be called | ||
457 | * @param conclude called when the conclusion was successful | ||
458 | * @param conclude_cls closure for the conclude callback | ||
459 | */ | ||
460 | void | ||
461 | GNUNET_CONSENSUS_conclude (struct GNUNET_CONSENSUS_Handle *consensus, | ||
462 | struct GNUNET_TIME_Relative timeout, | ||
463 | GNUNET_CONSENSUS_ConcludeCallback conclude, | ||
464 | void *conclude_cls) | ||
465 | { | ||
466 | GNUNET_assert (NULL == consensus->th); | ||
467 | GNUNET_assert (NULL == consensus->conclude_cb); | ||
468 | |||
469 | consensus->conclude_cls = conclude_cls; | ||
470 | consensus->conclude_cb = conclude; | ||
471 | consensus->conclude_deadline = GNUNET_TIME_relative_to_absolute(timeout); | ||
472 | |||
473 | consensus->th = | ||
474 | GNUNET_CLIENT_notify_transmit_ready (consensus->client, | ||
475 | sizeof (struct GNUNET_CONSENSUS_ConcludeMessage), | ||
476 | timeout, | ||
477 | GNUNET_NO, &transmit_conclude, consensus); | ||
478 | if (NULL == consensus->th) | ||
479 | { | ||
480 | conclude(conclude_cls, 0, NULL); | ||
481 | } | ||
482 | } | ||
483 | |||
484 | |||
485 | /** | ||
486 | * Destroy a consensus handle (free all state associated with | ||
487 | * it, no longer call any of the callbacks). | ||
488 | * | ||
489 | * @param consensus handle to destroy | ||
490 | */ | ||
491 | void | ||
492 | GNUNET_CONSENSUS_destroy (struct GNUNET_CONSENSUS_Handle *consensus) | ||
493 | { | ||
494 | if (consensus->client != NULL) | ||
495 | { | ||
496 | GNUNET_CLIENT_disconnect (consensus->client); | ||
497 | consensus->client = NULL; | ||
498 | } | ||
499 | GNUNET_free (consensus->peers); | ||
500 | GNUNET_free (consensus); | ||
501 | } | ||
502 | |||
diff --git a/src/consensus/gnunet-service-consensus.cc b/src/consensus/gnunet-service-consensus.cc index 82ea5ef79..9e8aba6bb 100644 --- a/src/consensus/gnunet-service-consensus.cc +++ b/src/consensus/gnunet-service-consensus.cc | |||
@@ -24,23 +24,87 @@ | |||
24 | #include <stdint.h> | 24 | #include <stdint.h> |
25 | 25 | ||
26 | #include "platform.h" | 26 | #include "platform.h" |
27 | #include "gnunet_protocols.h" | ||
27 | #include "gnunet_common.h" | 28 | #include "gnunet_common.h" |
28 | #include "gnunet_service_lib.h" | 29 | #include "gnunet_service_lib.h" |
30 | #include "gnunet_consensus_service.h" | ||
31 | #include "consensus.h" | ||
29 | 32 | ||
30 | using namespace std; | 33 | using namespace std; |
31 | 34 | ||
35 | |||
36 | |||
37 | struct ConsensusSession | ||
38 | { | ||
39 | |||
40 | }; | ||
41 | |||
42 | |||
43 | |||
44 | struct ConsensusClient | ||
45 | { | ||
46 | |||
47 | }; | ||
48 | |||
49 | |||
50 | |||
51 | /** | ||
52 | * Called when a client wants to join a consensus session. | ||
53 | */ | ||
54 | void | ||
55 | client_join (void *cls, | ||
56 | struct GNUNET_SERVER_Client *client, | ||
57 | const struct GNUNET_MessageHeader *message) | ||
58 | { | ||
59 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "client joined"); | ||
60 | } | ||
61 | |||
62 | |||
32 | /** | 63 | /** |
33 | * Process statistics requests. | 64 | * Called when a client performs an insert operation. |
65 | */ | ||
66 | void | ||
67 | client_insert (void *cls, | ||
68 | struct GNUNET_SERVER_Client *client, | ||
69 | const struct GNUNET_MessageHeader *message) | ||
70 | { | ||
71 | |||
72 | } | ||
73 | |||
74 | |||
75 | |||
76 | /** | ||
77 | * Called when a client performs the conclude operation. | ||
78 | */ | ||
79 | void | ||
80 | client_conclude (void *cls, | ||
81 | struct GNUNET_SERVER_Client *client, | ||
82 | const struct GNUNET_MessageHeader *message) | ||
83 | { | ||
84 | |||
85 | } | ||
86 | |||
87 | |||
88 | |||
89 | /** | ||
90 | * Process consensus requests. | ||
34 | * | 91 | * |
35 | * @param cls closure | 92 | * @param cls closure |
36 | * @param server the initialized server | 93 | * @param server the initialized server |
37 | * @param c configuration to use | 94 | * @param c configuration to use |
38 | */ | 95 | */ |
39 | static void | 96 | static void |
40 | run (void *cls, struct GNUNET_SERVER_Handle *server, | 97 | run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) |
41 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
42 | { | 98 | { |
43 | /* TODO */ | 99 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { |
100 | {&client_join, NULL, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN, 0}, | ||
101 | {&client_insert, NULL, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT, 0}, | ||
102 | {&client_conclude, NULL, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE, | ||
103 | sizeof (struct GNUNET_CONSENSUS_ConcludeMessage)}, | ||
104 | {NULL, NULL, 0, 0} | ||
105 | }; | ||
106 | |||
107 | GNUNET_SERVER_add_handlers(server, handlers); | ||
44 | } | 108 | } |
45 | 109 | ||
46 | 110 | ||
@@ -55,6 +119,6 @@ int | |||
55 | main (int argc, char *const *argv) | 119 | main (int argc, char *const *argv) |
56 | { | 120 | { |
57 | return (GNUNET_OK == | 121 | return (GNUNET_OK == |
58 | GNUNET_SERVICE_run (argc, argv, "statistics", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; | 122 | GNUNET_SERVICE_run (argc, argv, "consensus", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; |
59 | } | 123 | } |
60 | 124 | ||
diff --git a/src/consensus/test_consensus.conf b/src/consensus/test_consensus.conf new file mode 100644 index 000000000..143313ff2 --- /dev/null +++ b/src/consensus/test_consensus.conf | |||
@@ -0,0 +1,15 @@ | |||
1 | [consensus] | ||
2 | AUTOSTART = YES | ||
3 | # PORT = 2103 | ||
4 | HOSTNAME = localhost | ||
5 | HOME = $SERVICEHOME | ||
6 | BINARY = gnunet-service-consensus | ||
7 | ACCEPT_FROM = 127.0.0.1; | ||
8 | ACCEPT_FROM6 = ::1; | ||
9 | UNIXPATH = /tmp/gnunet-service-consensus.sock | ||
10 | UNIX_MATCH_UID = YES | ||
11 | UNIX_MATCH_GID = YES | ||
12 | OPTIONS = -LDEBUG | ||
13 | |||
14 | [transport] | ||
15 | OPTIONS = -LERROR | ||
diff --git a/src/consensus/test_consensus_api.c b/src/consensus/test_consensus_api.c new file mode 100644 index 000000000..a6bd60119 --- /dev/null +++ b/src/consensus/test_consensus_api.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 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 | * @file consensus/test_consensus_api.c | ||
22 | * @brief testcase for consensus_api.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_consensus_service.h" | ||
27 | #include "gnunet_testing_lib-new.h" | ||
28 | |||
29 | |||
30 | static struct GNUNET_CONSENSUS_Handle *consensus; | ||
31 | |||
32 | static struct GNUNET_HashCode session_id; | ||
33 | |||
34 | |||
35 | void | ||
36 | on_new_element (void *cls, | ||
37 | struct GNUNET_CONSENSUS_Element *element) | ||
38 | { | ||
39 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received new element\n"); | ||
40 | } | ||
41 | |||
42 | |||
43 | static void | ||
44 | run (void *cls, | ||
45 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
46 | struct GNUNET_TESTING_Peer *peer) | ||
47 | { | ||
48 | char *str = "foo"; | ||
49 | |||
50 | GNUNET_CRYPTO_hash (str, strlen (str), &session_id); | ||
51 | consensus = GNUNET_CONSENSUS_create (cfg, 0, NULL, &session_id, on_new_element, cls); | ||
52 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to consensus service.\n"); | ||
53 | GNUNET_assert (consensus != NULL); | ||
54 | } | ||
55 | |||
56 | |||
57 | int | ||
58 | main (int argc, char **argv) | ||
59 | { | ||
60 | int ret; | ||
61 | |||
62 | GNUNET_log_setup ("test_consensus_api", | ||
63 | "DEBUG", | ||
64 | NULL); | ||
65 | |||
66 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "testing consensus api\n"); | ||
67 | |||
68 | ret = GNUNET_TESTING_peer_run ("test_consensus_api", | ||
69 | "test_consensus.conf", | ||
70 | &run, NULL); | ||
71 | return ret; | ||
72 | } | ||
73 | |||