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.
 
 
 
 

3758 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. GNUNET_CRYPTO_eddsa_key_create (&hreq->place_key);
  1428. GNUNET_CRYPTO_eddsa_key_get_public (&hreq->place_key, &hreq->place_pub_key);
  1429. GNUNET_CRYPTO_eddsa_key_clear (&hreq->place_key);
  1430. app_place_save (app_id, (const struct PlaceEnterRequest *) hreq);
  1431. }
  1432. switch (host_enter (hreq, &hst))
  1433. {
  1434. case GNUNET_YES:
  1435. plc = c->place = &hst->place;
  1436. plc->host = hst;
  1437. break;
  1438. case GNUNET_NO:
  1439. {
  1440. plc = c->place = &hst->place;
  1441. plc->host = hst;
  1442. client_send_host_enter_ack (client, hst, GNUNET_OK);
  1443. break;
  1444. }
  1445. case GNUNET_SYSERR:
  1446. ret = GNUNET_SYSERR;
  1447. }
  1448. if (ret != GNUNET_SYSERR)
  1449. {
  1450. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1451. "%p Client connected as host to place %s.\n",
  1452. hst, GNUNET_h2s (&plc->pub_key_hash));
  1453. struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
  1454. cli->client = client;
  1455. GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
  1456. c->place = plc;
  1457. app_notify_place (&hreq->header, client);
  1458. }
  1459. GNUNET_CRYPTO_eddsa_key_clear (&hreq->place_key);
  1460. GNUNET_free (hreq);
  1461. if (GNUNET_OK == ret)
  1462. GNUNET_SERVICE_client_continue (client);
  1463. else
  1464. GNUNET_SERVICE_client_drop (client);
  1465. }
  1466. /**
  1467. * Enter place as guest.
  1468. *
  1469. * @param greq
  1470. * Guest entry request.
  1471. * @param[out] ret_gst
  1472. * Returned Guest struct.
  1473. *
  1474. * @return #GNUNET_YES if the guest entered the place just now,
  1475. * #GNUNET_NO if the place is already entered,
  1476. * #GNUNET_SYSERR on error.
  1477. */
  1478. static int
  1479. guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
  1480. {
  1481. int ret = GNUNET_NO;
  1482. uint16_t greq_size = ntohs (greq->header.size);
  1483. struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key = greq->ego_pub_key;
  1484. struct GNUNET_HashCode ego_pub_hash;
  1485. GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash);
  1486. struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
  1487. if (NULL == ego)
  1488. {
  1489. return GNUNET_SYSERR;
  1490. }
  1491. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1492. "entering as guest\n");
  1493. struct GNUNET_HashCode place_pub_hash;
  1494. GNUNET_CRYPTO_hash (&greq->place_pub_key, sizeof (greq->place_pub_key),
  1495. &place_pub_hash);
  1496. struct GNUNET_CONTAINER_MultiHashMap *
  1497. plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &place_pub_hash);
  1498. struct Guest *gst = NULL;
  1499. int new_guest;
  1500. if (NULL != plc_gst)
  1501. gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &ego_pub_hash);
  1502. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1503. "plc_gst = %p, gst = %p\n",
  1504. plc_gst,
  1505. gst);
  1506. if (NULL == gst)
  1507. {
  1508. gst = GNUNET_new (struct Guest);
  1509. new_guest = GNUNET_YES;
  1510. }
  1511. else new_guest = GNUNET_NO;
  1512. if (NULL == gst->slave)
  1513. {
  1514. gst->origin = greq->origin;
  1515. gst->relay_count = ntohl (greq->relay_count);
  1516. uint16_t len;
  1517. uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
  1518. const char *app_id = (const char *) &greq[1];
  1519. const char *p = app_id;
  1520. len = strnlen (app_id, remaining);
  1521. if (len == remaining)
  1522. {
  1523. GNUNET_free (gst);
  1524. GNUNET_break (0);
  1525. return GNUNET_SYSERR;
  1526. }
  1527. p += len + 1;
  1528. remaining -= len + 1;
  1529. const struct GNUNET_PeerIdentity *relays = NULL;
  1530. uint16_t relay_size = gst->relay_count * sizeof (*relays);
  1531. if (remaining < relay_size)
  1532. {
  1533. GNUNET_free (gst);
  1534. GNUNET_break (0);
  1535. return GNUNET_SYSERR;
  1536. }
  1537. if (0 < relay_size)
  1538. relays = (const struct GNUNET_PeerIdentity *) p;
  1539. p += relay_size;
  1540. remaining -= relay_size;
  1541. struct GNUNET_PSYC_Message *join_msg = NULL;
  1542. uint16_t join_msg_size = 0;
  1543. if (sizeof (struct GNUNET_MessageHeader) <= remaining)
  1544. {
  1545. join_msg = (struct GNUNET_PSYC_Message *) p;
  1546. join_msg_size = ntohs (join_msg->header.size);
  1547. p += join_msg_size;
  1548. remaining -= join_msg_size;
  1549. }
  1550. if (0 != remaining)
  1551. {
  1552. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1553. "%zu + %u + %u != %u\n",
  1554. sizeof (*greq), relay_size, join_msg_size, greq_size);
  1555. GNUNET_free (gst);
  1556. GNUNET_break (0);
  1557. return GNUNET_SYSERR;
  1558. }
  1559. if (0 < relay_size)
  1560. {
  1561. gst->relays = GNUNET_malloc (relay_size);
  1562. GNUNET_memcpy (gst->relays, relays, relay_size);
  1563. }
  1564. gst->join_flags = ntohl (greq->flags);
  1565. struct Place *plc = &gst->place;
  1566. place_init (plc);
  1567. plc->is_host = GNUNET_NO;
  1568. plc->pub_key = greq->place_pub_key;
  1569. plc->pub_key_hash = place_pub_hash;
  1570. plc->ego_pub_key = ego_pub_key;
  1571. plc->ego_pub_hash = ego_pub_hash;
  1572. plc->ego_key = ego->key;
  1573. if (NULL == plc_gst)
  1574. {
  1575. plc_gst = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1576. (void) GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst,
  1577. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1578. }
  1579. if (GNUNET_YES == new_guest)
  1580. {
  1581. (void) GNUNET_CONTAINER_multihashmap_put (plc_gst, &plc->ego_pub_hash, gst,
  1582. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1583. (void) GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, gst,
  1584. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1585. }
  1586. gst->slave
  1587. = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &plc->ego_key,
  1588. gst->join_flags, &gst->origin,
  1589. gst->relay_count, gst->relays,
  1590. &psyc_recv_message, NULL,
  1591. &psyc_slave_connected,
  1592. &psyc_recv_join_dcsn,
  1593. gst, join_msg);
  1594. plc->channel = GNUNET_PSYC_slave_get_channel (gst->slave);
  1595. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1596. "slave entered channel %p\n",
  1597. plc->channel);
  1598. ret = GNUNET_YES;
  1599. }
  1600. // TODO: explain to automatic code scanners why free(gst) not necessary
  1601. if (NULL != ret_gst)
  1602. *ret_gst = gst;
  1603. return ret;
  1604. }
  1605. static int
  1606. client_guest_enter (struct Client *c,
  1607. const struct GuestEnterRequest *greq)
  1608. {
  1609. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1610. "client_guest_enter\n");
  1611. struct GNUNET_PSYC_CountersResultMessage *result_msg;
  1612. struct GNUNET_MQ_Envelope *env;
  1613. struct GNUNET_SERVICE_Client *client = c->client;
  1614. uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
  1615. const char *app_id = NULL;
  1616. uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &greq[1],
  1617. remaining, 1, &app_id);
  1618. struct Guest *gst = NULL;
  1619. struct Place *plc = NULL;
  1620. if (0 == offset)
  1621. {
  1622. return GNUNET_SYSERR;
  1623. }
  1624. switch (guest_enter (greq, &gst))
  1625. {
  1626. case GNUNET_YES:
  1627. {
  1628. plc = c->place = &gst->place;
  1629. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1630. "guest entered successfully to local place %s\n",
  1631. GNUNET_h2s (&plc->pub_key_hash));
  1632. plc->guest = gst;
  1633. app_place_save (app_id, (const struct PlaceEnterRequest *) greq);
  1634. app_notify_place (&greq->header, client);
  1635. break;
  1636. }
  1637. case GNUNET_NO:
  1638. {
  1639. plc = c->place = &gst->place;
  1640. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1641. "guest re-entered successfully to local place %s\n",
  1642. GNUNET_h2s (&plc->pub_key_hash));
  1643. plc->guest = gst;
  1644. env = GNUNET_MQ_msg (result_msg,
  1645. GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
  1646. result_msg->result_code = htonl (GNUNET_OK);
  1647. result_msg->max_message_id = GNUNET_htonll (plc->max_message_id);
  1648. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1649. env);
  1650. if (NULL != gst->join_dcsn)
  1651. {
  1652. env = GNUNET_MQ_msg_copy (&gst->join_dcsn->header);
  1653. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1654. env);
  1655. }
  1656. break;
  1657. }
  1658. case GNUNET_SYSERR:
  1659. {
  1660. return GNUNET_SYSERR;
  1661. }
  1662. }
  1663. struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
  1664. cli->client = client;
  1665. GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
  1666. return GNUNET_OK;
  1667. }
  1668. static int
  1669. check_client_guest_enter (void *cls,
  1670. const struct GuestEnterRequest *greq)
  1671. {
  1672. return GNUNET_OK;
  1673. }
  1674. /**
  1675. * Handle a connecting client entering a place as guest.
  1676. */
  1677. static void
  1678. handle_client_guest_enter (void *cls,
  1679. const struct GuestEnterRequest *greq)
  1680. {
  1681. struct Client *c = cls;
  1682. if (GNUNET_SYSERR == client_guest_enter (c, greq))
  1683. {
  1684. GNUNET_break (0);
  1685. GNUNET_SERVICE_client_drop (c->client);
  1686. return;
  1687. }
  1688. GNUNET_SERVICE_client_continue (c->client);
  1689. }
  1690. struct GuestEnterByNameClosure
  1691. {
  1692. struct Client *client;
  1693. char *app_id;
  1694. char *password;
  1695. struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
  1696. struct GNUNET_MessageHeader *join_msg;
  1697. };
  1698. /**
  1699. * Result of a GNS name lookup for entering a place.
  1700. *
  1701. * @see GNUNET_SOCIAL_guest_enter_by_name
  1702. */
  1703. static void
  1704. gns_result_guest_enter (void *cls, uint32_t rd_count,
  1705. const struct GNUNET_GNSRECORD_Data *rd)
  1706. {
  1707. struct GuestEnterByNameClosure *gcls = cls;
  1708. struct Client *c = gcls->client;
  1709. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1710. "%p GNS result: %u records.\n",
  1711. c, rd_count);
  1712. const struct GNUNET_GNSRECORD_PlaceData *
  1713. rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data;
  1714. if (0 == rd_count || rd->data_size < sizeof (*rec))
  1715. {
  1716. GNUNET_break (0);
  1717. GNUNET_SERVICE_client_drop (c->client);
  1718. return;
  1719. }
  1720. uint16_t relay_count = ntohl (rec->relay_count);
  1721. struct GNUNET_PeerIdentity *relays = NULL;
  1722. if (0 < relay_count)
  1723. {
  1724. if (rd->data_size == sizeof (*rec) + relay_count * sizeof (struct GNUNET_PeerIdentity))
  1725. {
  1726. relays = (struct GNUNET_PeerIdentity *) &rec[1];
  1727. }
  1728. else
  1729. {
  1730. relay_count = 0;
  1731. GNUNET_break_op (0);
  1732. }
  1733. }
  1734. uint16_t app_id_size = strlen (gcls->app_id) + 1;
  1735. uint16_t relay_size = relay_count * sizeof (*relays);
  1736. uint16_t join_msg_size = 0;
  1737. if (NULL != gcls->join_msg)
  1738. join_msg_size = ntohs (gcls->join_msg->size);
  1739. uint16_t greq_size = sizeof (struct GuestEnterRequest)
  1740. + app_id_size + relay_size + join_msg_size;
  1741. struct GuestEnterRequest *greq = GNUNET_malloc (greq_size);
  1742. greq->header.size = htons (greq_size);
  1743. greq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER);
  1744. greq->ego_pub_key = gcls->ego_pub_key;
  1745. greq->place_pub_key = rec->place_pub_key;
  1746. greq->origin = rec->origin;
  1747. greq->relay_count = rec->relay_count;
  1748. void *p = &greq[1];
  1749. GNUNET_memcpy (p, gcls->app_id, app_id_size);
  1750. p += app_id_size;
  1751. GNUNET_memcpy (p, relays, relay_size);
  1752. p += relay_size;
  1753. GNUNET_memcpy (p, gcls->join_msg, join_msg_size);
  1754. client_guest_enter (c, greq);
  1755. GNUNET_free (gcls->app_id);
  1756. if (NULL != gcls->password)
  1757. GNUNET_free (gcls->password);
  1758. if (NULL != gcls->join_msg)
  1759. GNUNET_free (gcls->join_msg);
  1760. GNUNET_free (gcls);
  1761. GNUNET_free (greq);
  1762. }
  1763. static int
  1764. check_client_guest_enter_by_name (void *cls,
  1765. const struct GuestEnterByNameRequest *greq)
  1766. {
  1767. return GNUNET_OK;
  1768. }
  1769. /**
  1770. * Handle a connecting client entering a place as guest using a GNS address.
  1771. *
  1772. * Look up GNS address and generate a GuestEnterRequest from that.
  1773. */
  1774. static void
  1775. handle_client_guest_enter_by_name (void *cls,
  1776. const struct GuestEnterByNameRequest *greq)
  1777. {
  1778. struct Client *c = cls;
  1779. struct GNUNET_SERVICE_Client *client = c->client;
  1780. struct GuestEnterByNameClosure *gcls = GNUNET_malloc (sizeof (*gcls));
  1781. gcls->client = c;
  1782. gcls->ego_pub_key = greq->ego_pub_key;
  1783. const char *p = (const char *) &greq[1];
  1784. const char *app_id = NULL, *password = NULL, *gns_name = NULL;
  1785. uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
  1786. uint16_t offset = GNUNET_STRINGS_buffer_tokenize (p, remaining, 3,
  1787. &app_id,
  1788. &gns_name,
  1789. &password);
  1790. p += offset;
  1791. remaining -= offset;
  1792. if (0 != offset && sizeof (*gcls->join_msg) <= remaining)
  1793. {
  1794. gcls->join_msg = GNUNET_copy_message ((struct GNUNET_MessageHeader *) p);
  1795. remaining -= ntohs (gcls->join_msg->size);
  1796. }
  1797. if (0 == offset || 0 != remaining)
  1798. {
  1799. if (NULL != gcls->join_msg)
  1800. GNUNET_free (gcls->join_msg);
  1801. GNUNET_free (gcls);
  1802. GNUNET_break (0);
  1803. GNUNET_SERVICE_client_drop (client);
  1804. return;
  1805. }
  1806. uint16_t app_id_size = strlen (app_id) + 1;
  1807. gcls->app_id = GNUNET_malloc (app_id_size);
  1808. GNUNET_memcpy (gcls->app_id, app_id, app_id_size);
  1809. uint16_t password_size = strlen (password);
  1810. if (0 < password_size++)
  1811. {
  1812. gcls->password = GNUNET_malloc (password_size);
  1813. GNUNET_memcpy (gcls->password, password, password_size);
  1814. }
  1815. GNUNET_GNS_lookup (gns, gns_name,
  1816. &greq->ego_pub_key,
  1817. GNUNET_GNSRECORD_TYPE_PLACE,
  1818. GNUNET_GNS_LO_DEFAULT,
  1819. &gns_result_guest_enter, gcls);
  1820. GNUNET_SERVICE_client_continue (client);
  1821. }
  1822. static int
  1823. check_client_app_connect (void *cls,
  1824. const struct AppConnectRequest *creq)
  1825. {
  1826. return GNUNET_OK;
  1827. }
  1828. /**
  1829. * Handle application connection.
  1830. */
  1831. static void
  1832. handle_client_app_connect (void *cls,
  1833. const struct AppConnectRequest *creq)
  1834. {
  1835. struct Client *c = cls;
  1836. struct GNUNET_SERVICE_Client *client = c->client;
  1837. ssize_t app_id_size = ntohs (creq->header.size) - sizeof (*creq);
  1838. const char *app_id = NULL;
  1839. uint16_t offset;
  1840. if (app_id_size < 0)
  1841. {
  1842. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1843. "AppConnectRequest has invalid size\n");
  1844. GNUNET_break (0);
  1845. GNUNET_SERVICE_client_drop (client);
  1846. return;
  1847. }
  1848. offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &creq[1],
  1849. (size_t) app_id_size,
  1850. 1,
  1851. &app_id);
  1852. if (0 == offset || offset != app_id_size)
  1853. {
  1854. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1855. "AppConnectRequest contains invalid app ID\n");
  1856. GNUNET_break (0);
  1857. GNUNET_SERVICE_client_drop (client);
  1858. return;
  1859. }
  1860. struct GNUNET_HashCode app_id_hash;
  1861. GNUNET_CRYPTO_hash (app_id, (size_t) app_id_size, &app_id_hash);
  1862. GNUNET_CONTAINER_multihashmap_iterate (egos, ego_entry, client);
  1863. app_notify_ego_end (client);
  1864. struct GNUNET_CONTAINER_MultiHashMap *
  1865. app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
  1866. if (NULL != app_places)
  1867. GNUNET_CONTAINER_multihashmap_iterate (app_places, app_place_entry_notify, client);
  1868. app_notify_place_end (client);
  1869. struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
  1870. cli->client = client;
  1871. struct Application *app = GNUNET_CONTAINER_multihashmap_get (apps,
  1872. &app_id_hash);
  1873. if (NULL == app) {
  1874. app = GNUNET_malloc (sizeof (*app));
  1875. (void) GNUNET_CONTAINER_multihashmap_put (apps, &app_id_hash, app,
  1876. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1877. }
  1878. GNUNET_CONTAINER_DLL_insert (app->clients_head, app->clients_tail, cli);
  1879. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1880. "%p Application %s connected.\n", app, app_id);
  1881. c->app_id = GNUNET_malloc ((size_t) app_id_size);
  1882. GNUNET_memcpy (c->app_id, app_id, (size_t) app_id_size);
  1883. GNUNET_SERVICE_client_continue (client);
  1884. }
  1885. /**
  1886. * Handle application detach request.
  1887. */
  1888. static void
  1889. handle_client_app_detach (void *cls,
  1890. const struct AppDetachRequest *req)
  1891. {
  1892. struct Client *c = cls;
  1893. struct GNUNET_SERVICE_Client *client = c->client;
  1894. int ret = app_place_remove (c->app_id, &req->ego_pub_key, &req->place_pub_key);
  1895. client_send_result (client, req->op_id, ret, NULL, 0);
  1896. GNUNET_SERVICE_client_continue (client);
  1897. }
  1898. static void
  1899. place_leave_cb (void *cls)
  1900. {
  1901. struct Place *plc = cls;
  1902. place_send_leave_ack (plc);
  1903. (GNUNET_YES == plc->is_host)
  1904. ? cleanup_host ((struct Host *) plc)
  1905. : cleanup_guest ((struct Guest *) plc);
  1906. }
  1907. /**
  1908. * Handle application leave request.
  1909. */
  1910. static void
  1911. handle_client_place_leave (void *cls,
  1912. const struct GNUNET_MessageHeader *msg)
  1913. {
  1914. struct Client *c = cls;
  1915. struct GNUNET_SERVICE_Client *client = c->client;
  1916. struct Place *plc = c->place;
  1917. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1918. "got leave request from %s for place %s",
  1919. plc->is_host? "host" : "slave",
  1920. GNUNET_h2s (&plc->pub_key_hash));
  1921. if (NULL == plc)
  1922. {
  1923. GNUNET_break (0);
  1924. GNUNET_SERVICE_client_drop (client);
  1925. return;
  1926. }
  1927. if (GNUNET_YES != plc->is_disconnecting)
  1928. {
  1929. plc->is_disconnecting = GNUNET_YES;
  1930. if (plc->is_host)
  1931. {
  1932. struct Host *host = plc->host;
  1933. GNUNET_assert (NULL != host);
  1934. GNUNET_PSYC_master_stop (host->master, GNUNET_NO, &place_leave_cb, plc);
  1935. }
  1936. else
  1937. {
  1938. struct Guest *guest = plc->guest;
  1939. GNUNET_assert (NULL != guest);
  1940. GNUNET_PSYC_slave_part (guest->slave, GNUNET_NO, &place_leave_cb, plc);
  1941. }
  1942. }
  1943. else
  1944. {
  1945. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1946. "got leave request but place is already leaving\n");
  1947. }
  1948. GNUNET_SERVICE_client_continue (client);
  1949. }
  1950. struct JoinDecisionClosure
  1951. {
  1952. int32_t is_admitted;
  1953. struct GNUNET_PSYC_Message *msg;
  1954. };
  1955. /**
  1956. * Iterator callback for responding to join requests.
  1957. */
  1958. static int
  1959. psyc_send_join_decision (void *cls, const struct GNUNET_HashCode *pub_key_hash,
  1960. void *value)
  1961. {
  1962. struct JoinDecisionClosure *jcls = cls;
  1963. struct GNUNET_PSYC_JoinHandle *jh = value;
  1964. // FIXME: add relays
  1965. GNUNET_PSYC_join_decision (jh, jcls->is_admitted, 0, NULL, jcls->msg);
  1966. return GNUNET_YES;
  1967. }
  1968. static int
  1969. check_client_join_decision (void *cls,
  1970. const struct GNUNET_PSYC_JoinDecisionMessage *dcsn)
  1971. {
  1972. return GNUNET_OK;
  1973. }
  1974. /**
  1975. * Handle an entry decision from a host client.
  1976. */
  1977. static void
  1978. handle_client_join_decision (void *cls,
  1979. const struct GNUNET_PSYC_JoinDecisionMessage *dcsn)
  1980. {
  1981. struct Client *c = cls;
  1982. struct GNUNET_SERVICE_Client *client = c->client;
  1983. struct Place *plc = c->place;
  1984. if (NULL == plc || GNUNET_YES != plc->is_host)
  1985. {
  1986. GNUNET_break (0);
  1987. GNUNET_SERVICE_client_drop (client);
  1988. return;
  1989. }
  1990. struct Host *hst = plc->host;
  1991. struct JoinDecisionClosure jcls;
  1992. jcls.is_admitted = ntohl (dcsn->is_admitted);
  1993. jcls.msg
  1994. = (sizeof (*dcsn) + sizeof (*jcls.msg) <= ntohs (dcsn->header.size))
  1995. ? (struct GNUNET_PSYC_Message *) &dcsn[1]
  1996. : NULL;
  1997. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1998. "jcls.msg = %p\n",
  1999. jcls.msg);
  2000. struct GNUNET_HashCode slave_pub_hash;
  2001. GNUNET_CRYPTO_hash (&dcsn->slave_pub_key, sizeof (dcsn->slave_pub_key),
  2002. &slave_pub_hash);
  2003. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2004. "%p Got join decision (%d) from client for place %s..\n",
  2005. hst, jcls.is_admitted, GNUNET_h2s (&plc->pub_key_hash));
  2006. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2007. "%p ..and slave %s.\n",
  2008. hst, GNUNET_h2s (&slave_pub_hash));
  2009. GNUNET_CONTAINER_multihashmap_get_multiple (hst->join_reqs, &slave_pub_hash,
  2010. &psyc_send_join_decision, &jcls);
  2011. GNUNET_CONTAINER_multihashmap_remove_all (hst->join_reqs, &slave_pub_hash);
  2012. GNUNET_SERVICE_client_continue (client);
  2013. }
  2014. /**
  2015. * Send acknowledgement to a client.
  2016. *
  2017. * Sent after a message fragment has been passed on to multicast.
  2018. *
  2019. * @param plc The place struct for the client.
  2020. */
  2021. static void
  2022. send_message_ack (struct Place *plc, struct GNUNET_SERVICE_Client *client)
  2023. {
  2024. struct GNUNET_MQ_Envelope *env;
  2025. env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK);
  2026. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  2027. env);
  2028. }
  2029. /**
  2030. * Proceed to the next message part in the transmission queue.
  2031. *
  2032. * @param plc
  2033. * Place where the transmission is going on.
  2034. * @param tmit_msg
  2035. * Currently transmitted message.
  2036. * @param tmit_frag
  2037. * Currently transmitted message fragment.
  2038. *
  2039. * @return @a tmit_frag, or NULL if reached the end of fragment.
  2040. */
  2041. static struct FragmentTransmitQueue *
  2042. psyc_transmit_queue_next_part (struct Place *plc,
  2043. struct MessageTransmitQueue *tmit_msg,
  2044. struct FragmentTransmitQueue *tmit_frag)
  2045. {
  2046. uint16_t psize = ntohs (tmit_frag->next_part->size);
  2047. if ((char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1])
  2048. < tmit_frag->size)
  2049. {
  2050. tmit_frag->next_part
  2051. = (struct GNUNET_MessageHeader *) ((char *) tmit_frag->next_part + psize);
  2052. }
  2053. else /* Reached end of current fragment. */
  2054. {
  2055. if (NULL != tmit_frag->client)
  2056. send_message_ack (plc, tmit_frag->client);
  2057. GNUNET_CONTAINER_DLL_remove (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag);
  2058. GNUNET_free (tmit_frag);
  2059. tmit_frag = NULL;
  2060. }
  2061. return tmit_frag;
  2062. }
  2063. /**
  2064. * Proceed to next message in transmission queue.
  2065. *
  2066. * @param plc
  2067. * Place where the transmission is going on.
  2068. * @param tmit_msg
  2069. * Currently transmitted message.
  2070. *
  2071. * @return The next message in queue, or NULL if queue is empty.
  2072. */
  2073. static struct MessageTransmitQueue *
  2074. psyc_transmit_queue_next_msg (struct Place *plc,
  2075. struct MessageTransmitQueue *tmit_msg)
  2076. {
  2077. GNUNET_CONTAINER_DLL_remove (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg);
  2078. GNUNET_free (tmit_msg);
  2079. return plc->tmit_msgs_head;
  2080. }
  2081. /**
  2082. * Callback for data transmission to PSYC.
  2083. */
  2084. static int
  2085. psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  2086. {
  2087. struct Place *plc = cls;
  2088. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  2089. GNUNET_assert (NULL != tmit_msg);
  2090. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  2091. if (NULL == tmit_frag)
  2092. { /* Rest of the message have not arrived yet, pause transmission */
  2093. *data_size = 0;
  2094. return GNUNET_NO;
  2095. }
  2096. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  2097. if (NULL == pmsg)
  2098. {
  2099. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2100. "%p psyc_transmit_notify_data: nothing to send.\n", plc);
  2101. *data_size = 0;
  2102. return GNUNET_NO;
  2103. }
  2104. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2105. "%p psyc_transmit_notify_data()\n", plc);
  2106. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
  2107. uint16_t ptype = ntohs (pmsg->type);
  2108. uint16_t pdata_size = ntohs (pmsg->size) - sizeof (*pmsg);
  2109. int ret;
  2110. switch (ptype)
  2111. {
  2112. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
  2113. if (*data_size < pdata_size)
  2114. {
  2115. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2116. "%p psyc_transmit_notify_data: buffer size too small for data.\n", plc);
  2117. *data_size = 0;
  2118. return GNUNET_NO;
  2119. }
  2120. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2121. "%p psyc_transmit_notify_data: sending %u bytes.\n",
  2122. plc, pdata_size);
  2123. *data_size = pdata_size;
  2124. GNUNET_memcpy (data, &pmsg[1], *data_size);
  2125. ret = GNUNET_NO;
  2126. break;
  2127. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  2128. *data_size = 0;
  2129. ret = GNUNET_YES;
  2130. break;
  2131. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  2132. *data_size = 0;
  2133. ret = GNUNET_SYSERR;
  2134. break;
  2135. default:
  2136. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2137. "%p psyc_transmit_notify_data: unexpected message part of type %u.\n",
  2138. plc, ptype);
  2139. ret = GNUNET_SYSERR;
  2140. }
  2141. if (GNUNET_SYSERR == ret && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL != ptype)
  2142. {
  2143. *data_size = 0;
  2144. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  2145. GNUNET_SERVICE_client_drop (tmit_frag->client);
  2146. GNUNET_SCHEDULER_add_now (&cleanup_place, plc);
  2147. return ret;
  2148. }
  2149. else
  2150. {
  2151. tmit_frag = psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  2152. if (NULL != tmit_frag)
  2153. {
  2154. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  2155. ptype = ntohs (pmsg->type);
  2156. switch (ptype)
  2157. {
  2158. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  2159. ret = GNUNET_YES;
  2160. break;
  2161. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  2162. ret = GNUNET_SYSERR;
  2163. break;
  2164. }
  2165. switch (ptype)
  2166. {
  2167. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  2168. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  2169. tmit_frag = psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  2170. }
  2171. }
  2172. if (NULL == tmit_msg->frags_head
  2173. && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
  2174. { /* Reached end of current message. */
  2175. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  2176. }
  2177. }
  2178. if (ret != GNUNET_NO)
  2179. {
  2180. if (NULL != tmit_msg)
  2181. {
  2182. psyc_transmit_message (plc);
  2183. }
  2184. /* FIXME: handle partial message (when still in_transmit) */
  2185. }
  2186. return ret;
  2187. }
  2188. /**
  2189. * Callback for modifier transmission to PSYC.
  2190. */
  2191. static int
  2192. psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  2193. uint8_t *oper, uint32_t *full_value_size)
  2194. {
  2195. struct Place *plc = cls;
  2196. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  2197. GNUNET_assert (NULL != tmit_msg);
  2198. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  2199. if (NULL == tmit_frag)
  2200. { /* Rest of the message have not arrived yet, pause transmission */
  2201. *data_size = 0;
  2202. return GNUNET_NO;
  2203. }
  2204. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  2205. if (NULL == pmsg)
  2206. {
  2207. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2208. "%p psyc_transmit_notify_mod: nothing to send.\n", plc);
  2209. *data_size = 0;
  2210. return GNUNET_NO;
  2211. }
  2212. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2213. "%p psyc_transmit_notify_mod()\n", plc);
  2214. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
  2215. uint16_t ptype = ntohs (pmsg->type);
  2216. int ret;
  2217. switch (ptype)
  2218. {
  2219. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
  2220. {
  2221. if (NULL == oper)
  2222. {
  2223. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2224. "%p psyc_transmit_notify_mod: oper is NULL.\n", plc);
  2225. ret = GNUNET_SYSERR;
  2226. break;
  2227. }
  2228. struct GNUNET_PSYC_MessageModifier *
  2229. pmod = (struct GNUNET_PSYC_MessageModifier *) tmit_frag->next_part;
  2230. uint16_t mod_size = ntohs (pmod->header.size) - sizeof (*pmod);
  2231. if (*data_size < mod_size)
  2232. {
  2233. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2234. "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc);
  2235. *data_size = 0;
  2236. return GNUNET_NO;
  2237. }
  2238. *full_value_size = ntohl (pmod->value_size);
  2239. *oper = pmod->oper;
  2240. *data_size = mod_size;
  2241. GNUNET_memcpy (data, &pmod[1], mod_size);
  2242. ret = GNUNET_NO;
  2243. break;
  2244. }
  2245. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
  2246. {
  2247. if (NULL != oper)
  2248. {
  2249. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2250. "%p psyc_transmit_notify_mod: oper is not NULL.\n", plc);
  2251. ret = GNUNET_SYSERR;
  2252. break;
  2253. }
  2254. uint16_t mod_size = ntohs (pmsg->size) - sizeof (*pmsg);
  2255. if (*data_size < mod_size)
  2256. {
  2257. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2258. "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc);
  2259. *data_size = 0;
  2260. return GNUNET_NO;
  2261. }
  2262. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2263. "%p psyc_transmit_notify_mod: sending %u bytes.\n", plc, mod_size);
  2264. *data_size = mod_size;
  2265. GNUNET_memcpy (data, &pmsg[1], *data_size);
  2266. ret = GNUNET_NO;
  2267. break;
  2268. }
  2269. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
  2270. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  2271. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  2272. *data_size = 0;
  2273. ret = GNUNET_YES;
  2274. break;
  2275. default:
  2276. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2277. "%p psyc_transmit_notify_mod: unexpected message part of type %u.\n",
  2278. plc, ptype);
  2279. ret = GNUNET_SYSERR;
  2280. }
  2281. if (GNUNET_SYSERR == ret)
  2282. {
  2283. *data_size = 0;
  2284. ret = GNUNET_SYSERR;
  2285. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  2286. GNUNET_SERVICE_client_drop (tmit_frag->client);
  2287. GNUNET_SCHEDULER_add_now (&cleanup_place, plc);
  2288. }
  2289. else
  2290. {
  2291. if (GNUNET_YES != ret)
  2292. psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  2293. if (NULL == tmit_msg->frags_head
  2294. && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
  2295. { /* Reached end of current message. */
  2296. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  2297. }
  2298. }
  2299. return ret;
  2300. }
  2301. /**
  2302. * Callback for data transmission from a host to PSYC.
  2303. */
  2304. static int
  2305. host_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  2306. {
  2307. int ret = psyc_transmit_notify_data (cls, data_size, data);
  2308. if (GNUNET_NO != ret)
  2309. {
  2310. struct Host *hst = cls;
  2311. hst->tmit_handle = NULL;
  2312. }
  2313. return ret;
  2314. }
  2315. /**
  2316. * Callback for the transmit functions of multicast.
  2317. */
  2318. static int
  2319. guest_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  2320. {
  2321. int ret = psyc_transmit_notify_data (cls, data_size, data);
  2322. if (GNUNET_NO != ret)
  2323. {
  2324. struct Guest *gst = cls;
  2325. gst->tmit_handle = NULL;
  2326. }
  2327. return ret;
  2328. }
  2329. /**
  2330. * Callback for modifier transmission from a host to PSYC.
  2331. */
  2332. static int
  2333. host_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  2334. uint8_t *oper, uint32_t *full_value_size)
  2335. {
  2336. int ret = psyc_transmit_notify_mod (cls, data_size, data,
  2337. oper, full_value_size);
  2338. if (GNUNET_SYSERR == ret)
  2339. {
  2340. struct Host *hst = cls;
  2341. hst->tmit_handle = NULL;
  2342. }
  2343. return ret;
  2344. }
  2345. /**
  2346. * Callback for modifier transmission from a guest to PSYC.
  2347. */
  2348. static int
  2349. guest_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  2350. uint8_t *oper, uint32_t *full_value_size)
  2351. {
  2352. int ret = psyc_transmit_notify_mod (cls, data_size, data,
  2353. oper, full_value_size);
  2354. if (GNUNET_SYSERR == ret)
  2355. {
  2356. struct Guest *gst = cls;
  2357. gst->tmit_handle = NULL;
  2358. }
  2359. return ret;
  2360. }
  2361. /**
  2362. * Get method part of next message from transmission queue.
  2363. *
  2364. * @param plc
  2365. * Place
  2366. *
  2367. * @return #GNUNET_OK on success
  2368. * #GNUNET_NO if there are no more messages in queue.
  2369. * #GNUNET_SYSERR if the next message is malformed.
  2370. */
  2371. static struct GNUNET_PSYC_MessageMethod *
  2372. psyc_transmit_queue_next_method (struct Place *plc)
  2373. {
  2374. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  2375. if (NULL == tmit_msg)
  2376. return GNUNET_NO;
  2377. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  2378. if (NULL == tmit_frag)
  2379. {
  2380. GNUNET_break (0);
  2381. return GNUNET_NO;
  2382. }
  2383. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  2384. if (NULL == pmsg
  2385. || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD != ntohs (pmsg->type))
  2386. {
  2387. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2388. "%p psyc_transmit_queue_next_method: unexpected message part of type %u.\n",
  2389. plc, NULL != pmsg ? ntohs (pmsg->type) : 0);
  2390. GNUNET_break (0);
  2391. return NULL;
  2392. }
  2393. uint16_t psize = ntohs (pmsg->size);
  2394. struct GNUNET_PSYC_MessageMethod *
  2395. pmeth = (struct GNUNET_PSYC_MessageMethod *) GNUNET_copy_message (pmsg);
  2396. if (psize < sizeof (*pmeth) + 1 || '\0' != *((char *) pmeth + psize - 1))
  2397. {
  2398. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2399. "%p psyc_transmit_queue_next_method: invalid method name.\n",
  2400. plc);
  2401. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2402. "%zu <= %u || NUL != %u\n",
  2403. sizeof (*pmeth), psize, *((char *) pmeth + psize - 1));
  2404. GNUNET_break (0);
  2405. GNUNET_free (pmeth);
  2406. return NULL;
  2407. }
  2408. psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  2409. return pmeth;
  2410. }
  2411. /**
  2412. * Transmit the next message in queue from the host to the PSYC channel.
  2413. */
  2414. static int
  2415. psyc_master_transmit_message (struct Host *hst)
  2416. {
  2417. struct Place *plc = &hst->place;
  2418. if (NULL == hst->tmit_handle)
  2419. {
  2420. struct GNUNET_PSYC_MessageMethod *
  2421. pmeth = psyc_transmit_queue_next_method (plc);
  2422. if (NULL == pmeth)
  2423. return GNUNET_SYSERR;
  2424. hst->tmit_handle = (void *) &hst->tmit_handle;
  2425. struct GNUNET_PSYC_MasterTransmitHandle *
  2426. tmit_handle = GNUNET_PSYC_master_transmit (hst->master, (const char *) &pmeth[1],
  2427. &host_transmit_notify_mod,
  2428. &host_transmit_notify_data, hst,
  2429. pmeth->flags);
  2430. if (NULL != hst->tmit_handle)
  2431. hst->tmit_handle = tmit_handle;
  2432. GNUNET_free (pmeth);
  2433. }
  2434. else
  2435. {
  2436. GNUNET_PSYC_master_transmit_resume (hst->tmit_handle);
  2437. }
  2438. return GNUNET_OK;
  2439. }
  2440. /**
  2441. * Transmit the next message in queue from a guest to the PSYC channel.
  2442. */
  2443. static int
  2444. psyc_slave_transmit_message (struct Guest *gst)
  2445. {
  2446. struct Place *plc = &gst->place;
  2447. if (NULL == gst->tmit_handle)
  2448. {
  2449. struct GNUNET_PSYC_MessageMethod *
  2450. pmeth = psyc_transmit_queue_next_method (plc);
  2451. if (NULL == pmeth)
  2452. return GNUNET_SYSERR;
  2453. gst->tmit_handle = (void *) &gst->tmit_handle;
  2454. struct GNUNET_PSYC_SlaveTransmitHandle *
  2455. tmit_handle = GNUNET_PSYC_slave_transmit (gst->slave, (const char *) &pmeth[1],
  2456. &guest_transmit_notify_mod,
  2457. &guest_transmit_notify_data, gst,
  2458. pmeth->flags);
  2459. if (NULL != gst->tmit_handle)
  2460. gst->tmit_handle = tmit_handle;
  2461. GNUNET_free (pmeth);
  2462. }
  2463. else
  2464. {
  2465. GNUNET_PSYC_slave_transmit_resume (gst->tmit_handle);
  2466. }
  2467. return GNUNET_OK;
  2468. }
  2469. /**
  2470. * Transmit a message to PSYC.
  2471. */
  2472. static int
  2473. psyc_transmit_message (struct Place *plc)
  2474. {
  2475. return
  2476. (plc->is_host)
  2477. ? psyc_master_transmit_message ((struct Host *) plc)
  2478. : psyc_slave_transmit_message ((struct Guest *) plc);
  2479. }
  2480. /**
  2481. * Queue message parts for sending to PSYC.
  2482. *
  2483. * @param plc Place to send to.
  2484. * @param client Client the message originates from.
  2485. * @param data_size Size of @a data.
  2486. * @param data Concatenated message parts.
  2487. * @param first_ptype First message part type in @a data.
  2488. * @param last_ptype Last message part type in @a data.
  2489. */
  2490. static struct MessageTransmitQueue *
  2491. psyc_transmit_queue_message (struct Place *plc,
  2492. struct GNUNET_SERVICE_Client *client,
  2493. size_t data_size,
  2494. const void *data,
  2495. uint16_t first_ptype, uint16_t last_ptype,
  2496. struct MessageTransmitQueue *tmit_msg)
  2497. {
  2498. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == first_ptype)
  2499. {
  2500. tmit_msg = GNUNET_malloc (sizeof (*tmit_msg));
  2501. GNUNET_CONTAINER_DLL_insert_tail (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg);
  2502. }
  2503. else if (NULL == tmit_msg)
  2504. {
  2505. return NULL;
  2506. }
  2507. struct FragmentTransmitQueue *
  2508. tmit_frag = GNUNET_malloc (sizeof (*tmit_frag) + data_size);
  2509. GNUNET_memcpy (&tmit_frag[1], data, data_size);
  2510. tmit_frag->next_part = (struct GNUNET_MessageHeader *) &tmit_frag[1];
  2511. tmit_frag->client = client;
  2512. tmit_frag->size = data_size;
  2513. GNUNET_CONTAINER_DLL_insert_tail (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag);
  2514. tmit_msg->client = client;
  2515. return tmit_msg;
  2516. }
  2517. ///**
  2518. // * Cancel transmission of current message to PSYC.
  2519. // *
  2520. // * @param plc Place to send to.
  2521. // * @param client Client the message originates from.
  2522. // */
  2523. //static void
  2524. //psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVICE_Client *client)
  2525. //{
  2526. // uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL;
  2527. //
  2528. // struct GNUNET_MessageHeader msg;
  2529. // msg.size = htons (sizeof (msg));
  2530. // msg.type = htons (type);
  2531. //
  2532. // psyc_transmit_queue_message (plc, client, sizeof (msg), &msg, type, type, NULL);
  2533. // psyc_transmit_message (plc);
  2534. //
  2535. // /* FIXME: cleanup */
  2536. //}
  2537. static int
  2538. check_client_psyc_message (void *cls,
  2539. const struct GNUNET_MessageHeader *msg)
  2540. {
  2541. return GNUNET_OK;
  2542. }
  2543. /**
  2544. * Handle an incoming message from a client, to be transmitted to the place.
  2545. */
  2546. static void
  2547. handle_client_psyc_message (void *cls,
  2548. const struct GNUNET_MessageHeader *msg)
  2549. {
  2550. struct Client *c = cls;
  2551. struct GNUNET_SERVICE_Client *client = c->client;
  2552. struct Place *plc = c->place;
  2553. int ret;
  2554. if (NULL == plc)
  2555. {
  2556. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2557. "received PSYC message for non-existing client %p\n",
  2558. client);
  2559. GNUNET_break (0);
  2560. GNUNET_SERVICE_client_drop (client);
  2561. return;
  2562. }
  2563. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2564. "%p Received message of type %d from client.\n", plc, ntohs (msg->type));
  2565. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg);
  2566. if (GNUNET_YES != plc->is_ready)
  2567. {
  2568. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2569. "%p Place is not ready yet, disconnecting client.\n", plc);
  2570. GNUNET_break (0);
  2571. GNUNET_SERVICE_client_drop (client);
  2572. return;
  2573. }
  2574. uint16_t size = ntohs (msg->size);
  2575. uint16_t psize = size - sizeof (*msg);
  2576. if (psize < sizeof (struct GNUNET_MessageHeader)
  2577. || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < psize)
  2578. {
  2579. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2580. "%p Received message with invalid payload size (%u) from client.\n",
  2581. plc, psize);
  2582. GNUNET_break (0);
  2583. GNUNET_SERVICE_client_drop (client);
  2584. return;
  2585. }
  2586. uint16_t first_ptype = 0;
  2587. uint16_t last_ptype = 0;
  2588. if (GNUNET_SYSERR ==
  2589. GNUNET_PSYC_receive_check_parts (psize, (const char *) &msg[1],
  2590. &first_ptype, &last_ptype))
  2591. {
  2592. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2593. "%p Received invalid message part from client.\n", plc);
  2594. GNUNET_break (0);
  2595. GNUNET_SERVICE_client_drop (client);
  2596. return;
  2597. }
  2598. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2599. "%p Received message with first part type %u and last part type %u.\n",
  2600. plc, first_ptype, last_ptype);
  2601. c->tmit_msg
  2602. = psyc_transmit_queue_message (plc, client, psize, &msg[1],
  2603. first_ptype, last_ptype, c->tmit_msg);
  2604. if (NULL != c->tmit_msg)
  2605. {
  2606. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= last_ptype)
  2607. c->tmit_msg = NULL;
  2608. ret = psyc_transmit_message (plc);
  2609. }
  2610. else
  2611. {
  2612. ret = GNUNET_SYSERR;
  2613. }
  2614. if (GNUNET_OK != ret)
  2615. {
  2616. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2617. "%p Received invalid message part from client.\n", plc);
  2618. GNUNET_break (0);
  2619. GNUNET_SERVICE_client_drop (client);
  2620. return;
  2621. }
  2622. GNUNET_SERVICE_client_continue (client);
  2623. }
  2624. /**
  2625. * A historic message arrived from PSYC.
  2626. */
  2627. static void
  2628. psyc_recv_history_message (void *cls, const struct GNUNET_PSYC_MessageHeader *msg)
  2629. {
  2630. struct OperationClosure *opcls = cls;
  2631. struct Client *c = opcls->client;
  2632. struct Place *plc = c->place;
  2633. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2634. "%p Received historic message #%" PRId64 " (flags: %x)\n",
  2635. plc, GNUNET_ntohll (msg->message_id), ntohl (msg->flags));
  2636. uint16_t size = ntohs (msg->header.size);
  2637. struct GNUNET_OperationResultMessage *
  2638. res = GNUNET_malloc (sizeof (*res) + size);
  2639. res->header.size = htons (sizeof (*res) + size);
  2640. res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_HISTORY_RESULT);
  2641. res->op_id = opcls->op_id;
  2642. res->result_code = GNUNET_htonll (GNUNET_OK);
  2643. GNUNET_memcpy (&res[1], msg, size);
  2644. /** @todo FIXME: send only to requesting client */
  2645. place_send_msg (plc, GNUNET_MQ_msg_copy (&res->header));
  2646. GNUNET_free (res);
  2647. }
  2648. /**
  2649. * Result of message history replay from PSYC.
  2650. */
  2651. static void
  2652. psyc_recv_history_result (void *cls, int64_t result,
  2653. const void *err_msg, uint16_t err_msg_size)
  2654. {
  2655. struct OperationClosure *opcls = cls;
  2656. struct Client *c = opcls->client;
  2657. struct Place *plc = c->place;
  2658. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2659. "%p History replay #%" PRIu64 ": "
  2660. "PSYCstore returned %" PRId64 " (%.*s)\n",
  2661. plc, GNUNET_ntohll (opcls->op_id), result,
  2662. err_msg_size, (const char *) err_msg);
  2663. // FIXME: place might have been destroyed
  2664. client_send_result (c->client, opcls->op_id, result, err_msg, err_msg_size);
  2665. }
  2666. static int
  2667. check_client_history_replay (void *cls,
  2668. const struct GNUNET_PSYC_HistoryRequestMessage *req)
  2669. {
  2670. return GNUNET_OK;
  2671. }
  2672. /**
  2673. * Client requests channel history.
  2674. */
  2675. static void
  2676. handle_client_history_replay (void *cls,
  2677. const struct GNUNET_PSYC_HistoryRequestMessage *req)
  2678. {
  2679. struct Client *c = cls;
  2680. struct GNUNET_SERVICE_Client *client = c->client;
  2681. struct Place *plc = c->place;
  2682. if (NULL == plc)
  2683. {
  2684. GNUNET_break (0);
  2685. GNUNET_SERVICE_client_drop (client);
  2686. return;
  2687. }
  2688. uint16_t size = ntohs (req->header.size);
  2689. const char *method_prefix = (const char *) &req[1];
  2690. if (size < sizeof (*req) + 1
  2691. || '\0' != method_prefix[size - sizeof (*req) - 1])
  2692. {
  2693. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2694. "%p History replay #%" PRIu64 ": "
  2695. "invalid method prefix. size: %u < %zu?\n",
  2696. plc, GNUNET_ntohll (req->op_id), size, sizeof (*req) + 1);
  2697. GNUNET_break (0);
  2698. GNUNET_SERVICE_client_drop (client);
  2699. return;
  2700. }
  2701. struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
  2702. opcls->client = c;
  2703. opcls->op_id = req->op_id;
  2704. opcls->flags = ntohl (req->flags);
  2705. if (0 == req->message_limit)
  2706. GNUNET_PSYC_channel_history_replay (plc->channel,
  2707. GNUNET_ntohll (req->start_message_id),
  2708. GNUNET_ntohll (req->end_message_id),
  2709. method_prefix, opcls->flags,
  2710. psyc_recv_history_message, NULL,
  2711. psyc_recv_history_result, opcls);
  2712. else
  2713. GNUNET_PSYC_channel_history_replay_latest (plc->channel,
  2714. GNUNET_ntohll (req->message_limit),
  2715. method_prefix, opcls->flags,
  2716. psyc_recv_history_message, NULL,
  2717. psyc_recv_history_result, opcls);
  2718. GNUNET_SERVICE_client_continue (client);
  2719. }
  2720. /**
  2721. * A state variable part arrived from PSYC.
  2722. */
  2723. void
  2724. psyc_recv_state_var (void *cls,
  2725. const struct GNUNET_MessageHeader *mod,
  2726. const char *name,
  2727. const void *value,
  2728. uint32_t value_size,
  2729. uint32_t full_value_size)
  2730. {
  2731. struct GNUNET_OperationResultMessage *result_msg;
  2732. struct GNUNET_MQ_Envelope *env;
  2733. struct OperationClosure *opcls = cls;
  2734. struct Client *c = opcls->client;
  2735. struct Place *plc = c->place;
  2736. uint16_t size = ntohs (mod->size);
  2737. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2738. "%p Received state variable %s from PSYC\n",
  2739. plc, name);
  2740. env = GNUNET_MQ_msg_extra (result_msg,
  2741. size,
  2742. GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT);
  2743. result_msg->op_id = opcls->op_id;
  2744. result_msg->result_code = GNUNET_htonll (GNUNET_OK);
  2745. GNUNET_memcpy (&result_msg[1], mod, size);
  2746. /** @todo FIXME: send only to requesting client */
  2747. place_send_msg (plc, env);
  2748. }
  2749. /**
  2750. * Result of retrieving state variable from PSYC.
  2751. */
  2752. static void
  2753. psyc_recv_state_result (void *cls, int64_t result,
  2754. const void *err_msg, uint16_t err_msg_size)
  2755. {
  2756. struct OperationClosure *opcls = cls;
  2757. struct Client *c = opcls->client;
  2758. struct Place *plc = c->place;
  2759. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2760. "%p State get #%" PRIu64 ": "
  2761. "PSYCstore returned %" PRId64 " (%.*s)\n",
  2762. plc, GNUNET_ntohll (opcls->op_id), result,
  2763. err_msg_size, (const char *) err_msg);
  2764. // FIXME: place might have been destroyed
  2765. client_send_result (c->client, opcls->op_id, result, err_msg, err_msg_size);
  2766. }
  2767. static int
  2768. check_client_state_get (void *cls,
  2769. const struct GNUNET_PSYC_StateRequestMessage *req)
  2770. {
  2771. return GNUNET_OK;
  2772. }
  2773. /**
  2774. * Client requests channel history.
  2775. */
  2776. static void
  2777. handle_client_state_get (void *cls,
  2778. const struct GNUNET_PSYC_StateRequestMessage *req)
  2779. {
  2780. struct Client *c = cls;
  2781. struct GNUNET_SERVICE_Client *client = c->client;
  2782. struct Place *plc = c->place;
  2783. if (NULL == plc)
  2784. {
  2785. GNUNET_break (0);
  2786. GNUNET_SERVICE_client_drop (client);
  2787. return;
  2788. }
  2789. uint16_t size = ntohs (req->header.size);
  2790. const char *name = (const char *) &req[1];
  2791. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2792. "%p State get #%" PRIu64 ": %s\n",
  2793. plc, GNUNET_ntohll (req->op_id), name);
  2794. if (size < sizeof (*req) + 1
  2795. || '\0' != name[size - sizeof (*req) - 1])
  2796. {
  2797. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2798. "%p State get #%" PRIu64 ": "
  2799. "invalid name. size: %u < %zu?\n",
  2800. plc, GNUNET_ntohll (req->op_id), size, sizeof (*req) + 1);
  2801. GNUNET_break (0);
  2802. GNUNET_SERVICE_client_drop (client);
  2803. return;
  2804. }
  2805. struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
  2806. opcls->client = c;
  2807. opcls->op_id = req->op_id;
  2808. switch (ntohs (req->header.type))
  2809. {
  2810. case GNUNET_MESSAGE_TYPE_PSYC_STATE_GET:
  2811. GNUNET_PSYC_channel_state_get (plc->channel, name,
  2812. psyc_recv_state_var,
  2813. psyc_recv_state_result, opcls);
  2814. break;
  2815. case GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX:
  2816. GNUNET_PSYC_channel_state_get_prefix (plc->channel, name,
  2817. psyc_recv_state_var,
  2818. psyc_recv_state_result, opcls);
  2819. break;
  2820. default:
  2821. GNUNET_assert (0);
  2822. }
  2823. GNUNET_SERVICE_client_continue (client);
  2824. }
  2825. #define check_client_state_get_prefix check_client_state_get
  2826. #define handle_client_state_get_prefix handle_client_state_get
  2827. static void
  2828. namestore_recv_records_store_result (void *cls, int32_t result,
  2829. const char *err_msg)
  2830. {
  2831. struct OperationClosure *opcls = cls;
  2832. struct Client *c = opcls->client;
  2833. // FIXME: client might have been disconnected
  2834. client_send_result (c->client, opcls->op_id, result, err_msg,
  2835. (NULL != err_msg) ? strlen (err_msg) : 0);
  2836. GNUNET_free (opcls);
  2837. }
  2838. static int
  2839. check_client_zone_add_place (void *cls,
  2840. const struct ZoneAddPlaceRequest *preq)
  2841. {
  2842. return GNUNET_OK;
  2843. }
  2844. /**
  2845. * Handle request to add PLACE record to GNS zone.
  2846. */
  2847. static void
  2848. handle_client_zone_add_place (void *cls,
  2849. const struct ZoneAddPlaceRequest *preq)
  2850. {
  2851. struct Client *c = cls;
  2852. struct GNUNET_SERVICE_Client *client = c->client;
  2853. uint16_t remaining = ntohs (preq->header.size) - sizeof (*preq);
  2854. const char *p = (const char *) &preq[1];
  2855. const char *name = NULL, *password = NULL;
  2856. uint16_t offset = GNUNET_STRINGS_buffer_tokenize (p, remaining, 2,
  2857. &name, &password);
  2858. remaining -= offset;
  2859. p += offset;
  2860. const struct GNUNET_PeerIdentity *
  2861. relays = (const struct GNUNET_PeerIdentity *) p;
  2862. uint16_t relay_size = ntohl (preq->relay_count) * sizeof (*relays);
  2863. if (0 == offset || remaining != relay_size)
  2864. {
  2865. GNUNET_break (0);
  2866. client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0);
  2867. GNUNET_SERVICE_client_drop (client);
  2868. return;
  2869. }
  2870. struct GNUNET_GNSRECORD_Data rd = { };
  2871. rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
  2872. rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  2873. rd.expiration_time = GNUNET_ntohll (preq->expiration_time);
  2874. struct GNUNET_GNSRECORD_PlaceData *
  2875. rec = GNUNET_malloc (sizeof (*rec) + relay_size);
  2876. rec->place_pub_key = preq->place_pub_key;
  2877. rec->origin = this_peer;
  2878. rec->relay_count = preq->relay_count;
  2879. GNUNET_memcpy (&rec[1], relays, relay_size);
  2880. rd.data = rec;
  2881. rd.data_size = sizeof (*rec) + relay_size;
  2882. struct GNUNET_HashCode ego_pub_hash;
  2883. GNUNET_CRYPTO_hash (&preq->ego_pub_key, sizeof (preq->ego_pub_key), &ego_pub_hash);
  2884. struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
  2885. if (NULL == ego)
  2886. {
  2887. client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0);
  2888. }
  2889. else
  2890. {
  2891. struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
  2892. opcls->client = c;
  2893. opcls->op_id = preq->op_id;
  2894. GNUNET_NAMESTORE_records_store (namestore, &ego->key,
  2895. name, 1, &rd,
  2896. namestore_recv_records_store_result, opcls);
  2897. /** @todo refresh stored records later */
  2898. }
  2899. GNUNET_SERVICE_client_continue (client);
  2900. }
  2901. static int
  2902. check_client_zone_add_nym (void *cls,
  2903. const struct ZoneAddNymRequest *nreq)
  2904. {
  2905. return GNUNET_OK;
  2906. }
  2907. /**
  2908. * Handle request to add PLACE record to GNS zone.
  2909. */
  2910. static void
  2911. handle_client_zone_add_nym (void *cls,
  2912. const struct ZoneAddNymRequest *nreq)
  2913. {
  2914. struct Client *c = cls;
  2915. struct GNUNET_SERVICE_Client *client = c->client;
  2916. uint16_t name_size = ntohs (nreq->header.size) - sizeof (*nreq);
  2917. const char *name = NULL;
  2918. uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &nreq[1],
  2919. name_size, 1, &name);
  2920. if (0 == offset || offset != name_size)
  2921. {
  2922. GNUNET_break (0);
  2923. client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0);
  2924. GNUNET_SERVICE_client_continue (client);
  2925. return;
  2926. }
  2927. struct GNUNET_GNSRECORD_Data rd = { };
  2928. rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
  2929. rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  2930. rd.expiration_time = GNUNET_ntohll (nreq->expiration_time);
  2931. rd.data = &nreq->nym_pub_key;
  2932. rd.data_size = sizeof (nreq->nym_pub_key);
  2933. struct GNUNET_HashCode ego_pub_hash;
  2934. GNUNET_CRYPTO_hash (&nreq->ego_pub_key, sizeof (nreq->ego_pub_key), &ego_pub_hash);
  2935. struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
  2936. if (NULL == ego)
  2937. {
  2938. client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0);
  2939. }
  2940. else
  2941. {
  2942. struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
  2943. opcls->client = c;
  2944. opcls->op_id = nreq->op_id;
  2945. GNUNET_NAMESTORE_records_store (namestore, &ego->key,
  2946. name, 1, &rd,
  2947. namestore_recv_records_store_result, opcls);
  2948. /** @todo refresh stored records later */
  2949. }
  2950. GNUNET_SERVICE_client_continue (client);
  2951. }
  2952. const char *
  2953. path_basename (const char *path)
  2954. {
  2955. const char *basename = strrchr (path, DIR_SEPARATOR);
  2956. if (NULL != basename)
  2957. basename++;
  2958. if (NULL == basename || '\0' == *basename)
  2959. return NULL;
  2960. return basename;
  2961. }
  2962. struct PlaceLoadClosure
  2963. {
  2964. const char *app_id;
  2965. const char *ego_pub_str;
  2966. };
  2967. /** Load a place file */
  2968. int
  2969. file_place_load (void *cls, const char *place_filename)
  2970. {
  2971. struct PlaceLoadClosure *plcls = cls;
  2972. const char *place_pub_str = path_basename (place_filename);
  2973. if (NULL == place_pub_str)
  2974. {
  2975. GNUNET_break (0);
  2976. return GNUNET_OK;
  2977. }
  2978. char *filename = NULL;
  2979. GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s",
  2980. dir_social, DIR_SEPARATOR,
  2981. "places", DIR_SEPARATOR,
  2982. plcls->ego_pub_str, DIR_SEPARATOR,
  2983. place_pub_str);
  2984. uint64_t file_size = 0;
  2985. if (GNUNET_OK !=
  2986. GNUNET_DISK_file_size (filename, &file_size, GNUNET_YES, GNUNET_YES)
  2987. || file_size < sizeof (struct PlaceEnterRequest))
  2988. {
  2989. GNUNET_free (filename);
  2990. return GNUNET_OK;
  2991. }
  2992. struct PlaceEnterRequest *ereq = GNUNET_malloc (file_size);
  2993. ssize_t read_size = GNUNET_DISK_fn_read (filename, ereq, file_size);
  2994. GNUNET_free (filename);
  2995. if (read_size < 0 || read_size < sizeof (*ereq))
  2996. {
  2997. GNUNET_free (ereq);
  2998. return GNUNET_OK;
  2999. }
  3000. uint16_t ereq_size = ntohs (ereq->header.size);
  3001. if (read_size != ereq_size)
  3002. {
  3003. GNUNET_free (ereq);
  3004. return GNUNET_OK;
  3005. }
  3006. switch (ntohs (ereq->header.type))
  3007. {
  3008. case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER:
  3009. if (ereq_size < sizeof (struct HostEnterRequest))
  3010. {
  3011. GNUNET_free (ereq);
  3012. return GNUNET_OK;
  3013. }
  3014. struct HostEnterRequest *hreq = (struct HostEnterRequest *) ereq;
  3015. host_enter (hreq, NULL);
  3016. break;
  3017. case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
  3018. if (ereq_size < sizeof (struct GuestEnterRequest))
  3019. {
  3020. GNUNET_free (ereq);
  3021. return GNUNET_OK;
  3022. }
  3023. struct GuestEnterRequest *greq = (struct GuestEnterRequest *) ereq;
  3024. guest_enter (greq, NULL);
  3025. break;
  3026. default:
  3027. GNUNET_free (ereq);
  3028. return GNUNET_OK;
  3029. }
  3030. if (GNUNET_SYSERR == app_place_add (plcls->app_id, ereq))
  3031. {
  3032. GNUNET_assert (0);
  3033. }
  3034. GNUNET_free (ereq);
  3035. return GNUNET_OK;
  3036. }
  3037. /**
  3038. * Read @e place_pub_str entries in @a dir_ego
  3039. *
  3040. * @param dir_ego
  3041. * Data directory of an application ego.
  3042. * $GNUNET_DATA_HOME/social/apps/$app_id/$ego_pub_str/
  3043. */
  3044. int
  3045. scan_app_ego_dir (void *cls, const char *dir_ego)
  3046. {
  3047. struct PlaceLoadClosure *plcls = cls;
  3048. plcls->ego_pub_str = path_basename (dir_ego);
  3049. if (NULL != plcls->ego_pub_str)
  3050. GNUNET_DISK_directory_scan (dir_ego, file_place_load, plcls);
  3051. return GNUNET_OK;
  3052. }
  3053. /**
  3054. * Read @e ego_pub_str entries in @a dir_app
  3055. *
  3056. * @param dir_app
  3057. * Data directory of an application.
  3058. * $GNUNET_DATA_HOME/social/apps/$app_id/
  3059. */
  3060. int
  3061. scan_app_dir (void *cls, const char *dir_app)
  3062. {
  3063. if (GNUNET_YES != GNUNET_DISK_directory_test (dir_app, GNUNET_YES))
  3064. return GNUNET_OK;
  3065. struct PlaceLoadClosure plcls;
  3066. plcls.app_id = path_basename (dir_app);
  3067. if (NULL != plcls.app_id)
  3068. GNUNET_DISK_directory_scan (dir_app, scan_app_ego_dir, &plcls);
  3069. return GNUNET_OK;
  3070. }
  3071. static void
  3072. identity_recv_ego (void *cls, struct GNUNET_IDENTITY_Ego *id_ego,
  3073. void **ctx, const char *name)
  3074. {
  3075. if (NULL == id_ego) // end of initial list of egos
  3076. return;
  3077. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3078. "social service received ego %s\n",
  3079. name);
  3080. struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
  3081. GNUNET_IDENTITY_ego_get_public_key (id_ego, &ego_pub_key);
  3082. struct GNUNET_HashCode ego_pub_hash;
  3083. GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash);
  3084. struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
  3085. if (NULL == ego && NULL == name)
  3086. {
  3087. // an ego that is none of our business has been deleted
  3088. return;
  3089. }
  3090. if (NULL != ego)
  3091. {
  3092. // one of our egos has been changed
  3093. GNUNET_free (ego->name);
  3094. if (NULL == name)
  3095. {
  3096. // one of our egos has been deleted
  3097. GNUNET_CONTAINER_multihashmap_remove (egos, &ego_pub_hash, ego);
  3098. GNUNET_free (ego);
  3099. return;
  3100. }
  3101. }
  3102. else
  3103. {
  3104. ego = GNUNET_malloc (sizeof (*ego));
  3105. }
  3106. ego->key = *(GNUNET_IDENTITY_ego_get_private_key (id_ego));
  3107. size_t name_size = strlen (name) + 1;
  3108. ego->name = GNUNET_malloc (name_size);
  3109. GNUNET_memcpy (ego->name, name, name_size);
  3110. GNUNET_CONTAINER_multihashmap_put (egos, &ego_pub_hash, ego,
  3111. GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
  3112. // FIXME: notify clients about changed ego
  3113. }
  3114. /**
  3115. * Initialize the PSYC service.
  3116. *
  3117. * @param cls Closure.
  3118. * @param server The initialized server.
  3119. * @param c Configuration to use.
  3120. */
  3121. static void
  3122. run (void *cls,
  3123. const struct GNUNET_CONFIGURATION_Handle *c,
  3124. struct GNUNET_SERVICE_Handle *svc)
  3125. {
  3126. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3127. "starting social service\n");
  3128. cfg = c;
  3129. service = svc;
  3130. GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
  3131. hosts = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  3132. guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  3133. place_guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  3134. egos = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  3135. apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  3136. places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
  3137. apps_places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
  3138. //places_apps = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
  3139. id = GNUNET_IDENTITY_connect (cfg, &identity_recv_ego, NULL);
  3140. gns = GNUNET_GNS_connect (cfg);
  3141. namestore = GNUNET_NAMESTORE_connect (cfg);
  3142. stats = GNUNET_STATISTICS_create ("social", cfg);
  3143. if (GNUNET_OK !=
  3144. GNUNET_CONFIGURATION_get_value_filename (cfg, "social", "DATA_HOME",
  3145. &dir_social))
  3146. {
  3147. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  3148. "social", "DATA_HOME");
  3149. GNUNET_break (0);
  3150. return;
  3151. }
  3152. GNUNET_asprintf (&dir_places, "%s%c%s",
  3153. dir_social, DIR_SEPARATOR, "places");
  3154. GNUNET_asprintf (&dir_apps, "%s%c%s",
  3155. dir_social, DIR_SEPARATOR, "apps");
  3156. GNUNET_DISK_directory_scan (dir_apps, scan_app_dir, NULL);
  3157. GNUNET_SCHEDULER_add_shutdown (shutdown_task, NULL);
  3158. }
  3159. /**
  3160. * Define "main" method using service macro.
  3161. */
  3162. GNUNET_SERVICE_MAIN
  3163. ("social",
  3164. GNUNET_SERVICE_OPTION_NONE,
  3165. run,
  3166. client_notify_connect,
  3167. client_notify_disconnect,
  3168. NULL,
  3169. GNUNET_MQ_hd_var_size (client_host_enter,
  3170. GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER,
  3171. struct HostEnterRequest,
  3172. NULL),
  3173. GNUNET_MQ_hd_var_size (client_guest_enter,
  3174. GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER,
  3175. struct GuestEnterRequest,
  3176. NULL),
  3177. GNUNET_MQ_hd_var_size (client_guest_enter_by_name,
  3178. GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_BY_NAME,
  3179. struct GuestEnterByNameRequest,
  3180. NULL),
  3181. GNUNET_MQ_hd_var_size (client_join_decision,
  3182. GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
  3183. struct GNUNET_PSYC_JoinDecisionMessage,
  3184. NULL),
  3185. GNUNET_MQ_hd_var_size (client_psyc_message,
  3186. GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
  3187. struct GNUNET_MessageHeader,
  3188. NULL),
  3189. GNUNET_MQ_hd_var_size (client_history_replay,
  3190. GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY,
  3191. struct GNUNET_PSYC_HistoryRequestMessage,
  3192. NULL),
  3193. GNUNET_MQ_hd_var_size (client_state_get,
  3194. GNUNET_MESSAGE_TYPE_PSYC_STATE_GET,
  3195. struct GNUNET_PSYC_StateRequestMessage,
  3196. NULL),
  3197. GNUNET_MQ_hd_var_size (client_state_get_prefix,
  3198. GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX,
  3199. struct GNUNET_PSYC_StateRequestMessage,
  3200. NULL),
  3201. GNUNET_MQ_hd_var_size (client_zone_add_place,
  3202. GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE,
  3203. struct ZoneAddPlaceRequest,
  3204. NULL),
  3205. GNUNET_MQ_hd_var_size (client_zone_add_nym,
  3206. GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM,
  3207. struct ZoneAddNymRequest,
  3208. NULL),
  3209. GNUNET_MQ_hd_var_size (client_app_connect,
  3210. GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT,
  3211. struct AppConnectRequest,
  3212. NULL),
  3213. GNUNET_MQ_hd_fixed_size (client_app_detach,
  3214. GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH,
  3215. struct AppDetachRequest,
  3216. NULL),
  3217. GNUNET_MQ_hd_fixed_size (client_place_leave,
  3218. GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE,
  3219. struct GNUNET_MessageHeader,
  3220. NULL),
  3221. GNUNET_MQ_hd_var_size (client_msg_proc_set,
  3222. GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_SET,
  3223. struct MsgProcRequest,
  3224. NULL),
  3225. GNUNET_MQ_hd_fixed_size (client_msg_proc_clear,
  3226. GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_CLEAR,
  3227. struct GNUNET_MessageHeader,
  3228. NULL));
  3229. /* end of gnunet-service-social.c */