aboutsummaryrefslogtreecommitdiff
path: root/src/peerstore
diff options
context:
space:
mode:
authorOmar Tarabai <tarabai@devegypt.com>2014-05-13 22:08:22 +0000
committerOmar Tarabai <tarabai@devegypt.com>2014-05-13 22:08:22 +0000
commitdb2ee15ca4302b0e7fa78e318833cd136265b746 (patch)
tree118bf881b689d5f2f42353611e9e132ea128eadb /src/peerstore
parent748449cc89a8ef631b8c3c5c3b9168634fc355a5 (diff)
downloadgnunet-db2ee15ca4302b0e7fa78e318833cd136265b746.tar.gz
gnunet-db2ee15ca4302b0e7fa78e318833cd136265b746.zip
PEERSTORE api overhaul
Diffstat (limited to 'src/peerstore')
-rw-r--r--src/peerstore/gnunet-service-peerstore.c62
-rw-r--r--src/peerstore/peerstore.h35
-rw-r--r--src/peerstore/peerstore_api.c509
-rw-r--r--src/peerstore/plugin_peerstore_sqlite.c25
-rw-r--r--src/peerstore/test_peerstore_api.c9
5 files changed, 119 insertions, 521 deletions
diff --git a/src/peerstore/gnunet-service-peerstore.c b/src/peerstore/gnunet-service-peerstore.c
index 837c5ca75..303f25027 100644
--- a/src/peerstore/gnunet-service-peerstore.c
+++ b/src/peerstore/gnunet-service-peerstore.c
@@ -90,65 +90,59 @@ void handle_store (void *cls,
90 const struct GNUNET_MessageHeader *message) 90 const struct GNUNET_MessageHeader *message)
91{ 91{
92 struct StoreRequestMessage *req; 92 struct StoreRequestMessage *req;
93 uint16_t msg_size; 93 uint16_t req_size;
94 uint16_t sub_system_size; 94 uint16_t ss_size;
95 uint16_t key_size;
95 uint16_t value_size; 96 uint16_t value_size;
96 char *sub_system; 97 char *sub_system;
98 char *key;
97 void *value; 99 void *value;
100 uint16_t response_type;
98 struct GNUNET_SERVER_TransmitContext *tc; 101 struct GNUNET_SERVER_TransmitContext *tc;
99 struct StoreResponseMessage *res;
100 char *emsg;
101 size_t emsg_size = 0;
102 char *emsg_dest;
103 102
104 msg_size = ntohs(message->size); 103 req_size = ntohs(message->size);
105 if(msg_size < sizeof(struct StoreRequestMessage)) 104 if(req_size < sizeof(struct StoreRequestMessage))
106 { 105 {
107 GNUNET_break(0); 106 GNUNET_break(0);
108 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); 107 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
109 return; 108 return;
110 } 109 }
111 req = (struct StoreRequestMessage *)message; 110 req = (struct StoreRequestMessage *)message;
112 sub_system_size = ntohs(req->sub_system_size); 111 ss_size = ntohs(req->sub_system_size);
112 key_size = ntohs(req->key_size);
113 value_size = ntohs(req->value_size); 113 value_size = ntohs(req->value_size);
114 if(sub_system_size + value_size + sizeof(struct StoreRequestMessage) 114 if(ss_size + key_size + value_size + sizeof(struct StoreRequestMessage)
115 != msg_size) 115 != req_size)
116 { 116 {
117 GNUNET_break(0); 117 GNUNET_break(0);
118 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); 118 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
119 return; 119 return;
120 } 120 }
121 sub_system = (char *)&req[1]; 121 sub_system = (char *)&req[1];
122 value = sub_system + sub_system_size; 122 key = sub_system + ss_size;
123 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Received a store request (size: %lu) for sub system `%s' and peer `%s'\n", 123 value = key + key_size;
124 msg_size, 124 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Received a store request (size: %lu) for sub system `%s', peer `%s', key `%s'\n",
125 value_size,
126 sub_system,
127 GNUNET_i2s (&req->peer),
128 key);
129 if(GNUNET_OK == db->store_record(db->cls,
125 sub_system, 130 sub_system,
126 GNUNET_i2s (&req->peer));
127 if(GNUNET_OK != db->store_record(db->cls,
128 &req->peer, 131 &req->peer,
129 sub_system, 132 key,
130 value, 133 value,
131 value_size)) 134 value_size))
132 { 135 {
133 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to store requested value, sqlite database error."); 136 response_type = GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_OK;
134 emsg = _("Failed to store requested value, sqlite database error.");
135 emsg_size = strlen(emsg) + 1;
136 } 137 }
137 res = GNUNET_malloc(sizeof(struct StoreResponseMessage) + emsg_size); 138 else
138 res->emsg_size = htons(emsg_size);
139 res->header.size = htons(sizeof(struct StoreResponseMessage) + emsg_size);
140 res->header.type = htons(GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT);
141 if(emsg_size > 0)
142 { 139 {
143 res->success = htons(GNUNET_NO); 140 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to store requested value, sqlite database error.");
144 emsg_dest = (char *)&res[1]; 141 response_type = GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_FAIL;
145 memcpy(emsg_dest, emsg, emsg_size);
146 } 142 }
147 else 143
148 res->success = htons(GNUNET_YES);
149 tc = GNUNET_SERVER_transmit_context_create (client); 144 tc = GNUNET_SERVER_transmit_context_create (client);
150 GNUNET_SERVER_transmit_context_append_message(tc, (struct GNUNET_MessageHeader *)res); 145 GNUNET_SERVER_transmit_context_append_data(tc, NULL, 0, response_type);
151 GNUNET_free(res);
152 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); 146 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
153 147
154} 148}
diff --git a/src/peerstore/peerstore.h b/src/peerstore/peerstore.h
index 0acc3ec4b..29e2ed866 100644
--- a/src/peerstore/peerstore.h
+++ b/src/peerstore/peerstore.h
@@ -40,48 +40,33 @@ struct StoreRequestMessage
40 struct GNUNET_MessageHeader header; 40 struct GNUNET_MessageHeader header;
41 41
42 /** 42 /**
43 * Peer Identity
44 */
45 struct GNUNET_PeerIdentity peer;
46
47 /**
48 * Size of the sub_system string 43 * Size of the sub_system string
49 * Allocated at position 0 after this struct 44 * Allocated at position 0 after this struct
50 */ 45 */
51 size_t sub_system_size; 46 size_t sub_system_size;
52 47
53 /** 48 /**
54 * Size of value blob 49 * Peer Identity
55 * Allocated at position 1 after this struct
56 */ 50 */
57 size_t value_size; 51 struct GNUNET_PeerIdentity peer;
58 52
59 /** 53 /**
60 * Lifetime of entry 54 * Size of the key string
55 * Allocated at position 1 after this struct
61 */ 56 */
62 struct GNUNET_TIME_Relative lifetime; 57 size_t key_size;
63 58
64};
65
66/**
67 * Message carrying a PEERSTORE store response
68 */
69struct StoreResponseMessage
70{
71 /** 59 /**
72 * GNUnet message header 60 * Size of value blob
61 * Allocated at position 2 after this struct
73 */ 62 */
74 struct GNUNET_MessageHeader header; 63 size_t value_size;
75 64
76 /** 65 /**
77 * Was the store operation successful (#GNUNET_YES / #GNUNET_NO) 66 * Lifetime of entry
78 */ 67 */
79 uint16_t success GNUNET_PACKED; 68 struct GNUNET_TIME_Relative lifetime;
80 69
81 /**
82 * Size of the following error message (0 if no error)
83 */
84 size_t emsg_size GNUNET_PACKED;
85}; 70};
86 71
87GNUNET_NETWORK_STRUCT_END 72GNUNET_NETWORK_STRUCT_END
diff --git a/src/peerstore/peerstore_api.c b/src/peerstore/peerstore_api.c
index 63b64eaf6..4bc36bddc 100644
--- a/src/peerstore/peerstore_api.c
+++ b/src/peerstore/peerstore_api.c
@@ -42,174 +42,38 @@ struct GNUNET_PEERSTORE_Handle
42 /** 42 /**
43 * Our configuration. 43 * Our configuration.
44 */ 44 */
45 const struct GNUNET_CONFIGURATION_Handle *cfg; 45 const struct GNUNET_CONFIGURATION_Handle *cfg;
46 46
47 /** 47 /**
48 * Connection to the service. 48 * Connection to the service.
49 */ 49 */
50 struct GNUNET_CLIENT_Connection *client; 50 struct GNUNET_CLIENT_Connection *client;
51 51
52 /**
53 * Head of transmission queue.
54 */
55 struct GNUNET_PEERSTORE_RequestContext *rc_head;
56
57 /**
58 * Tail of transmission queue.
59 */
60 struct GNUNET_PEERSTORE_RequestContext *rc_tail;
61
62 /**
63 * Handle for the current transmission request, or NULL if none is pending.
64 */
65 struct GNUNET_CLIENT_TransmitHandle *th;
66
67 /**
68 * Head of store requests DLL.
69 */
70 struct GNUNET_PEERSTORE_StoreContext *sc_head;
71
72 /**
73 * Tail of store requests DLL.
74 */
75 struct GNUNET_PEERSTORE_StoreContext *sc_tail;
76
77 /**
78 * ID for a reconnect task.
79 */
80 GNUNET_SCHEDULER_TaskIdentifier r_task;
81
82 /**
83 * Are we now receiving?
84 */
85 int in_receive;
86
87};
88
89/**
90 * Entry in the transmission queue to PEERSTORE service.
91 *
92 */
93struct GNUNET_PEERSTORE_RequestContext
94{
95 /**
96 * This is a linked list.
97 */
98 struct GNUNET_PEERSTORE_RequestContext *next;
99
100 /**
101 * This is a linked list.
102 */
103 struct GNUNET_PEERSTORE_RequestContext *prev;
104
105 /**
106 * Handle to the PEERSTORE service.
107 */
108 struct GNUNET_PEERSTORE_Handle *h;
109
110 /**
111 * Function to call after request has been transmitted, or NULL.
112 */
113 GNUNET_PEERSTORE_Continuation cont;
114
115 /**
116 * Closure for 'cont'.
117 */
118 void *cont_cls;
119
120 /**
121 * Number of bytes of the request message (follows after this struct).
122 */
123 size_t size;
124
125}; 52};
126 53
127/** 54/**
128 * Context for a store request 55 * Context for a store request
129 *
130 */ 56 */
131struct GNUNET_PEERSTORE_StoreContext 57struct GNUNET_PEERSTORE_StoreContext
132{ 58{
133 /**
134 * Kept in a DLL.
135 */
136 struct GNUNET_PEERSTORE_StoreContext *next;
137
138 /**
139 * Kept in a DLL.
140 */
141 struct GNUNET_PEERSTORE_StoreContext *prev;
142
143 /**
144 * Handle to the PEERSTORE service.
145 */
146 struct GNUNET_PEERSTORE_Handle *h;
147 59
148 /** 60 /**
149 * Our entry in the transmission queue. 61 * Continuation called with service response
150 */
151 struct GNUNET_PEERSTORE_RequestContext *rc;
152
153 /**
154 * Function to call with store operation result
155 */ 62 */
156 GNUNET_PEERSTORE_Continuation cont; 63 GNUNET_PEERSTORE_Continuation cont;
157 64
158 /** 65 /**
159 * Closure for 'cont'. 66 * Closure for 'cont'
160 */ 67 */
161 void *cont_cls; 68 void *cont_cls;
162 69
163 /**
164 * Set to GNUNET_YES if we are currently receiving replies from the
165 * service.
166 */
167 int request_transmitted;
168
169}; 70};
170 71
171/******************************************************************************/ 72/******************************************************************************/
172/*********************** DECLARATIONS *************************/
173/******************************************************************************/
174
175/**
176 * Close the existing connection to PEERSTORE and reconnect.
177 *
178 * @param h handle to the service
179 */
180static void
181reconnect (struct GNUNET_PEERSTORE_Handle *h);
182
183/**
184 * Check if we have a request pending in the transmission queue and are
185 * able to transmit it right now. If so, schedule transmission.
186 *
187 * @param h handle to the service
188 */
189static void
190trigger_transmit (struct GNUNET_PEERSTORE_Handle *h);
191
192/******************************************************************************/
193/******************* CONNECTION FUNCTIONS *********************/ 73/******************* CONNECTION FUNCTIONS *********************/
194/******************************************************************************/ 74/******************************************************************************/
195 75
196/** 76/**
197 * Task scheduled to re-try connecting to the peerstore service.
198 *
199 * @param cls the 'struct GNUNET_PEERSTORE_Handle'
200 * @param tc scheduler context
201 */
202static void
203reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
204{
205 struct GNUNET_PEERSTORE_Handle *h = cls;
206
207 LOG(GNUNET_ERROR_TYPE_DEBUG, "Reconnect task executed\n");
208 h->r_task = GNUNET_SCHEDULER_NO_TASK;
209 reconnect (h);
210}
211
212/**
213 * Connect to the PEERSTORE service. 77 * Connect to the PEERSTORE service.
214 * 78 *
215 * @return NULL on error 79 * @return NULL on error
@@ -239,324 +103,69 @@ GNUNET_PEERSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
239void 103void
240GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h) 104GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
241{ 105{
242 struct GNUNET_PEERSTORE_StoreContext *sc;
243 struct GNUNET_PEERSTORE_RequestContext *rc;
244
245 while (NULL != (sc = h->sc_head))
246 {
247 GNUNET_break (GNUNET_YES == sc->request_transmitted);
248 sc->request_transmitted = GNUNET_NO;
249 GNUNET_PEERSTORE_store_cancel(sc);
250 }
251 while (NULL != (rc = h->rc_head))
252 {
253 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc);
254 if (NULL != rc->cont)
255 rc->cont (rc->cont_cls, _("aborted due to explicit disconnect request"));
256 GNUNET_free (rc);
257 }
258 if (NULL != h->th)
259 {
260 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
261 h->th = NULL;
262 }
263 if (NULL != h->client) 106 if (NULL != h->client)
264 { 107 {
265 GNUNET_CLIENT_disconnect (h->client); 108 GNUNET_CLIENT_disconnect (h->client);
266 h->client = NULL; 109 h->client = NULL;
267 } 110 }
268 if (GNUNET_SCHEDULER_NO_TASK != h->r_task) 111 GNUNET_free(h);
269 {
270 GNUNET_SCHEDULER_cancel (h->r_task);
271 h->r_task = GNUNET_SCHEDULER_NO_TASK;
272 }
273 GNUNET_free (h);
274 LOG(GNUNET_ERROR_TYPE_DEBUG, "Disconnected, BYE!\n"); 112 LOG(GNUNET_ERROR_TYPE_DEBUG, "Disconnected, BYE!\n");
275} 113}
276 114
277/**
278 * Close the existing connection to PEERSTORE and reconnect.
279 *
280 * @param h handle to the service
281 */
282static void
283reconnect (struct GNUNET_PEERSTORE_Handle *h)
284{
285 LOG(GNUNET_ERROR_TYPE_DEBUG, "Reconnecting...\n");
286 if (GNUNET_SCHEDULER_NO_TASK != h->r_task)
287 {
288 GNUNET_SCHEDULER_cancel (h->r_task);
289 h->r_task = GNUNET_SCHEDULER_NO_TASK;
290 }
291 if (NULL != h->th)
292 {
293 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
294 h->th = NULL;
295 }
296 if (NULL != h->client)
297 {
298 GNUNET_CLIENT_disconnect (h->client);
299 h->client = NULL;
300 }
301 h->in_receive = GNUNET_NO;
302 h->client = GNUNET_CLIENT_connect ("peerstore", h->cfg);
303 if (NULL == h->client)
304 {
305 h->r_task =
306 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task,
307 h);
308 return;
309 }
310 trigger_transmit (h);
311}
312
313/**
314 * Transmit the request at the head of the transmission queue
315 * and trigger continuation (if any).
316 *
317 * @param cls the 'struct GNUNET_PEERSTORE_Handle' (with the queue)
318 * @param size size of the buffer (0 on error)
319 * @param buf where to copy the message
320 * @return number of bytes copied to buf
321 */
322static size_t
323do_transmit (void *cls, size_t size, void *buf)
324{
325 struct GNUNET_PEERSTORE_Handle *h = cls;
326 struct GNUNET_PEERSTORE_RequestContext *rc = h->rc_head;
327 size_t ret;
328
329 h->th = NULL;
330 if (NULL == rc)
331 return 0; /* request was canceled in the meantime */
332 if (NULL == buf)
333 {
334 /* peerstore service died */
335 LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
336 "Failed to transmit message to `%s' service.\n", "PEERSTORE");
337 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc);
338 reconnect (h);
339 if (NULL != rc->cont)
340 rc->cont (rc->cont_cls, _("failed to transmit request (service down?)"));
341 GNUNET_free (rc);
342 return 0;
343 }
344 ret = rc->size;
345 if (size < ret)
346 {
347 /* change in head of queue (i.e. cancel + add), try again */
348 trigger_transmit (h);
349 return 0;
350 }
351 LOG (GNUNET_ERROR_TYPE_DEBUG,
352 "Transmitting request of size %u to `%s' service.\n", ret, "PEERSTORE");
353 memcpy (buf, &rc[1], ret);
354 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc);
355 trigger_transmit (h);
356 if (NULL != rc->cont)
357 rc->cont (rc->cont_cls, NULL);
358 GNUNET_free (rc);
359 return ret;
360}
361
362/**
363 * Check if we have a request pending in the transmission queue and are
364 * able to transmit it right now. If so, schedule transmission.
365 *
366 * @param h handle to the service
367 */
368static void
369trigger_transmit (struct GNUNET_PEERSTORE_Handle *h)
370{
371 struct GNUNET_PEERSTORE_RequestContext *rc;
372
373 if (NULL == (rc = h->rc_head))
374 return; /* no requests queued */
375 if (NULL != h->th)
376 return; /* request already pending */
377 if (NULL == h->client)
378 {
379 /* disconnected, try to reconnect */
380 reconnect (h);
381 return;
382 }
383 h->th =
384 GNUNET_CLIENT_notify_transmit_ready (h->client, rc->size,
385 GNUNET_TIME_UNIT_FOREVER_REL,
386 GNUNET_YES,
387 &do_transmit, h);
388}
389 115
390/******************************************************************************/ 116/******************************************************************************/
391/******************* ADD FUNCTIONS *********************/ 117/******************* ADD FUNCTIONS *********************/
392/******************************************************************************/ 118/******************************************************************************/
393 119
394/** 120/**
395 * Cancel a store request 121 * When a response for store request is received
396 * 122 *
397 * @param sc Store request context 123 * @param cls unused
398 */
399void
400GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc)
401{
402 struct GNUNET_PEERSTORE_Handle *h;
403
404 h = sc->h;
405 sc->cont = NULL;
406 if (GNUNET_YES == sc->request_transmitted)
407 return; /* need to finish processing */
408 GNUNET_CONTAINER_DLL_remove (h->sc_head,
409 h->sc_tail,
410 sc);
411 if (NULL != sc->rc)
412 {
413 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, sc->rc);
414 GNUNET_free (sc->rc);
415 }
416 GNUNET_free (sc);
417}
418
419/**
420 * Function called with server response message
421 * after a store operation is requested
422 *
423 * @param cls a 'struct GNUNET_PEERSTORE_Handle'
424 * @param msg message received, NULL on timeout or fatal error 124 * @param msg message received, NULL on timeout or fatal error
425 */ 125 */
426static void 126void store_response_receiver (void *cls, const struct GNUNET_MessageHeader *msg)
427store_receive(void *cls, const struct GNUNET_MessageHeader *msg)
428{ 127{
429 struct GNUNET_PEERSTORE_Handle *h = cls; 128 struct GNUNET_PEERSTORE_StoreContext *sc = cls;
430 struct GNUNET_PEERSTORE_StoreContext *sc = h->sc_head; 129 uint16_t msg_type;
431 GNUNET_PEERSTORE_Continuation cont;
432 void *cont_cls;
433 uint16_t response_type;
434 uint16_t response_size;
435 struct StoreResponseMessage *srm;
436 int malformed = GNUNET_NO;
437 char *emsg;
438 130
439 h->in_receive = GNUNET_NO; 131 if(NULL == sc->cont)
440 if (NULL == sc)
441 {
442 /* didn't expect a response, reconnect */
443 reconnect (h);
444 return; 132 return;
445 }
446 cont = sc->cont;
447 cont_cls = sc->cont_cls;
448 sc->request_transmitted = GNUNET_NO;
449 //cancel the request since we only need one response
450 GNUNET_PEERSTORE_store_cancel(sc);
451 if(NULL == msg) 133 if(NULL == msg)
452 { 134 {
453 LOG(GNUNET_ERROR_TYPE_ERROR, "`PEERSTORE' service died\n"); 135 sc->cont(sc->cont_cls, GNUNET_SYSERR);
454 reconnect (h);
455 if (NULL != cont)
456 cont (cont_cls,
457 _("Failed to receive response from `PEERSTORE' service."));
458 return;
459 }
460 response_type = ntohs(msg->type);
461 response_size = ntohs(msg->size);
462 if(GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT != response_type)
463 {
464 LOG(GNUNET_ERROR_TYPE_ERROR, "Received an unexpected response type: %lu to store request\n", response_type);
465 reconnect(h);
466 if (NULL != cont)
467 cont (cont_cls,
468 _("Received an unexpected response from `PEERSTORE' service."));
469 return; 136 return;
470 } 137 }
471 if(response_size < sizeof(struct StoreResponseMessage)) 138 msg_type = ntohs(msg->type);
472 { 139 if(GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_OK == msg_type)
473 malformed = GNUNET_YES; 140 sc->cont(sc->cont_cls, GNUNET_OK);
474 } 141 else if(GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_FAIL == msg_type)
142 sc->cont(sc->cont_cls, GNUNET_SYSERR);
475 else 143 else
476 { 144 {
477 srm = (struct StoreResponseMessage *)msg; 145 LOG(GNUNET_ERROR_TYPE_ERROR, "Invalid response from `PEERSTORE' service.\n");
478 if(sizeof(struct StoreResponseMessage) + ntohs(srm->emsg_size) != response_size) 146 sc->cont(sc->cont_cls, GNUNET_SYSERR);
479 malformed = GNUNET_YES;
480 }
481 if(GNUNET_YES == malformed)
482 {
483 LOG(GNUNET_ERROR_TYPE_ERROR, "Received a malformed response from `PEERSTORE' service.\n");
484 reconnect(h);
485 if (NULL != cont)
486 cont (cont_cls,
487 _("Received a malformed response from `PEERSTORE' service."));
488 return;
489 }
490 LOG(GNUNET_ERROR_TYPE_DEBUG, "Received a response of type %lu from server\n", response_type);
491 trigger_transmit(h);
492 if ( (GNUNET_NO == h->in_receive) && (NULL != h->sc_head) )
493 {
494 LOG(GNUNET_ERROR_TYPE_DEBUG,
495 "A store request was sent but response not received, receiving now.\n");
496 h->in_receive = GNUNET_YES;
497 GNUNET_CLIENT_receive (h->client,
498 &store_receive,
499 h,
500 GNUNET_TIME_UNIT_FOREVER_REL);
501 }
502 if(NULL != cont)
503 {
504 LOG(GNUNET_ERROR_TYPE_DEBUG, "Calling continuation of store request\n");
505 srm = (struct StoreResponseMessage *)msg;
506 emsg = NULL;
507 if(GNUNET_NO == ntohs(srm->success))
508 {
509 emsg = GNUNET_malloc(ntohs(srm->emsg_size));
510 memcpy(emsg, &srm[1], ntohs(srm->emsg_size));
511 }
512 cont(cont_cls, emsg);
513 } 147 }
148
514} 149}
515 150
516/** 151/**
517 * Called after store request is sent 152 * Cancel a store request
518 * Waits for response from service
519 * 153 *
520 * @param cls a 'struct GNUNET_PEERSTORE_StoreContext' 154 * @param sc Store request context
521 * @parma emsg error message (or NULL)
522 */ 155 */
523void store_trigger_receive(void *cls, const char *emsg) 156void
157GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc)
524{ 158{
525 struct GNUNET_PEERSTORE_StoreContext *sc = cls; 159 sc->cont = NULL;
526 struct GNUNET_PEERSTORE_Handle *h = sc->h;
527 GNUNET_PEERSTORE_Continuation cont;
528 void *cont_cls;
529
530 sc->rc = NULL;
531 if(NULL != emsg)
532 {
533 cont = sc->cont;
534 cont_cls = sc->cont_cls;
535 GNUNET_PEERSTORE_store_cancel (sc);
536 reconnect (h);
537 if (NULL != cont)
538 cont (cont_cls, emsg);
539 return;
540 }
541 LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for response from `%s' service.\n",
542 "PEERSTORE");
543 sc->request_transmitted = GNUNET_YES;
544 if (GNUNET_NO == h->in_receive)
545 {
546 h->in_receive = GNUNET_YES;
547 GNUNET_CLIENT_receive (h->client,
548 &store_receive,
549 h,
550 GNUNET_TIME_UNIT_FOREVER_REL);
551 }
552} 160}
553 161
554/** 162/**
555 * Store a new entry in the PEERSTORE 163 * Store a new entry in the PEERSTORE
556 * 164 *
557 * @param h Handle to the PEERSTORE service 165 * @param h Handle to the PEERSTORE service
558 * @param peer Peer Identity
559 * @param sub_system name of the sub system 166 * @param sub_system name of the sub system
167 * @param peer Peer Identity
168 * @param key entry key
560 * @param value entry value BLOB 169 * @param value entry value BLOB
561 * @param size size of 'value' 170 * @param size size of 'value'
562 * @param lifetime relative time after which the entry is (possibly) deleted 171 * @param lifetime relative time after which the entry is (possibly) deleted
@@ -565,52 +174,54 @@ void store_trigger_receive(void *cls, const char *emsg)
565 */ 174 */
566struct GNUNET_PEERSTORE_StoreContext * 175struct GNUNET_PEERSTORE_StoreContext *
567GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h, 176GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
568 const struct GNUNET_PeerIdentity *peer,
569 const char *sub_system, 177 const char *sub_system,
178 const struct GNUNET_PeerIdentity *peer,
179 const char *key,
570 const void *value, 180 const void *value,
571 size_t size, 181 size_t size,
572 struct GNUNET_TIME_Relative lifetime, 182 struct GNUNET_TIME_Relative lifetime,
573 GNUNET_PEERSTORE_Continuation cont, 183 GNUNET_PEERSTORE_Continuation cont,
574 void *cont_cls) 184 void *cont_cls)
575{ 185{
576 struct GNUNET_PEERSTORE_RequestContext *rc;
577 struct StoreRequestMessage *entry;
578 struct GNUNET_PEERSTORE_StoreContext *sc; 186 struct GNUNET_PEERSTORE_StoreContext *sc;
579 char *ss; 187 struct StoreRequestMessage *srm;
580 void *val; 188 size_t ss_size;
581 size_t sub_system_size; 189 size_t key_size;
582 size_t request_size; 190 size_t request_size;
191 void *dummy;
583 192
584 LOG (GNUNET_ERROR_TYPE_DEBUG, 193 LOG (GNUNET_ERROR_TYPE_DEBUG,
585 "Storing value (size: %lu) for subsytem `%s' and peer `%s'\n", 194 "Storing value (size: %lu) for subsytem `%s', peer `%s', key `%s'\n",
586 size, sub_system, GNUNET_i2s (peer)); 195 size, sub_system, GNUNET_i2s (peer), key);
587 sub_system_size = strlen(sub_system) + 1;
588 request_size = sizeof(struct StoreRequestMessage) + sub_system_size + size;
589 rc = GNUNET_malloc(sizeof(struct GNUNET_PEERSTORE_RequestContext) + request_size);
590 rc->h = h;
591 rc->size = request_size;
592 entry = (struct StoreRequestMessage *)&rc[1];
593 entry->header.size = htons(request_size);
594 entry->header.type = htons(GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
595 entry->peer = *peer;
596 entry->sub_system_size = htons(sub_system_size);
597 entry->value_size = htons(size);
598 entry->lifetime = lifetime;
599 ss = (char *)&entry[1];
600 memcpy(ss, sub_system, sub_system_size);
601 val = ss + sub_system_size;
602 memcpy(val, value, size);
603 sc = GNUNET_new(struct GNUNET_PEERSTORE_StoreContext); 196 sc = GNUNET_new(struct GNUNET_PEERSTORE_StoreContext);
604 sc->cont = cont; 197 sc->cont = cont;
605 sc->cont_cls = cont_cls; 198 sc->cont_cls = cont_cls;
606 sc->h = h; 199 ss_size = strlen(sub_system) + 1;
607 sc->rc = rc; 200 key_size = strlen(key) + 1;
608 sc->request_transmitted = GNUNET_NO; 201 request_size = sizeof(struct StoreRequestMessage) +
609 rc->cont = &store_trigger_receive; 202 ss_size +
610 rc->cont_cls = sc; 203 key_size +
611 GNUNET_CONTAINER_DLL_insert_tail(h->rc_head, h->rc_tail, rc); 204 size;
612 GNUNET_CONTAINER_DLL_insert_tail(h->sc_head, h->sc_tail, sc); 205 srm = GNUNET_malloc(request_size);
613 trigger_transmit (h); 206 srm->header.size = htons(request_size);
207 srm->header.type = htons(GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
208 srm->key_size = htons(key_size);
209 srm->lifetime = lifetime;
210 srm->peer = *peer;
211 srm->sub_system_size = htons(ss_size);
212 srm->value_size = htons(size);
213 dummy = &srm[1];
214 memcpy(dummy, sub_system, ss_size);
215 dummy += ss_size;
216 memcpy(dummy, key, key_size);
217 dummy += key_size;
218 memcpy(dummy, value, size);
219 GNUNET_CLIENT_transmit_and_get_response(h->client,
220 (const struct GNUNET_MessageHeader *)srm,
221 GNUNET_TIME_UNIT_FOREVER_REL,
222 GNUNET_YES,
223 &store_response_receiver,
224 sc);
614 return sc; 225 return sc;
615 226
616} 227}
diff --git a/src/peerstore/plugin_peerstore_sqlite.c b/src/peerstore/plugin_peerstore_sqlite.c
index 6aa6edf3b..ac6d30931 100644
--- a/src/peerstore/plugin_peerstore_sqlite.c
+++ b/src/peerstore/plugin_peerstore_sqlite.c
@@ -213,9 +213,10 @@ peerstore_sqlite_iterate_records (void *cls,
213 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 213 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
214 */ 214 */
215static int 215static int
216peerstore_sqlite_store_record (void *cls, 216peerstore_sqlite_store_record(void *cls,
217 const struct GNUNET_PeerIdentity *peer,
218 const char *sub_system, 217 const char *sub_system,
218 const struct GNUNET_PeerIdentity *peer,
219 const char *key,
219 const void *value, 220 const void *value,
220 size_t size) 221 size_t size)
221{ 222{
@@ -224,9 +225,10 @@ peerstore_sqlite_store_record (void *cls,
224 225
225 //FIXME: check if value exists with the same key first 226 //FIXME: check if value exists with the same key first
226 227
227 if(SQLITE_OK != sqlite3_bind_blob(stmt, 1, peer, sizeof(struct GNUNET_PeerIdentity), SQLITE_STATIC) 228 if(SQLITE_OK != sqlite3_bind_text(stmt, 1, sub_system, strlen(sub_system) + 1, SQLITE_STATIC)
228 || SQLITE_OK != sqlite3_bind_text(stmt, 2, sub_system, strlen(sub_system) + 1, SQLITE_STATIC) 229 || SQLITE_OK != sqlite3_bind_blob(stmt, 2, peer, sizeof(struct GNUNET_PeerIdentity), SQLITE_STATIC)
229 || SQLITE_OK != sqlite3_bind_blob(stmt, 3, value, size, SQLITE_STATIC)) 230 || SQLITE_OK != sqlite3_bind_text(stmt, 3, key, strlen(key) + 1, SQLITE_STATIC)
231 || SQLITE_OK != sqlite3_bind_blob(stmt, 4, value, size, SQLITE_STATIC))
230 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 232 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
231 "sqlite3_bind"); 233 "sqlite3_bind");
232 else if (SQLITE_DONE != sqlite3_step (stmt)) 234 else if (SQLITE_DONE != sqlite3_step (stmt))
@@ -347,16 +349,17 @@ database_setup (struct Plugin *plugin)
347 /* Create tables */ 349 /* Create tables */
348 350
349 sql_exec (plugin->dbh, 351 sql_exec (plugin->dbh,
350 "CREATE TABLE IF NOT EXISTS peerstoredata (\n" 352 "CREATE TABLE IF NOT EXISTS peerstoredata (\n"
351 " peer_id BLOB NOT NULL,\n" 353 " sub_system TEXT NOT NULL,\n"
352 " sub_system TEXT NOT NULL,\n" 354 " peer_id BLOB NOT NULL,\n"
353 " value BLOB NULL" 355 " key TEXT NOT NULL,\n"
354 ");"); 356 " value BLOB NULL"
357 ");");
355 358
356 /* Prepare statements */ 359 /* Prepare statements */
357 360
358 sql_prepare (plugin->dbh, 361 sql_prepare (plugin->dbh,
359 "INSERT INTO peerstoredata (peer_id, sub_system, value) VALUES (?,?,?);", 362 "INSERT INTO peerstoredata (sub_system, peer_id, key, value) VALUES (?,?,?,?);",
360 &plugin->insert_peerstoredata); 363 &plugin->insert_peerstoredata);
361 sql_prepare(plugin->dbh, 364 sql_prepare(plugin->dbh,
362 "SELECT peer_id, sub_system, value FROM peerstoredata", 365 "SELECT peer_id, sub_system, value FROM peerstoredata",
diff --git a/src/peerstore/test_peerstore_api.c b/src/peerstore/test_peerstore_api.c
index 8cb2c4516..781187865 100644
--- a/src/peerstore/test_peerstore_api.c
+++ b/src/peerstore/test_peerstore_api.c
@@ -30,8 +30,12 @@ static int ok = 1;
30 30
31struct GNUNET_PEERSTORE_Handle *h; 31struct GNUNET_PEERSTORE_Handle *h;
32 32
33void store_cont(void *cls, const char *emsg) 33void store_cont(void *cls, int success)
34{ 34{
35 if(GNUNET_OK == success)
36 ok = 0;
37 else
38 ok = 1;
35 GNUNET_PEERSTORE_disconnect(h); 39 GNUNET_PEERSTORE_disconnect(h);
36} 40}
37 41
@@ -49,8 +53,9 @@ run (void *cls,
49 h = GNUNET_PEERSTORE_connect(cfg); 53 h = GNUNET_PEERSTORE_connect(cfg);
50 GNUNET_assert(NULL != h); 54 GNUNET_assert(NULL != h);
51 GNUNET_PEERSTORE_store(h, 55 GNUNET_PEERSTORE_store(h,
52 &pid,
53 "peerstore-test", 56 "peerstore-test",
57 &pid,
58 "peerstore-test-key",
54 val, 59 val,
55 val_size, 60 val_size,
56 GNUNET_TIME_UNIT_FOREVER_REL, 61 GNUNET_TIME_UNIT_FOREVER_REL,