diff options
author | Omar Tarabai <tarabai@devegypt.com> | 2014-05-13 22:08:22 +0000 |
---|---|---|
committer | Omar Tarabai <tarabai@devegypt.com> | 2014-05-13 22:08:22 +0000 |
commit | db2ee15ca4302b0e7fa78e318833cd136265b746 (patch) | |
tree | 118bf881b689d5f2f42353611e9e132ea128eadb /src/peerstore | |
parent | 748449cc89a8ef631b8c3c5c3b9168634fc355a5 (diff) | |
download | gnunet-db2ee15ca4302b0e7fa78e318833cd136265b746.tar.gz gnunet-db2ee15ca4302b0e7fa78e318833cd136265b746.zip |
PEERSTORE api overhaul
Diffstat (limited to 'src/peerstore')
-rw-r--r-- | src/peerstore/gnunet-service-peerstore.c | 62 | ||||
-rw-r--r-- | src/peerstore/peerstore.h | 35 | ||||
-rw-r--r-- | src/peerstore/peerstore_api.c | 509 | ||||
-rw-r--r-- | src/peerstore/plugin_peerstore_sqlite.c | 25 | ||||
-rw-r--r-- | src/peerstore/test_peerstore_api.c | 9 |
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 | */ | ||
69 | struct 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 | ||
87 | GNUNET_NETWORK_STRUCT_END | 72 | GNUNET_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 | */ | ||
93 | struct 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 | */ |
131 | struct GNUNET_PEERSTORE_StoreContext | 57 | struct 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 | */ | ||
180 | static void | ||
181 | reconnect (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 | */ | ||
189 | static void | ||
190 | trigger_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 | */ | ||
202 | static void | ||
203 | reconnect_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) | |||
239 | void | 103 | void |
240 | GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h) | 104 | GNUNET_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 | */ | ||
282 | static void | ||
283 | reconnect (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 | */ | ||
322 | static size_t | ||
323 | do_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 | */ | ||
368 | static void | ||
369 | trigger_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 | */ | ||
399 | void | ||
400 | GNUNET_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 | */ |
426 | static void | 126 | void store_response_receiver (void *cls, const struct GNUNET_MessageHeader *msg) |
427 | store_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 | */ |
523 | void store_trigger_receive(void *cls, const char *emsg) | 156 | void |
157 | GNUNET_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 | */ |
566 | struct GNUNET_PEERSTORE_StoreContext * | 175 | struct GNUNET_PEERSTORE_StoreContext * |
567 | GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h, | 176 | GNUNET_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 | */ |
215 | static int | 215 | static int |
216 | peerstore_sqlite_store_record (void *cls, | 216 | peerstore_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 | ||
31 | struct GNUNET_PEERSTORE_Handle *h; | 31 | struct GNUNET_PEERSTORE_Handle *h; |
32 | 32 | ||
33 | void store_cont(void *cls, const char *emsg) | 33 | void 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, |