aboutsummaryrefslogtreecommitdiff
path: root/src/set/set_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/set/set_api.c')
-rw-r--r--src/set/set_api.c395
1 files changed, 395 insertions, 0 deletions
diff --git a/src/set/set_api.c b/src/set/set_api.c
index e69de29bb..d7898ab42 100644
--- a/src/set/set_api.c
+++ b/src/set/set_api.c
@@ -0,0 +1,395 @@
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 set/set_api.c
23 * @brief api for the set service
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_protocols.h"
29#include "gnunet_client_lib.h"
30#include "gnunet_set_service.h"
31#include "set.h"
32#include "mq.h"
33
34
35#define LOG(kind,...) GNUNET_log_from (kind, "set-api",__VA_ARGS__)
36
37/**
38 * Opaque handle to a set.
39 */
40struct GNUNET_SET_Handle
41{
42 struct GNUNET_CLIENT_Connection *client;
43 struct GNUNET_MQ_MessageQueue *mq;
44 unsigned int messages_since_ack;
45};
46
47/**
48 * Opaque handle to a set operation request from another peer.
49 */
50struct GNUNET_SET_Request
51{
52 uint32_t request_id;
53 int accepted;
54};
55
56
57struct GNUNET_SET_OperationHandle
58{
59 GNUNET_SET_ResultIterator result_cb;
60 void *result_cls;
61 struct GNUNET_SET_Handle *set;
62 uint32_t request_id;
63};
64
65
66/**
67 * Opaque handle to a listen operation.
68 */
69struct GNUNET_SET_ListenHandle
70{
71 struct GNUNET_CLIENT_Connection *client;
72 struct GNUNET_MQ_MessageQueue* mq;
73 GNUNET_SET_ListenCallback listen_cb;
74 void *listen_cls;
75};
76
77
78void
79handle_result (void *cls, struct GNUNET_MessageHeader *mh)
80{
81 struct ResultMessage *msg = (struct ResultMessage *) mh;
82 struct GNUNET_SET_Handle *set = cls;
83 struct GNUNET_SET_OperationHandle *oh;
84 struct GNUNET_SET_Element e;
85
86 if (set->messages_since_ack >= GNUNET_SET_ACK_WINDOW/2)
87 {
88 struct GNUNET_MQ_Message *mqm;
89 mqm = GNUNET_MQ_msg_raw (GNUNET_MESSAGE_TYPE_SET_ACK);
90 GNUNET_MQ_send (set->mq, mqm);
91 }
92
93 oh = GNUNET_MQ_assoc_remove (set->mq, ntohl (msg->request_id));
94 GNUNET_break (NULL != oh);
95 if (htons (msg->result_status) != GNUNET_SET_STATUS_OK)
96 {
97 oh->result_cb (oh->result_cls, NULL, htons (msg->result_status));
98 GNUNET_free (oh);
99 return;
100 }
101 e.data = &msg[1];
102 e.size = ntohs (mh->size) - sizeof (struct ResultMessage);
103 e.type = msg->element_type;
104 oh->result_cb (oh->result_cls, &e, htons (msg->result_status));
105}
106
107void
108handle_request (void *cls, struct GNUNET_MessageHeader *mh)
109{
110 struct RequestMessage *msg = (struct RequestMessage *) mh;
111 struct GNUNET_SET_ListenHandle *lh = cls;
112 struct GNUNET_SET_Request *req;
113
114 req = GNUNET_new (struct GNUNET_SET_Request);
115 req->request_id = ntohl (msg->request_id);
116 lh->listen_cb (lh->listen_cls, &msg->peer_id, &mh[1], req);
117 if (GNUNET_NO == req->accepted)
118 GNUNET_free (req);
119}
120
121
122/**
123 * Create an empty set, supporting the specified operation.
124 *
125 * @param cfg configuration to use for connecting to the
126 * set service
127 * @param op operation supported by the set
128 * Note that the operation has to be specified
129 * beforehand, as certain set operations need to maintain
130 * data structures spefific to the operation
131 * @return a handle to the set
132 */
133struct GNUNET_SET_Handle *
134GNUNET_SET_create (struct GNUNET_CONFIGURATION_Handle *cfg,
135 enum GNUNET_SET_OperationType op)
136{
137 struct GNUNET_SET_Handle *set;
138 struct GNUNET_MQ_Message *mqm;
139 struct SetCreateMessage *msg;
140 static const struct GNUNET_MQ_Handler mq_handlers[] = {
141 {handle_result, GNUNET_MESSAGE_TYPE_SET_RESULT},
142 GNUNET_MQ_HANDLERS_END
143 };
144
145 set = GNUNET_new (struct GNUNET_SET_Handle);
146 set->client = GNUNET_CLIENT_connect ("set", cfg);
147 GNUNET_assert (NULL != set->client);
148 set->mq = GNUNET_MQ_queue_for_connection_client (set->client, mq_handlers, set);
149 mqm = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_CREATE);
150 msg->operation = htons (op);
151 GNUNET_MQ_send (set->mq, mqm);
152 return set;
153}
154
155
156/**
157 * Add an element to the given set.
158 * After the element has been added (in the sense of being
159 * transmitted to the set service), cont will be called.
160 * Calls to add_element can be queued
161 *
162 * @param set set to add element to
163 * @param element element to add to the set
164 * @param cont continuation called after the element has been added
165 * @param cont_cls closure for cont
166 */
167void
168GNUNET_SET_add_element (struct GNUNET_SET_Handle *set,
169 const struct GNUNET_SET_Element *element,
170 GNUNET_SET_Continuation cont,
171 void *cont_cls)
172{
173 struct GNUNET_MQ_Message *mqm;
174 struct ElementMessage *msg;
175
176 mqm = GNUNET_MQ_msg_extra (msg, element->size, GNUNET_MESSAGE_TYPE_SET_ADD);
177 msg->element_type = element->type;
178 memcpy (&msg[1], element->data, element->size);
179 GNUNET_MQ_notify_sent (mqm, cont, cont_cls);
180 GNUNET_MQ_send (set->mq, mqm);
181}
182
183
184/**
185 * Remove an element to the given set.
186 * After the element has been removed (in the sense of the
187 * request being transmitted to the set service), cont will be called.
188 * Calls to remove_element can be queued
189 *
190 * @param set set to remove element from
191 * @param element element to remove from the set
192 * @param cont continuation called after the element has been removed
193 * @param cont_cls closure for cont
194 */
195void
196GNUNET_SET_remove_element (struct GNUNET_SET_Handle *set,
197 const struct GNUNET_SET_Element *element,
198 GNUNET_SET_Continuation cont,
199 void *cont_cls)
200{
201 struct GNUNET_MQ_Message *mqm;
202 struct ElementMessage *msg;
203
204 mqm = GNUNET_MQ_msg_extra (msg, element->size, GNUNET_MESSAGE_TYPE_SET_REMOVE);
205 msg->element_type = element->type;
206 memcpy (&msg[1], element->data, element->size);
207 GNUNET_MQ_notify_sent (mqm, cont, cont_cls);
208 GNUNET_MQ_send (set->mq, mqm);
209}
210
211
212/**
213 * Destroy the set handle, and free all associated resources.
214 */
215void
216GNUNET_SET_destroy (struct GNUNET_SET_Handle *set)
217{
218 GNUNET_CLIENT_disconnect (set->client);
219 set->client = NULL;
220 GNUNET_MQ_destroy (set->mq);
221 set->mq = NULL;
222}
223
224static void
225operation_destroy (void *cls)
226{
227 struct GNUNET_SET_OperationHandle *oh = cls;
228 struct GNUNET_SET_OperationHandle *oh_assoc;
229
230 oh_assoc = GNUNET_MQ_assoc_remove (oh->set->mq, oh->request_id);
231 GNUNET_assert (oh_assoc == oh);
232}
233
234
235/**
236 * Evaluate a set operation with our set and the set of another peer.
237 *
238 * @param set set to use
239 * @param other_peer peer with the other set
240 * @param app_id hash for the application using the set
241 * @param context_msg additional information for the request
242 * @param result_cb called on error or success
243 * @param result_cls closure for result_cb
244 * @return a handle to cancel the operation
245 */
246struct GNUNET_SET_OperationHandle *
247GNUNET_SET_evaluate (struct GNUNET_SET_Handle *set,
248 const struct GNUNET_PeerIdentity *other_peer,
249 const struct GNUNET_HashCode *app_id,
250 const struct GNUNET_MessageHeader *context_msg,
251 struct GNUNET_TIME_Relative timeout,
252 enum GNUNET_SET_ResultMode result_mode,
253 GNUNET_SET_ResultIterator result_cb,
254 void *result_cls)
255{
256 struct GNUNET_MQ_Message *mqm;
257 struct EvaluateMessage *msg;
258 struct GNUNET_SET_OperationHandle *oh;
259
260 oh = GNUNET_new (struct GNUNET_SET_OperationHandle);
261 oh->result_cb = result_cb;
262 oh->result_cls = result_cls;
263 oh->set = set;
264
265 mqm = GNUNET_MQ_msg_extra (msg, htons(context_msg->size), GNUNET_MESSAGE_TYPE_SET_EVALUATE);
266 msg->request_id = htonl (GNUNET_MQ_assoc_add (set->mq, mqm, oh));
267 msg->other_peer = *other_peer;
268 msg->app_id = *app_id;
269 msg->timeout = GNUNET_TIME_relative_hton (timeout);
270 memcpy (&msg[1], context_msg, htons (context_msg->size));
271 GNUNET_MQ_notify_timeout (mqm, operation_destroy, oh);
272 GNUNET_MQ_notify_destroy (mqm, operation_destroy, oh);
273 GNUNET_MQ_send (set->mq, mqm);
274
275 return oh;
276}
277
278
279/**
280 * Wait for set operation requests for the given application id
281 *
282 * @param cfg configuration to use for connecting to
283 * the set service
284 * @param operation operation we want to listen for
285 * @param app_id id of the application that handles set operation requests
286 * @param listen_cb called for each incoming request matching the operation
287 * and application id
288 * @param listen_cls handle for listen_cb
289 * @return a handle that can be used to cancel the listen operation
290 */
291struct GNUNET_SET_ListenHandle *
292GNUNET_SET_listen (struct GNUNET_CONFIGURATION_Handle *cfg,
293 enum GNUNET_SET_OperationType operation,
294 const struct GNUNET_HashCode *app_id,
295 GNUNET_SET_ListenCallback listen_cb,
296 void *listen_cls)
297{
298 struct GNUNET_SET_ListenHandle *lh;
299 struct GNUNET_MQ_Message *mqm;
300 struct ListenMessage *msg;
301 static const struct GNUNET_MQ_Handler mq_handlers[] = {
302 {handle_request, GNUNET_MESSAGE_TYPE_SET_REQUEST},
303 GNUNET_MQ_HANDLERS_END
304 };
305
306 lh = GNUNET_new (struct GNUNET_SET_ListenHandle);
307 lh->client = GNUNET_CLIENT_connect ("set", cfg);
308 lh->listen_cb = listen_cb;
309 lh->listen_cls = listen_cls;
310 GNUNET_assert (NULL != lh->client);
311 lh->mq = GNUNET_MQ_queue_for_connection_client (lh->client, mq_handlers, lh);
312 mqm = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_LISTEN);
313 msg->operation = htons (operation);
314 msg->app_id = *app_id;
315 GNUNET_MQ_send (lh->mq, mqm);
316
317 return lh;
318}
319
320
321/**
322 * Cancel the given listen operation.
323 *
324 * @param lh handle for the listen operation
325 */
326void
327GNUNET_SET_listen_cancel (struct GNUNET_SET_ListenHandle *lh)
328{
329 GNUNET_MQ_destroy (lh->mq);
330 lh->mq = NULL;
331 GNUNET_CLIENT_disconnect (lh->client);
332 lh->client = NULL;
333 lh->listen_cb = NULL;
334 lh->listen_cls = NULL;
335}
336
337
338/**
339 * Accept a request we got via GNUNET_SET_listen
340 *
341 * @param request request to accept
342 * @param set set used for the requested operation
343 * @param timeout timeout for the set operation
344 * @param result_cb callback for the results
345 * @param cls closure for result_cb
346 */
347struct GNUNET_SET_OperationHandle *
348GNUNET_SET_accept (struct GNUNET_SET_Request *request,
349 struct GNUNET_SET_Handle *set,
350 struct GNUNET_TIME_Relative timeout,
351 enum GNUNET_SET_ResultMode result_mode,
352 GNUNET_SET_ResultIterator result_cb,
353 void *result_cls)
354{
355 struct GNUNET_MQ_Message *mqm;
356 struct AcceptMessage *msg;
357 struct GNUNET_SET_OperationHandle *oh;
358
359 /* don't accept a request twice! */
360 GNUNET_assert (GNUNET_NO == request->accepted);
361 request->accepted = GNUNET_YES;
362
363 oh = GNUNET_new (struct GNUNET_SET_OperationHandle);
364 oh->result_cb = result_cb;
365 oh->result_cls = result_cls;
366 oh->set = set;
367
368 mqm = GNUNET_MQ_msg (msg , GNUNET_MESSAGE_TYPE_SET_ACCEPT);
369 msg->timeout = GNUNET_TIME_relative_hton (timeout);
370 msg->request_id = htonl (request->request_id);
371 GNUNET_MQ_notify_timeout (mqm, operation_destroy, oh);
372 GNUNET_MQ_notify_destroy (mqm, operation_destroy, oh);
373 GNUNET_MQ_send (set->mq, mqm);
374
375 return oh;
376}
377
378
379/**
380 * Cancel the given set operation.
381 *
382 * @param op set operation to cancel
383 */
384void
385GNUNET_SET_operation_cancel (struct GNUNET_SET_OperationHandle *h)
386{
387 struct GNUNET_MQ_Message *mqm;
388 struct GNUNET_SET_OperationHandle *h_assoc;
389
390 h_assoc = GNUNET_MQ_assoc_remove (h->set->mq, h->request_id);
391 GNUNET_assert (h_assoc == h);
392 mqm = GNUNET_MQ_msg_raw (GNUNET_MESSAGE_TYPE_SET_CANCEL);
393 GNUNET_MQ_send (h->set->mq, mqm);
394}
395