aboutsummaryrefslogtreecommitdiff
path: root/src/peerstore/peerstore_api.c
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/peerstore_api.c
parent748449cc89a8ef631b8c3c5c3b9168634fc355a5 (diff)
downloadgnunet-db2ee15ca4302b0e7fa78e318833cd136265b746.tar.gz
gnunet-db2ee15ca4302b0e7fa78e318833cd136265b746.zip
PEERSTORE api overhaul
Diffstat (limited to 'src/peerstore/peerstore_api.c')
-rw-r--r--src/peerstore/peerstore_api.c509
1 files changed, 60 insertions, 449 deletions
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}