2 This file is part of GNUnet.
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.
22 * @file peerstore/peerstore_api.c
23 * @brief API for peerstore
24 * @author Omar Tarabai
27 #include "gnunet_util_lib.h"
28 #include "peerstore.h"
29 #include "peerstore_common.h"
31 #define LOG(kind,...) GNUNET_log_from (kind, "peerstore-api",__VA_ARGS__)
33 /******************************************************************************/
34 /************************ DATA STRUCTURES ****************************/
35 /******************************************************************************/
38 * Handle to the PEERSTORE service.
40 struct GNUNET_PEERSTORE_Handle
46 const struct GNUNET_CONFIGURATION_Handle *cfg;
49 * Connection to the service.
51 struct GNUNET_CLIENT_Connection *client;
56 struct GNUNET_MQ_Handle *mq;
59 * Head of active STORE requests.
61 struct GNUNET_PEERSTORE_StoreContext *store_head;
64 * Tail of active STORE requests.
66 struct GNUNET_PEERSTORE_StoreContext *store_tail;
71 * Context for a store request
73 struct GNUNET_PEERSTORE_StoreContext
78 struct GNUNET_PEERSTORE_StoreContext *next;
83 struct GNUNET_PEERSTORE_StoreContext *prev;
86 * Handle to the PEERSTORE service.
88 struct GNUNET_PEERSTORE_Handle *h;
91 * MQ Envelope with store request message
93 struct GNUNET_MQ_Envelope *ev;
96 * Continuation called with service response
98 GNUNET_PEERSTORE_Continuation cont;
106 * #GNUNET_YES / #GNUNET_NO
107 * if sent, cannot be canceled
113 /******************************************************************************/
114 /******************* DECLARATIONS *********************/
115 /******************************************************************************/
118 * When a response for store request is received
120 * @param cls a 'struct GNUNET_PEERSTORE_StoreContext *'
121 * @param msg message received, NULL on timeout or fatal error
123 void handle_store_result (void *cls, const struct GNUNET_MessageHeader *msg);
126 reconnect (struct GNUNET_PEERSTORE_Handle *h);
129 * MQ message handlers
131 static const struct GNUNET_MQ_MessageHandler mq_handlers[] = {
132 {&handle_store_result, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_OK, sizeof(struct GNUNET_MessageHeader)},
133 {&handle_store_result, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_FAIL, sizeof(struct GNUNET_MessageHeader)},
134 GNUNET_MQ_HANDLERS_END
137 /******************************************************************************/
138 /******************* CONNECTION FUNCTIONS *********************/
139 /******************************************************************************/
142 handle_client_error (void *cls, enum GNUNET_MQ_Error error)
144 struct GNUNET_PEERSTORE_Handle *h = cls;
146 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Received an error notification from MQ of type: %d\n", error);
151 * Close the existing connection to PEERSTORE and reconnect.
153 * @param h handle to the service
156 reconnect (struct GNUNET_PEERSTORE_Handle *h)
159 LOG(GNUNET_ERROR_TYPE_DEBUG, "Reconnecting...\n");
162 GNUNET_MQ_destroy(h->mq);
165 if (NULL != h->client)
167 GNUNET_CLIENT_disconnect (h->client);
170 h->client = GNUNET_CLIENT_connect ("peerstore", h->cfg);
171 h->mq = GNUNET_MQ_queue_for_connection_client(h->client,
173 &handle_client_error,
179 * Connect to the PEERSTORE service.
181 * @return NULL on error
183 struct GNUNET_PEERSTORE_Handle *
184 GNUNET_PEERSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
186 struct GNUNET_PEERSTORE_Handle *h;
188 h = GNUNET_new (struct GNUNET_PEERSTORE_Handle);
189 h->client = GNUNET_CLIENT_connect ("peerstore", cfg);
190 if(NULL == h->client)
196 h->mq = GNUNET_MQ_queue_for_connection_client(h->client,
198 &handle_client_error,
205 LOG(GNUNET_ERROR_TYPE_DEBUG, "New connection created\n");
210 * Disconnect from the PEERSTORE service
211 * Do not call in case of pending requests
213 * @param h handle to disconnect
216 GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
220 GNUNET_MQ_destroy(h->mq);
223 if (NULL != h->client)
225 GNUNET_CLIENT_disconnect (h->client);
229 LOG(GNUNET_ERROR_TYPE_DEBUG, "Disconnected, BYE!\n");
233 /******************************************************************************/
234 /******************* STORE FUNCTIONS *********************/
235 /******************************************************************************/
238 * When a response for store request is received
240 * @param cls a 'struct GNUNET_PEERSTORE_StoreContext *'
241 * @param msg message received, NULL on timeout or fatal error
243 void handle_store_result (void *cls, const struct GNUNET_MessageHeader *msg)
245 struct GNUNET_PEERSTORE_Handle *h = cls;
246 struct GNUNET_PEERSTORE_StoreContext *sc;
248 GNUNET_PEERSTORE_Continuation cont;
254 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Unexpected store response, this should not happen.\n");
259 cont_cls = sc->cont_cls;
260 GNUNET_CONTAINER_DLL_remove(h->store_head, h->store_tail, sc);
262 if(NULL == msg) /* Connection error */
265 cont(cont_cls, GNUNET_SYSERR);
269 if(NULL != cont) /* Run continuation */
271 msg_type = ntohs(msg->type);
272 if(GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_OK == msg_type)
273 cont(cont_cls, GNUNET_OK);
274 else if(GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_FAIL == msg_type)
275 cont(cont_cls, GNUNET_SYSERR);
281 * Callback after MQ envelope is sent
283 * @param cls a 'struct GNUNET_PEERSTORE_StoreContext *'
285 void store_request_sent (void *cls)
287 struct GNUNET_PEERSTORE_StoreContext *sc = cls;
289 sc->request_sent = GNUNET_YES;
293 * Cancel a store request
295 * @param sc Store request context
298 GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc)
300 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
301 "Canceling store request.\n");
302 if(GNUNET_NO == sc->request_sent)
305 GNUNET_MQ_discard(sc->ev);
306 GNUNET_CONTAINER_DLL_remove(sc->h->store_head, sc->h->store_tail, sc);
310 { /* request already sent, will have to wait for response */
317 * Store a new entry in the PEERSTORE
319 * @param h Handle to the PEERSTORE service
320 * @param sub_system name of the sub system
321 * @param peer Peer Identity
322 * @param key entry key
323 * @param value entry value BLOB
324 * @param size size of 'value'
325 * @param expiry absolute time after which the entry is (possibly) deleted
326 * @param cont Continuation function after the store request is processed
327 * @param cont_cls Closure for 'cont'
329 struct GNUNET_PEERSTORE_StoreContext *
330 GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
331 const char *sub_system,
332 const struct GNUNET_PeerIdentity *peer,
336 struct GNUNET_TIME_Absolute expiry,
337 GNUNET_PEERSTORE_Continuation cont,
340 struct GNUNET_MQ_Envelope *ev;
341 struct GNUNET_PEERSTORE_StoreContext *sc;
343 LOG (GNUNET_ERROR_TYPE_DEBUG,
344 "Storing value (size: %lu) for subsytem `%s', peer `%s', key `%s'\n",
345 size, sub_system, GNUNET_i2s (peer), key);
346 ev = PEERSTORE_create_record_mq_envelope(sub_system,
352 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
353 GNUNET_MQ_send(h->mq, ev);
354 GNUNET_MQ_notify_sent(ev, &store_request_sent, ev);
355 sc = GNUNET_new(struct GNUNET_PEERSTORE_StoreContext);
358 sc->cont_cls = cont_cls;
360 sc->request_sent = GNUNET_NO;
361 GNUNET_CONTAINER_DLL_insert(h->store_head, h->store_tail, sc);
366 /* end of peerstore_api.c */