You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1050 lines
29 KiB

  1. /**
  2. * This file is part of GNUnet
  3. * Copyright (C) 2013 GNUnet e.V.
  4. *
  5. * GNUnet is free software: you can redistribute it and/or modify it
  6. * under the terms of the GNU Affero General Public License as published
  7. * by the Free Software Foundation, either version 3 of the License,
  8. * or (at your option) any later version.
  9. *
  10. * GNUnet is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. SPDX-License-Identifier: AGPL3.0-or-later
  18. */
  19. /**
  20. * @file psycstore/gnunet-service-psycstore.c
  21. * @brief PSYCstore service
  22. * @author Gabor X Toth
  23. * @author Christian Grothoff
  24. */
  25. #include <inttypes.h>
  26. #include "platform.h"
  27. #include "gnunet_util_lib.h"
  28. #include "gnunet_constants.h"
  29. #include "gnunet_protocols.h"
  30. #include "gnunet_statistics_service.h"
  31. #include "gnunet_psyc_util_lib.h"
  32. #include "gnunet_psycstore_service.h"
  33. #include "gnunet_psycstore_plugin.h"
  34. #include "psycstore.h"
  35. /**
  36. * Handle to our current configuration.
  37. */
  38. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  39. /**
  40. * Service handle.
  41. */
  42. static struct GNUNET_SERVICE_Handle *service;
  43. /**
  44. * Handle to the statistics service.
  45. */
  46. static struct GNUNET_STATISTICS_Handle *stats;
  47. /**
  48. * Database handle
  49. */
  50. static struct GNUNET_PSYCSTORE_PluginFunctions *db;
  51. /**
  52. * Name of the database plugin
  53. */
  54. static char *db_lib_name;
  55. /**
  56. * Task run during shutdown.
  57. *
  58. * @param cls unused
  59. */
  60. static void
  61. shutdown_task (void *cls)
  62. {
  63. if (NULL != stats)
  64. {
  65. GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
  66. stats = NULL;
  67. }
  68. GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db));
  69. GNUNET_free (db_lib_name);
  70. db_lib_name = NULL;
  71. }
  72. /**
  73. * Send a result code back to the client.
  74. *
  75. * @param client
  76. * Client that should receive the result code.
  77. * @param result_code
  78. * Code to transmit.
  79. * @param op_id
  80. * Operation ID in network byte order.
  81. * @param err_msg
  82. * Error message to include (or NULL for none).
  83. */
  84. static void
  85. send_result_code (struct GNUNET_SERVICE_Client *client,
  86. uint64_t op_id,
  87. int64_t result_code,
  88. const char *err_msg)
  89. {
  90. struct OperationResult *res;
  91. size_t err_size = 0;
  92. if (NULL != err_msg)
  93. err_size = strnlen (err_msg,
  94. GNUNET_MAX_MESSAGE_SIZE - sizeof (*res) - 1) + 1;
  95. struct GNUNET_MQ_Envelope *
  96. env = GNUNET_MQ_msg_extra (res, err_size,
  97. GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE);
  98. res->result_code = GNUNET_htonll (result_code - INT64_MIN);
  99. res->op_id = op_id;
  100. if (0 < err_size)
  101. {
  102. GNUNET_memcpy (&res[1], err_msg, err_size);
  103. ((char *) &res[1])[err_size - 1] = '\0';
  104. }
  105. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  106. "Sending result to client: %" PRId64 " (%s)\n",
  107. result_code, err_msg);
  108. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
  109. }
  110. enum
  111. {
  112. MEMBERSHIP_TEST_NOT_NEEDED = 0,
  113. MEMBERSHIP_TEST_NEEDED = 1,
  114. MEMBERSHIP_TEST_DONE = 2,
  115. } MessageMembershipTest;
  116. struct SendClosure
  117. {
  118. struct GNUNET_SERVICE_Client *client;
  119. /**
  120. * Channel's public key.
  121. */
  122. struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
  123. /**
  124. * Slave's public key.
  125. */
  126. struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
  127. /**
  128. * Operation ID.
  129. */
  130. uint64_t op_id;
  131. /**
  132. * Membership test result.
  133. */
  134. int membership_test_result;
  135. /**
  136. * Do membership test with @a slave_key before returning fragment?
  137. * @see enum MessageMembershipTest
  138. */
  139. uint8_t membership_test;
  140. };
  141. static int
  142. send_fragment (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg,
  143. enum GNUNET_PSYCSTORE_MessageFlags flags)
  144. {
  145. struct SendClosure *sc = cls;
  146. struct FragmentResult *res;
  147. if (MEMBERSHIP_TEST_NEEDED == sc->membership_test)
  148. {
  149. sc->membership_test = MEMBERSHIP_TEST_DONE;
  150. sc->membership_test_result
  151. = db->membership_test (db->cls, &sc->channel_key, &sc->slave_key,
  152. GNUNET_ntohll (msg->message_id));
  153. switch (sc->membership_test_result)
  154. {
  155. case GNUNET_YES:
  156. break;
  157. case GNUNET_NO:
  158. case GNUNET_SYSERR:
  159. return GNUNET_NO;
  160. }
  161. }
  162. size_t msg_size = ntohs (msg->header.size);
  163. struct GNUNET_MQ_Envelope *
  164. env = GNUNET_MQ_msg_extra (res, msg_size,
  165. GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_FRAGMENT);
  166. res->op_id = sc->op_id;
  167. res->psycstore_flags = htonl (flags);
  168. GNUNET_memcpy (&res[1], msg, msg_size);
  169. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  170. "Sending fragment %llu to client\n",
  171. (unsigned long long) GNUNET_ntohll (msg->fragment_id));
  172. GNUNET_free (msg);
  173. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (sc->client), env);
  174. return GNUNET_YES;
  175. }
  176. static int
  177. send_state_var (void *cls, const char *name,
  178. const void *value, uint32_t value_size)
  179. {
  180. struct SendClosure *sc = cls;
  181. struct StateResult *res;
  182. size_t name_size = strlen (name) + 1;
  183. /** @todo FIXME: split up value into 64k chunks */
  184. struct GNUNET_MQ_Envelope *
  185. env = GNUNET_MQ_msg_extra (res, name_size + value_size,
  186. GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE);
  187. res->op_id = sc->op_id;
  188. res->name_size = htons (name_size);
  189. GNUNET_memcpy (&res[1], name, name_size);
  190. GNUNET_memcpy ((char *) &res[1] + name_size, value, value_size);
  191. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  192. "Sending state variable %s to client\n", name);
  193. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (sc->client), env);
  194. return GNUNET_OK;
  195. }
  196. static void
  197. handle_client_membership_store (void *cls,
  198. const struct MembershipStoreRequest *req)
  199. {
  200. struct GNUNET_SERVICE_Client *client = cls;
  201. int ret = db->membership_store (db->cls, &req->channel_key, &req->slave_key,
  202. req->did_join,
  203. GNUNET_ntohll (req->announced_at),
  204. GNUNET_ntohll (req->effective_since),
  205. GNUNET_ntohll (req->group_generation));
  206. if (ret != GNUNET_OK)
  207. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  208. _("Failed to store membership information!\n"));
  209. send_result_code (client, req->op_id, ret, NULL);
  210. GNUNET_SERVICE_client_continue (client);
  211. }
  212. static void
  213. handle_client_membership_test (void *cls,
  214. const struct MembershipTestRequest *req)
  215. {
  216. struct GNUNET_SERVICE_Client *client = cls;
  217. int ret = db->membership_test (db->cls, &req->channel_key, &req->slave_key,
  218. GNUNET_ntohll (req->message_id));
  219. switch (ret)
  220. {
  221. case GNUNET_YES:
  222. case GNUNET_NO:
  223. break;
  224. default:
  225. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  226. _("Failed to test membership!\n"));
  227. }
  228. send_result_code (client, req->op_id, ret, NULL);
  229. GNUNET_SERVICE_client_continue (client);
  230. }
  231. static int
  232. check_client_fragment_store (void *cls,
  233. const struct FragmentStoreRequest *req)
  234. {
  235. return GNUNET_OK;
  236. }
  237. static void
  238. handle_client_fragment_store (void *cls,
  239. const struct FragmentStoreRequest *req)
  240. {
  241. struct GNUNET_SERVICE_Client *client = cls;
  242. const struct GNUNET_MessageHeader *
  243. msg = GNUNET_MQ_extract_nested_mh (req);
  244. if (NULL == msg
  245. || ntohs (msg->size) < sizeof (struct GNUNET_MULTICAST_MessageHeader))
  246. {
  247. GNUNET_break (0);
  248. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  249. _("Dropping invalid fragment\n"));
  250. GNUNET_SERVICE_client_drop (client);
  251. return;
  252. }
  253. int ret = db->fragment_store (db->cls, &req->channel_key,
  254. (const struct GNUNET_MULTICAST_MessageHeader *)
  255. msg, ntohl (req->psycstore_flags));
  256. if (ret != GNUNET_OK)
  257. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  258. _("Failed to store fragment\n"));
  259. send_result_code (client, req->op_id, ret, NULL);
  260. GNUNET_SERVICE_client_continue (client);
  261. }
  262. static void
  263. handle_client_fragment_get (void *cls,
  264. const struct FragmentGetRequest *req)
  265. {
  266. struct GNUNET_SERVICE_Client *client = cls;
  267. struct SendClosure
  268. sc = { .op_id = req->op_id,
  269. .client = client,
  270. .channel_key = req->channel_key,
  271. .slave_key = req->slave_key,
  272. .membership_test = req->do_membership_test };
  273. int64_t ret;
  274. uint64_t ret_frags = 0;
  275. uint64_t first_fragment_id = GNUNET_ntohll (req->first_fragment_id);
  276. uint64_t last_fragment_id = GNUNET_ntohll (req->last_fragment_id);
  277. uint64_t limit = GNUNET_ntohll (req->fragment_limit);
  278. if (0 == limit)
  279. ret = db->fragment_get (db->cls, &req->channel_key,
  280. first_fragment_id, last_fragment_id,
  281. &ret_frags, send_fragment, &sc);
  282. else
  283. ret = db->fragment_get_latest (db->cls, &req->channel_key, limit,
  284. &ret_frags, send_fragment, &sc);
  285. switch (ret)
  286. {
  287. case GNUNET_YES:
  288. case GNUNET_NO:
  289. if (MEMBERSHIP_TEST_DONE == sc.membership_test)
  290. {
  291. switch (sc.membership_test_result)
  292. {
  293. case GNUNET_YES:
  294. break;
  295. case GNUNET_NO:
  296. ret = GNUNET_PSYCSTORE_MEMBERSHIP_TEST_FAILED;
  297. break;
  298. case GNUNET_SYSERR:
  299. ret = GNUNET_SYSERR;
  300. break;
  301. }
  302. }
  303. break;
  304. default:
  305. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  306. _("Failed to get fragment!\n"));
  307. }
  308. send_result_code (client, req->op_id, (ret < 0) ? ret : ret_frags, NULL);
  309. GNUNET_SERVICE_client_continue (client);
  310. }
  311. static int
  312. check_client_message_get (void *cls,
  313. const struct MessageGetRequest *req)
  314. {
  315. return GNUNET_OK;
  316. }
  317. static void
  318. handle_client_message_get (void *cls,
  319. const struct MessageGetRequest *req)
  320. {
  321. struct GNUNET_SERVICE_Client *client = cls;
  322. uint16_t size = ntohs (req->header.size);
  323. const char *method_prefix = (const char *) &req[1];
  324. if (size < sizeof (*req) + 1
  325. || '\0' != method_prefix[size - sizeof (*req) - 1])
  326. {
  327. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  328. "Message get: invalid method prefix. size: %u < %u?\n",
  329. size,
  330. (unsigned int) (sizeof (*req) + 1));
  331. GNUNET_break (0);
  332. GNUNET_SERVICE_client_drop (client);
  333. return;
  334. }
  335. struct SendClosure
  336. sc = { .op_id = req->op_id,
  337. .client = client,
  338. .channel_key = req->channel_key,
  339. .slave_key = req->slave_key,
  340. .membership_test = req->do_membership_test };
  341. int64_t ret;
  342. uint64_t ret_frags = 0;
  343. uint64_t first_message_id = GNUNET_ntohll (req->first_message_id);
  344. uint64_t last_message_id = GNUNET_ntohll (req->last_message_id);
  345. uint64_t msg_limit = GNUNET_ntohll (req->message_limit);
  346. uint64_t frag_limit = GNUNET_ntohll (req->fragment_limit);
  347. /** @todo method_prefix */
  348. if (0 == msg_limit)
  349. ret = db->message_get (db->cls, &req->channel_key,
  350. first_message_id, last_message_id, frag_limit,
  351. &ret_frags, send_fragment, &sc);
  352. else
  353. ret = db->message_get_latest (db->cls, &req->channel_key, msg_limit,
  354. &ret_frags, send_fragment, &sc);
  355. switch (ret)
  356. {
  357. case GNUNET_YES:
  358. case GNUNET_NO:
  359. break;
  360. default:
  361. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  362. _("Failed to get message!\n"));
  363. }
  364. send_result_code (client, req->op_id, (ret < 0) ? ret : ret_frags, NULL);
  365. GNUNET_SERVICE_client_continue (client);
  366. }
  367. static void
  368. handle_client_message_get_fragment (void *cls,
  369. const struct MessageGetFragmentRequest *req)
  370. {
  371. struct GNUNET_SERVICE_Client *client = cls;
  372. struct SendClosure
  373. sc = { .op_id = req->op_id, .client = client,
  374. .channel_key = req->channel_key, .slave_key = req->slave_key,
  375. .membership_test = req->do_membership_test };
  376. int ret = db->message_get_fragment (db->cls, &req->channel_key,
  377. GNUNET_ntohll (req->message_id),
  378. GNUNET_ntohll (req->fragment_offset),
  379. &send_fragment, &sc);
  380. switch (ret)
  381. {
  382. case GNUNET_YES:
  383. case GNUNET_NO:
  384. break;
  385. default:
  386. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  387. _("Failed to get message fragment!\n"));
  388. }
  389. send_result_code (client, req->op_id, ret, NULL);
  390. GNUNET_SERVICE_client_continue (client);
  391. }
  392. static void
  393. handle_client_counters_get (void *cls,
  394. const struct OperationRequest *req)
  395. {
  396. struct GNUNET_SERVICE_Client *client = cls;
  397. struct CountersResult *res;
  398. struct GNUNET_MQ_Envelope *
  399. env = GNUNET_MQ_msg (res, GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS);
  400. int ret = db->counters_message_get (db->cls, &req->channel_key,
  401. &res->max_fragment_id, &res->max_message_id,
  402. &res->max_group_generation);
  403. switch (ret)
  404. {
  405. case GNUNET_OK:
  406. ret = db->counters_state_get (db->cls, &req->channel_key,
  407. &res->max_state_message_id);
  408. case GNUNET_NO:
  409. break;
  410. default:
  411. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  412. _("Failed to get master counters!\n"));
  413. }
  414. res->result_code = htonl (ret);
  415. res->op_id = req->op_id;
  416. res->max_fragment_id = GNUNET_htonll (res->max_fragment_id);
  417. res->max_message_id = GNUNET_htonll (res->max_message_id);
  418. res->max_group_generation = GNUNET_htonll (res->max_group_generation);
  419. res->max_state_message_id = GNUNET_htonll (res->max_state_message_id);
  420. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
  421. GNUNET_SERVICE_client_continue (client);
  422. }
  423. struct StateModifyClosure
  424. {
  425. const struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
  426. struct GNUNET_PSYC_ReceiveHandle *recv;
  427. enum GNUNET_PSYC_MessageState msg_state;
  428. char mod_oper;
  429. char *mod_name;
  430. char *mod_value;
  431. uint32_t mod_value_size;
  432. uint32_t mod_value_remaining;
  433. };
  434. static void
  435. recv_state_message_part (void *cls,
  436. const struct GNUNET_PSYC_MessageHeader *msg,
  437. const struct GNUNET_MessageHeader *pmsg)
  438. {
  439. struct StateModifyClosure *scls = cls;
  440. uint16_t psize;
  441. if (NULL == msg)
  442. { // FIXME: error on unknown message
  443. return;
  444. }
  445. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  446. "recv_state_message_part() message_id: %" PRIu64
  447. ", fragment_offset: %" PRIu64 ", flags: %u\n",
  448. GNUNET_ntohll (msg->message_id),
  449. GNUNET_ntohll (msg->fragment_offset),
  450. ntohl (msg->flags));
  451. if (NULL == pmsg)
  452. {
  453. scls->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR;
  454. return;
  455. }
  456. switch (ntohs (pmsg->type))
  457. {
  458. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
  459. {
  460. scls->msg_state = GNUNET_PSYC_MESSAGE_STATE_METHOD;
  461. break;
  462. }
  463. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
  464. {
  465. struct GNUNET_PSYC_MessageModifier *
  466. pmod = (struct GNUNET_PSYC_MessageModifier *) pmsg;
  467. psize = ntohs (pmod->header.size);
  468. uint16_t name_size = ntohs (pmod->name_size);
  469. uint32_t value_size = ntohl (pmod->value_size);
  470. const char *name = (const char *) &pmod[1];
  471. const void *value = name + name_size;
  472. if (GNUNET_PSYC_OP_SET != pmod->oper)
  473. { // Apply non-transient operation.
  474. if (psize == sizeof (*pmod) + name_size + value_size)
  475. {
  476. db->state_modify_op (db->cls, &scls->channel_key,
  477. pmod->oper, name, value, value_size);
  478. }
  479. else
  480. {
  481. scls->mod_oper = pmod->oper;
  482. scls->mod_name = GNUNET_malloc (name_size);
  483. GNUNET_memcpy (scls->mod_name, name, name_size);
  484. scls->mod_value_size = value_size;
  485. scls->mod_value = GNUNET_malloc (scls->mod_value_size);
  486. scls->mod_value_remaining
  487. = scls->mod_value_size - (psize - sizeof (*pmod) - name_size);
  488. GNUNET_memcpy (scls->mod_value, value, value_size - scls->mod_value_remaining);
  489. }
  490. }
  491. scls->msg_state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER;
  492. break;
  493. }
  494. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
  495. if (GNUNET_PSYC_OP_SET != scls->mod_oper)
  496. {
  497. if (scls->mod_value_remaining == 0)
  498. {
  499. GNUNET_break_op (0);
  500. scls->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR;
  501. }
  502. psize = ntohs (pmsg->size);
  503. GNUNET_memcpy (scls->mod_value + (scls->mod_value_size - scls->mod_value_remaining),
  504. &pmsg[1], psize - sizeof (*pmsg));
  505. scls->mod_value_remaining -= psize - sizeof (*pmsg);
  506. if (0 == scls->mod_value_remaining)
  507. {
  508. db->state_modify_op (db->cls, &scls->channel_key,
  509. scls->mod_oper, scls->mod_name,
  510. scls->mod_value, scls->mod_value_size);
  511. GNUNET_free (scls->mod_name);
  512. GNUNET_free (scls->mod_value);
  513. scls->mod_oper = 0;
  514. scls->mod_name = NULL;
  515. scls->mod_value = NULL;
  516. scls->mod_value_size = 0;
  517. }
  518. }
  519. scls->msg_state = GNUNET_PSYC_MESSAGE_STATE_MOD_CONT;
  520. break;
  521. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
  522. scls->msg_state = GNUNET_PSYC_MESSAGE_STATE_DATA;
  523. break;
  524. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  525. scls->msg_state = GNUNET_PSYC_MESSAGE_STATE_END;
  526. break;
  527. default:
  528. scls->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR;
  529. }
  530. }
  531. static int
  532. recv_state_fragment (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg,
  533. enum GNUNET_PSYCSTORE_MessageFlags flags)
  534. {
  535. struct StateModifyClosure *scls = cls;
  536. if (NULL == scls->recv)
  537. {
  538. scls->recv = GNUNET_PSYC_receive_create (NULL, recv_state_message_part,
  539. scls);
  540. }
  541. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  542. "recv_state_fragment: %" PRIu64 "\n", GNUNET_ntohll (msg->fragment_id));
  543. struct GNUNET_PSYC_MessageHeader *
  544. pmsg = GNUNET_PSYC_message_header_create (msg, flags);
  545. GNUNET_PSYC_receive_message (scls->recv, pmsg);
  546. GNUNET_free (pmsg);
  547. return GNUNET_YES;
  548. }
  549. static void
  550. handle_client_state_modify (void *cls,
  551. const struct StateModifyRequest *req)
  552. {
  553. struct GNUNET_SERVICE_Client *client = cls;
  554. uint64_t message_id = GNUNET_ntohll (req->message_id);
  555. uint64_t state_delta = GNUNET_ntohll (req->state_delta);
  556. uint64_t ret_frags = 0;
  557. struct StateModifyClosure
  558. scls = { .channel_key = req->channel_key };
  559. int ret = db->state_modify_begin (db->cls, &req->channel_key,
  560. message_id, state_delta);
  561. if (GNUNET_OK != ret)
  562. {
  563. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  564. _("Failed to begin modifying state: %d\n"), ret);
  565. }
  566. else
  567. {
  568. ret = db->message_get (db->cls, &req->channel_key,
  569. message_id, message_id, 0,
  570. &ret_frags, recv_state_fragment, &scls);
  571. if (GNUNET_OK != ret)
  572. {
  573. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  574. _("Failed to modify state: %d\n"), ret);
  575. GNUNET_break (0);
  576. }
  577. else
  578. {
  579. if (GNUNET_OK != db->state_modify_end (db->cls, &req->channel_key, message_id))
  580. {
  581. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  582. _("Failed to end modifying state!\n"));
  583. GNUNET_break (0);
  584. }
  585. }
  586. if (NULL != scls.recv)
  587. {
  588. GNUNET_PSYC_receive_destroy (scls.recv);
  589. }
  590. }
  591. send_result_code (client, req->op_id, ret, NULL);
  592. GNUNET_SERVICE_client_continue (client);
  593. }
  594. static int
  595. check_client_state_sync (void *cls,
  596. const struct StateSyncRequest *req)
  597. {
  598. return GNUNET_OK;
  599. }
  600. /** @todo FIXME: stop processing further state sync messages after an error */
  601. static void
  602. handle_client_state_sync (void *cls,
  603. const struct StateSyncRequest *req)
  604. {
  605. struct GNUNET_SERVICE_Client *client = cls;
  606. int ret = GNUNET_SYSERR;
  607. const char *name = (const char *) &req[1];
  608. uint16_t name_size = ntohs (req->name_size);
  609. if (name_size <= 2 || '\0' != name[name_size - 1])
  610. {
  611. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  612. _("Tried to set invalid state variable name!\n"));
  613. GNUNET_break_op (0);
  614. }
  615. else
  616. {
  617. ret = GNUNET_OK;
  618. if (req->flags & STATE_OP_FIRST)
  619. {
  620. ret = db->state_sync_begin (db->cls, &req->channel_key);
  621. }
  622. if (ret != GNUNET_OK)
  623. {
  624. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  625. _("Failed to begin synchronizing state!\n"));
  626. }
  627. else
  628. {
  629. ret = db->state_sync_assign (db->cls, &req->channel_key, name,
  630. name + ntohs (req->name_size),
  631. ntohs (req->header.size) - sizeof (*req)
  632. - ntohs (req->name_size));
  633. }
  634. if (GNUNET_OK == ret && req->flags & STATE_OP_LAST)
  635. {
  636. ret = db->state_sync_end (db->cls, &req->channel_key,
  637. GNUNET_ntohll (req->max_state_message_id),
  638. GNUNET_ntohll (req->state_hash_message_id));
  639. if (ret != GNUNET_OK)
  640. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  641. _("Failed to end synchronizing state!\n"));
  642. }
  643. }
  644. send_result_code (client, req->op_id, ret, NULL);
  645. GNUNET_SERVICE_client_continue (client);
  646. }
  647. static void
  648. handle_client_state_reset (void *cls,
  649. const struct OperationRequest *req)
  650. {
  651. struct GNUNET_SERVICE_Client *client = cls;
  652. int ret = db->state_reset (db->cls, &req->channel_key);
  653. if (ret != GNUNET_OK)
  654. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  655. _("Failed to reset state!\n"));
  656. send_result_code (client, req->op_id, ret, NULL);
  657. GNUNET_SERVICE_client_continue (client);
  658. }
  659. static void
  660. handle_client_state_hash_update (void *cls,
  661. const struct StateHashUpdateRequest *req)
  662. {
  663. struct GNUNET_SERVICE_Client *client = cls;
  664. int ret = db->state_reset (db->cls, &req->channel_key);
  665. if (ret != GNUNET_OK)
  666. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  667. _("Failed to reset state!\n"));
  668. send_result_code (client, req->op_id, ret, NULL);
  669. GNUNET_SERVICE_client_continue (client);
  670. }
  671. static int
  672. check_client_state_get (void *cls,
  673. const struct OperationRequest *req)
  674. {
  675. return GNUNET_OK;
  676. }
  677. static void
  678. handle_client_state_get (void *cls,
  679. const struct OperationRequest *req)
  680. {
  681. struct GNUNET_SERVICE_Client *client = cls;
  682. struct SendClosure sc = { .op_id = req->op_id, .client = client };
  683. int64_t ret = GNUNET_SYSERR;
  684. const char *name = (const char *) &req[1];
  685. uint16_t name_size = ntohs (req->header.size) - sizeof (*req);
  686. if (name_size <= 2 || '\0' != name[name_size - 1])
  687. {
  688. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  689. _("Tried to get invalid state variable name!\n"));
  690. GNUNET_break (0);
  691. }
  692. else
  693. {
  694. ret = db->state_get (db->cls, &req->channel_key, name,
  695. &send_state_var, &sc);
  696. if (GNUNET_NO == ret && name_size >= 5) /* min: _a_b\0 */
  697. {
  698. char *p, *n = GNUNET_malloc (name_size);
  699. GNUNET_memcpy (n, name, name_size);
  700. while (&n[1] < (p = strrchr (n, '_')) && GNUNET_NO == ret)
  701. {
  702. *p = '\0';
  703. ret = db->state_get (db->cls, &req->channel_key, n,
  704. &send_state_var, &sc);
  705. }
  706. GNUNET_free (n);
  707. }
  708. }
  709. switch (ret)
  710. {
  711. case GNUNET_OK:
  712. case GNUNET_NO:
  713. break;
  714. default:
  715. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  716. _("Failed to get state variable!\n"));
  717. }
  718. send_result_code (client, req->op_id, ret, NULL);
  719. GNUNET_SERVICE_client_continue (client);
  720. }
  721. static int
  722. check_client_state_get_prefix (void *cls,
  723. const struct OperationRequest *req)
  724. {
  725. return GNUNET_OK;
  726. }
  727. static void
  728. handle_client_state_get_prefix (void *cls,
  729. const struct OperationRequest *req)
  730. {
  731. struct GNUNET_SERVICE_Client *client = cls;
  732. struct SendClosure sc = { .op_id = req->op_id, .client = client };
  733. int64_t ret = GNUNET_SYSERR;
  734. const char *name = (const char *) &req[1];
  735. uint16_t name_size = ntohs (req->header.size) - sizeof (*req);
  736. if (name_size <= 1 || '\0' != name[name_size - 1])
  737. {
  738. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  739. _("Tried to get invalid state variable name!\n"));
  740. GNUNET_break (0);
  741. }
  742. else
  743. {
  744. ret = db->state_get_prefix (db->cls, &req->channel_key, name,
  745. &send_state_var, &sc);
  746. }
  747. switch (ret)
  748. {
  749. case GNUNET_OK:
  750. case GNUNET_NO:
  751. break;
  752. default:
  753. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  754. _("Failed to get state variable!\n"));
  755. }
  756. send_result_code (client, req->op_id, ret, NULL);
  757. GNUNET_SERVICE_client_continue (client);
  758. }
  759. /**
  760. * A new client connected.
  761. *
  762. * @param cls NULL
  763. * @param client client to add
  764. * @param mq message queue for @a client
  765. * @return @a client
  766. */
  767. static void *
  768. client_notify_connect (void *cls,
  769. struct GNUNET_SERVICE_Client *client,
  770. struct GNUNET_MQ_Handle *mq)
  771. {
  772. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
  773. return client;
  774. }
  775. /**
  776. * Called whenever a client is disconnected.
  777. * Frees our resources associated with that client.
  778. *
  779. * @param cls closure
  780. * @param client identification of the client
  781. * @param app_ctx must match @a client
  782. */
  783. static void
  784. client_notify_disconnect (void *cls,
  785. struct GNUNET_SERVICE_Client *client,
  786. void *app_ctx)
  787. {
  788. }
  789. /**
  790. * Initialize the PSYCstore service.
  791. *
  792. * @param cls Closure.
  793. * @param server The initialized server.
  794. * @param c Configuration to use.
  795. */
  796. static void
  797. run (void *cls,
  798. const struct GNUNET_CONFIGURATION_Handle *c,
  799. struct GNUNET_SERVICE_Handle *svc)
  800. {
  801. cfg = c;
  802. service = svc;
  803. /* Loading database plugin */
  804. char *database;
  805. if (GNUNET_OK !=
  806. GNUNET_CONFIGURATION_get_value_string (cfg, "psycstore", "database",
  807. &database))
  808. {
  809. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  810. "psycstore",
  811. "database");
  812. }
  813. else
  814. {
  815. GNUNET_asprintf (&db_lib_name,
  816. "libgnunet_plugin_psycstore_%s",
  817. database);
  818. db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
  819. GNUNET_free (database);
  820. }
  821. if (NULL == db)
  822. {
  823. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  824. "Could not load database backend `%s'\n",
  825. db_lib_name);
  826. GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
  827. return;
  828. }
  829. stats = GNUNET_STATISTICS_create ("psycstore", cfg);
  830. GNUNET_SCHEDULER_add_shutdown (shutdown_task,
  831. NULL);
  832. }
  833. /**
  834. * Define "main" method using service macro.
  835. */
  836. GNUNET_SERVICE_MAIN
  837. ("psycstore",
  838. GNUNET_SERVICE_OPTION_NONE,
  839. run,
  840. client_notify_connect,
  841. client_notify_disconnect,
  842. NULL,
  843. GNUNET_MQ_hd_fixed_size (client_membership_store,
  844. GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE,
  845. struct MembershipStoreRequest,
  846. NULL),
  847. GNUNET_MQ_hd_fixed_size (client_membership_test,
  848. GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST,
  849. struct MembershipTestRequest,
  850. NULL),
  851. GNUNET_MQ_hd_var_size (client_fragment_store,
  852. GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE,
  853. struct FragmentStoreRequest,
  854. NULL),
  855. GNUNET_MQ_hd_fixed_size (client_fragment_get,
  856. GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET,
  857. struct FragmentGetRequest,
  858. NULL),
  859. GNUNET_MQ_hd_var_size (client_message_get,
  860. GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET,
  861. struct MessageGetRequest,
  862. NULL),
  863. GNUNET_MQ_hd_fixed_size (client_message_get_fragment,
  864. GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET_FRAGMENT,
  865. struct MessageGetFragmentRequest,
  866. NULL),
  867. GNUNET_MQ_hd_fixed_size (client_counters_get,
  868. GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET,
  869. struct OperationRequest,
  870. NULL),
  871. GNUNET_MQ_hd_fixed_size (client_state_modify,
  872. GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY,
  873. struct StateModifyRequest,
  874. NULL),
  875. GNUNET_MQ_hd_var_size (client_state_sync,
  876. GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC,
  877. struct StateSyncRequest,
  878. NULL),
  879. GNUNET_MQ_hd_fixed_size (client_state_reset,
  880. GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_RESET,
  881. struct OperationRequest,
  882. NULL),
  883. GNUNET_MQ_hd_fixed_size (client_state_hash_update,
  884. GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_HASH_UPDATE,
  885. struct StateHashUpdateRequest,
  886. NULL),
  887. GNUNET_MQ_hd_var_size (client_state_get,
  888. GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET,
  889. struct OperationRequest,
  890. NULL),
  891. GNUNET_MQ_hd_var_size (client_state_get_prefix,
  892. GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET_PREFIX,
  893. struct OperationRequest,
  894. NULL));
  895. /* end of gnunet-service-psycstore.c */