2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
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.
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.
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.
23 * @brief api for the set service
24 * @author Florian Dold
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_client_lib.h"
30 #include "gnunet_set_service.h"
35 #define LOG(kind,...) GNUNET_log_from (kind, "set-api",__VA_ARGS__)
38 * Opaque handle to a set.
40 struct GNUNET_SET_Handle
42 struct GNUNET_CLIENT_Connection *client;
43 struct GNUNET_MQ_MessageQueue *mq;
44 unsigned int messages_since_ack;
48 * Opaque handle to a set operation request from another peer.
50 struct GNUNET_SET_Request
57 struct GNUNET_SET_OperationHandle
59 GNUNET_SET_ResultIterator result_cb;
61 struct GNUNET_SET_Handle *set;
67 * Opaque handle to a listen operation.
69 struct GNUNET_SET_ListenHandle
71 struct GNUNET_CLIENT_Connection *client;
72 struct GNUNET_MQ_MessageQueue* mq;
73 GNUNET_SET_ListenCallback listen_cb;
79 handle_result (void *cls, struct GNUNET_MessageHeader *mh)
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;
86 if (set->messages_since_ack >= GNUNET_SET_ACK_WINDOW/2)
88 struct GNUNET_MQ_Message *mqm;
89 mqm = GNUNET_MQ_msg_raw (GNUNET_MESSAGE_TYPE_SET_ACK);
90 GNUNET_MQ_send (set->mq, mqm);
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)
97 oh->result_cb (oh->result_cls, NULL, htons (msg->result_status));
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));
108 handle_request (void *cls, struct GNUNET_MessageHeader *mh)
110 struct RequestMessage *msg = (struct RequestMessage *) mh;
111 struct GNUNET_SET_ListenHandle *lh = cls;
112 struct GNUNET_SET_Request *req;
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)
123 * Create an empty set, supporting the specified operation.
125 * @param cfg configuration to use for connecting to the
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
133 struct GNUNET_SET_Handle *
134 GNUNET_SET_create (struct GNUNET_CONFIGURATION_Handle *cfg,
135 enum GNUNET_SET_OperationType op)
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
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);
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
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
168 GNUNET_SET_add_element (struct GNUNET_SET_Handle *set,
169 const struct GNUNET_SET_Element *element,
170 GNUNET_SET_Continuation cont,
173 struct GNUNET_MQ_Message *mqm;
174 struct ElementMessage *msg;
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);
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
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
196 GNUNET_SET_remove_element (struct GNUNET_SET_Handle *set,
197 const struct GNUNET_SET_Element *element,
198 GNUNET_SET_Continuation cont,
201 struct GNUNET_MQ_Message *mqm;
202 struct ElementMessage *msg;
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);
213 * Destroy the set handle, and free all associated resources.
216 GNUNET_SET_destroy (struct GNUNET_SET_Handle *set)
218 GNUNET_CLIENT_disconnect (set->client);
220 GNUNET_MQ_destroy (set->mq);
225 operation_destroy (void *cls)
227 struct GNUNET_SET_OperationHandle *oh = cls;
228 struct GNUNET_SET_OperationHandle *oh_assoc;
230 oh_assoc = GNUNET_MQ_assoc_remove (oh->set->mq, oh->request_id);
231 GNUNET_assert (oh_assoc == oh);
236 * Evaluate a set operation with our set and the set of another peer.
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
246 struct GNUNET_SET_OperationHandle *
247 GNUNET_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,
256 struct GNUNET_MQ_Message *mqm;
257 struct EvaluateMessage *msg;
258 struct GNUNET_SET_OperationHandle *oh;
260 oh = GNUNET_new (struct GNUNET_SET_OperationHandle);
261 oh->result_cb = result_cb;
262 oh->result_cls = result_cls;
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);
280 * Wait for set operation requests for the given application id
282 * @param cfg configuration to use for connecting to
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
288 * @param listen_cls handle for listen_cb
289 * @return a handle that can be used to cancel the listen operation
291 struct GNUNET_SET_ListenHandle *
292 GNUNET_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,
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
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);
322 * Cancel the given listen operation.
324 * @param lh handle for the listen operation
327 GNUNET_SET_listen_cancel (struct GNUNET_SET_ListenHandle *lh)
329 GNUNET_MQ_destroy (lh->mq);
331 GNUNET_CLIENT_disconnect (lh->client);
333 lh->listen_cb = NULL;
334 lh->listen_cls = NULL;
339 * Accept a request we got via GNUNET_SET_listen
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
347 struct GNUNET_SET_OperationHandle *
348 GNUNET_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,
355 struct GNUNET_MQ_Message *mqm;
356 struct AcceptMessage *msg;
357 struct GNUNET_SET_OperationHandle *oh;
359 /* don't accept a request twice! */
360 GNUNET_assert (GNUNET_NO == request->accepted);
361 request->accepted = GNUNET_YES;
363 oh = GNUNET_new (struct GNUNET_SET_OperationHandle);
364 oh->result_cb = result_cb;
365 oh->result_cls = result_cls;
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);
380 * Cancel the given set operation.
382 * @param op set operation to cancel
385 GNUNET_SET_operation_cancel (struct GNUNET_SET_OperationHandle *h)
387 struct GNUNET_MQ_Message *mqm;
388 struct GNUNET_SET_OperationHandle *h_assoc;
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);