diff options
author | Gabor X Toth <*@tg-x.net> | 2013-09-16 04:59:05 +0000 |
---|---|---|
committer | Gabor X Toth <*@tg-x.net> | 2013-09-16 04:59:05 +0000 |
commit | f78e9753a91497f1deb5e20d10868c27ab4a6013 (patch) | |
tree | f49653367e00fd4b611ec6ec281144d4568bd111 /src/psycstore/gnunet-service-psycstore.c | |
parent | fbae7143d25a258b9dfabefa9ca3956e9228cb0e (diff) | |
download | gnunet-f78e9753a91497f1deb5e20d10868c27ab4a6013.tar.gz gnunet-f78e9753a91497f1deb5e20d10868c27ab4a6013.zip |
PSYCstore service and API implementation
Diffstat (limited to 'src/psycstore/gnunet-service-psycstore.c')
-rw-r--r-- | src/psycstore/gnunet-service-psycstore.c | 661 |
1 files changed, 601 insertions, 60 deletions
diff --git a/src/psycstore/gnunet-service-psycstore.c b/src/psycstore/gnunet-service-psycstore.c index 5bc35d227..3d6cfdc40 100644 --- a/src/psycstore/gnunet-service-psycstore.c +++ b/src/psycstore/gnunet-service-psycstore.c | |||
@@ -1,21 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | * This file is part of GNUnet |
3 | (C) 2013 Christian Grothoff (and other contributing authors) | 3 | * (C) 2013 Christian Grothoff (and other contributing authors) |
4 | 4 | * | |
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 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 | 7 | * by the Free Software Foundation; either version 3, or (at your |
8 | option) any later version. | 8 | * option) any later version. |
9 | 9 | * | |
10 | GNUnet is distributed in the hope that it will be useful, but | 10 | * GNUnet is distributed in the hope that it will be useful, but |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | General Public License for more details. | 13 | * General Public License for more details. |
14 | 14 | * | |
15 | You should have received a copy of the GNU General Public License | 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 | 16 | * along with GNUnet; see the file COPYING. If not, write to the |
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 | Boston, MA 02111-1307, USA. | 18 | * Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
@@ -89,71 +89,134 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
89 | } | 89 | } |
90 | 90 | ||
91 | 91 | ||
92 | /** | 92 | /** |
93 | * Send a result code back to the client. | 93 | * Send a result code back to the client. |
94 | * | 94 | * |
95 | * @param client client that should receive the result code | 95 | * @param client Client that should receive the result code. |
96 | * @param result_code code to transmit | 96 | * @param result_code Code to transmit. |
97 | * @param emsg error message to include (or NULL for none) | 97 | * @param op_id Operation ID. |
98 | * @param err_msg Error message to include (or NULL for none). | ||
98 | */ | 99 | */ |
99 | static void | 100 | static void |
100 | send_result_code (struct GNUNET_SERVER_Client *client, | 101 | send_result_code (struct GNUNET_SERVER_Client *client, uint32_t result_code, |
101 | uint32_t result_code, | 102 | uint32_t op_id, const char *err_msg) |
102 | const char *emsg) | ||
103 | { | 103 | { |
104 | struct ResultCodeMessage *rcm; | 104 | struct OperationResult *res; |
105 | size_t elen; | 105 | size_t err_len; |
106 | 106 | ||
107 | if (NULL == emsg) | 107 | if (NULL == err_msg) |
108 | elen = 0; | 108 | err_len = 0; |
109 | else | 109 | else |
110 | elen = strlen (emsg) + 1; | 110 | err_len = strlen (err_msg) + 1; |
111 | rcm = GNUNET_malloc (sizeof (struct ResultCodeMessage) + elen); | 111 | res = GNUNET_malloc (sizeof (struct OperationResult) + err_len); |
112 | rcm->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE); | 112 | res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE); |
113 | rcm->header.size = htons (sizeof (struct ResultCodeMessage) + elen); | 113 | res->header.size = htons (sizeof (struct OperationResult) + err_len); |
114 | rcm->result_code = htonl (result_code); | 114 | res->result_code = htonl (result_code); |
115 | memcpy (&rcm[1], emsg, elen); | 115 | res->op_id = op_id; |
116 | memcpy (&res[1], err_msg, err_len); | ||
116 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 117 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
117 | "Sending result %d (%s) to client\n", | 118 | "Sending result %d (%s) to client\n", |
118 | (int) result_code, | 119 | (int) result_code, |
119 | emsg); | 120 | err_msg); |
120 | GNUNET_SERVER_notification_context_unicast (nc, client, &rcm->header, | 121 | GNUNET_SERVER_notification_context_add (nc, client); |
122 | GNUNET_SERVER_notification_context_unicast (nc, client, &res->header, | ||
123 | GNUNET_NO); | ||
124 | GNUNET_free (res); | ||
125 | } | ||
126 | |||
127 | |||
128 | struct SendClosure | ||
129 | { | ||
130 | struct GNUNET_SERVER_Client *client; | ||
131 | uint64_t op_id; | ||
132 | }; | ||
133 | |||
134 | |||
135 | static int | ||
136 | send_fragment (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg, | ||
137 | enum GNUNET_PSYCSTORE_MessageFlags flags) | ||
138 | { | ||
139 | struct SendClosure *sc = cls; | ||
140 | struct FragmentResult *res; | ||
141 | size_t msg_size = ntohs (msg->header.size); | ||
142 | |||
143 | res = GNUNET_malloc (sizeof (struct FragmentResult) + msg_size); | ||
144 | res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_FRAGMENT); | ||
145 | res->header.size = htons (sizeof (struct FragmentResult) + msg_size); | ||
146 | res->op_id = sc->op_id; | ||
147 | res->psycstore_flags = htonl (flags); | ||
148 | memcpy (&res[1], msg, msg_size); | ||
149 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
150 | "Sending fragment %ld to client\n", | ||
151 | GNUNET_ntohll (msg->fragment_id)); | ||
152 | GNUNET_free (msg); | ||
153 | GNUNET_SERVER_notification_context_add (nc, sc->client); | ||
154 | GNUNET_SERVER_notification_context_unicast (nc, sc->client, &res->header, | ||
121 | GNUNET_NO); | 155 | GNUNET_NO); |
122 | GNUNET_free (rcm); | 156 | GNUNET_free (res); |
157 | return GNUNET_OK; | ||
158 | } | ||
159 | |||
160 | |||
161 | static int | ||
162 | send_state_var (void *cls, const char *name, | ||
163 | const void *value, size_t value_size) | ||
164 | { | ||
165 | struct SendClosure *sc = cls; | ||
166 | struct StateResult *res; | ||
167 | size_t name_size = strlen (name) + 1; | ||
168 | |||
169 | res = GNUNET_malloc (sizeof (struct StateResult) + name_size + value_size); | ||
170 | res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE); | ||
171 | res->header.size = htons (sizeof (struct StateResult) + name_size + value_size); | ||
172 | res->op_id = sc->op_id; | ||
173 | res->name_size = htons (name_size); | ||
174 | memcpy (&res[1], name, name_size); | ||
175 | memcpy ((void *) &res[1] + name_size, value, value_size); | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
177 | "Sending state variable %s to client\n", name); | ||
178 | GNUNET_SERVER_notification_context_add (nc, sc->client); | ||
179 | GNUNET_SERVER_notification_context_unicast (nc, sc->client, &res->header, | ||
180 | GNUNET_NO); | ||
181 | GNUNET_free (res); | ||
182 | return GNUNET_OK; | ||
123 | } | 183 | } |
124 | 184 | ||
125 | 185 | ||
126 | static void | 186 | static void |
127 | handle_membership_store (void *cls, | 187 | handle_membership_store (void *cls, |
128 | struct GNUNET_SERVER_Client *client, | 188 | struct GNUNET_SERVER_Client *client, |
129 | const struct GNUNET_MessageHeader *message) | 189 | const struct GNUNET_MessageHeader *msg) |
130 | { | 190 | { |
131 | const struct MembershipStoreMessage *msg = | 191 | const struct MembershipStoreRequest *req = |
132 | (const struct MembershipStoreMessage *) message; | 192 | (const struct MembershipStoreRequest *) msg; |
133 | 193 | ||
134 | int res = db->membership_store (db->cls, msg->channel_key, msg->slave_key, | 194 | int ret = db->membership_store (db->cls, &req->channel_key, &req->slave_key, |
135 | msg->did_join, msg->announced_at, | 195 | ntohl (req->did_join), |
136 | msg->effective_since, msg->group_generation); | 196 | GNUNET_ntohll (req->announced_at), |
197 | GNUNET_ntohll (req->effective_since), | ||
198 | GNUNET_ntohll (req->group_generation)); | ||
137 | 199 | ||
138 | if (res != GNUNET_OK) | 200 | if (ret != GNUNET_OK) |
139 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 201 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
140 | _("Failed to store membership information!\n")); | 202 | _("Failed to store membership information!\n")); |
141 | 203 | ||
142 | send_result_code (client, res, NULL); | 204 | send_result_code (client, ret, req->op_id, NULL); |
205 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
143 | } | 206 | } |
144 | 207 | ||
145 | 208 | ||
146 | static void | 209 | static void |
147 | handle_membership_test (void *cls, | 210 | handle_membership_test (void *cls, |
148 | struct GNUNET_SERVER_Client *client, | 211 | struct GNUNET_SERVER_Client *client, |
149 | const struct GNUNET_MessageHeader *message) | 212 | const struct GNUNET_MessageHeader *msg) |
150 | { | 213 | { |
151 | const struct MembershipTestMessage *msg = | 214 | const struct MembershipTestRequest *req = |
152 | (const struct MembershipTestMessage *) message; | 215 | (const struct MembershipTestRequest *) msg; |
153 | 216 | ||
154 | int res = db->membership_test (db->cls, msg->channel_key, msg->slave_key, | 217 | int ret = db->membership_test (db->cls, &req->channel_key, &req->slave_key, |
155 | msg->message_id); | 218 | GNUNET_ntohll (req->message_id)); |
156 | switch (res) | 219 | switch (ret) |
157 | { | 220 | { |
158 | case GNUNET_YES: | 221 | case GNUNET_YES: |
159 | case GNUNET_NO: | 222 | case GNUNET_NO: |
@@ -163,7 +226,440 @@ handle_membership_test (void *cls, | |||
163 | _("Failed to test membership!\n")); | 226 | _("Failed to test membership!\n")); |
164 | } | 227 | } |
165 | 228 | ||
166 | send_result_code (client, res, NULL); | 229 | send_result_code (client, ret, req->op_id, NULL); |
230 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
231 | } | ||
232 | |||
233 | |||
234 | static void | ||
235 | handle_fragment_store (void *cls, | ||
236 | struct GNUNET_SERVER_Client *client, | ||
237 | const struct GNUNET_MessageHeader *msg) | ||
238 | { | ||
239 | const struct FragmentStoreRequest *req = | ||
240 | (const struct FragmentStoreRequest *) msg; | ||
241 | |||
242 | int ret = db->fragment_store (db->cls, &req->channel_key, | ||
243 | (const struct GNUNET_MULTICAST_MessageHeader *) | ||
244 | &req[1], ntohl (req->psycstore_flags)); | ||
245 | |||
246 | if (ret != GNUNET_OK) | ||
247 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
248 | _("Failed to store fragment!\n")); | ||
249 | |||
250 | send_result_code (client, ret, req->op_id, NULL); | ||
251 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
252 | } | ||
253 | |||
254 | |||
255 | static void | ||
256 | handle_fragment_get (void *cls, | ||
257 | struct GNUNET_SERVER_Client *client, | ||
258 | const struct GNUNET_MessageHeader *msg) | ||
259 | { | ||
260 | const struct FragmentGetRequest *req | ||
261 | = (const struct FragmentGetRequest *) msg; | ||
262 | struct SendClosure sc = { .op_id = req->op_id, .client = client }; | ||
263 | |||
264 | int ret = db->fragment_get (db->cls, &req->channel_key, | ||
265 | GNUNET_ntohll (req->fragment_id), | ||
266 | &send_fragment, &sc); | ||
267 | switch (ret) | ||
268 | { | ||
269 | case GNUNET_YES: | ||
270 | case GNUNET_NO: | ||
271 | break; | ||
272 | default: | ||
273 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
274 | _("Failed to get fragment!\n")); | ||
275 | } | ||
276 | |||
277 | send_result_code (client, ret, req->op_id, NULL); | ||
278 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
279 | } | ||
280 | |||
281 | |||
282 | static void | ||
283 | handle_message_get (void *cls, | ||
284 | struct GNUNET_SERVER_Client *client, | ||
285 | const struct GNUNET_MessageHeader *msg) | ||
286 | { | ||
287 | const struct MessageGetRequest *req = (const struct MessageGetRequest *) msg; | ||
288 | struct SendClosure sc = { .op_id = req->op_id, .client = client }; | ||
289 | uint64_t ret_frags = 0; | ||
290 | int64_t ret = db->message_get (db->cls, &req->channel_key, | ||
291 | GNUNET_ntohll (req->message_id), | ||
292 | &ret_frags, &send_fragment, &sc); | ||
293 | switch (ret) | ||
294 | { | ||
295 | case GNUNET_YES: | ||
296 | case GNUNET_NO: | ||
297 | break; | ||
298 | default: | ||
299 | ret_frags = ret; | ||
300 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
301 | _("Failed to get message!\n")); | ||
302 | } | ||
303 | |||
304 | send_result_code (client, ret_frags, req->op_id, NULL); | ||
305 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
306 | } | ||
307 | |||
308 | |||
309 | static void | ||
310 | handle_message_get_fragment (void *cls, | ||
311 | struct GNUNET_SERVER_Client *client, | ||
312 | const struct GNUNET_MessageHeader *msg) | ||
313 | { | ||
314 | const struct MessageGetFragmentRequest *req = | ||
315 | (const struct MessageGetFragmentRequest *) msg; | ||
316 | |||
317 | struct SendClosure sc = { .op_id = req->op_id, .client = client }; | ||
318 | |||
319 | int ret = db->message_get_fragment (db->cls, &req->channel_key, | ||
320 | GNUNET_ntohll (req->message_id), | ||
321 | GNUNET_ntohll (req->fragment_offset), | ||
322 | &send_fragment, &sc); | ||
323 | switch (ret) | ||
324 | { | ||
325 | case GNUNET_YES: | ||
326 | case GNUNET_NO: | ||
327 | break; | ||
328 | default: | ||
329 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
330 | _("Failed to get message fragment!\n")); | ||
331 | } | ||
332 | |||
333 | send_result_code (client, ret, req->op_id, NULL); | ||
334 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
335 | } | ||
336 | |||
337 | |||
338 | static void | ||
339 | handle_counters_get_master (void *cls, | ||
340 | struct GNUNET_SERVER_Client *client, | ||
341 | const struct GNUNET_MessageHeader *msg) | ||
342 | { | ||
343 | const struct OperationRequest *req = (const struct OperationRequest *) msg; | ||
344 | struct MasterCountersResult res = { {0} }; | ||
345 | |||
346 | int ret = db->counters_get_master (db->cls, &req->channel_key, | ||
347 | &res.fragment_id, &res.message_id, | ||
348 | &res.group_generation); | ||
349 | switch (ret) | ||
350 | { | ||
351 | case GNUNET_YES: | ||
352 | case GNUNET_NO: | ||
353 | break; | ||
354 | default: | ||
355 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
356 | _("Failed to get master counters!\n")); | ||
357 | } | ||
358 | |||
359 | res.header.type | ||
360 | = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS_MASTER); | ||
361 | res.header.size = htons (sizeof (res)); | ||
362 | res.result_code = htonl (ret); | ||
363 | res.op_id = req->op_id; | ||
364 | res.fragment_id = GNUNET_htonll (res.fragment_id); | ||
365 | res.message_id = GNUNET_htonll (res.message_id); | ||
366 | res.group_generation = GNUNET_htonll (res.group_generation); | ||
367 | |||
368 | GNUNET_SERVER_notification_context_add (nc, client); | ||
369 | GNUNET_SERVER_notification_context_unicast (nc, client, &res.header, | ||
370 | GNUNET_NO); | ||
371 | |||
372 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
373 | } | ||
374 | |||
375 | |||
376 | static void | ||
377 | handle_counters_get_slave (void *cls, | ||
378 | struct GNUNET_SERVER_Client *client, | ||
379 | const struct GNUNET_MessageHeader *msg) | ||
380 | { | ||
381 | const struct OperationRequest *req = (const struct OperationRequest *) msg; | ||
382 | struct SlaveCountersResult res = { {0} }; | ||
383 | |||
384 | int ret = db->counters_get_slave (db->cls, &req->channel_key, | ||
385 | &res.max_known_msg_id); | ||
386 | |||
387 | switch (ret) | ||
388 | { | ||
389 | case GNUNET_YES: | ||
390 | case GNUNET_NO: | ||
391 | break; | ||
392 | default: | ||
393 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
394 | _("Failed to get slave counters!\n")); | ||
395 | } | ||
396 | |||
397 | res.header.type | ||
398 | = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS_SLAVE); | ||
399 | res.header.size = htons (sizeof (res)); | ||
400 | res.result_code = htonl (ret); | ||
401 | res.op_id = req->op_id; | ||
402 | res.max_known_msg_id = GNUNET_htonll (res.max_known_msg_id); | ||
403 | |||
404 | GNUNET_SERVER_notification_context_add (nc, client); | ||
405 | GNUNET_SERVER_notification_context_unicast (nc, client, &res.header, | ||
406 | GNUNET_NO); | ||
407 | |||
408 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
409 | } | ||
410 | |||
411 | |||
412 | /* FIXME: stop processing further state modify messages after an error */ | ||
413 | static void | ||
414 | handle_state_modify (void *cls, | ||
415 | struct GNUNET_SERVER_Client *client, | ||
416 | const struct GNUNET_MessageHeader *msg) | ||
417 | { | ||
418 | const struct StateModifyRequest *req | ||
419 | = (const struct StateModifyRequest *) msg; | ||
420 | |||
421 | int ret = GNUNET_SYSERR; | ||
422 | const char *name = (const char *) &req[1]; | ||
423 | uint16_t name_size = ntohs (req->name_size); | ||
424 | |||
425 | if (name_size <= 2 || '\0' != name[name_size - 1]) | ||
426 | { | ||
427 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
428 | _("Tried to set invalid state variable name!\n")); | ||
429 | GNUNET_break_op (0); | ||
430 | } | ||
431 | else | ||
432 | { | ||
433 | ret = GNUNET_OK; | ||
434 | |||
435 | if (req->flags & STATE_OP_FIRST) | ||
436 | { | ||
437 | ret = db->state_modify_begin (db->cls, &req->channel_key, | ||
438 | GNUNET_ntohll (req->message_id), | ||
439 | GNUNET_ntohll (req->state_delta)); | ||
440 | } | ||
441 | if (ret != GNUNET_OK) | ||
442 | { | ||
443 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
444 | _("Failed to begin modifying state!\n")); | ||
445 | } | ||
446 | else | ||
447 | { | ||
448 | switch (req->oper) | ||
449 | { | ||
450 | case GNUNET_ENV_OP_ASSIGN: | ||
451 | ret = db->state_modify_set (db->cls, &req->channel_key, | ||
452 | (const char *) &req[1], | ||
453 | name + ntohs (req->name_size), | ||
454 | ntohs (req->header.size) - sizeof (*req) | ||
455 | - ntohs (req->name_size)); | ||
456 | break; | ||
457 | default: | ||
458 | #if TODO | ||
459 | ret = GNUNET_ENV_operation ((const char *) &req[1], | ||
460 | current_value, current_value_size, | ||
461 | req->oper, name + ntohs (req->name_size), | ||
462 | ntohs (req->header.size) - sizeof (*req) | ||
463 | - ntohs (req->name_size), &value, &value_size); | ||
464 | #endif | ||
465 | ret = GNUNET_SYSERR; | ||
466 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
467 | _("Unknown operator: %c\n"), req->oper); | ||
468 | } | ||
469 | } | ||
470 | |||
471 | if (GNUNET_OK == ret && req->flags & STATE_OP_LAST) | ||
472 | { | ||
473 | ret = db->state_modify_end (db->cls, &req->channel_key, | ||
474 | GNUNET_ntohll (req->message_id)); | ||
475 | if (ret != GNUNET_OK) | ||
476 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
477 | _("Failed to end modifying state!\n")); | ||
478 | } | ||
479 | } | ||
480 | send_result_code (client, ret, req->op_id, NULL); | ||
481 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
482 | } | ||
483 | |||
484 | |||
485 | /* FIXME: stop processing further state sync messages after an error */ | ||
486 | static void | ||
487 | handle_state_sync (void *cls, | ||
488 | struct GNUNET_SERVER_Client *client, | ||
489 | const struct GNUNET_MessageHeader *msg) | ||
490 | { | ||
491 | const struct StateSyncRequest *req | ||
492 | = (const struct StateSyncRequest *) msg; | ||
493 | |||
494 | int ret = GNUNET_SYSERR; | ||
495 | const char *name = (const char *) &req[1]; | ||
496 | uint16_t name_size = ntohs (req->name_size); | ||
497 | |||
498 | if (name_size <= 2 || '\0' != name[name_size - 1]) | ||
499 | { | ||
500 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
501 | _("Tried to set invalid state variable name!\n")); | ||
502 | GNUNET_break_op (0); | ||
503 | } | ||
504 | else | ||
505 | { | ||
506 | ret = GNUNET_OK; | ||
507 | |||
508 | if (req->flags & STATE_OP_FIRST) | ||
509 | { | ||
510 | ret = db->state_sync_begin (db->cls, &req->channel_key); | ||
511 | } | ||
512 | if (ret != GNUNET_OK) | ||
513 | { | ||
514 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
515 | _("Failed to begin synchronizing state!\n")); | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | ret = db->state_sync_set (db->cls, &req->channel_key, name, | ||
520 | name + ntohs (req->name_size), | ||
521 | ntohs (req->header.size) - sizeof (*req) | ||
522 | - ntohs (req->name_size)); | ||
523 | } | ||
524 | |||
525 | if (GNUNET_OK == ret && req->flags & STATE_OP_LAST) | ||
526 | { | ||
527 | ret = db->state_sync_end (db->cls, &req->channel_key, | ||
528 | GNUNET_ntohll (req->message_id)); | ||
529 | if (ret != GNUNET_OK) | ||
530 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
531 | _("Failed to end synchronizing state!\n")); | ||
532 | } | ||
533 | } | ||
534 | send_result_code (client, ret, req->op_id, NULL); | ||
535 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
536 | } | ||
537 | |||
538 | |||
539 | static void | ||
540 | handle_state_reset (void *cls, | ||
541 | struct GNUNET_SERVER_Client *client, | ||
542 | const struct GNUNET_MessageHeader *msg) | ||
543 | { | ||
544 | const struct OperationRequest *req = | ||
545 | (const struct OperationRequest *) msg; | ||
546 | |||
547 | int ret = db->state_reset (db->cls, &req->channel_key); | ||
548 | |||
549 | if (ret != GNUNET_OK) | ||
550 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
551 | _("Failed to reset state!\n")); | ||
552 | |||
553 | send_result_code (client, ret, req->op_id, NULL); | ||
554 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
555 | } | ||
556 | |||
557 | |||
558 | static void | ||
559 | handle_state_hash_update (void *cls, | ||
560 | struct GNUNET_SERVER_Client *client, | ||
561 | const struct GNUNET_MessageHeader *msg) | ||
562 | { | ||
563 | const struct OperationRequest *req = | ||
564 | (const struct OperationRequest *) msg; | ||
565 | |||
566 | int ret = db->state_reset (db->cls, &req->channel_key); | ||
567 | |||
568 | if (ret != GNUNET_OK) | ||
569 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
570 | _("Failed to reset state!\n")); | ||
571 | |||
572 | send_result_code (client, ret, req->op_id, NULL); | ||
573 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
574 | } | ||
575 | |||
576 | |||
577 | static void | ||
578 | handle_state_get (void *cls, | ||
579 | struct GNUNET_SERVER_Client *client, | ||
580 | const struct GNUNET_MessageHeader *msg) | ||
581 | { | ||
582 | const struct OperationRequest *req = | ||
583 | (const struct OperationRequest *) msg; | ||
584 | |||
585 | struct SendClosure sc = { .op_id = req->op_id, .client = client }; | ||
586 | int64_t ret = GNUNET_SYSERR; | ||
587 | const char *name = (const char *) &req[1]; | ||
588 | uint16_t name_size = ntohs (req->header.size) - sizeof (*req); | ||
589 | |||
590 | if (name_size <= 2 || '\0' != name[name_size - 1]) | ||
591 | { | ||
592 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
593 | _("Tried to get invalid state variable name!\n")); | ||
594 | GNUNET_break (0); | ||
595 | } | ||
596 | else | ||
597 | { | ||
598 | ret = db->state_get (db->cls, &req->channel_key, name, | ||
599 | &send_state_var, &sc); | ||
600 | if (GNUNET_NO == ret && name_size >= 5) /* min: _a_b\0 */ | ||
601 | { | ||
602 | char *p, *n = GNUNET_malloc (name_size); | ||
603 | memcpy (n, name, name_size); | ||
604 | while (&n[1] < (p = strrchr (n, '_')) && GNUNET_NO == ret) | ||
605 | { | ||
606 | *p = '\0'; | ||
607 | ret = db->state_get (db->cls, &req->channel_key, n, | ||
608 | &send_state_var, &sc); | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | switch (ret) | ||
613 | { | ||
614 | case GNUNET_OK: | ||
615 | case GNUNET_NO: | ||
616 | break; | ||
617 | default: | ||
618 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
619 | _("Failed to get state variable!\n")); | ||
620 | } | ||
621 | |||
622 | send_result_code (client, ret, req->op_id, NULL); | ||
623 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
624 | } | ||
625 | |||
626 | |||
627 | static void | ||
628 | handle_state_get_prefix (void *cls, | ||
629 | struct GNUNET_SERVER_Client *client, | ||
630 | const struct GNUNET_MessageHeader *msg) | ||
631 | { | ||
632 | const struct OperationRequest *req = | ||
633 | (const struct OperationRequest *) msg; | ||
634 | |||
635 | struct SendClosure sc = { .op_id = req->op_id, .client = client }; | ||
636 | int64_t ret = GNUNET_SYSERR; | ||
637 | const char *name = (const char *) &req[1]; | ||
638 | uint16_t name_size = ntohs (req->header.size) - sizeof (*req); | ||
639 | |||
640 | if (name_size <= 1 || '\0' != name[name_size - 1]) | ||
641 | { | ||
642 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
643 | _("Tried to get invalid state variable name!\n")); | ||
644 | GNUNET_break (0); | ||
645 | } | ||
646 | else | ||
647 | { | ||
648 | ret = db->state_get_prefix (db->cls, &req->channel_key, name, | ||
649 | &send_state_var, &sc); | ||
650 | } | ||
651 | switch (ret) | ||
652 | { | ||
653 | case GNUNET_OK: | ||
654 | case GNUNET_NO: | ||
655 | break; | ||
656 | default: | ||
657 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
658 | _("Failed to get state variable!\n")); | ||
659 | } | ||
660 | |||
661 | send_result_code (client, ret, req->op_id, NULL); | ||
662 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
167 | } | 663 | } |
168 | 664 | ||
169 | 665 | ||
@@ -180,13 +676,58 @@ run (void *cls, | |||
180 | const struct GNUNET_CONFIGURATION_Handle *c) | 676 | const struct GNUNET_CONFIGURATION_Handle *c) |
181 | { | 677 | { |
182 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { | 678 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { |
183 | {&handle_membership_store, NULL, | 679 | { &handle_membership_store, NULL, |
184 | GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE, | 680 | GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE, |
185 | sizeof (struct MembershipStoreMessage)}, | 681 | sizeof (struct MembershipStoreRequest) }, |
186 | {&handle_membership_test, NULL, | 682 | |
187 | GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST, | 683 | { &handle_membership_test, NULL, |
188 | sizeof (struct MembershipTestMessage)}, | 684 | GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST, |
189 | {NULL, NULL, 0, 0} | 685 | sizeof (struct MembershipTestRequest) }, |
686 | |||
687 | { &handle_fragment_store, NULL, | ||
688 | GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE, 0, }, | ||
689 | |||
690 | { &handle_fragment_get, NULL, | ||
691 | GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET, | ||
692 | sizeof (struct FragmentGetRequest) }, | ||
693 | |||
694 | { &handle_message_get, NULL, | ||
695 | GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET, | ||
696 | sizeof (struct MessageGetRequest) }, | ||
697 | |||
698 | { &handle_message_get_fragment, NULL, | ||
699 | GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET_FRAGMENT, | ||
700 | sizeof (struct MessageGetFragmentRequest) }, | ||
701 | |||
702 | { &handle_counters_get_master, NULL, | ||
703 | GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET_MASTER, | ||
704 | sizeof (struct OperationRequest) }, | ||
705 | |||
706 | { &handle_counters_get_slave, NULL, | ||
707 | GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET_SLAVE, | ||
708 | sizeof (struct OperationRequest) }, | ||
709 | |||
710 | { &handle_state_modify, NULL, | ||
711 | GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY, 0 }, | ||
712 | |||
713 | { &handle_state_sync, NULL, | ||
714 | GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC, 0 }, | ||
715 | |||
716 | { &handle_state_reset, NULL, | ||
717 | GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_RESET, | ||
718 | sizeof (struct OperationRequest) }, | ||
719 | |||
720 | { &handle_state_hash_update, NULL, | ||
721 | GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_HASH_UPDATE, | ||
722 | sizeof (struct StateHashUpdateRequest) }, | ||
723 | |||
724 | { &handle_state_get, NULL, | ||
725 | GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET, 0 }, | ||
726 | |||
727 | { &handle_state_get_prefix, NULL, | ||
728 | GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET_PREFIX, 0 }, | ||
729 | |||
730 | { NULL, NULL, 0, 0 } | ||
190 | }; | 731 | }; |
191 | 732 | ||
192 | cfg = c; | 733 | cfg = c; |