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.
 
 
 
 

3761 lines
103 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 social/gnunet-service-social.c
  21. * @brief Social service
  22. * @author Gabor X Toth
  23. */
  24. #include <inttypes.h>
  25. #include <strings.h>
  26. #include <gnunet/platform.h>
  27. #include <gnunet/gnunet_util_lib.h>
  28. #include <gnunet/gnunet_constants.h>
  29. #include <gnunet/gnunet_protocols.h>
  30. #include <gnunet/gnunet_identity_service.h>
  31. #include <gnunet/gnunet_namestore_service.h>
  32. #include <gnunet/gnunet_gns_service.h>
  33. #include <gnunet/gnunet_statistics_service.h>
  34. #include "gnunet_psyc_service.h"
  35. #include "gnunet_psyc_util_lib.h"
  36. #include "gnunet_social_service.h"
  37. #include "social.h"
  38. /**
  39. * Handle to our current configuration.
  40. */
  41. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  42. /**
  43. * Service handle.
  44. */
  45. static struct GNUNET_SERVICE_Handle *service;
  46. /* Handles to other services */
  47. static struct GNUNET_IDENTITY_Handle *id;
  48. static struct GNUNET_GNS_Handle *gns;
  49. static struct GNUNET_NAMESTORE_Handle *namestore;
  50. static struct GNUNET_STATISTICS_Handle *stats;
  51. /**
  52. * ID of this peer.
  53. */
  54. static struct GNUNET_PeerIdentity this_peer;
  55. /**
  56. * All connected hosts.
  57. * H(place_pub_key) -> struct Host
  58. */
  59. static struct GNUNET_CONTAINER_MultiHashMap *hosts;
  60. /**
  61. * All connected guests.
  62. * H(place_pub_key) -> struct Guest
  63. */
  64. static struct GNUNET_CONTAINER_MultiHashMap *guests;
  65. /**
  66. * Connected guests per place.
  67. * H(place_pub_key) -> ego_pub_key -> struct Guest
  68. */
  69. static struct GNUNET_CONTAINER_MultiHashMap *place_guests;
  70. /**
  71. * Places entered as host or guest.
  72. * H(place_pub_key) -> struct HostEnterRequest OR struct GuestEnterRequest
  73. */
  74. static struct GNUNET_CONTAINER_MultiHashMap *places;
  75. /**
  76. * Places entered per application.
  77. * H(app_id) -> H(place_pub_key) -> NULL
  78. */
  79. static struct GNUNET_CONTAINER_MultiHashMap *apps_places;
  80. /**
  81. * Application subscriptions per place.
  82. * H(place_pub_key) -> H(app_id)
  83. */
  84. //static struct GNUNET_CONTAINER_MultiHashMap *places_apps;
  85. /**
  86. * Connected applications.
  87. * H(app_id) -> struct Application
  88. */
  89. static struct GNUNET_CONTAINER_MultiHashMap *apps;
  90. /**
  91. * All egos.
  92. * H(ego_pub_key) -> struct Ego
  93. */
  94. static struct GNUNET_CONTAINER_MultiHashMap *egos;
  95. /**
  96. * Directory for storing social data.
  97. * Default: $GNUNET_DATA_HOME/social
  98. */
  99. static char *dir_social;
  100. /**
  101. * Directory for storing place data.
  102. * $dir_social/places
  103. */
  104. static char *dir_places;
  105. /**
  106. * Directory for storing app data.
  107. * $dir_social/apps
  108. */
  109. static char *dir_apps;
  110. /**
  111. * Message fragment transmission queue.
  112. */
  113. struct FragmentTransmitQueue
  114. {
  115. struct FragmentTransmitQueue *prev;
  116. struct FragmentTransmitQueue *next;
  117. struct GNUNET_SERVICE_Client *client;
  118. /**
  119. * Pointer to the next message part inside the data after this struct.
  120. */
  121. struct GNUNET_MessageHeader *next_part;
  122. /**
  123. * Size of message.
  124. */
  125. uint16_t size;
  126. /**
  127. * @see enum GNUNET_PSYC_MessageState
  128. */
  129. uint8_t state;
  130. /* Followed by one or more message parts. */
  131. };
  132. /**
  133. * Message transmission queue.
  134. */
  135. struct MessageTransmitQueue
  136. {
  137. struct MessageTransmitQueue *prev;
  138. struct MessageTransmitQueue *next;
  139. struct FragmentTransmitQueue *frags_head;
  140. struct FragmentTransmitQueue *frags_tail;
  141. struct GNUNET_SERVICE_Client *client;
  142. };
  143. /**
  144. * List of connected clients.
  145. */
  146. struct ClientListItem
  147. {
  148. struct ClientListItem *prev;
  149. struct ClientListItem *next;
  150. struct GNUNET_SERVICE_Client *client;
  151. };
  152. /**
  153. * Common part of the client context for both a host and guest.
  154. */
  155. struct Place
  156. {
  157. struct ClientListItem *clients_head;
  158. struct ClientListItem *clients_tail;
  159. struct MessageTransmitQueue *tmit_msgs_head;
  160. struct MessageTransmitQueue *tmit_msgs_tail;
  161. struct GNUNET_PSYC_Channel *channel;
  162. /**
  163. * Private key of home in case of a host.
  164. */
  165. struct GNUNET_CRYPTO_EddsaPublicKey key;
  166. /**
  167. * Public key of place.
  168. */
  169. struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
  170. /**
  171. * Hash of @a pub_key.
  172. */
  173. struct GNUNET_HashCode pub_key_hash;
  174. /**
  175. * Private key of ego.
  176. */
  177. struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key;
  178. /**
  179. * Public key of ego.
  180. */
  181. struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
  182. /**
  183. * Hash of @a ego_pub_key.
  184. */
  185. struct GNUNET_HashCode ego_pub_hash;
  186. /**
  187. * Slicer for processing incoming messages.
  188. */
  189. struct GNUNET_PSYC_Slicer *slicer;
  190. /**
  191. * Last message ID received for the place.
  192. * 0 if there is no such message.
  193. */
  194. uint64_t max_message_id;
  195. /**
  196. * Offset where the file is currently being written.
  197. */
  198. uint64_t file_offset;
  199. /**
  200. * Whether or not to save the file (#GNUNET_YES or #GNUNET_NO)
  201. */
  202. uint8_t file_save;
  203. /**
  204. * Is this place ready to receive messages from client?
  205. * #GNUNET_YES or #GNUNET_NO
  206. */
  207. uint8_t is_ready;
  208. /**
  209. * Is the client disconnecting?
  210. * #GNUNET_YES or #GNUNET_NO
  211. */
  212. uint8_t is_disconnecting;
  213. /**
  214. * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)?
  215. */
  216. uint8_t is_host;
  217. union {
  218. struct Host *host;
  219. struct Guest *guest;
  220. };
  221. };
  222. /**
  223. * Client context for a host.
  224. */
  225. struct Host
  226. {
  227. /**
  228. * Place struct common for Host and Guest
  229. */
  230. struct Place place;
  231. /**
  232. * Handle for the multicast origin.
  233. */
  234. struct GNUNET_PSYC_Master *master;
  235. /**
  236. * Transmit handle for multicast.
  237. */
  238. struct GNUNET_PSYC_MasterTransmitHandle *tmit_handle;
  239. /**
  240. * Incoming join requests.
  241. * guest_key -> struct GNUNET_PSYC_JoinHandle *
  242. */
  243. struct GNUNET_CONTAINER_MultiHashMap *join_reqs;
  244. /**
  245. * Messages being relayed.
  246. */
  247. struct GNUNET_CONTAINER_MultiHashMap *relay_msgs;
  248. /**
  249. * @see enum GNUNET_PSYC_Policy
  250. */
  251. enum GNUNET_PSYC_Policy policy;
  252. };
  253. /**
  254. * Client context for a guest.
  255. */
  256. struct Guest
  257. {
  258. /**
  259. * Place struct common for Host and Guest.
  260. */
  261. struct Place place;
  262. /**
  263. * Handle for the PSYC slave.
  264. */
  265. struct GNUNET_PSYC_Slave *slave;
  266. /**
  267. * Transmit handle for multicast.
  268. */
  269. struct GNUNET_PSYC_SlaveTransmitHandle *tmit_handle;
  270. /**
  271. * Peer identity of the origin.
  272. */
  273. struct GNUNET_PeerIdentity origin;
  274. /**
  275. * Number of items in @a relays.
  276. */
  277. uint32_t relay_count;
  278. /**
  279. * Relays that multicast can use to connect.
  280. */
  281. struct GNUNET_PeerIdentity *relays;
  282. /**
  283. * Join request to be transmitted to the master on join.
  284. */
  285. struct GNUNET_MessageHeader *join_req; // FIXME: not used!
  286. /**
  287. * Join decision received from PSYC.
  288. */
  289. struct GNUNET_PSYC_JoinDecisionMessage *join_dcsn;
  290. /**
  291. * Join flags for the PSYC service.
  292. */
  293. enum GNUNET_PSYC_SlaveJoinFlags join_flags;
  294. };
  295. /**
  296. * Context for a client.
  297. */
  298. struct Client
  299. {
  300. /**
  301. * Client handle.
  302. */
  303. struct GNUNET_SERVICE_Client *client;
  304. /**
  305. * Place where the client entered.
  306. */
  307. struct Place *place;
  308. /**
  309. * Message queue for the message currently being transmitted
  310. * by this client.
  311. */
  312. struct MessageTransmitQueue *tmit_msg;
  313. /**
  314. * ID for application clients.
  315. */
  316. char *app_id;
  317. };
  318. struct Application
  319. {
  320. struct ClientListItem *clients_head;
  321. struct ClientListItem *clients_tail;
  322. };
  323. struct Ego {
  324. struct GNUNET_CRYPTO_EcdsaPrivateKey key;
  325. char *name;
  326. };
  327. struct OperationClosure
  328. {
  329. struct Client *client;
  330. uint64_t op_id;
  331. uint32_t flags;
  332. };
  333. static int
  334. psyc_transmit_message (struct Place *plc);
  335. /**
  336. * Clean up place data structures after a client disconnected.
  337. *
  338. * @param cls the `struct Place` to clean up
  339. */
  340. static void
  341. cleanup_place (void *cls);
  342. static struct MessageTransmitQueue *
  343. psyc_transmit_queue_message (struct Place *plc,
  344. struct GNUNET_SERVICE_Client *client,
  345. size_t data_size,
  346. const void *data,
  347. uint16_t first_ptype, uint16_t last_ptype,
  348. struct MessageTransmitQueue *tmit_msg);
  349. static int
  350. place_entry_cleanup (void *cls,
  351. const struct GNUNET_HashCode *key,
  352. void *value)
  353. {
  354. struct Place *plc = value;
  355. cleanup_place (plc);
  356. return GNUNET_YES;
  357. }
  358. /**
  359. * Task run during shutdown.
  360. *
  361. * @param cls unused
  362. */
  363. static void
  364. shutdown_task (void *cls)
  365. {
  366. GNUNET_CONTAINER_multihashmap_iterate (hosts, place_entry_cleanup, NULL);
  367. GNUNET_CONTAINER_multihashmap_iterate (guests, place_entry_cleanup, NULL);
  368. if (NULL != id)
  369. {
  370. GNUNET_IDENTITY_disconnect (id);
  371. id = NULL;
  372. }
  373. if (NULL != namestore)
  374. {
  375. GNUNET_NAMESTORE_disconnect (namestore);
  376. namestore = NULL;
  377. }
  378. if (NULL != gns)
  379. {
  380. GNUNET_GNS_disconnect (gns);
  381. gns = NULL;
  382. }
  383. if (NULL != stats)
  384. {
  385. GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
  386. stats = NULL;
  387. }
  388. }
  389. /**
  390. * Clean up host data structures after a client disconnected.
  391. */
  392. static void
  393. cleanup_host (struct Host *hst)
  394. {
  395. struct Place *plc = &hst->place;
  396. GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs);
  397. GNUNET_CONTAINER_multihashmap_destroy (hst->relay_msgs);
  398. GNUNET_CONTAINER_multihashmap_remove (hosts, &plc->pub_key_hash, plc);
  399. }
  400. /**
  401. * Clean up guest data structures after a client disconnected.
  402. */
  403. static void
  404. cleanup_guest (struct Guest *gst)
  405. {
  406. struct Place *plc = &gst->place;
  407. struct GNUNET_CONTAINER_MultiHashMap *
  408. plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
  409. &plc->pub_key_hash);
  410. if (NULL != plc_gst)
  411. {
  412. GNUNET_CONTAINER_multihashmap_remove (plc_gst, &plc->ego_pub_hash, gst);
  413. if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst))
  414. {
  415. GNUNET_CONTAINER_multihashmap_remove (place_guests, &plc->pub_key_hash,
  416. plc_gst);
  417. GNUNET_CONTAINER_multihashmap_destroy (plc_gst);
  418. }
  419. }
  420. GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, gst);
  421. if (NULL != gst->join_req)
  422. GNUNET_free (gst->join_req);
  423. if (NULL != gst->relays)
  424. GNUNET_free (gst->relays);
  425. GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, plc);
  426. }
  427. /**
  428. * Clean up place data structures after a client disconnected.
  429. *
  430. * @param cls the `struct Place` to clean up
  431. */
  432. static void
  433. cleanup_place (void *cls)
  434. {
  435. struct Place *plc = cls;
  436. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  437. "cleaning up place %s\n",
  438. GNUNET_h2s (&plc->pub_key_hash));
  439. (GNUNET_YES == plc->is_host)
  440. ? cleanup_host ((struct Host *) plc)
  441. : cleanup_guest ((struct Guest *) plc);
  442. GNUNET_PSYC_slicer_destroy (plc->slicer);
  443. GNUNET_free (plc);
  444. }
  445. /**
  446. * Called whenever a client is disconnected.
  447. * Frees our resources associated with that client.
  448. *
  449. * @param cls closure
  450. * @param client identification of the client
  451. * @param app_ctx must match @a client
  452. */
  453. static void
  454. client_notify_disconnect (void *cls,
  455. struct GNUNET_SERVICE_Client *client,
  456. void *app_ctx)
  457. {
  458. struct Client *c = app_ctx;
  459. struct Place *plc = c->place;
  460. if (NULL != c->app_id)
  461. GNUNET_free (c->app_id);
  462. GNUNET_free (c);
  463. if (NULL == plc)
  464. return; // application client, nothing to do
  465. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  466. "%p Client (%s) disconnected from place %s\n",
  467. plc, (GNUNET_YES == plc->is_host) ? "host" : "guest",
  468. GNUNET_h2s (&plc->pub_key_hash));
  469. struct ClientListItem *cli = plc->clients_head;
  470. while (NULL != cli)
  471. {
  472. if (cli->client == client)
  473. {
  474. GNUNET_CONTAINER_DLL_remove (plc->clients_head,
  475. plc->clients_tail,
  476. cli);
  477. GNUNET_free (cli);
  478. break;
  479. }
  480. cli = cli->next;
  481. }
  482. if (GNUNET_YES == plc->is_disconnecting)
  483. {
  484. GNUNET_PSYC_slicer_destroy (plc->slicer);
  485. GNUNET_free (plc);
  486. }
  487. }
  488. /**
  489. * A new client connected.
  490. *
  491. * @param cls NULL
  492. * @param client client to add
  493. * @param mq message queue for @a client
  494. * @return @a client
  495. */
  496. static void *
  497. client_notify_connect (void *cls,
  498. struct GNUNET_SERVICE_Client *client,
  499. struct GNUNET_MQ_Handle *mq)
  500. {
  501. struct Client *c = GNUNET_new (struct Client);
  502. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  503. "Client %p connected with queue %p\n",
  504. client,
  505. mq);
  506. c->client = client;
  507. return c;
  508. }
  509. /**
  510. * Send message to all clients connected to a place and
  511. * takes care of freeing @env.
  512. */
  513. static void
  514. place_send_msg (const struct Place *plc,
  515. struct GNUNET_MQ_Envelope *env)
  516. {
  517. struct ClientListItem *cli = plc->clients_head;
  518. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  519. "%p Sending message to clients of place.\n", plc);
  520. while (NULL != cli)
  521. {
  522. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  523. "Sending message to client %p\n",
  524. cli);
  525. GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client),
  526. env);
  527. cli = cli->next;
  528. }
  529. GNUNET_MQ_discard (env);
  530. }
  531. static void
  532. place_send_leave_ack (struct Place *plc)
  533. {
  534. struct GNUNET_MQ_Envelope *env;
  535. for (struct ClientListItem *cli = plc->clients_head;
  536. NULL != cli;
  537. cli = cli->next)
  538. {
  539. env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK);
  540. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cli->client),
  541. env);
  542. }
  543. }
  544. /**
  545. * Send a result code back to the client.
  546. *
  547. * @param client
  548. * Client that should receive the result code.
  549. * @param result_code
  550. * Code to transmit.
  551. * @param op_id
  552. * Operation ID in network byte order.
  553. * @param data
  554. * Data payload or NULL.
  555. * @param data_size
  556. * Size of @a data.
  557. */
  558. static void
  559. client_send_result (struct GNUNET_SERVICE_Client *client, uint64_t op_id,
  560. int64_t result_code, const void *data, uint16_t data_size)
  561. {
  562. struct GNUNET_MQ_Envelope *env;
  563. struct GNUNET_OperationResultMessage *res;
  564. env = GNUNET_MQ_msg_extra (res,
  565. data_size,
  566. GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE);
  567. res->result_code = GNUNET_htonll (result_code);
  568. res->op_id = op_id;
  569. if (0 < data_size)
  570. GNUNET_memcpy (&res[1], data, data_size);
  571. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  572. "%p Sending result to client for operation #%" PRIu64 ": "
  573. "%" PRId64 " (size: %u)\n",
  574. client, GNUNET_ntohll (op_id), result_code, data_size);
  575. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
  576. }
  577. static void
  578. client_send_host_enter_ack (struct GNUNET_SERVICE_Client *client,
  579. struct Host *hst, uint32_t result)
  580. {
  581. struct GNUNET_MQ_Envelope *env;
  582. struct HostEnterAck *hack;
  583. struct Place *plc = &hst->place;
  584. env = GNUNET_MQ_msg (hack,
  585. GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
  586. hack->result_code = htonl (result);
  587. hack->max_message_id = GNUNET_htonll (plc->max_message_id);
  588. hack->place_pub_key = plc->pub_key;
  589. if (NULL != client)
  590. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  591. env);
  592. else
  593. place_send_msg (plc, env);
  594. }
  595. /**
  596. * Called after a PSYC master is started.
  597. */
  598. static void
  599. psyc_master_started (void *cls, int result, uint64_t max_message_id)
  600. {
  601. struct Host *hst = cls;
  602. struct Place *plc = &hst->place;
  603. plc->max_message_id = max_message_id;
  604. plc->is_ready = GNUNET_YES;
  605. client_send_host_enter_ack (NULL, hst, result);
  606. }
  607. /**
  608. * Called when a PSYC master receives a join request.
  609. */
  610. static void
  611. psyc_recv_join_request (void *cls,
  612. const struct GNUNET_PSYC_JoinRequestMessage *req,
  613. const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
  614. const struct GNUNET_PSYC_Message *join_msg,
  615. struct GNUNET_PSYC_JoinHandle *jh)
  616. {
  617. struct Host *hst = cls;
  618. struct GNUNET_HashCode slave_key_hash;
  619. GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
  620. GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh,
  621. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  622. place_send_msg (&hst->place,
  623. GNUNET_MQ_msg_copy (&req->header));
  624. }
  625. /**
  626. * Called after a PSYC slave is connected.
  627. */
  628. static void
  629. psyc_slave_connected (void *cls, int result, uint64_t max_message_id)
  630. {
  631. struct GNUNET_PSYC_CountersResultMessage *res;
  632. struct GNUNET_MQ_Envelope *env;
  633. struct Guest *gst = cls;
  634. struct Place *plc = &gst->place;
  635. plc->max_message_id = max_message_id;
  636. plc->is_ready = GNUNET_YES;
  637. env = GNUNET_MQ_msg (res,
  638. GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
  639. res->result_code =
  640. (result != GNUNET_SYSERR) ? htonl (GNUNET_OK) : htonl (GNUNET_SYSERR);
  641. res->max_message_id = GNUNET_htonll (plc->max_message_id);
  642. place_send_msg (plc, env);
  643. }
  644. static void
  645. slave_parted_after_join_decision (void *cls)
  646. {
  647. struct Guest *gst = cls;
  648. GNUNET_assert (NULL != gst->join_dcsn);
  649. place_send_msg (&gst->place, GNUNET_MQ_msg_copy (&gst->join_dcsn->header));
  650. }
  651. /**
  652. * Called when a PSYC slave receives a join decision.
  653. */
  654. static void
  655. psyc_recv_join_dcsn (void *cls,
  656. const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
  657. int is_admitted,
  658. const struct GNUNET_PSYC_Message *join_msg)
  659. {
  660. struct Guest *gst = cls;
  661. gst->join_dcsn = GNUNET_malloc (dcsn->header.size);
  662. GNUNET_memcpy (gst->join_dcsn,
  663. dcsn,
  664. dcsn->header.size);
  665. if (GNUNET_NO == is_admitted)
  666. {
  667. GNUNET_PSYC_slave_part (gst->slave,
  668. GNUNET_NO,
  669. &slave_parted_after_join_decision,
  670. gst);
  671. gst->slave = NULL;
  672. return;
  673. }
  674. place_send_msg (&gst->place, GNUNET_MQ_msg_copy (&gst->join_dcsn->header));
  675. }
  676. /**
  677. * Called when a PSYC master or slave receives a message.
  678. */
  679. static void
  680. psyc_recv_message (void *cls,
  681. const struct GNUNET_PSYC_MessageHeader *msg)
  682. {
  683. struct Place *plc = cls;
  684. char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&msg->slave_pub_key);
  685. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  686. "%p Received PSYC message of size %u from %s.\n",
  687. plc, ntohs (msg->header.size), str);
  688. GNUNET_free (str);
  689. GNUNET_PSYC_slicer_message (plc->slicer, msg);
  690. place_send_msg (plc, GNUNET_MQ_msg_copy (&msg->header));
  691. }
  692. /**
  693. * Relay a message part received from a guest to the the place.
  694. *
  695. * @param hst
  696. * Host.
  697. * @param pmsg
  698. * Message part.
  699. * @param nym_pub_key
  700. * Nym the message is received from.
  701. */
  702. static void
  703. host_relay_message_part (struct Host *hst,
  704. const struct GNUNET_MessageHeader *pmsg,
  705. const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key)
  706. {
  707. /* separate queue per nym */
  708. struct GNUNET_HashCode nym_pub_hash;
  709. GNUNET_CRYPTO_hash (nym_pub_key, sizeof (*nym_pub_key), &nym_pub_hash);
  710. struct MessageTransmitQueue *
  711. tmit_msg = GNUNET_CONTAINER_multihashmap_get (hst->relay_msgs, &nym_pub_hash);
  712. uint16_t ptype = ntohs (pmsg->type);
  713. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype)
  714. {
  715. /* FIXME: last message was unfinished, cancel & remove from queue */
  716. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  717. "FIXME: last message was unfinished.\n");
  718. }
  719. tmit_msg = psyc_transmit_queue_message (&hst->place, NULL, ntohs (pmsg->size),
  720. pmsg, ptype, ptype, tmit_msg);
  721. switch (ptype)
  722. {
  723. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
  724. GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put
  725. (hst->relay_msgs, &nym_pub_hash, tmit_msg,
  726. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  727. break;
  728. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  729. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  730. GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove
  731. (hst->relay_msgs, &nym_pub_hash, tmit_msg));
  732. break;
  733. }
  734. }
  735. /**
  736. * Received a method to be relayed from a guest.
  737. */
  738. static void
  739. place_recv_relay_method (void *cls,
  740. const struct GNUNET_PSYC_MessageHeader *msg,
  741. const struct GNUNET_PSYC_MessageMethod *meth,
  742. uint64_t message_id,
  743. const char *method_name)
  744. {
  745. struct Place *plc = cls;
  746. if (GNUNET_PSYC_MESSAGE_REQUEST & ntohs (msg->flags)
  747. && GNUNET_YES == plc->is_host)
  748. {
  749. struct Host *hst = cls;
  750. host_relay_message_part (hst, &meth->header, &msg->slave_pub_key);
  751. }
  752. }
  753. /**
  754. * Received a modifier to be relayed from a guest.
  755. */
  756. static void
  757. place_recv_relay_modifier (void *cls,
  758. const struct GNUNET_PSYC_MessageHeader *msg,
  759. const struct GNUNET_MessageHeader *pmsg,
  760. uint64_t message_id,
  761. enum GNUNET_PSYC_Operator oper,
  762. const char *name,
  763. const void *value,
  764. uint16_t value_size,
  765. uint16_t full_value_size)
  766. {
  767. struct Place *plc = cls;
  768. if (GNUNET_PSYC_MESSAGE_REQUEST & ntohs (msg->flags)
  769. && GNUNET_YES == plc->is_host)
  770. {
  771. struct Host *hst = cls;
  772. host_relay_message_part (hst, pmsg, &msg->slave_pub_key);
  773. }
  774. }
  775. /**
  776. * Received a data fragment to be relayed from a guest.
  777. */
  778. static void
  779. place_recv_relay_data (void *cls,
  780. const struct GNUNET_PSYC_MessageHeader *msg,
  781. const struct GNUNET_MessageHeader *pmsg,
  782. uint64_t message_id,
  783. const void *data,
  784. uint16_t data_size)
  785. {
  786. struct Place *plc = cls;
  787. if (GNUNET_PSYC_MESSAGE_REQUEST & ntohs (msg->flags)
  788. && GNUNET_YES == plc->is_host)
  789. {
  790. struct Host *hst = cls;
  791. host_relay_message_part (hst, pmsg, &msg->slave_pub_key);
  792. }
  793. }
  794. /**
  795. * Received end of message to be relayed from a guest.
  796. */
  797. static void
  798. place_recv_relay_eom (void *cls,
  799. const struct GNUNET_PSYC_MessageHeader *msg,
  800. const struct GNUNET_MessageHeader *pmsg,
  801. uint64_t message_id,
  802. uint8_t is_cancelled)
  803. {
  804. struct Place *plc = cls;
  805. if (GNUNET_PSYC_MESSAGE_REQUEST & ntohs (msg->flags)
  806. && GNUNET_YES == plc->is_host)
  807. {
  808. struct Host *hst = cls;
  809. host_relay_message_part (hst, pmsg, &msg->slave_pub_key);
  810. }
  811. }
  812. /**
  813. * Received a method to be saved to disk.
  814. *
  815. * Create a new file for writing the data part of the message into,
  816. * if the file does not yet exist.
  817. */
  818. static void
  819. place_recv_save_method (void *cls,
  820. const struct GNUNET_PSYC_MessageHeader *msg,
  821. const struct GNUNET_PSYC_MessageMethod *meth,
  822. uint64_t message_id,
  823. const char *method_name)
  824. {
  825. struct Place *plc = cls;
  826. plc->file_offset = 0;
  827. plc->file_save = GNUNET_NO;
  828. char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&plc->pub_key);
  829. char *filename = NULL;
  830. GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%" PRIu64 ".part",
  831. dir_social, DIR_SEPARATOR,
  832. "files", DIR_SEPARATOR,
  833. place_pub_str, DIR_SEPARATOR,
  834. GNUNET_ntohll (msg->message_id));
  835. GNUNET_free (place_pub_str);
  836. /* save if does not already exist */
  837. if (GNUNET_YES != GNUNET_DISK_file_test (filename))
  838. {
  839. if (0 == GNUNET_DISK_fn_write (filename, NULL, 0,
  840. GNUNET_DISK_PERM_USER_READ
  841. | GNUNET_DISK_PERM_USER_WRITE))
  842. {
  843. plc->file_save = GNUNET_YES;
  844. }
  845. else
  846. {
  847. GNUNET_break (0);
  848. }
  849. }
  850. GNUNET_free (filename);
  851. }
  852. /**
  853. * Received a data fragment to be saved to disk.
  854. *
  855. * Append data fragment to the file.
  856. */
  857. static void
  858. place_recv_save_data (void *cls,
  859. const struct GNUNET_PSYC_MessageHeader *msg,
  860. const struct GNUNET_MessageHeader *pmsg,
  861. uint64_t message_id,
  862. const void *data,
  863. uint16_t data_size)
  864. {
  865. struct Place *plc = cls;
  866. if (GNUNET_YES != plc->file_save)
  867. return;
  868. char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&plc->pub_key);
  869. char *filename = NULL;
  870. GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%" PRIu64 ".part",
  871. dir_social, DIR_SEPARATOR,
  872. "files", DIR_SEPARATOR,
  873. place_pub_str, DIR_SEPARATOR,
  874. GNUNET_ntohll (msg->message_id));
  875. GNUNET_free (place_pub_str);
  876. if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
  877. {
  878. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "create", filename);
  879. GNUNET_free (filename);
  880. return;
  881. }
  882. struct GNUNET_DISK_FileHandle *
  883. fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE,
  884. GNUNET_DISK_PERM_NONE);
  885. if (NULL != fh)
  886. {
  887. if (plc->file_offset != GNUNET_DISK_file_seek
  888. (fh, plc->file_offset, GNUNET_DISK_SEEK_SET)) {
  889. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "seek", filename);
  890. GNUNET_DISK_file_close (fh);
  891. GNUNET_free (filename);
  892. return;
  893. }
  894. GNUNET_DISK_file_write (fh, data, data_size);
  895. GNUNET_DISK_file_close (fh);
  896. GNUNET_free (filename);
  897. }
  898. else
  899. {
  900. GNUNET_free (filename);
  901. GNUNET_break (0);
  902. }
  903. plc->file_offset += data_size;
  904. }
  905. /**
  906. * Received end of message to be saved to disk.
  907. *
  908. * Remove .part ending from the filename.
  909. */
  910. static void
  911. place_recv_save_eom (void *cls,
  912. const struct GNUNET_PSYC_MessageHeader *msg,
  913. const struct GNUNET_MessageHeader *pmsg,
  914. uint64_t message_id,
  915. uint8_t is_cancelled)
  916. {
  917. struct Place *plc = cls;
  918. if (GNUNET_YES != plc->file_save)
  919. return;
  920. char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&plc->pub_key);
  921. char *fn = NULL;
  922. GNUNET_asprintf (&fn, "%s%c%s%c%s%c%" PRIu64,
  923. dir_social, DIR_SEPARATOR,
  924. "files", DIR_SEPARATOR,
  925. place_pub_str, DIR_SEPARATOR,
  926. GNUNET_ntohll (msg->message_id));
  927. GNUNET_free (place_pub_str);
  928. char *fn_part = NULL;
  929. GNUNET_asprintf (&fn_part, "%s.part", fn);
  930. if (rename (fn_part, fn)) {
  931. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  932. "Failed to rename %s into %s: %s (%d)\n",
  933. fn_part, fn, strerror (errno), errno);
  934. }
  935. GNUNET_free (fn);
  936. GNUNET_free (fn_part);
  937. }
  938. /**
  939. * Initialize place data structure.
  940. */
  941. static void
  942. place_init (struct Place *plc)
  943. {
  944. plc->slicer = GNUNET_PSYC_slicer_create ();
  945. }
  946. /**
  947. * Add a place to the @e places hash map.
  948. *
  949. * @param ereq
  950. * Entry request.
  951. *
  952. * @return #GNUNET_OK if the place was added
  953. * #GNUNET_NO if the place already exists in the hash map
  954. * #GNUNET_SYSERR on error
  955. */
  956. static int
  957. place_add (const struct PlaceEnterRequest *ereq)
  958. {
  959. struct EgoPlacePublicKey ego_place_pub_key = {
  960. .ego_pub_key = ereq->ego_pub_key,
  961. .place_pub_key = ereq->place_pub_key,
  962. };
  963. struct GNUNET_HashCode ego_place_pub_hash;
  964. GNUNET_CRYPTO_hash (&ego_place_pub_key, sizeof (ego_place_pub_key), &ego_place_pub_hash);
  965. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  966. " ego_place_pub_hash = %s\n", GNUNET_h2s (&ego_place_pub_hash));
  967. struct GNUNET_MessageHeader *
  968. place_msg = GNUNET_CONTAINER_multihashmap_get (places, &ego_place_pub_hash);
  969. if (NULL != place_msg)
  970. return GNUNET_NO;
  971. place_msg = GNUNET_copy_message (&ereq->header);
  972. if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (places, &ego_place_pub_hash, place_msg,
  973. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
  974. {
  975. GNUNET_break (0);
  976. GNUNET_free (place_msg);
  977. return GNUNET_SYSERR;
  978. }
  979. return GNUNET_OK;
  980. }
  981. /**
  982. * Add a place to the @e app_places hash map.
  983. *
  984. * @param app_id
  985. * Application ID.
  986. * @param ereq
  987. * Entry request.
  988. *
  989. * @return #GNUNET_OK if the place was added
  990. * #GNUNET_NO if the place already exists in the hash map
  991. * #GNUNET_SYSERR on error
  992. */
  993. static int
  994. app_place_add (const char *app_id,
  995. const struct PlaceEnterRequest *ereq)
  996. {
  997. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  998. "Adding app place to hashmap:\n");
  999. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1000. " app_id = %s\n", app_id);
  1001. struct GNUNET_HashCode app_id_hash;
  1002. GNUNET_CRYPTO_hash (app_id, strlen (app_id) + 1, &app_id_hash);
  1003. struct EgoPlacePublicKey ego_place_pub_key = {
  1004. .ego_pub_key = ereq->ego_pub_key,
  1005. .place_pub_key = ereq->place_pub_key,
  1006. };
  1007. struct GNUNET_HashCode ego_place_pub_hash;
  1008. GNUNET_CRYPTO_hash (&ego_place_pub_key, sizeof (ego_place_pub_key), &ego_place_pub_hash);
  1009. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1010. " ego_place_pub_hash = %s\n", GNUNET_h2s (&ego_place_pub_hash));
  1011. struct GNUNET_CONTAINER_MultiHashMap *
  1012. app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
  1013. if (NULL == app_places)
  1014. {
  1015. app_places = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1016. GNUNET_CONTAINER_multihashmap_put (apps_places, &app_id_hash, app_places,
  1017. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1018. }
  1019. if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (app_places, &ego_place_pub_hash))
  1020. return GNUNET_NO;
  1021. if (GNUNET_SYSERR == place_add (ereq))
  1022. {
  1023. return GNUNET_SYSERR;
  1024. }
  1025. if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (app_places, &ego_place_pub_hash, NULL,
  1026. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
  1027. {
  1028. GNUNET_break (0);
  1029. return GNUNET_SYSERR;
  1030. }
  1031. return GNUNET_OK;
  1032. }
  1033. /**
  1034. * Save place entry message to disk.
  1035. *
  1036. * @param app_id
  1037. * Application ID.
  1038. * @param ereq
  1039. * Entry request message.
  1040. */
  1041. static int
  1042. app_place_save (const char *app_id,
  1043. const struct PlaceEnterRequest *ereq)
  1044. {
  1045. if (GNUNET_SYSERR == app_place_add (app_id, ereq))
  1046. {
  1047. GNUNET_assert (0);
  1048. }
  1049. if (NULL == dir_places)
  1050. return GNUNET_SYSERR;
  1051. char *ego_pub_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ereq->ego_pub_key);
  1052. char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&ereq->place_pub_key);
  1053. char *filename = NULL;
  1054. GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s",
  1055. dir_social, DIR_SEPARATOR,
  1056. "places", DIR_SEPARATOR,
  1057. ego_pub_str, DIR_SEPARATOR,
  1058. place_pub_str);
  1059. int ret = GNUNET_DISK_directory_create_for_file (filename);
  1060. if (GNUNET_OK != ret
  1061. || 0 > GNUNET_DISK_fn_write (filename, ereq, ntohs (ereq->header.size),
  1062. GNUNET_DISK_PERM_USER_READ
  1063. | GNUNET_DISK_PERM_USER_WRITE))
  1064. {
  1065. GNUNET_break (0);
  1066. ret = GNUNET_SYSERR;
  1067. }
  1068. GNUNET_free (filename);
  1069. if (ret == GNUNET_OK)
  1070. {
  1071. GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s%c" "%s",
  1072. dir_social, DIR_SEPARATOR,
  1073. "apps", DIR_SEPARATOR,
  1074. app_id, DIR_SEPARATOR,
  1075. ego_pub_str, DIR_SEPARATOR,
  1076. place_pub_str);
  1077. ret = GNUNET_DISK_directory_create_for_file (filename);
  1078. if (GNUNET_OK != ret
  1079. || 0 > GNUNET_DISK_fn_write (filename, "", 0,
  1080. GNUNET_DISK_PERM_USER_READ
  1081. | GNUNET_DISK_PERM_USER_WRITE))
  1082. {
  1083. GNUNET_break (0);
  1084. ret = GNUNET_SYSERR;
  1085. }
  1086. GNUNET_free (filename);
  1087. }
  1088. GNUNET_free (ego_pub_str);
  1089. GNUNET_free (place_pub_str);
  1090. return ret;
  1091. }
  1092. int
  1093. app_place_remove (const char *app_id,
  1094. const struct GNUNET_CRYPTO_EcdsaPublicKey *ego_pub_key,
  1095. const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key)
  1096. {
  1097. struct GNUNET_HashCode ego_pub_hash;
  1098. struct GNUNET_HashCode place_pub_hash;
  1099. GNUNET_CRYPTO_hash (ego_pub_key, sizeof (*ego_pub_key), &ego_pub_hash);
  1100. GNUNET_CRYPTO_hash (place_pub_key, sizeof (*place_pub_key), &place_pub_hash);
  1101. char *ego_pub_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (ego_pub_key);
  1102. char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (place_pub_key);
  1103. char *app_place_filename = NULL;
  1104. GNUNET_asprintf (&app_place_filename,
  1105. "%s%c" "%s%c" "%s%c" "%s%c" "%s",
  1106. dir_social, DIR_SEPARATOR,
  1107. "apps", DIR_SEPARATOR,
  1108. app_id, DIR_SEPARATOR,
  1109. ego_pub_str, DIR_SEPARATOR,
  1110. place_pub_str);
  1111. GNUNET_free (ego_pub_str);
  1112. GNUNET_free (place_pub_str);
  1113. struct GNUNET_HashCode app_id_hash;
  1114. GNUNET_CRYPTO_hash (app_id, strlen (app_id) + 1, &app_id_hash);
  1115. struct GNUNET_CONTAINER_MultiHashMap *
  1116. app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
  1117. if (NULL != app_places)
  1118. GNUNET_CONTAINER_multihashmap_remove (app_places, &place_pub_hash, NULL);
  1119. int ret = GNUNET_OK;
  1120. if (0 != unlink (app_place_filename))
  1121. {
  1122. GNUNET_break (0);
  1123. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1124. "Error removing app place file: %s: %s (%d)\n",
  1125. app_place_filename, strerror (errno), errno);
  1126. ret = GNUNET_SYSERR;
  1127. }
  1128. GNUNET_free (app_place_filename);
  1129. return ret;
  1130. }
  1131. /**
  1132. * Enter place as host.
  1133. *
  1134. * @param hreq
  1135. * Host entry request.
  1136. * @param[out] ret_hst
  1137. * Returned Host struct.
  1138. *
  1139. * @return #GNUNET_YES if the host entered the place just now,
  1140. * #GNUNET_NO if the place is already entered,
  1141. * #GNUNET_SYSERR if place_pub_key was set
  1142. * but its private key was not found
  1143. */
  1144. static int
  1145. host_enter (const struct HostEnterRequest *hreq, struct Host **ret_hst)
  1146. {
  1147. int ret = GNUNET_NO;
  1148. struct GNUNET_HashCode place_pub_hash;
  1149. GNUNET_CRYPTO_hash (&hreq->place_pub_key, sizeof (hreq->place_pub_key),
  1150. &place_pub_hash);
  1151. struct Host *hst = GNUNET_CONTAINER_multihashmap_get (hosts, &place_pub_hash);
  1152. if (NULL == hst)
  1153. {
  1154. hst = GNUNET_new (struct Host);
  1155. hst->policy = hreq->policy;
  1156. hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1157. hst->relay_msgs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1158. struct Place *plc = &hst->place;
  1159. place_init (plc);
  1160. plc->is_host = GNUNET_YES;
  1161. plc->pub_key = hreq->place_pub_key;
  1162. plc->pub_key_hash = place_pub_hash;
  1163. GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc,
  1164. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1165. hst->master = GNUNET_PSYC_master_start (cfg, &hreq->place_key, hst->policy,
  1166. &psyc_master_started,
  1167. &psyc_recv_join_request,
  1168. &psyc_recv_message, NULL, hst);
  1169. plc->channel = GNUNET_PSYC_master_get_channel (hst->master);
  1170. ret = GNUNET_YES;
  1171. }
  1172. if (NULL != ret_hst)
  1173. *ret_hst = hst;
  1174. return ret;
  1175. }
  1176. static int
  1177. msg_proc_parse (const struct MsgProcRequest *mpreq,
  1178. uint32_t *flags,
  1179. const char **method_prefix,
  1180. struct GNUNET_HashCode *method_hash)
  1181. {
  1182. ssize_t method_size = ntohs (mpreq->header.size) - sizeof (*mpreq);
  1183. uint16_t offset;
  1184. if (method_size < 0)
  1185. {
  1186. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1187. "MsgProcRequest has invalid size\n");
  1188. return GNUNET_SYSERR;
  1189. }
  1190. offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &mpreq[1],
  1191. method_size,
  1192. 1,
  1193. method_prefix);
  1194. if (0 == offset || offset != method_size || *method_prefix == NULL)
  1195. {
  1196. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1197. "MsgProcRequest contains invalid method\n");
  1198. return GNUNET_SYSERR;
  1199. }
  1200. GNUNET_CRYPTO_hash (*method_prefix, (size_t) method_size, method_hash);
  1201. *flags = ntohl (mpreq->flags);
  1202. return GNUNET_OK;
  1203. }
  1204. void
  1205. app_notify_place (const struct GNUNET_MessageHeader *msg,
  1206. struct GNUNET_SERVICE_Client *client)
  1207. {
  1208. struct AppPlaceMessage *amsg;
  1209. struct GNUNET_MQ_Envelope *env;
  1210. uint16_t msg_size = ntohs (msg->size);
  1211. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1212. "%p Sending place notification of type %u to client.\n",
  1213. client, ntohs (msg->type));
  1214. switch (ntohs (msg->type))
  1215. {
  1216. case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER:
  1217. {
  1218. struct HostEnterRequest *hreq = (struct HostEnterRequest *) msg;
  1219. if (msg_size < sizeof (struct HostEnterRequest))
  1220. return;
  1221. env = GNUNET_MQ_msg (amsg,
  1222. GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE);
  1223. // FIXME: also notify about not entered places
  1224. amsg->place_state = GNUNET_SOCIAL_PLACE_STATE_ENTERED;
  1225. amsg->is_host = GNUNET_YES;
  1226. amsg->ego_pub_key = hreq->ego_pub_key;
  1227. amsg->place_pub_key = hreq->place_pub_key;
  1228. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1229. env);
  1230. break;
  1231. }
  1232. case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
  1233. {
  1234. if (msg_size < sizeof (struct GuestEnterRequest))
  1235. return;
  1236. struct GuestEnterRequest *greq = (struct GuestEnterRequest *) msg;
  1237. env = GNUNET_MQ_msg (amsg,
  1238. GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE);
  1239. // FIXME: also notify about not entered places
  1240. amsg->place_state = GNUNET_SOCIAL_PLACE_STATE_ENTERED;
  1241. amsg->is_host = GNUNET_NO;
  1242. amsg->ego_pub_key = greq->ego_pub_key;
  1243. amsg->place_pub_key = greq->place_pub_key;
  1244. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1245. env);
  1246. break;
  1247. }
  1248. default:
  1249. return;
  1250. }
  1251. }
  1252. void
  1253. app_notify_place_end (struct GNUNET_SERVICE_Client *client)
  1254. {
  1255. struct GNUNET_MQ_Envelope *env;
  1256. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1257. "%p Sending end of place list notification to client\n",
  1258. client);
  1259. env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE_END);
  1260. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1261. env);
  1262. }
  1263. void
  1264. app_notify_ego (struct Ego *ego, struct GNUNET_SERVICE_Client *client)
  1265. {
  1266. struct AppEgoMessage *emsg;
  1267. struct GNUNET_MQ_Envelope *env;
  1268. size_t name_size = strlen (ego->name) + 1;
  1269. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1270. "%p Sending ego notification to client: %s\n",
  1271. client, ego->name);
  1272. env = GNUNET_MQ_msg_extra (emsg,
  1273. name_size,
  1274. GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO);
  1275. GNUNET_CRYPTO_ecdsa_key_get_public (&ego->key, &emsg->ego_pub_key);
  1276. GNUNET_memcpy (&emsg[1], ego->name, name_size);
  1277. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1278. env);
  1279. }
  1280. void
  1281. app_notify_ego_end (struct GNUNET_SERVICE_Client *client)
  1282. {
  1283. struct GNUNET_MQ_Envelope *env;
  1284. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1285. "%p Sending end of ego list notification to client\n",
  1286. client);
  1287. env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO_END);
  1288. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1289. env);
  1290. }
  1291. int
  1292. app_place_entry_notify (void *cls, const struct GNUNET_HashCode *key, void *value)
  1293. {
  1294. struct GNUNET_MessageHeader *
  1295. msg = GNUNET_CONTAINER_multihashmap_get (places, key);
  1296. if (NULL != msg)
  1297. app_notify_place (msg, cls);
  1298. return GNUNET_YES;
  1299. }
  1300. int
  1301. ego_entry (void *cls, const struct GNUNET_HashCode *key, void *value)
  1302. {
  1303. app_notify_ego (value, cls);
  1304. return GNUNET_YES;
  1305. }
  1306. static int
  1307. check_client_msg_proc_set (void *cls,
  1308. const struct MsgProcRequest *mpreq)
  1309. {
  1310. return GNUNET_OK;
  1311. }
  1312. /**
  1313. * Handle a client setting message proccesing flags for a method prefix.
  1314. */
  1315. static void
  1316. handle_client_msg_proc_set (void *cls,
  1317. const struct MsgProcRequest *mpreq)
  1318. {
  1319. struct Client *c = cls;
  1320. struct GNUNET_SERVICE_Client *client = c->client;
  1321. struct Place *plc = c->place;
  1322. if (NULL == plc)
  1323. {
  1324. GNUNET_break (0);
  1325. GNUNET_SERVICE_client_drop (client);
  1326. return;
  1327. }
  1328. const char *method_prefix = NULL;
  1329. uint32_t flags = 0;
  1330. struct GNUNET_HashCode method_hash;
  1331. if (GNUNET_OK !=
  1332. msg_proc_parse (mpreq, &flags, &method_prefix, &method_hash))
  1333. {
  1334. GNUNET_break (0);
  1335. GNUNET_SERVICE_client_drop (client);
  1336. return;
  1337. }
  1338. #if 0
  1339. GNUNET_PSYC_slicer_method_remove (plc->slicer, method_prefix,
  1340. place_recv_relay_method,
  1341. place_recv_relay_modifier,
  1342. place_recv_relay_data,
  1343. place_recv_relay_eom);
  1344. GNUNET_PSYC_slicer_method_remove (plc->slicer, method_prefix,
  1345. place_recv_save_method,
  1346. NULL,
  1347. place_recv_save_data,
  1348. place_recv_save_eom);
  1349. #endif
  1350. if (flags & GNUNET_SOCIAL_MSG_PROC_RELAY)
  1351. {
  1352. GNUNET_PSYC_slicer_method_add (plc->slicer, method_prefix, NULL,
  1353. place_recv_relay_method,
  1354. place_recv_relay_modifier,
  1355. place_recv_relay_data,
  1356. place_recv_relay_eom,
  1357. plc);
  1358. }
  1359. if (flags & GNUNET_SOCIAL_MSG_PROC_SAVE)
  1360. {
  1361. GNUNET_PSYC_slicer_method_add (plc->slicer, method_prefix, NULL,
  1362. place_recv_save_method,
  1363. NULL,
  1364. place_recv_save_data,
  1365. place_recv_save_eom,
  1366. plc);
  1367. }
  1368. /** @todo Save flags to be able to resume relaying/saving after restart */
  1369. GNUNET_SERVICE_client_continue (client);
  1370. }
  1371. /**
  1372. * Handle a connecting client requesting to clear all relay rules.
  1373. */
  1374. static void
  1375. handle_client_msg_proc_clear (void *cls,
  1376. const struct GNUNET_MessageHeader *msg)
  1377. {
  1378. struct Client *c = cls;
  1379. struct GNUNET_SERVICE_Client *client = c->client;
  1380. struct Place *plc = c->place;
  1381. if (NULL == plc)
  1382. {
  1383. GNUNET_break (0);
  1384. GNUNET_SERVICE_client_drop (client);
  1385. return;
  1386. }
  1387. GNUNET_PSYC_slicer_clear (plc->slicer);
  1388. GNUNET_SERVICE_client_continue (client);
  1389. }
  1390. static int
  1391. check_client_host_enter (void *cls,
  1392. const struct HostEnterRequest *hr)
  1393. {
  1394. return GNUNET_OK;
  1395. }
  1396. /**
  1397. * Handle a connecting client entering a place as host.
  1398. */
  1399. static void
  1400. handle_client_host_enter (void *cls,
  1401. const struct HostEnterRequest *hr)
  1402. {
  1403. struct Client *c = cls;
  1404. struct GNUNET_SERVICE_Client *client = c->client;
  1405. struct HostEnterRequest *
  1406. hreq = (struct HostEnterRequest *) GNUNET_copy_message (&hr->header);
  1407. uint8_t app_id_size = ntohs (hreq->header.size) - sizeof (*hreq);
  1408. const char *app_id = NULL;
  1409. uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &hreq[1],
  1410. app_id_size, 1, &app_id);
  1411. if (0 == offset || offset != app_id_size || app_id == NULL)
  1412. {
  1413. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1414. "offset = %u, app_id_size = %u, app_id = %s\n",
  1415. offset, app_id_size, app_id);
  1416. GNUNET_break (0);
  1417. GNUNET_SERVICE_client_drop (client);
  1418. return;
  1419. }
  1420. struct Host *hst = NULL;
  1421. struct Place *plc = NULL;
  1422. int ret = GNUNET_OK;
  1423. struct GNUNET_CRYPTO_EddsaPublicKey empty_pub_key;
  1424. memset (&empty_pub_key, 0, sizeof (empty_pub_key));
  1425. if (0 == memcmp (&hreq->place_pub_key, &empty_pub_key, sizeof (empty_pub_key)))
  1426. { // no public key set: create new private key & save the place
  1427. struct GNUNET_CRYPTO_EddsaPrivateKey *
  1428. place_key = GNUNET_CRYPTO_eddsa_key_create ();
  1429. hreq->place_key = *place_key;
  1430. GNUNET_CRYPTO_eddsa_key_get_public (place_key, &hreq->place_pub_key);
  1431. GNUNET_CRYPTO_eddsa_key_clear (place_key);
  1432. GNUNET_free (place_key);
  1433. app_place_save (app_id, (const struct PlaceEnterRequest *) hreq);
  1434. }
  1435. switch (host_enter (hreq, &hst))
  1436. {
  1437. case GNUNET_YES:
  1438. plc = c->place = &hst->place;
  1439. plc->host = hst;
  1440. break;
  1441. case GNUNET_NO:
  1442. {
  1443. plc = c->place = &hst->place;
  1444. plc->host = hst;
  1445. client_send_host_enter_ack (client, hst, GNUNET_OK);
  1446. break;
  1447. }
  1448. case GNUNET_SYSERR:
  1449. ret = GNUNET_SYSERR;
  1450. }
  1451. if (ret != GNUNET_SYSERR)
  1452. {
  1453. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1454. "%p Client connected as host to place %s.\n",
  1455. hst, GNUNET_h2s (&plc->pub_key_hash));
  1456. struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
  1457. cli->client = client;
  1458. GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
  1459. c->place = plc;
  1460. app_notify_place (&hreq->header, client);
  1461. }
  1462. GNUNET_CRYPTO_eddsa_key_clear (&hreq->place_key);
  1463. GNUNET_free (hreq);
  1464. if (GNUNET_OK == ret)
  1465. GNUNET_SERVICE_client_continue (client);
  1466. else
  1467. GNUNET_SERVICE_client_drop (client);
  1468. }
  1469. /**
  1470. * Enter place as guest.
  1471. *
  1472. * @param greq
  1473. * Guest entry request.
  1474. * @param[out] ret_gst
  1475. * Returned Guest struct.
  1476. *
  1477. * @return #GNUNET_YES if the guest entered the place just now,
  1478. * #GNUNET_NO if the place is already entered,
  1479. * #GNUNET_SYSERR on error.
  1480. */
  1481. static int
  1482. guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
  1483. {
  1484. int ret = GNUNET_NO;
  1485. uint16_t greq_size = ntohs (greq->header.size);
  1486. struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key = greq->ego_pub_key;
  1487. struct GNUNET_HashCode ego_pub_hash;
  1488. GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash);
  1489. struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
  1490. if (NULL == ego)
  1491. {
  1492. return GNUNET_SYSERR;
  1493. }
  1494. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1495. "entering as guest\n");
  1496. struct GNUNET_HashCode place_pub_hash;
  1497. GNUNET_CRYPTO_hash (&greq->place_pub_key, sizeof (greq->place_pub_key),
  1498. &place_pub_hash);
  1499. struct GNUNET_CONTAINER_MultiHashMap *
  1500. plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &place_pub_hash);
  1501. struct Guest *gst = NULL;
  1502. int new_guest;
  1503. if (NULL != plc_gst)
  1504. gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &ego_pub_hash);
  1505. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1506. "plc_gst = %p, gst = %p\n",
  1507. plc_gst,
  1508. gst);
  1509. if (NULL == gst)
  1510. {
  1511. gst = GNUNET_new (struct Guest);
  1512. new_guest = GNUNET_YES;
  1513. }
  1514. else new_guest = GNUNET_NO;
  1515. if (NULL == gst->slave)
  1516. {
  1517. gst->origin = greq->origin;
  1518. gst->relay_count = ntohl (greq->relay_count);
  1519. uint16_t len;
  1520. uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
  1521. const char *app_id = (const char *) &greq[1];
  1522. const char *p = app_id;
  1523. len = strnlen (app_id, remaining);
  1524. if (len == remaining)
  1525. {
  1526. GNUNET_free (gst);
  1527. GNUNET_break (0);
  1528. return GNUNET_SYSERR;
  1529. }
  1530. p += len + 1;
  1531. remaining -= len + 1;
  1532. const struct GNUNET_PeerIdentity *relays = NULL;
  1533. uint16_t relay_size = gst->relay_count * sizeof (*relays);
  1534. if (remaining < relay_size)
  1535. {
  1536. GNUNET_free (gst);
  1537. GNUNET_break (0);
  1538. return GNUNET_SYSERR;
  1539. }
  1540. if (0 < relay_size)
  1541. relays = (const struct GNUNET_PeerIdentity *) p;
  1542. p += relay_size;
  1543. remaining -= relay_size;
  1544. struct GNUNET_PSYC_Message *join_msg = NULL;
  1545. uint16_t join_msg_size = 0;
  1546. if (sizeof (struct GNUNET_MessageHeader) <= remaining)
  1547. {
  1548. join_msg = (struct GNUNET_PSYC_Message *) p;
  1549. join_msg_size = ntohs (join_msg->header.size);
  1550. p += join_msg_size;
  1551. remaining -= join_msg_size;
  1552. }
  1553. if (0 != remaining)
  1554. {
  1555. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1556. "%zu + %u + %u != %u\n",
  1557. sizeof (*greq), relay_size, join_msg_size, greq_size);
  1558. GNUNET_free (gst);
  1559. GNUNET_break (0);
  1560. return GNUNET_SYSERR;
  1561. }
  1562. if (0 < relay_size)
  1563. {
  1564. gst->relays = GNUNET_malloc (relay_size);
  1565. GNUNET_memcpy (gst->relays, relays, relay_size);
  1566. }
  1567. gst->join_flags = ntohl (greq->flags);
  1568. struct Place *plc = &gst->place;
  1569. place_init (plc);
  1570. plc->is_host = GNUNET_NO;
  1571. plc->pub_key = greq->place_pub_key;
  1572. plc->pub_key_hash = place_pub_hash;
  1573. plc->ego_pub_key = ego_pub_key;
  1574. plc->ego_pub_hash = ego_pub_hash;
  1575. plc->ego_key = ego->key;
  1576. if (NULL == plc_gst)
  1577. {
  1578. plc_gst = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1579. (void) GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst,
  1580. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1581. }
  1582. if (GNUNET_YES == new_guest)
  1583. {
  1584. (void) GNUNET_CONTAINER_multihashmap_put (plc_gst, &plc->ego_pub_hash, gst,
  1585. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1586. (void) GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, gst,
  1587. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1588. }
  1589. gst->slave
  1590. = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &plc->ego_key,
  1591. gst->join_flags, &gst->origin,
  1592. gst->relay_count, gst->relays,
  1593. &psyc_recv_message, NULL,
  1594. &psyc_slave_connected,
  1595. &psyc_recv_join_dcsn,
  1596. gst, join_msg);
  1597. plc->channel = GNUNET_PSYC_slave_get_channel (gst->slave);
  1598. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1599. "slave entered channel %p\n",
  1600. plc->channel);
  1601. ret = GNUNET_YES;
  1602. }
  1603. // TODO: explain to automatic code scanners why free(gst) not necessary
  1604. if (NULL != ret_gst)
  1605. *ret_gst = gst;
  1606. return ret;
  1607. }
  1608. static int
  1609. client_guest_enter (struct Client *c,
  1610. const struct GuestEnterRequest *greq)
  1611. {
  1612. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1613. "client_guest_enter\n");
  1614. struct GNUNET_PSYC_CountersResultMessage *result_msg;
  1615. struct GNUNET_MQ_Envelope *env;
  1616. struct GNUNET_SERVICE_Client *client = c->client;
  1617. uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
  1618. const char *app_id = NULL;
  1619. uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &greq[1],
  1620. remaining, 1, &app_id);
  1621. struct Guest *gst = NULL;
  1622. struct Place *plc = NULL;
  1623. if (0 == offset)
  1624. {
  1625. return GNUNET_SYSERR;
  1626. }
  1627. switch (guest_enter (greq, &gst))
  1628. {
  1629. case GNUNET_YES:
  1630. {
  1631. plc = c->place = &gst->place;
  1632. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1633. "guest entered successfully to local place %s\n",
  1634. GNUNET_h2s (&plc->pub_key_hash));
  1635. plc->guest = gst;
  1636. app_place_save (app_id, (const struct PlaceEnterRequest *) greq);
  1637. app_notify_place (&greq->header, client);
  1638. break;
  1639. }
  1640. case GNUNET_NO:
  1641. {
  1642. plc = c->place = &gst->place;
  1643. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1644. "guest re-entered successfully to local place %s\n",
  1645. GNUNET_h2s (&plc->pub_key_hash));
  1646. plc->guest = gst;
  1647. env = GNUNET_MQ_msg (result_msg,
  1648. GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
  1649. result_msg->result_code = htonl (GNUNET_OK);
  1650. result_msg->max_message_id = GNUNET_htonll (plc->max_message_id);
  1651. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1652. env);
  1653. if (NULL != gst->join_dcsn)
  1654. {
  1655. env = GNUNET_MQ_msg_copy (&gst->join_dcsn->header);
  1656. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1657. env);
  1658. }
  1659. break;
  1660. }
  1661. case GNUNET_SYSERR:
  1662. {
  1663. return GNUNET_SYSERR;
  1664. }
  1665. }
  1666. struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
  1667. cli->client = client;
  1668. GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
  1669. return GNUNET_OK;
  1670. }
  1671. static int
  1672. check_client_guest_enter (void *cls,
  1673. const struct GuestEnterRequest *greq)
  1674. {
  1675. return GNUNET_OK;
  1676. }
  1677. /**
  1678. * Handle a connecting client entering a place as guest.
  1679. */
  1680. static void
  1681. handle_client_guest_enter (void *cls,
  1682. const struct GuestEnterRequest *greq)
  1683. {
  1684. struct Client *c = cls;
  1685. if (GNUNET_SYSERR == client_guest_enter (c, greq))
  1686. {
  1687. GNUNET_break (0);
  1688. GNUNET_SERVICE_client_drop (c->client);
  1689. return;
  1690. }
  1691. GNUNET_SERVICE_client_continue (c->client);
  1692. }
  1693. struct GuestEnterByNameClosure
  1694. {
  1695. struct Client *client;
  1696. char *app_id;
  1697. char *password;
  1698. struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
  1699. struct GNUNET_MessageHeader *join_msg;
  1700. };
  1701. /**
  1702. * Result of a GNS name lookup for entering a place.
  1703. *
  1704. * @see GNUNET_SOCIAL_guest_enter_by_name
  1705. */
  1706. static void
  1707. gns_result_guest_enter (void *cls, uint32_t rd_count,
  1708. const struct GNUNET_GNSRECORD_Data *rd)
  1709. {
  1710. struct GuestEnterByNameClosure *gcls = cls;
  1711. struct Client *c = gcls->client;
  1712. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1713. "%p GNS result: %u records.\n",
  1714. c, rd_count);
  1715. const struct GNUNET_GNSRECORD_PlaceData *
  1716. rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data;
  1717. if (0 == rd_count || rd->data_size < sizeof (*rec))
  1718. {
  1719. GNUNET_break (0);
  1720. GNUNET_SERVICE_client_drop (c->client);
  1721. return;
  1722. }
  1723. uint16_t relay_count = ntohl (rec->relay_count);
  1724. struct GNUNET_PeerIdentity *relays = NULL;
  1725. if (0 < relay_count)
  1726. {
  1727. if (rd->data_size == sizeof (*rec) + relay_count * sizeof (struct GNUNET_PeerIdentity))
  1728. {
  1729. relays = (struct GNUNET_PeerIdentity *) &rec[1];
  1730. }
  1731. else
  1732. {
  1733. relay_count = 0;
  1734. GNUNET_break_op (0);
  1735. }
  1736. }
  1737. uint16_t app_id_size = strlen (gcls->app_id) + 1;
  1738. uint16_t relay_size = relay_count * sizeof (*relays);
  1739. uint16_t join_msg_size = 0;
  1740. if (NULL != gcls->join_msg)
  1741. join_msg_size = ntohs (gcls->join_msg->size);
  1742. uint16_t greq_size = sizeof (struct GuestEnterRequest)
  1743. + app_id_size + relay_size + join_msg_size;
  1744. struct GuestEnterRequest *greq = GNUNET_malloc (greq_size);
  1745. greq->header.size = htons (greq_size);
  1746. greq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER);
  1747. greq->ego_pub_key = gcls->ego_pub_key;
  1748. greq->place_pub_key = rec->place_pub_key;
  1749. greq->origin = rec->origin;
  1750. greq->relay_count = rec->relay_count;
  1751. void *p = &greq[1];
  1752. GNUNET_memcpy (p, gcls->app_id, app_id_size);
  1753. p += app_id_size;
  1754. GNUNET_memcpy (p, relays, relay_size);
  1755. p += relay_size;
  1756. GNUNET_memcpy (p, gcls->join_msg, join_msg_size);
  1757. client_guest_enter (c, greq);
  1758. GNUNET_free (gcls->app_id);
  1759. if (NULL != gcls->password)
  1760. GNUNET_free (gcls->password);
  1761. if (NULL != gcls->join_msg)
  1762. GNUNET_free (gcls->join_msg);
  1763. GNUNET_free (gcls);
  1764. GNUNET_free (greq);
  1765. }
  1766. static int
  1767. check_client_guest_enter_by_name (void *cls,
  1768. const struct GuestEnterByNameRequest *greq)
  1769. {
  1770. return GNUNET_OK;
  1771. }
  1772. /**
  1773. * Handle a connecting client entering a place as guest using a GNS address.
  1774. *
  1775. * Look up GNS address and generate a GuestEnterRequest from that.
  1776. */
  1777. static void
  1778. handle_client_guest_enter_by_name (void *cls,
  1779. const struct GuestEnterByNameRequest *greq)
  1780. {
  1781. struct Client *c = cls;
  1782. struct GNUNET_SERVICE_Client *client = c->client;
  1783. struct GuestEnterByNameClosure *gcls = GNUNET_malloc (sizeof (*gcls));
  1784. gcls->client = c;
  1785. gcls->ego_pub_key = greq->ego_pub_key;
  1786. const char *p = (const char *) &greq[1];
  1787. const char *app_id = NULL, *password = NULL, *gns_name = NULL;
  1788. uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
  1789. uint16_t offset = GNUNET_STRINGS_buffer_tokenize (p, remaining, 3,
  1790. &app_id,
  1791. &gns_name,
  1792. &password);
  1793. p += offset;
  1794. remaining -= offset;
  1795. if (0 != offset && sizeof (*gcls->join_msg) <= remaining)
  1796. {
  1797. gcls->join_msg = GNUNET_copy_message ((struct GNUNET_MessageHeader *) p);
  1798. remaining -= ntohs (gcls->join_msg->size);
  1799. }
  1800. if (0 == offset || 0 != remaining)
  1801. {
  1802. if (NULL != gcls->join_msg)
  1803. GNUNET_free (gcls->join_msg);
  1804. GNUNET_free (gcls);
  1805. GNUNET_break (0);
  1806. GNUNET_SERVICE_client_drop (client);
  1807. return;
  1808. }
  1809. uint16_t app_id_size = strlen (app_id) + 1;
  1810. gcls->app_id = GNUNET_malloc (app_id_size);
  1811. GNUNET_memcpy (gcls->app_id, app_id, app_id_size);
  1812. uint16_t password_size = strlen (password);
  1813. if (0 < password_size++)
  1814. {
  1815. gcls->password = GNUNET_malloc (password_size);
  1816. GNUNET_memcpy (gcls->password, password, password_size);
  1817. }
  1818. GNUNET_GNS_lookup (gns, gns_name,
  1819. &greq->ego_pub_key,
  1820. GNUNET_GNSRECORD_TYPE_PLACE,
  1821. GNUNET_GNS_LO_DEFAULT,
  1822. &gns_result_guest_enter, gcls);
  1823. GNUNET_SERVICE_client_continue (client);
  1824. }
  1825. static int
  1826. check_client_app_connect (void *cls,
  1827. const struct AppConnectRequest *creq)
  1828. {
  1829. return GNUNET_OK;
  1830. }
  1831. /**
  1832. * Handle application connection.
  1833. */
  1834. static void
  1835. handle_client_app_connect (void *cls,
  1836. const struct AppConnectRequest *creq)
  1837. {
  1838. struct Client *c = cls;
  1839. struct GNUNET_SERVICE_Client *client = c->client;
  1840. ssize_t app_id_size = ntohs (creq->header.size) - sizeof (*creq);
  1841. const char *app_id = NULL;
  1842. uint16_t offset;
  1843. if (app_id_size < 0)
  1844. {
  1845. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1846. "AppConnectRequest has invalid size\n");
  1847. GNUNET_break (0);
  1848. GNUNET_SERVICE_client_drop (client);
  1849. return;
  1850. }
  1851. offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &creq[1],
  1852. (size_t) app_id_size,
  1853. 1,
  1854. &app_id);
  1855. if (0 == offset || offset != app_id_size)
  1856. {
  1857. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1858. "AppConnectRequest contains invalid app ID\n");
  1859. GNUNET_break (0);
  1860. GNUNET_SERVICE_client_drop (client);
  1861. return;
  1862. }
  1863. struct GNUNET_HashCode app_id_hash;
  1864. GNUNET_CRYPTO_hash (app_id, (size_t) app_id_size, &app_id_hash);
  1865. GNUNET_CONTAINER_multihashmap_iterate (egos, ego_entry, client);
  1866. app_notify_ego_end (client);
  1867. struct GNUNET_CONTAINER_MultiHashMap *
  1868. app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
  1869. if (NULL != app_places)
  1870. GNUNET_CONTAINER_multihashmap_iterate (app_places, app_place_entry_notify, client);
  1871. app_notify_place_end (client);
  1872. struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
  1873. cli->client = client;
  1874. struct Application *app = GNUNET_CONTAINER_multihashmap_get (apps,
  1875. &app_id_hash);
  1876. if (NULL == app) {
  1877. app = GNUNET_malloc (sizeof (*app));
  1878. (void) GNUNET_CONTAINER_multihashmap_put (apps, &app_id_hash, app,
  1879. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1880. }
  1881. GNUNET_CONTAINER_DLL_insert (app->clients_head, app->clients_tail, cli);
  1882. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1883. "%p Application %s connected.\n", app, app_id);
  1884. c->app_id = GNUNET_malloc ((size_t) app_id_size);
  1885. GNUNET_memcpy (c->app_id, app_id, (size_t) app_id_size);
  1886. GNUNET_SERVICE_client_continue (client);
  1887. }
  1888. /**
  1889. * Handle application detach request.
  1890. */
  1891. static void
  1892. handle_client_app_detach (void *cls,
  1893. const struct AppDetachRequest *req)
  1894. {
  1895. struct Client *c = cls;
  1896. struct GNUNET_SERVICE_Client *client = c->client;
  1897. int ret = app_place_remove (c->app_id, &req->ego_pub_key, &req->place_pub_key);
  1898. client_send_result (client, req->op_id, ret, NULL, 0);
  1899. GNUNET_SERVICE_client_continue (client);
  1900. }
  1901. static void
  1902. place_leave_cb (void *cls)
  1903. {
  1904. struct Place *plc = cls;
  1905. place_send_leave_ack (plc);
  1906. (GNUNET_YES == plc->is_host)
  1907. ? cleanup_host ((struct Host *) plc)
  1908. : cleanup_guest ((struct Guest *) plc);
  1909. }
  1910. /**
  1911. * Handle application leave request.
  1912. */
  1913. static void
  1914. handle_client_place_leave (void *cls,
  1915. const struct GNUNET_MessageHeader *msg)
  1916. {
  1917. struct Client *c = cls;
  1918. struct GNUNET_SERVICE_Client *client = c->client;
  1919. struct Place *plc = c->place;
  1920. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1921. "got leave request from %s for place %s",
  1922. plc->is_host? "host" : "slave",
  1923. GNUNET_h2s (&plc->pub_key_hash));
  1924. if (NULL == plc)
  1925. {
  1926. GNUNET_break (0);
  1927. GNUNET_SERVICE_client_drop (client);
  1928. return;
  1929. }
  1930. if (GNUNET_YES != plc->is_disconnecting)
  1931. {
  1932. plc->is_disconnecting = GNUNET_YES;
  1933. if (plc->is_host)
  1934. {
  1935. struct Host *host = plc->host;
  1936. GNUNET_assert (NULL != host);
  1937. GNUNET_PSYC_master_stop (host->master, GNUNET_NO, &place_leave_cb, plc);
  1938. }
  1939. else
  1940. {
  1941. struct Guest *guest = plc->guest;
  1942. GNUNET_assert (NULL != guest);
  1943. GNUNET_PSYC_slave_part (guest->slave, GNUNET_NO, &place_leave_cb, plc);
  1944. }
  1945. }
  1946. else
  1947. {
  1948. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1949. "got leave request but place is already leaving\n");
  1950. }
  1951. GNUNET_SERVICE_client_continue (client);
  1952. }
  1953. struct JoinDecisionClosure
  1954. {
  1955. int32_t is_admitted;
  1956. struct GNUNET_PSYC_Message *msg;
  1957. };
  1958. /**
  1959. * Iterator callback for responding to join requests.
  1960. */
  1961. static int
  1962. psyc_send_join_decision (void *cls, const struct GNUNET_HashCode *pub_key_hash,
  1963. void *value)
  1964. {
  1965. struct JoinDecisionClosure *jcls = cls;
  1966. struct GNUNET_PSYC_JoinHandle *jh = value;
  1967. // FIXME: add relays
  1968. GNUNET_PSYC_join_decision (jh, jcls->is_admitted, 0, NULL, jcls->msg);
  1969. return GNUNET_YES;
  1970. }
  1971. static int
  1972. check_client_join_decision (void *cls,
  1973. const struct GNUNET_PSYC_JoinDecisionMessage *dcsn)
  1974. {
  1975. return GNUNET_OK;
  1976. }
  1977. /**
  1978. * Handle an entry decision from a host client.
  1979. */
  1980. static void
  1981. handle_client_join_decision (void *cls,
  1982. const struct GNUNET_PSYC_JoinDecisionMessage *dcsn)
  1983. {
  1984. struct Client *c = cls;
  1985. struct GNUNET_SERVICE_Client *client = c->client;
  1986. struct Place *plc = c->place;
  1987. if (NULL == plc || GNUNET_YES != plc->is_host)
  1988. {
  1989. GNUNET_break (0);
  1990. GNUNET_SERVICE_client_drop (client);
  1991. return;
  1992. }
  1993. struct Host *hst = plc->host;
  1994. struct JoinDecisionClosure jcls;
  1995. jcls.is_admitted = ntohl (dcsn->is_admitted);
  1996. jcls.msg
  1997. = (sizeof (*dcsn) + sizeof (*jcls.msg) <= ntohs (dcsn->header.size))
  1998. ? (struct GNUNET_PSYC_Message *) &dcsn[1]
  1999. : NULL;
  2000. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2001. "jcls.msg = %p\n",
  2002. jcls.msg);
  2003. struct GNUNET_HashCode slave_pub_hash;
  2004. GNUNET_CRYPTO_hash (&dcsn->slave_pub_key, sizeof (dcsn->slave_pub_key),
  2005. &slave_pub_hash);
  2006. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2007. "%p Got join decision (%d) from client for place %s..\n",
  2008. hst, jcls.is_admitted, GNUNET_h2s (&plc->pub_key_hash));
  2009. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2010. "%p ..and slave %s.\n",
  2011. hst, GNUNET_h2s (&slave_pub_hash));
  2012. GNUNET_CONTAINER_multihashmap_get_multiple (hst->join_reqs, &slave_pub_hash,
  2013. &psyc_send_join_decision, &jcls);
  2014. GNUNET_CONTAINER_multihashmap_remove_all (hst->join_reqs, &slave_pub_hash);
  2015. GNUNET_SERVICE_client_continue (client);
  2016. }
  2017. /**
  2018. * Send acknowledgement to a client.
  2019. *
  2020. * Sent after a message fragment has been passed on to multicast.
  2021. *
  2022. * @param plc The place struct for the client.
  2023. */
  2024. static void
  2025. send_message_ack (struct Place *plc, struct GNUNET_SERVICE_Client *client)
  2026. {
  2027. struct GNUNET_MQ_Envelope *env;
  2028. env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK);
  2029. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  2030. env);
  2031. }
  2032. /**
  2033. * Proceed to the next message part in the transmission queue.
  2034. *
  2035. * @param plc
  2036. * Place where the transmission is going on.
  2037. * @param tmit_msg
  2038. * Currently transmitted message.
  2039. * @param tmit_frag
  2040. * Currently transmitted message fragment.
  2041. *
  2042. * @return @a tmit_frag, or NULL if reached the end of fragment.
  2043. */
  2044. static struct FragmentTransmitQueue *
  2045. psyc_transmit_queue_next_part (struct Place *plc,
  2046. struct MessageTransmitQueue *tmit_msg,
  2047. struct FragmentTransmitQueue *tmit_frag)
  2048. {
  2049. uint16_t psize = ntohs (tmit_frag->next_part->size);
  2050. if ((char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1])
  2051. < tmit_frag->size)
  2052. {
  2053. tmit_frag->next_part
  2054. = (struct GNUNET_MessageHeader *) ((char *) tmit_frag->next_part + psize);
  2055. }
  2056. else /* Reached end of current fragment. */
  2057. {
  2058. if (NULL != tmit_frag->client)
  2059. send_message_ack (plc, tmit_frag->client);
  2060. GNUNET_CONTAINER_DLL_remove (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag);
  2061. GNUNET_free (tmit_frag);
  2062. tmit_frag = NULL;
  2063. }
  2064. return tmit_frag;
  2065. }
  2066. /**
  2067. * Proceed to next message in transmission queue.
  2068. *
  2069. * @param plc
  2070. * Place where the transmission is going on.
  2071. * @param tmit_msg
  2072. * Currently transmitted message.
  2073. *
  2074. * @return The next message in queue, or NULL if queue is empty.
  2075. */
  2076. static struct MessageTransmitQueue *
  2077. psyc_transmit_queue_next_msg (struct Place *plc,
  2078. struct MessageTransmitQueue *tmit_msg)
  2079. {
  2080. GNUNET_CONTAINER_DLL_remove (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg);
  2081. GNUNET_free (tmit_msg);
  2082. return plc->tmit_msgs_head;
  2083. }
  2084. /**
  2085. * Callback for data transmission to PSYC.
  2086. */
  2087. static int
  2088. psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  2089. {
  2090. struct Place *plc = cls;
  2091. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  2092. GNUNET_assert (NULL != tmit_msg);
  2093. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  2094. if (NULL == tmit_frag)
  2095. { /* Rest of the message have not arrived yet, pause transmission */
  2096. *data_size = 0;
  2097. return GNUNET_NO;
  2098. }
  2099. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  2100. if (NULL == pmsg)
  2101. {
  2102. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2103. "%p psyc_transmit_notify_data: nothing to send.\n", plc);
  2104. *data_size = 0;
  2105. return GNUNET_NO;
  2106. }
  2107. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2108. "%p psyc_transmit_notify_data()\n", plc);
  2109. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
  2110. uint16_t ptype = ntohs (pmsg->type);
  2111. uint16_t pdata_size = ntohs (pmsg->size) - sizeof (*pmsg);
  2112. int ret;
  2113. switch (ptype)
  2114. {
  2115. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
  2116. if (*data_size < pdata_size)
  2117. {
  2118. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2119. "%p psyc_transmit_notify_data: buffer size too small for data.\n", plc);
  2120. *data_size = 0;
  2121. return GNUNET_NO;
  2122. }
  2123. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2124. "%p psyc_transmit_notify_data: sending %u bytes.\n",
  2125. plc, pdata_size);
  2126. *data_size = pdata_size;
  2127. GNUNET_memcpy (data, &pmsg[1], *data_size);
  2128. ret = GNUNET_NO;
  2129. break;
  2130. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  2131. *data_size = 0;
  2132. ret = GNUNET_YES;
  2133. break;
  2134. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  2135. *data_size = 0;
  2136. ret = GNUNET_SYSERR;
  2137. break;
  2138. default:
  2139. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2140. "%p psyc_transmit_notify_data: unexpected message part of type %u.\n",
  2141. plc, ptype);
  2142. ret = GNUNET_SYSERR;
  2143. }
  2144. if (GNUNET_SYSERR == ret && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL != ptype)
  2145. {
  2146. *data_size = 0;
  2147. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  2148. GNUNET_SERVICE_client_drop (tmit_frag->client);
  2149. GNUNET_SCHEDULER_add_now (&cleanup_place, plc);
  2150. return ret;
  2151. }
  2152. else
  2153. {
  2154. tmit_frag = psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  2155. if (NULL != tmit_frag)
  2156. {
  2157. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  2158. ptype = ntohs (pmsg->type);
  2159. switch (ptype)
  2160. {
  2161. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  2162. ret = GNUNET_YES;
  2163. break;
  2164. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  2165. ret = GNUNET_SYSERR;
  2166. break;
  2167. }
  2168. switch (ptype)
  2169. {
  2170. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  2171. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  2172. tmit_frag = psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  2173. }
  2174. }
  2175. if (NULL == tmit_msg->frags_head
  2176. && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
  2177. { /* Reached end of current message. */
  2178. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  2179. }
  2180. }
  2181. if (ret != GNUNET_NO)
  2182. {
  2183. if (NULL != tmit_msg)
  2184. {
  2185. psyc_transmit_message (plc);
  2186. }
  2187. /* FIXME: handle partial message (when still in_transmit) */
  2188. }
  2189. return ret;
  2190. }
  2191. /**
  2192. * Callback for modifier transmission to PSYC.
  2193. */
  2194. static int
  2195. psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  2196. uint8_t *oper, uint32_t *full_value_size)
  2197. {
  2198. struct Place *plc = cls;
  2199. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  2200. GNUNET_assert (NULL != tmit_msg);
  2201. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  2202. if (NULL == tmit_frag)
  2203. { /* Rest of the message have not arrived yet, pause transmission */
  2204. *data_size = 0;
  2205. return GNUNET_NO;
  2206. }
  2207. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  2208. if (NULL == pmsg)
  2209. {
  2210. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2211. "%p psyc_transmit_notify_mod: nothing to send.\n", plc);
  2212. *data_size = 0;
  2213. return GNUNET_NO;
  2214. }
  2215. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2216. "%p psyc_transmit_notify_mod()\n", plc);
  2217. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
  2218. uint16_t ptype = ntohs (pmsg->type);
  2219. int ret;
  2220. switch (ptype)
  2221. {
  2222. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
  2223. {
  2224. if (NULL == oper)
  2225. {
  2226. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2227. "%p psyc_transmit_notify_mod: oper is NULL.\n", plc);
  2228. ret = GNUNET_SYSERR;
  2229. break;
  2230. }
  2231. struct GNUNET_PSYC_MessageModifier *
  2232. pmod = (struct GNUNET_PSYC_MessageModifier *) tmit_frag->next_part;
  2233. uint16_t mod_size = ntohs (pmod->header.size) - sizeof (*pmod);
  2234. if (*data_size < mod_size)
  2235. {
  2236. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2237. "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc);
  2238. *data_size = 0;
  2239. return GNUNET_NO;
  2240. }
  2241. *full_value_size = ntohl (pmod->value_size);
  2242. *oper = pmod->oper;
  2243. *data_size = mod_size;
  2244. GNUNET_memcpy (data, &pmod[1], mod_size);
  2245. ret = GNUNET_NO;
  2246. break;
  2247. }
  2248. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
  2249. {
  2250. if (NULL != oper)
  2251. {
  2252. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2253. "%p psyc_transmit_notify_mod: oper is not NULL.\n", plc);
  2254. ret = GNUNET_SYSERR;
  2255. break;
  2256. }
  2257. uint16_t mod_size = ntohs (pmsg->size) - sizeof (*pmsg);
  2258. if (*data_size < mod_size)
  2259. {
  2260. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2261. "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc);
  2262. *data_size = 0;
  2263. return GNUNET_NO;
  2264. }
  2265. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2266. "%p psyc_transmit_notify_mod: sending %u bytes.\n", plc, mod_size);
  2267. *data_size = mod_size;
  2268. GNUNET_memcpy (data, &pmsg[1], *data_size);
  2269. ret = GNUNET_NO;
  2270. break;
  2271. }
  2272. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
  2273. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  2274. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  2275. *data_size = 0;
  2276. ret = GNUNET_YES;
  2277. break;
  2278. default:
  2279. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2280. "%p psyc_transmit_notify_mod: unexpected message part of type %u.\n",
  2281. plc, ptype);
  2282. ret = GNUNET_SYSERR;
  2283. }
  2284. if (GNUNET_SYSERR == ret)
  2285. {
  2286. *data_size = 0;
  2287. ret = GNUNET_SYSERR;
  2288. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  2289. GNUNET_SERVICE_client_drop (tmit_frag->client);
  2290. GNUNET_SCHEDULER_add_now (&cleanup_place, plc);
  2291. }
  2292. else
  2293. {
  2294. if (GNUNET_YES != ret)
  2295. psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  2296. if (NULL == tmit_msg->frags_head
  2297. && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
  2298. { /* Reached end of current message. */
  2299. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  2300. }
  2301. }
  2302. return ret;
  2303. }
  2304. /**
  2305. * Callback for data transmission from a host to PSYC.
  2306. */
  2307. static int
  2308. host_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  2309. {
  2310. int ret = psyc_transmit_notify_data (cls, data_size, data);
  2311. if (GNUNET_NO != ret)
  2312. {
  2313. struct Host *hst = cls;
  2314. hst->tmit_handle = NULL;
  2315. }
  2316. return ret;
  2317. }
  2318. /**
  2319. * Callback for the transmit functions of multicast.
  2320. */
  2321. static int
  2322. guest_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  2323. {
  2324. int ret = psyc_transmit_notify_data (cls, data_size, data);
  2325. if (GNUNET_NO != ret)
  2326. {
  2327. struct Guest *gst = cls;
  2328. gst->tmit_handle = NULL;
  2329. }
  2330. return ret;
  2331. }
  2332. /**
  2333. * Callback for modifier transmission from a host to PSYC.
  2334. */
  2335. static int
  2336. host_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  2337. uint8_t *oper, uint32_t *full_value_size)
  2338. {
  2339. int ret = psyc_transmit_notify_mod (cls, data_size, data,
  2340. oper, full_value_size);
  2341. if (GNUNET_SYSERR == ret)
  2342. {
  2343. struct Host *hst = cls;
  2344. hst->tmit_handle = NULL;
  2345. }
  2346. return ret;
  2347. }
  2348. /**
  2349. * Callback for modifier transmission from a guest to PSYC.
  2350. */
  2351. static int
  2352. guest_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  2353. uint8_t *oper, uint32_t *full_value_size)
  2354. {
  2355. int ret = psyc_transmit_notify_mod (cls, data_size, data,
  2356. oper, full_value_size);
  2357. if (GNUNET_SYSERR == ret)
  2358. {
  2359. struct Guest *gst = cls;
  2360. gst->tmit_handle = NULL;
  2361. }
  2362. return ret;
  2363. }
  2364. /**
  2365. * Get method part of next message from transmission queue.
  2366. *
  2367. * @param plc
  2368. * Place
  2369. *
  2370. * @return #GNUNET_OK on success
  2371. * #GNUNET_NO if there are no more messages in queue.
  2372. * #GNUNET_SYSERR if the next message is malformed.
  2373. */
  2374. static struct GNUNET_PSYC_MessageMethod *
  2375. psyc_transmit_queue_next_method (struct Place *plc)
  2376. {
  2377. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  2378. if (NULL == tmit_msg)
  2379. return GNUNET_NO;
  2380. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  2381. if (NULL == tmit_frag)
  2382. {
  2383. GNUNET_break (0);
  2384. return GNUNET_NO;
  2385. }
  2386. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  2387. if (NULL == pmsg
  2388. || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD != ntohs (pmsg->type))
  2389. {
  2390. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2391. "%p psyc_transmit_queue_next_method: unexpected message part of type %u.\n",
  2392. plc, NULL != pmsg ? ntohs (pmsg->type) : 0);
  2393. GNUNET_break (0);
  2394. return NULL;
  2395. }
  2396. uint16_t psize = ntohs (pmsg->size);
  2397. struct GNUNET_PSYC_MessageMethod *
  2398. pmeth = (struct GNUNET_PSYC_MessageMethod *) GNUNET_copy_message (pmsg);
  2399. if (psize < sizeof (*pmeth) + 1 || '\0' != *((char *) pmeth + psize - 1))
  2400. {
  2401. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2402. "%p psyc_transmit_queue_next_method: invalid method name.\n",
  2403. plc);
  2404. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2405. "%zu <= %u || NUL != %u\n",
  2406. sizeof (*pmeth), psize, *((char *) pmeth + psize - 1));
  2407. GNUNET_break (0);
  2408. GNUNET_free (pmeth);
  2409. return NULL;
  2410. }
  2411. psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  2412. return pmeth;
  2413. }
  2414. /**
  2415. * Transmit the next message in queue from the host to the PSYC channel.
  2416. */
  2417. static int
  2418. psyc_master_transmit_message (struct Host *hst)
  2419. {
  2420. struct Place *plc = &hst->place;
  2421. if (NULL == hst->tmit_handle)
  2422. {
  2423. struct GNUNET_PSYC_MessageMethod *
  2424. pmeth = psyc_transmit_queue_next_method (plc);
  2425. if (NULL == pmeth)
  2426. return GNUNET_SYSERR;
  2427. hst->tmit_handle = (void *) &hst->tmit_handle;
  2428. struct GNUNET_PSYC_MasterTransmitHandle *
  2429. tmit_handle = GNUNET_PSYC_master_transmit (hst->master, (const char *) &pmeth[1],
  2430. &host_transmit_notify_mod,
  2431. &host_transmit_notify_data, hst,
  2432. pmeth->flags);
  2433. if (NULL != hst->tmit_handle)
  2434. hst->tmit_handle = tmit_handle;
  2435. GNUNET_free (pmeth);
  2436. }
  2437. else
  2438. {
  2439. GNUNET_PSYC_master_transmit_resume (hst->tmit_handle);
  2440. }
  2441. return GNUNET_OK;
  2442. }
  2443. /**
  2444. * Transmit the next message in queue from a guest to the PSYC channel.
  2445. */
  2446. static int
  2447. psyc_slave_transmit_message (struct Guest *gst)
  2448. {
  2449. struct Place *plc = &gst->place;
  2450. if (NULL == gst->tmit_handle)
  2451. {
  2452. struct GNUNET_PSYC_MessageMethod *
  2453. pmeth = psyc_transmit_queue_next_method (plc);
  2454. if (NULL == pmeth)
  2455. return GNUNET_SYSERR;
  2456. gst->tmit_handle = (void *) &gst->tmit_handle;
  2457. struct GNUNET_PSYC_SlaveTransmitHandle *
  2458. tmit_handle = GNUNET_PSYC_slave_transmit (gst->slave, (const char *) &pmeth[1],
  2459. &guest_transmit_notify_mod,
  2460. &guest_transmit_notify_data, gst,
  2461. pmeth->flags);
  2462. if (NULL != gst->tmit_handle)
  2463. gst->tmit_handle = tmit_handle;
  2464. GNUNET_free (pmeth);
  2465. }
  2466. else
  2467. {
  2468. GNUNET_PSYC_slave_transmit_resume (gst->tmit_handle);
  2469. }
  2470. return GNUNET_OK;
  2471. }
  2472. /**
  2473. * Transmit a message to PSYC.
  2474. */
  2475. static int
  2476. psyc_transmit_message (struct Place *plc)
  2477. {
  2478. return
  2479. (plc->is_host)
  2480. ? psyc_master_transmit_message ((struct Host *) plc)
  2481. : psyc_slave_transmit_message ((struct Guest *) plc);
  2482. }
  2483. /**
  2484. * Queue message parts for sending to PSYC.
  2485. *
  2486. * @param plc Place to send to.
  2487. * @param client Client the message originates from.
  2488. * @param data_size Size of @a data.
  2489. * @param data Concatenated message parts.
  2490. * @param first_ptype First message part type in @a data.
  2491. * @param last_ptype Last message part type in @a data.
  2492. */
  2493. static struct MessageTransmitQueue *
  2494. psyc_transmit_queue_message (struct Place *plc,
  2495. struct GNUNET_SERVICE_Client *client,
  2496. size_t data_size,
  2497. const void *data,
  2498. uint16_t first_ptype, uint16_t last_ptype,
  2499. struct MessageTransmitQueue *tmit_msg)
  2500. {
  2501. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == first_ptype)
  2502. {
  2503. tmit_msg = GNUNET_malloc (sizeof (*tmit_msg));
  2504. GNUNET_CONTAINER_DLL_insert_tail (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg);
  2505. }
  2506. else if (NULL == tmit_msg)
  2507. {
  2508. return NULL;
  2509. }
  2510. struct FragmentTransmitQueue *
  2511. tmit_frag = GNUNET_malloc (sizeof (*tmit_frag) + data_size);
  2512. GNUNET_memcpy (&tmit_frag[1], data, data_size);
  2513. tmit_frag->next_part = (struct GNUNET_MessageHeader *) &tmit_frag[1];
  2514. tmit_frag->client = client;
  2515. tmit_frag->size = data_size;
  2516. GNUNET_CONTAINER_DLL_insert_tail (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag);
  2517. tmit_msg->client = client;
  2518. return tmit_msg;
  2519. }
  2520. ///**
  2521. // * Cancel transmission of current message to PSYC.
  2522. // *
  2523. // * @param plc Place to send to.
  2524. // * @param client Client the message originates from.
  2525. // */
  2526. //static void
  2527. //psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVICE_Client *client)
  2528. //{
  2529. // uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL;
  2530. //
  2531. // struct GNUNET_MessageHeader msg;
  2532. // msg.size = htons (sizeof (msg));
  2533. // msg.type = htons (type);
  2534. //
  2535. // psyc_transmit_queue_message (plc, client, sizeof (msg), &msg, type, type, NULL);
  2536. // psyc_transmit_message (plc);
  2537. //
  2538. // /* FIXME: cleanup */
  2539. //}
  2540. static int
  2541. check_client_psyc_message (void *cls,
  2542. const struct GNUNET_MessageHeader *msg)
  2543. {
  2544. return GNUNET_OK;
  2545. }
  2546. /**
  2547. * Handle an incoming message from a client, to be transmitted to the place.
  2548. */
  2549. static void
  2550. handle_client_psyc_message (void *cls,
  2551. const struct GNUNET_MessageHeader *msg)
  2552. {
  2553. struct Client *c = cls;
  2554. struct GNUNET_SERVICE_Client *client = c->client;
  2555. struct Place *plc = c->place;
  2556. int ret;
  2557. if (NULL == plc)
  2558. {
  2559. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2560. "received PSYC message for non-existing client %p\n",
  2561. client);
  2562. GNUNET_break (0);
  2563. GNUNET_SERVICE_client_drop (client);
  2564. return;
  2565. }
  2566. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2567. "%p Received message of type %d from client.\n", plc, ntohs (msg->type));
  2568. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg);
  2569. if (GNUNET_YES != plc->is_ready)
  2570. {
  2571. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2572. "%p Place is not ready yet, disconnecting client.\n", plc);
  2573. GNUNET_break (0);
  2574. GNUNET_SERVICE_client_drop (client);
  2575. return;
  2576. }
  2577. uint16_t size = ntohs (msg->size);
  2578. uint16_t psize = size - sizeof (*msg);
  2579. if (psize < sizeof (struct GNUNET_MessageHeader)
  2580. || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < psize)
  2581. {
  2582. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2583. "%p Received message with invalid payload size (%u) from client.\n",
  2584. plc, psize);
  2585. GNUNET_break (0);
  2586. GNUNET_SERVICE_client_drop (client);
  2587. return;
  2588. }
  2589. uint16_t first_ptype = 0;
  2590. uint16_t last_ptype = 0;
  2591. if (GNUNET_SYSERR ==
  2592. GNUNET_PSYC_receive_check_parts (psize, (const char *) &msg[1],
  2593. &first_ptype, &last_ptype))
  2594. {
  2595. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2596. "%p Received invalid message part from client.\n", plc);
  2597. GNUNET_break (0);
  2598. GNUNET_SERVICE_client_drop (client);
  2599. return;
  2600. }
  2601. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2602. "%p Received message with first part type %u and last part type %u.\n",
  2603. plc, first_ptype, last_ptype);
  2604. c->tmit_msg
  2605. = psyc_transmit_queue_message (plc, client, psize, &msg[1],
  2606. first_ptype, last_ptype, c->tmit_msg);
  2607. if (NULL != c->tmit_msg)
  2608. {
  2609. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= last_ptype)
  2610. c->tmit_msg = NULL;
  2611. ret = psyc_transmit_message (plc);
  2612. }
  2613. else
  2614. {
  2615. ret = GNUNET_SYSERR;
  2616. }
  2617. if (GNUNET_OK != ret)
  2618. {
  2619. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2620. "%p Received invalid message part from client.\n", plc);
  2621. GNUNET_break (0);
  2622. GNUNET_SERVICE_client_drop (client);
  2623. return;
  2624. }
  2625. GNUNET_SERVICE_client_continue (client);
  2626. }
  2627. /**
  2628. * A historic message arrived from PSYC.
  2629. */
  2630. static void
  2631. psyc_recv_history_message (void *cls, const struct GNUNET_PSYC_MessageHeader *msg)
  2632. {
  2633. struct OperationClosure *opcls = cls;
  2634. struct Client *c = opcls->client;
  2635. struct Place *plc = c->place;
  2636. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2637. "%p Received historic message #%" PRId64 " (flags: %x)\n",
  2638. plc, GNUNET_ntohll (msg->message_id), ntohl (msg->flags));
  2639. uint16_t size = ntohs (msg->header.size);
  2640. struct GNUNET_OperationResultMessage *
  2641. res = GNUNET_malloc (sizeof (*res) + size);
  2642. res->header.size = htons (sizeof (*res) + size);
  2643. res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_HISTORY_RESULT);
  2644. res->op_id = opcls->op_id;
  2645. res->result_code = GNUNET_htonll (GNUNET_OK);
  2646. GNUNET_memcpy (&res[1], msg, size);
  2647. /** @todo FIXME: send only to requesting client */
  2648. place_send_msg (plc, GNUNET_MQ_msg_copy (&res->header));
  2649. GNUNET_free (res);
  2650. }
  2651. /**
  2652. * Result of message history replay from PSYC.
  2653. */
  2654. static void
  2655. psyc_recv_history_result (void *cls, int64_t result,
  2656. const void *err_msg, uint16_t err_msg_size)
  2657. {
  2658. struct OperationClosure *opcls = cls;
  2659. struct Client *c = opcls->client;
  2660. struct Place *plc = c->place;
  2661. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2662. "%p History replay #%" PRIu64 ": "
  2663. "PSYCstore returned %" PRId64 " (%.*s)\n",
  2664. plc, GNUNET_ntohll (opcls->op_id), result,
  2665. err_msg_size, (const char *) err_msg);
  2666. // FIXME: place might have been destroyed
  2667. client_send_result (c->client, opcls->op_id, result, err_msg, err_msg_size);
  2668. }
  2669. static int
  2670. check_client_history_replay (void *cls,
  2671. const struct GNUNET_PSYC_HistoryRequestMessage *req)
  2672. {
  2673. return GNUNET_OK;
  2674. }
  2675. /**
  2676. * Client requests channel history.
  2677. */
  2678. static void
  2679. handle_client_history_replay (void *cls,
  2680. const struct GNUNET_PSYC_HistoryRequestMessage *req)
  2681. {
  2682. struct Client *c = cls;
  2683. struct GNUNET_SERVICE_Client *client = c->client;
  2684. struct Place *plc = c->place;
  2685. if (NULL == plc)
  2686. {
  2687. GNUNET_break (0);
  2688. GNUNET_SERVICE_client_drop (client);
  2689. return;
  2690. }
  2691. uint16_t size = ntohs (req->header.size);
  2692. const char *method_prefix = (const char *) &req[1];
  2693. if (size < sizeof (*req) + 1
  2694. || '\0' != method_prefix[size - sizeof (*req) - 1])
  2695. {
  2696. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2697. "%p History replay #%" PRIu64 ": "
  2698. "invalid method prefix. size: %u < %zu?\n",
  2699. plc, GNUNET_ntohll (req->op_id), size, sizeof (*req) + 1);
  2700. GNUNET_break (0);
  2701. GNUNET_SERVICE_client_drop (client);
  2702. return;
  2703. }
  2704. struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
  2705. opcls->client = c;
  2706. opcls->op_id = req->op_id;
  2707. opcls->flags = ntohl (req->flags);
  2708. if (0 == req->message_limit)
  2709. GNUNET_PSYC_channel_history_replay (plc->channel,
  2710. GNUNET_ntohll (req->start_message_id),
  2711. GNUNET_ntohll (req->end_message_id),
  2712. method_prefix, opcls->flags,
  2713. psyc_recv_history_message, NULL,
  2714. psyc_recv_history_result, opcls);
  2715. else
  2716. GNUNET_PSYC_channel_history_replay_latest (plc->channel,
  2717. GNUNET_ntohll (req->message_limit),
  2718. method_prefix, opcls->flags,
  2719. psyc_recv_history_message, NULL,
  2720. psyc_recv_history_result, opcls);
  2721. GNUNET_SERVICE_client_continue (client);
  2722. }
  2723. /**
  2724. * A state variable part arrived from PSYC.
  2725. */
  2726. void
  2727. psyc_recv_state_var (void *cls,
  2728. const struct GNUNET_MessageHeader *mod,
  2729. const char *name,
  2730. const void *value,
  2731. uint32_t value_size,
  2732. uint32_t full_value_size)
  2733. {
  2734. struct GNUNET_OperationResultMessage *result_msg;
  2735. struct GNUNET_MQ_Envelope *env;
  2736. struct OperationClosure *opcls = cls;
  2737. struct Client *c = opcls->client;
  2738. struct Place *plc = c->place;
  2739. uint16_t size = ntohs (mod->size);
  2740. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2741. "%p Received state variable %s from PSYC\n",
  2742. plc, name);
  2743. env = GNUNET_MQ_msg_extra (result_msg,
  2744. size,
  2745. GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT);
  2746. result_msg->op_id = opcls->op_id;
  2747. result_msg->result_code = GNUNET_htonll (GNUNET_OK);
  2748. GNUNET_memcpy (&result_msg[1], mod, size);
  2749. /** @todo FIXME: send only to requesting client */
  2750. place_send_msg (plc, env);
  2751. }
  2752. /**
  2753. * Result of retrieving state variable from PSYC.
  2754. */
  2755. static void
  2756. psyc_recv_state_result (void *cls, int64_t result,
  2757. const void *err_msg, uint16_t err_msg_size)
  2758. {
  2759. struct OperationClosure *opcls = cls;
  2760. struct Client *c = opcls->client;
  2761. struct Place *plc = c->place;
  2762. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2763. "%p State get #%" PRIu64 ": "
  2764. "PSYCstore returned %" PRId64 " (%.*s)\n",
  2765. plc, GNUNET_ntohll (opcls->op_id), result,
  2766. err_msg_size, (const char *) err_msg);
  2767. // FIXME: place might have been destroyed
  2768. client_send_result (c->client, opcls->op_id, result, err_msg, err_msg_size);
  2769. }
  2770. static int
  2771. check_client_state_get (void *cls,
  2772. const struct GNUNET_PSYC_StateRequestMessage *req)
  2773. {
  2774. return GNUNET_OK;
  2775. }
  2776. /**
  2777. * Client requests channel history.
  2778. */
  2779. static void
  2780. handle_client_state_get (void *cls,
  2781. const struct GNUNET_PSYC_StateRequestMessage *req)
  2782. {
  2783. struct Client *c = cls;
  2784. struct GNUNET_SERVICE_Client *client = c->client;
  2785. struct Place *plc = c->place;
  2786. if (NULL == plc)
  2787. {
  2788. GNUNET_break (0);
  2789. GNUNET_SERVICE_client_drop (client);
  2790. return;
  2791. }
  2792. uint16_t size = ntohs (req->header.size);
  2793. const char *name = (const char *) &req[1];
  2794. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2795. "%p State get #%" PRIu64 ": %s\n",
  2796. plc, GNUNET_ntohll (req->op_id), name);
  2797. if (size < sizeof (*req) + 1
  2798. || '\0' != name[size - sizeof (*req) - 1])
  2799. {
  2800. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2801. "%p State get #%" PRIu64 ": "
  2802. "invalid name. size: %u < %zu?\n",
  2803. plc, GNUNET_ntohll (req->op_id), size, sizeof (*req) + 1);
  2804. GNUNET_break (0);
  2805. GNUNET_SERVICE_client_drop (client);
  2806. return;
  2807. }
  2808. struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
  2809. opcls->client = c;
  2810. opcls->op_id = req->op_id;
  2811. switch (ntohs (req->header.type))
  2812. {
  2813. case GNUNET_MESSAGE_TYPE_PSYC_STATE_GET:
  2814. GNUNET_PSYC_channel_state_get (plc->channel, name,
  2815. psyc_recv_state_var,
  2816. psyc_recv_state_result, opcls);
  2817. break;
  2818. case GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX:
  2819. GNUNET_PSYC_channel_state_get_prefix (plc->channel, name,
  2820. psyc_recv_state_var,
  2821. psyc_recv_state_result, opcls);
  2822. break;
  2823. default:
  2824. GNUNET_assert (0);
  2825. }
  2826. GNUNET_SERVICE_client_continue (client);
  2827. }
  2828. #define check_client_state_get_prefix check_client_state_get
  2829. #define handle_client_state_get_prefix handle_client_state_get
  2830. static void
  2831. namestore_recv_records_store_result (void *cls, int32_t result,
  2832. const char *err_msg)
  2833. {
  2834. struct OperationClosure *opcls = cls;
  2835. struct Client *c = opcls->client;
  2836. // FIXME: client might have been disconnected
  2837. client_send_result (c->client, opcls->op_id, result, err_msg,
  2838. (NULL != err_msg) ? strlen (err_msg) : 0);
  2839. GNUNET_free (opcls);
  2840. }
  2841. static int
  2842. check_client_zone_add_place (void *cls,
  2843. const struct ZoneAddPlaceRequest *preq)
  2844. {
  2845. return GNUNET_OK;
  2846. }
  2847. /**
  2848. * Handle request to add PLACE record to GNS zone.
  2849. */
  2850. static void
  2851. handle_client_zone_add_place (void *cls,
  2852. const struct ZoneAddPlaceRequest *preq)
  2853. {
  2854. struct Client *c = cls;
  2855. struct GNUNET_SERVICE_Client *client = c->client;
  2856. uint16_t remaining = ntohs (preq->header.size) - sizeof (*preq);
  2857. const char *p = (const char *) &preq[1];
  2858. const char *name = NULL, *password = NULL;
  2859. uint16_t offset = GNUNET_STRINGS_buffer_tokenize (p, remaining, 2,
  2860. &name, &password);
  2861. remaining -= offset;
  2862. p += offset;
  2863. const struct GNUNET_PeerIdentity *
  2864. relays = (const struct GNUNET_PeerIdentity *) p;
  2865. uint16_t relay_size = ntohl (preq->relay_count) * sizeof (*relays);
  2866. if (0 == offset || remaining != relay_size)
  2867. {
  2868. GNUNET_break (0);
  2869. client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0);
  2870. GNUNET_SERVICE_client_drop (client);
  2871. return;
  2872. }
  2873. struct GNUNET_GNSRECORD_Data rd = { };
  2874. rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
  2875. rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  2876. rd.expiration_time = GNUNET_ntohll (preq->expiration_time);
  2877. struct GNUNET_GNSRECORD_PlaceData *
  2878. rec = GNUNET_malloc (sizeof (*rec) + relay_size);
  2879. rec->place_pub_key = preq->place_pub_key;
  2880. rec->origin = this_peer;
  2881. rec->relay_count = preq->relay_count;
  2882. GNUNET_memcpy (&rec[1], relays, relay_size);
  2883. rd.data = rec;
  2884. rd.data_size = sizeof (*rec) + relay_size;
  2885. struct GNUNET_HashCode ego_pub_hash;
  2886. GNUNET_CRYPTO_hash (&preq->ego_pub_key, sizeof (preq->ego_pub_key), &ego_pub_hash);
  2887. struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
  2888. if (NULL == ego)
  2889. {
  2890. client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0);
  2891. }
  2892. else
  2893. {
  2894. struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
  2895. opcls->client = c;
  2896. opcls->op_id = preq->op_id;
  2897. GNUNET_NAMESTORE_records_store (namestore, &ego->key,
  2898. name, 1, &rd,
  2899. namestore_recv_records_store_result, opcls);
  2900. /** @todo refresh stored records later */
  2901. }
  2902. GNUNET_SERVICE_client_continue (client);
  2903. }
  2904. static int
  2905. check_client_zone_add_nym (void *cls,
  2906. const struct ZoneAddNymRequest *nreq)
  2907. {
  2908. return GNUNET_OK;
  2909. }
  2910. /**
  2911. * Handle request to add PLACE record to GNS zone.
  2912. */
  2913. static void
  2914. handle_client_zone_add_nym (void *cls,
  2915. const struct ZoneAddNymRequest *nreq)
  2916. {
  2917. struct Client *c = cls;
  2918. struct GNUNET_SERVICE_Client *client = c->client;
  2919. uint16_t name_size = ntohs (nreq->header.size) - sizeof (*nreq);
  2920. const char *name = NULL;
  2921. uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &nreq[1],
  2922. name_size, 1, &name);
  2923. if (0 == offset || offset != name_size)
  2924. {
  2925. GNUNET_break (0);
  2926. client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0);
  2927. GNUNET_SERVICE_client_continue (client);
  2928. return;
  2929. }
  2930. struct GNUNET_GNSRECORD_Data rd = { };
  2931. rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
  2932. rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  2933. rd.expiration_time = GNUNET_ntohll (nreq->expiration_time);
  2934. rd.data = &nreq->nym_pub_key;
  2935. rd.data_size = sizeof (nreq->nym_pub_key);
  2936. struct GNUNET_HashCode ego_pub_hash;
  2937. GNUNET_CRYPTO_hash (&nreq->ego_pub_key, sizeof (nreq->ego_pub_key), &ego_pub_hash);
  2938. struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
  2939. if (NULL == ego)
  2940. {
  2941. client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0);
  2942. }
  2943. else
  2944. {
  2945. struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
  2946. opcls->client = c;
  2947. opcls->op_id = nreq->op_id;
  2948. GNUNET_NAMESTORE_records_store (namestore, &ego->key,
  2949. name, 1, &rd,
  2950. namestore_recv_records_store_result, opcls);
  2951. /** @todo refresh stored records later */
  2952. }
  2953. GNUNET_SERVICE_client_continue (client);
  2954. }
  2955. const char *
  2956. path_basename (const char *path)
  2957. {
  2958. const char *basename = strrchr (path, DIR_SEPARATOR);
  2959. if (NULL != basename)
  2960. basename++;
  2961. if (NULL == basename || '\0' == *basename)
  2962. return NULL;
  2963. return basename;
  2964. }
  2965. struct PlaceLoadClosure
  2966. {
  2967. const char *app_id;
  2968. const char *ego_pub_str;
  2969. };
  2970. /** Load a place file */
  2971. int
  2972. file_place_load (void *cls, const char *place_filename)
  2973. {
  2974. struct PlaceLoadClosure *plcls = cls;
  2975. const char *place_pub_str = path_basename (place_filename);
  2976. if (NULL == place_pub_str)
  2977. {
  2978. GNUNET_break (0);
  2979. return GNUNET_OK;
  2980. }
  2981. char *filename = NULL;
  2982. GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s",
  2983. dir_social, DIR_SEPARATOR,
  2984. "places", DIR_SEPARATOR,
  2985. plcls->ego_pub_str, DIR_SEPARATOR,
  2986. place_pub_str);
  2987. uint64_t file_size = 0;
  2988. if (GNUNET_OK !=
  2989. GNUNET_DISK_file_size (filename, &file_size, GNUNET_YES, GNUNET_YES)
  2990. || file_size < sizeof (struct PlaceEnterRequest))
  2991. {
  2992. GNUNET_free (filename);
  2993. return GNUNET_OK;
  2994. }
  2995. struct PlaceEnterRequest *ereq = GNUNET_malloc (file_size);
  2996. ssize_t read_size = GNUNET_DISK_fn_read (filename, ereq, file_size);
  2997. GNUNET_free (filename);
  2998. if (read_size < 0 || read_size < sizeof (*ereq))
  2999. {
  3000. GNUNET_free (ereq);
  3001. return GNUNET_OK;
  3002. }
  3003. uint16_t ereq_size = ntohs (ereq->header.size);
  3004. if (read_size != ereq_size)
  3005. {
  3006. GNUNET_free (ereq);
  3007. return GNUNET_OK;
  3008. }
  3009. switch (ntohs (ereq->header.type))
  3010. {
  3011. case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER:
  3012. if (ereq_size < sizeof (struct HostEnterRequest))
  3013. {
  3014. GNUNET_free (ereq);
  3015. return GNUNET_OK;
  3016. }
  3017. struct HostEnterRequest *hreq = (struct HostEnterRequest *) ereq;
  3018. host_enter (hreq, NULL);
  3019. break;
  3020. case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
  3021. if (ereq_size < sizeof (struct GuestEnterRequest))
  3022. {
  3023. GNUNET_free (ereq);
  3024. return GNUNET_OK;
  3025. }
  3026. struct GuestEnterRequest *greq = (struct GuestEnterRequest *) ereq;
  3027. guest_enter (greq, NULL);
  3028. break;
  3029. default:
  3030. GNUNET_free (ereq);
  3031. return GNUNET_OK;
  3032. }
  3033. if (GNUNET_SYSERR == app_place_add (plcls->app_id, ereq))
  3034. {
  3035. GNUNET_assert (0);
  3036. }
  3037. GNUNET_free (ereq);
  3038. return GNUNET_OK;
  3039. }
  3040. /**
  3041. * Read @e place_pub_str entries in @a dir_ego
  3042. *
  3043. * @param dir_ego
  3044. * Data directory of an application ego.
  3045. * $GNUNET_DATA_HOME/social/apps/$app_id/$ego_pub_str/
  3046. */
  3047. int
  3048. scan_app_ego_dir (void *cls, const char *dir_ego)
  3049. {
  3050. struct PlaceLoadClosure *plcls = cls;
  3051. plcls->ego_pub_str = path_basename (dir_ego);
  3052. if (NULL != plcls->ego_pub_str)
  3053. GNUNET_DISK_directory_scan (dir_ego, file_place_load, plcls);
  3054. return GNUNET_OK;
  3055. }
  3056. /**
  3057. * Read @e ego_pub_str entries in @a dir_app
  3058. *
  3059. * @param dir_app
  3060. * Data directory of an application.
  3061. * $GNUNET_DATA_HOME/social/apps/$app_id/
  3062. */
  3063. int
  3064. scan_app_dir (void *cls, const char *dir_app)
  3065. {
  3066. if (GNUNET_YES != GNUNET_DISK_directory_test (dir_app, GNUNET_YES))
  3067. return GNUNET_OK;
  3068. struct PlaceLoadClosure plcls;
  3069. plcls.app_id = path_basename (dir_app);
  3070. if (NULL != plcls.app_id)
  3071. GNUNET_DISK_directory_scan (dir_app, scan_app_ego_dir, &plcls);
  3072. return GNUNET_OK;
  3073. }
  3074. static void
  3075. identity_recv_ego (void *cls, struct GNUNET_IDENTITY_Ego *id_ego,
  3076. void **ctx, const char *name)
  3077. {
  3078. if (NULL == id_ego) // end of initial list of egos
  3079. return;
  3080. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3081. "social service received ego %s\n",
  3082. name);
  3083. struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
  3084. GNUNET_IDENTITY_ego_get_public_key (id_ego, &ego_pub_key);
  3085. struct GNUNET_HashCode ego_pub_hash;
  3086. GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash);
  3087. struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
  3088. if (NULL == ego && NULL == name)
  3089. {
  3090. // an ego that is none of our business has been deleted
  3091. return;
  3092. }
  3093. if (NULL != ego)
  3094. {
  3095. // one of our egos has been changed
  3096. GNUNET_free (ego->name);
  3097. if (NULL == name)
  3098. {
  3099. // one of our egos has been deleted
  3100. GNUNET_CONTAINER_multihashmap_remove (egos, &ego_pub_hash, ego);
  3101. GNUNET_free (ego);
  3102. return;
  3103. }
  3104. }
  3105. else
  3106. {
  3107. ego = GNUNET_malloc (sizeof (*ego));
  3108. }
  3109. ego->key = *(GNUNET_IDENTITY_ego_get_private_key (id_ego));
  3110. size_t name_size = strlen (name) + 1;
  3111. ego->name = GNUNET_malloc (name_size);
  3112. GNUNET_memcpy (ego->name, name, name_size);
  3113. GNUNET_CONTAINER_multihashmap_put (egos, &ego_pub_hash, ego,
  3114. GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
  3115. // FIXME: notify clients about changed ego
  3116. }
  3117. /**
  3118. * Initialize the PSYC service.
  3119. *
  3120. * @param cls Closure.
  3121. * @param server The initialized server.
  3122. * @param c Configuration to use.
  3123. */
  3124. static void
  3125. run (void *cls,
  3126. const struct GNUNET_CONFIGURATION_Handle *c,
  3127. struct GNUNET_SERVICE_Handle *svc)
  3128. {
  3129. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3130. "starting social service\n");
  3131. cfg = c;
  3132. service = svc;
  3133. GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
  3134. hosts = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  3135. guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  3136. place_guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  3137. egos = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  3138. apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  3139. places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
  3140. apps_places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
  3141. //places_apps = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
  3142. id = GNUNET_IDENTITY_connect (cfg, &identity_recv_ego, NULL);
  3143. gns = GNUNET_GNS_connect (cfg);
  3144. namestore = GNUNET_NAMESTORE_connect (cfg);
  3145. stats = GNUNET_STATISTICS_create ("social", cfg);
  3146. if (GNUNET_OK !=
  3147. GNUNET_CONFIGURATION_get_value_filename (cfg, "social", "DATA_HOME",
  3148. &dir_social))
  3149. {
  3150. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  3151. "social", "DATA_HOME");
  3152. GNUNET_break (0);
  3153. return;
  3154. }
  3155. GNUNET_asprintf (&dir_places, "%s%c%s",
  3156. dir_social, DIR_SEPARATOR, "places");
  3157. GNUNET_asprintf (&dir_apps, "%s%c%s",
  3158. dir_social, DIR_SEPARATOR, "apps");
  3159. GNUNET_DISK_directory_scan (dir_apps, scan_app_dir, NULL);
  3160. GNUNET_SCHEDULER_add_shutdown (shutdown_task, NULL);
  3161. }
  3162. /**
  3163. * Define "main" method using service macro.
  3164. */
  3165. GNUNET_SERVICE_MAIN
  3166. ("social",
  3167. GNUNET_SERVICE_OPTION_NONE,
  3168. run,
  3169. client_notify_connect,
  3170. client_notify_disconnect,
  3171. NULL,
  3172. GNUNET_MQ_hd_var_size (client_host_enter,
  3173. GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER,
  3174. struct HostEnterRequest,
  3175. NULL),
  3176. GNUNET_MQ_hd_var_size (client_guest_enter,
  3177. GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER,
  3178. struct GuestEnterRequest,
  3179. NULL),
  3180. GNUNET_MQ_hd_var_size (client_guest_enter_by_name,
  3181. GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_BY_NAME,
  3182. struct GuestEnterByNameRequest,
  3183. NULL),
  3184. GNUNET_MQ_hd_var_size (client_join_decision,
  3185. GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
  3186. struct GNUNET_PSYC_JoinDecisionMessage,
  3187. NULL),
  3188. GNUNET_MQ_hd_var_size (client_psyc_message,
  3189. GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
  3190. struct GNUNET_MessageHeader,
  3191. NULL),
  3192. GNUNET_MQ_hd_var_size (client_history_replay,
  3193. GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY,
  3194. struct GNUNET_PSYC_HistoryRequestMessage,
  3195. NULL),
  3196. GNUNET_MQ_hd_var_size (client_state_get,
  3197. GNUNET_MESSAGE_TYPE_PSYC_STATE_GET,
  3198. struct GNUNET_PSYC_StateRequestMessage,
  3199. NULL),
  3200. GNUNET_MQ_hd_var_size (client_state_get_prefix,
  3201. GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX,
  3202. struct GNUNET_PSYC_StateRequestMessage,
  3203. NULL),
  3204. GNUNET_MQ_hd_var_size (client_zone_add_place,
  3205. GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE,
  3206. struct ZoneAddPlaceRequest,
  3207. NULL),
  3208. GNUNET_MQ_hd_var_size (client_zone_add_nym,
  3209. GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM,
  3210. struct ZoneAddNymRequest,
  3211. NULL),
  3212. GNUNET_MQ_hd_var_size (client_app_connect,
  3213. GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT,
  3214. struct AppConnectRequest,
  3215. NULL),
  3216. GNUNET_MQ_hd_fixed_size (client_app_detach,
  3217. GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH,
  3218. struct AppDetachRequest,
  3219. NULL),
  3220. GNUNET_MQ_hd_fixed_size (client_place_leave,
  3221. GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE,
  3222. struct GNUNET_MessageHeader,
  3223. NULL),
  3224. GNUNET_MQ_hd_var_size (client_msg_proc_set,
  3225. GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_SET,
  3226. struct MsgProcRequest,
  3227. NULL),
  3228. GNUNET_MQ_hd_fixed_size (client_msg_proc_clear,
  3229. GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_CLEAR,
  3230. struct GNUNET_MessageHeader,
  3231. NULL));
  3232. /* end of gnunet-service-social.c */