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.
 
 
 
 

2234 lines
60 KiB

  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file multicast/gnunet-service-multicast.c
  18. * @brief program that does multicast
  19. * @author Christian Grothoff
  20. */
  21. #include <gnunet/platform.h>
  22. #include <gnunet/gnunet_util_lib.h>
  23. #include <gnunet/gnunet_signatures.h>
  24. #include <gnunet/gnunet_applications.h>
  25. #include <gnunet/gnunet_statistics_service.h>
  26. #include <gnunet/gnunet_cadet_service.h>
  27. #include "gnunet_multicast_service.h"
  28. #include "multicast.h"
  29. /**
  30. * Handle to our current configuration.
  31. */
  32. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  33. /**
  34. * Service handle.
  35. */
  36. static struct GNUNET_SERVICE_Handle *service;
  37. /**
  38. * CADET handle.
  39. */
  40. static struct GNUNET_CADET_Handle *cadet;
  41. /**
  42. * Identity of this peer.
  43. */
  44. static struct GNUNET_PeerIdentity this_peer;
  45. /**
  46. * Handle to the statistics service.
  47. */
  48. static struct GNUNET_STATISTICS_Handle *stats;
  49. /**
  50. * All connected origin clients.
  51. * Group's pub_key_hash -> struct Origin * (uniq)
  52. */
  53. static struct GNUNET_CONTAINER_MultiHashMap *origins;
  54. /**
  55. * All connected member clients.
  56. * Group's pub_key_hash -> struct Member * (multi)
  57. */
  58. static struct GNUNET_CONTAINER_MultiHashMap *members;
  59. /**
  60. * Connected member clients per group.
  61. * Group's pub_key_hash -> Member's pub_key_hash (uniq) -> struct Member * (uniq)
  62. */
  63. static struct GNUNET_CONTAINER_MultiHashMap *group_members;
  64. /**
  65. * Incoming CADET channels with connected children in the tree.
  66. * Group's pub_key_hash -> struct Channel * (multi)
  67. */
  68. static struct GNUNET_CONTAINER_MultiHashMap *channels_in;
  69. /**
  70. * Outgoing CADET channels connecting to parents in the tree.
  71. * Group's pub_key_hash -> struct Channel * (multi)
  72. */
  73. static struct GNUNET_CONTAINER_MultiHashMap *channels_out;
  74. /**
  75. * Incoming replay requests from CADET.
  76. * Group's pub_key_hash ->
  77. * H(fragment_id, message_id, fragment_offset, flags) -> struct Channel *
  78. */
  79. static struct GNUNET_CONTAINER_MultiHashMap *replay_req_cadet;
  80. /**
  81. * Incoming replay requests from clients.
  82. * Group's pub_key_hash ->
  83. * H(fragment_id, message_id, fragment_offset, flags) -> struct GNUNET_SERVICE_Client *
  84. */
  85. static struct GNUNET_CONTAINER_MultiHashMap *replay_req_client;
  86. /**
  87. * Join status of a remote peer.
  88. */
  89. enum JoinStatus
  90. {
  91. JOIN_REFUSED = -1,
  92. JOIN_NOT_ASKED = 0,
  93. JOIN_WAITING = 1,
  94. JOIN_ADMITTED = 2,
  95. };
  96. enum ChannelDirection
  97. {
  98. DIR_INCOMING = 0,
  99. DIR_OUTGOING = 1,
  100. };
  101. /**
  102. * Context for a CADET channel.
  103. */
  104. struct Channel
  105. {
  106. /**
  107. * Group the channel belongs to.
  108. *
  109. * Only set for outgoing channels.
  110. */
  111. struct Group *group;
  112. /**
  113. * CADET channel.
  114. */
  115. struct GNUNET_CADET_Channel *channel;
  116. // FIXME: not used
  117. /**
  118. * CADET transmission handle.
  119. */
  120. struct GNUNET_CADET_TransmitHandle *tmit_handle;
  121. /**
  122. * Public key of the target group.
  123. */
  124. struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
  125. /**
  126. * Hash of @a group_pub_key.
  127. */
  128. struct GNUNET_HashCode group_pub_hash;
  129. /**
  130. * Public key of the joining member.
  131. */
  132. struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
  133. /**
  134. * Remote peer identity.
  135. */
  136. struct GNUNET_PeerIdentity peer;
  137. /**
  138. * Current window size, set by cadet_notify_window_change()
  139. */
  140. int32_t window_size;
  141. /**
  142. * Is the connection established?
  143. */
  144. int8_t is_connected;
  145. /**
  146. * Is the remote peer admitted to the group?
  147. * @see enum JoinStatus
  148. */
  149. int8_t join_status;
  150. /**
  151. * Number of messages waiting to be sent to CADET.
  152. */
  153. uint8_t msgs_pending;
  154. /**
  155. * Channel direction.
  156. * @see enum ChannelDirection
  157. */
  158. uint8_t direction;
  159. };
  160. /**
  161. * List of connected clients.
  162. */
  163. struct ClientList
  164. {
  165. struct ClientList *prev;
  166. struct ClientList *next;
  167. struct GNUNET_SERVICE_Client *client;
  168. };
  169. /**
  170. * Client context for an origin or member.
  171. */
  172. struct Group
  173. {
  174. struct ClientList *clients_head;
  175. struct ClientList *clients_tail;
  176. /**
  177. * Public key of the group.
  178. */
  179. struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
  180. /**
  181. * Hash of @a pub_key.
  182. */
  183. struct GNUNET_HashCode pub_key_hash;
  184. /**
  185. * CADET port hash.
  186. */
  187. struct GNUNET_HashCode cadet_port_hash;
  188. /**
  189. * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
  190. */
  191. uint8_t is_disconnected;
  192. /**
  193. * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
  194. */
  195. uint8_t is_origin;
  196. union {
  197. struct Origin *origin;
  198. struct Member *member;
  199. };
  200. };
  201. /**
  202. * Client context for a group's origin.
  203. */
  204. struct Origin
  205. {
  206. struct Group group;
  207. /**
  208. * Private key of the group.
  209. */
  210. struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
  211. /**
  212. * CADET port.
  213. */
  214. struct GNUNET_CADET_Port *cadet_port;
  215. /**
  216. * Last message fragment ID sent to the group.
  217. */
  218. uint64_t max_fragment_id;
  219. };
  220. /**
  221. * Client context for a group member.
  222. */
  223. struct Member
  224. {
  225. struct Group group;
  226. /**
  227. * Private key of the member.
  228. */
  229. struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
  230. /**
  231. * Public key of the member.
  232. */
  233. struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
  234. /**
  235. * Hash of @a pub_key.
  236. */
  237. struct GNUNET_HashCode pub_key_hash;
  238. /**
  239. * Join request sent to the origin / members.
  240. */
  241. struct MulticastJoinRequestMessage *join_req;
  242. /**
  243. * Join decision sent in reply to our request.
  244. *
  245. * Only a positive decision is stored here, in case of a negative decision the
  246. * client is disconnected.
  247. */
  248. struct MulticastJoinDecisionMessageHeader *join_dcsn;
  249. /**
  250. * CADET channel to the origin.
  251. */
  252. struct Channel *origin_channel;
  253. /**
  254. * Peer identity of origin.
  255. */
  256. struct GNUNET_PeerIdentity origin;
  257. /**
  258. * Peer identity of relays (other members to connect).
  259. */
  260. struct GNUNET_PeerIdentity *relays;
  261. /**
  262. * Last request fragment ID sent to the origin.
  263. */
  264. uint64_t max_fragment_id;
  265. /**
  266. * Number of @a relays.
  267. */
  268. uint32_t relay_count;
  269. };
  270. /**
  271. * Client context.
  272. */
  273. struct Client {
  274. struct GNUNET_SERVICE_Client *client;
  275. struct Group *group;
  276. };
  277. struct ReplayRequestKey
  278. {
  279. uint64_t fragment_id;
  280. uint64_t message_id;
  281. uint64_t fragment_offset;
  282. uint64_t flags;
  283. };
  284. static struct Channel *
  285. cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer);
  286. static void
  287. cadet_channel_destroy (struct Channel *chn);
  288. static void
  289. client_send_join_decision (struct Member *mem,
  290. const struct MulticastJoinDecisionMessageHeader *hdcsn);
  291. /**
  292. * Task run during shutdown.
  293. *
  294. * @param cls unused
  295. */
  296. static void
  297. shutdown_task (void *cls)
  298. {
  299. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  300. "shutting down\n");
  301. if (NULL != cadet)
  302. {
  303. GNUNET_CADET_disconnect (cadet);
  304. cadet = NULL;
  305. }
  306. if (NULL != stats)
  307. {
  308. GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
  309. stats = NULL;
  310. }
  311. /* FIXME: do more clean up here */
  312. }
  313. /**
  314. * Clean up origin data structures after a client disconnected.
  315. */
  316. static void
  317. cleanup_origin (struct Origin *orig)
  318. {
  319. struct Group *grp = &orig->group;
  320. GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
  321. if (NULL != orig->cadet_port)
  322. {
  323. GNUNET_CADET_close_port (orig->cadet_port);
  324. orig->cadet_port = NULL;
  325. }
  326. GNUNET_free (orig);
  327. }
  328. /**
  329. * Clean up member data structures after a client disconnected.
  330. */
  331. static void
  332. cleanup_member (struct Member *mem)
  333. {
  334. struct Group *grp = &mem->group;
  335. struct GNUNET_CONTAINER_MultiHashMap *
  336. grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
  337. &grp->pub_key_hash);
  338. GNUNET_assert (NULL != grp_mem);
  339. GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
  340. if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
  341. {
  342. GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
  343. grp_mem);
  344. GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
  345. }
  346. if (NULL != mem->join_dcsn)
  347. {
  348. GNUNET_free (mem->join_dcsn);
  349. mem->join_dcsn = NULL;
  350. }
  351. if (NULL != mem->origin_channel)
  352. {
  353. GNUNET_CADET_channel_destroy (mem->origin_channel->channel);
  354. mem->origin_channel = NULL;
  355. }
  356. GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
  357. GNUNET_free (mem);
  358. }
  359. /**
  360. * Clean up group data structures after a client disconnected.
  361. */
  362. static void
  363. cleanup_group (struct Group *grp)
  364. {
  365. (GNUNET_YES == grp->is_origin)
  366. ? cleanup_origin (grp->origin)
  367. : cleanup_member (grp->member);
  368. }
  369. void
  370. replay_key_hash (uint64_t fragment_id, uint64_t message_id,
  371. uint64_t fragment_offset, uint64_t flags,
  372. struct GNUNET_HashCode *key_hash)
  373. {
  374. struct ReplayRequestKey key = {
  375. .fragment_id = fragment_id,
  376. .message_id = message_id,
  377. .fragment_offset = fragment_offset,
  378. .flags = flags,
  379. };
  380. GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
  381. }
  382. /**
  383. * Remove channel from replay request hashmap.
  384. *
  385. * @param chn
  386. * Channel to remove.
  387. *
  388. * @return #GNUNET_YES if there are more entries to process,
  389. * #GNUNET_NO when reached end of hashmap.
  390. */
  391. static int
  392. replay_req_remove_cadet (struct Channel *chn)
  393. {
  394. if (NULL == chn || NULL == chn->group)
  395. return GNUNET_SYSERR;
  396. struct GNUNET_CONTAINER_MultiHashMap *
  397. grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
  398. &chn->group->pub_key_hash);
  399. if (NULL == grp_replay_req)
  400. return GNUNET_NO;
  401. struct GNUNET_CONTAINER_MultiHashMapIterator *
  402. it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
  403. struct GNUNET_HashCode key;
  404. const struct Channel *c;
  405. while (GNUNET_YES
  406. == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
  407. (const void **) &c))
  408. {
  409. if (c == chn)
  410. {
  411. GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
  412. GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
  413. return GNUNET_YES;
  414. }
  415. }
  416. GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
  417. return GNUNET_NO;
  418. }
  419. /**
  420. * Remove client from replay request hashmap.
  421. *
  422. * @param client
  423. * Client to remove.
  424. *
  425. * @return #GNUNET_YES if there are more entries to process,
  426. * #GNUNET_NO when reached end of hashmap.
  427. */
  428. static int
  429. replay_req_remove_client (struct Group *grp, struct GNUNET_SERVICE_Client *client)
  430. {
  431. struct GNUNET_CONTAINER_MultiHashMap *
  432. grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
  433. &grp->pub_key_hash);
  434. if (NULL == grp_replay_req)
  435. return GNUNET_NO;
  436. struct GNUNET_CONTAINER_MultiHashMapIterator *
  437. it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
  438. struct GNUNET_HashCode key;
  439. const struct GNUNET_SERVICE_Client *c;
  440. while (GNUNET_YES
  441. == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
  442. (const void **) &c))
  443. {
  444. if (c == client)
  445. {
  446. GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, client);
  447. GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
  448. return GNUNET_YES;
  449. }
  450. }
  451. GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
  452. return GNUNET_NO;
  453. }
  454. /**
  455. * Send message to a client.
  456. */
  457. static void
  458. client_send (struct GNUNET_SERVICE_Client *client,
  459. const struct GNUNET_MessageHeader *msg)
  460. {
  461. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  462. "%p Sending message to client.\n", client);
  463. struct GNUNET_MQ_Envelope *
  464. env = GNUNET_MQ_msg_copy (msg);
  465. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  466. env);
  467. }
  468. /**
  469. * Send message to all clients connected to the group.
  470. */
  471. static void
  472. client_send_group_keep_envelope (const struct Group *grp,
  473. struct GNUNET_MQ_Envelope *env)
  474. {
  475. struct ClientList *cli = grp->clients_head;
  476. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  477. "%p Sending message to all clients of the group.\n",
  478. grp);
  479. while (NULL != cli)
  480. {
  481. GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client),
  482. env);
  483. cli = cli->next;
  484. }
  485. }
  486. /**
  487. * Send message to all clients connected to the group and
  488. * takes care of freeing @env.
  489. */
  490. static void
  491. client_send_group (const struct Group *grp,
  492. struct GNUNET_MQ_Envelope *env)
  493. {
  494. client_send_group_keep_envelope (grp, env);
  495. GNUNET_MQ_discard (env);
  496. }
  497. /**
  498. * Iterator callback for sending a message to origin clients.
  499. */
  500. static int
  501. client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
  502. void *origin)
  503. {
  504. struct GNUNET_MQ_Envelope *env = cls;
  505. struct Member *orig = origin;
  506. client_send_group_keep_envelope (&orig->group, env);
  507. return GNUNET_YES;
  508. }
  509. /**
  510. * Iterator callback for sending a message to member clients.
  511. */
  512. static int
  513. client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
  514. void *member)
  515. {
  516. struct GNUNET_MQ_Envelope *env = cls;
  517. struct Member *mem = member;
  518. if (NULL != mem->join_dcsn)
  519. { /* Only send message to admitted members */
  520. client_send_group_keep_envelope (&mem->group, env);
  521. }
  522. return GNUNET_YES;
  523. }
  524. /**
  525. * Send message to all origin and member clients connected to the group.
  526. *
  527. * @param pub_key_hash
  528. * H(key_pub) of the group.
  529. * @param msg
  530. * Message to send.
  531. */
  532. static int
  533. client_send_all (struct GNUNET_HashCode *pub_key_hash,
  534. struct GNUNET_MQ_Envelope *env)
  535. {
  536. int n = 0;
  537. n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
  538. client_send_origin_cb,
  539. (void *) env);
  540. n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
  541. client_send_member_cb,
  542. (void *) env);
  543. GNUNET_MQ_discard (env);
  544. return n;
  545. }
  546. /**
  547. * Send message to a random origin client or a random member client.
  548. *
  549. * @param grp The group to send @a msg to.
  550. * @param msg Message to send.
  551. */
  552. static int
  553. client_send_random (struct GNUNET_HashCode *pub_key_hash,
  554. struct GNUNET_MQ_Envelope *env)
  555. {
  556. int n = 0;
  557. n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
  558. (void *) env);
  559. if (n <= 0)
  560. n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
  561. (void *) env);
  562. GNUNET_MQ_discard (env);
  563. return n;
  564. }
  565. /**
  566. * Send message to all origin clients connected to the group.
  567. *
  568. * @param pub_key_hash
  569. * H(key_pub) of the group.
  570. * @param msg
  571. * Message to send.
  572. */
  573. static int
  574. client_send_origin (struct GNUNET_HashCode *pub_key_hash,
  575. struct GNUNET_MQ_Envelope *env)
  576. {
  577. int n = 0;
  578. n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
  579. client_send_origin_cb,
  580. (void *) env);
  581. return n;
  582. }
  583. /**
  584. * Send fragment acknowledgement to all clients of the channel.
  585. *
  586. * @param pub_key_hash
  587. * H(key_pub) of the group.
  588. */
  589. static void
  590. client_send_ack (struct GNUNET_HashCode *pub_key_hash)
  591. {
  592. struct GNUNET_MQ_Envelope *env;
  593. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  594. "Sending message ACK to client.\n");
  595. env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
  596. client_send_all (pub_key_hash, env);
  597. }
  598. struct CadetTransmitClosure
  599. {
  600. struct Channel *chn;
  601. const struct GNUNET_MessageHeader *msg;
  602. };
  603. /**
  604. * Send a message to a CADET channel.
  605. *
  606. * @param chn Channel.
  607. * @param msg Message.
  608. */
  609. static void
  610. cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
  611. {
  612. struct GNUNET_MQ_Envelope *
  613. env = GNUNET_MQ_msg_copy (msg);
  614. GNUNET_MQ_send (GNUNET_CADET_get_mq (chn->channel), env);
  615. if (0 < chn->window_size)
  616. {
  617. client_send_ack (&chn->group_pub_hash);
  618. }
  619. else
  620. {
  621. chn->msgs_pending++;
  622. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  623. "%p Queuing message. Pending messages: %u\n",
  624. chn, chn->msgs_pending);
  625. }
  626. }
  627. /**
  628. * Create CADET channel and send a join request.
  629. */
  630. static void
  631. cadet_send_join_request (struct Member *mem)
  632. {
  633. mem->origin_channel = cadet_channel_create (&mem->group, &mem->origin);
  634. cadet_send_channel (mem->origin_channel, &mem->join_req->header);
  635. uint32_t i;
  636. for (i = 0; i < mem->relay_count; i++)
  637. {
  638. struct Channel *
  639. chn = cadet_channel_create (&mem->group, &mem->relays[i]);
  640. cadet_send_channel (chn, &mem->join_req->header);
  641. }
  642. }
  643. static int
  644. cadet_send_join_decision_cb (void *cls,
  645. const struct GNUNET_HashCode *group_pub_hash,
  646. void *channel)
  647. {
  648. const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
  649. struct Channel *chn = channel;
  650. const struct MulticastJoinDecisionMessage *dcsn =
  651. (struct MulticastJoinDecisionMessage *) &hdcsn[1];
  652. if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
  653. && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
  654. {
  655. if (GNUNET_YES == ntohl (dcsn->is_admitted))
  656. {
  657. chn->join_status = JOIN_ADMITTED;
  658. }
  659. else
  660. {
  661. chn->join_status = JOIN_REFUSED;
  662. }
  663. cadet_send_channel (chn, &hdcsn->header);
  664. return GNUNET_YES;
  665. }
  666. // return GNUNET_YES to continue the multihashmap_get iteration
  667. return GNUNET_YES;
  668. }
  669. /**
  670. * Send join decision to a remote peer.
  671. */
  672. static void
  673. cadet_send_join_decision (struct Group *grp,
  674. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  675. {
  676. GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
  677. &cadet_send_join_decision_cb,
  678. (void *) hdcsn);
  679. }
  680. /**
  681. * Iterator callback for sending a message to origin clients.
  682. */
  683. static int
  684. cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
  685. void *channel)
  686. {
  687. const struct GNUNET_MessageHeader *msg = cls;
  688. struct Channel *chn = channel;
  689. if (JOIN_ADMITTED == chn->join_status)
  690. cadet_send_channel (chn, msg);
  691. return GNUNET_YES;
  692. }
  693. /**
  694. * Send message to all connected children.
  695. */
  696. static int
  697. cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
  698. const struct GNUNET_MessageHeader *msg)
  699. {
  700. int n = 0;
  701. if (channels_in != NULL)
  702. n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
  703. cadet_send_cb, (void *) msg);
  704. return n;
  705. }
  706. #if 0 // unused as yet
  707. /**
  708. * Send message to all connected parents.
  709. */
  710. static int
  711. cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
  712. const struct GNUNET_MessageHeader *msg)
  713. {
  714. int n = 0;
  715. if (channels_in != NULL)
  716. n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
  717. cadet_send_cb, (void *) msg);
  718. return n;
  719. }
  720. #endif
  721. /**
  722. * CADET channel connect handler.
  723. *
  724. * @see GNUNET_CADET_ConnectEventHandler()
  725. */
  726. static void *
  727. cadet_notify_connect (void *cls,
  728. struct GNUNET_CADET_Channel *channel,
  729. const struct GNUNET_PeerIdentity *source)
  730. {
  731. struct Channel *chn = GNUNET_malloc (sizeof (struct Channel));
  732. chn->group = cls;
  733. chn->channel = channel;
  734. chn->direction = DIR_INCOMING;
  735. chn->join_status = JOIN_NOT_ASKED;
  736. GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group->pub_key_hash, chn,
  737. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  738. return chn;
  739. }
  740. /**
  741. * CADET window size change handler.
  742. *
  743. * @see GNUNET_CADET_WindowSizeEventHandler()
  744. */
  745. static void
  746. cadet_notify_window_change (void *cls,
  747. const struct GNUNET_CADET_Channel *channel,
  748. int window_size)
  749. {
  750. struct Channel *chn = cls;
  751. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  752. "%p Window size changed to %d. Pending messages: %u\n",
  753. chn, window_size, chn->msgs_pending);
  754. chn->is_connected = GNUNET_YES;
  755. chn->window_size = (int32_t) window_size;
  756. for (int i = 0; i < window_size; i++)
  757. {
  758. if (0 < chn->msgs_pending)
  759. {
  760. client_send_ack (&chn->group_pub_hash);
  761. chn->msgs_pending--;
  762. }
  763. else
  764. {
  765. break;
  766. }
  767. }
  768. }
  769. /**
  770. * CADET channel disconnect handler.
  771. *
  772. * @see GNUNET_CADET_DisconnectEventHandler()
  773. */
  774. static void
  775. cadet_notify_disconnect (void *cls,
  776. const struct GNUNET_CADET_Channel *channel)
  777. {
  778. if (NULL == cls)
  779. return;
  780. struct Channel *chn = cls;
  781. if (NULL != chn->group)
  782. {
  783. if (GNUNET_NO == chn->group->is_origin)
  784. {
  785. struct Member *mem = (struct Member *) chn->group;
  786. if (chn == mem->origin_channel)
  787. mem->origin_channel = NULL;
  788. }
  789. }
  790. int ret;
  791. do
  792. {
  793. ret = replay_req_remove_cadet (chn);
  794. }
  795. while (GNUNET_YES == ret);
  796. GNUNET_free (chn);
  797. }
  798. static int
  799. check_cadet_join_request (void *cls,
  800. const struct MulticastJoinRequestMessage *req)
  801. {
  802. struct Channel *chn = cls;
  803. if (NULL == chn
  804. || JOIN_NOT_ASKED != chn->join_status)
  805. {
  806. return GNUNET_SYSERR;
  807. }
  808. uint16_t size = ntohs (req->header.size);
  809. if (size < sizeof (*req))
  810. {
  811. GNUNET_break_op (0);
  812. return GNUNET_SYSERR;
  813. }
  814. if (ntohl (req->purpose.size) != (size
  815. - sizeof (req->header)
  816. - sizeof (req->reserved)
  817. - sizeof (req->signature)))
  818. {
  819. GNUNET_break_op (0);
  820. return GNUNET_SYSERR;
  821. }
  822. if (GNUNET_OK !=
  823. GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
  824. &req->purpose, &req->signature,
  825. &req->member_pub_key))
  826. {
  827. GNUNET_break_op (0);
  828. return GNUNET_SYSERR;
  829. }
  830. return GNUNET_OK;
  831. }
  832. /**
  833. * Incoming join request message from CADET.
  834. */
  835. static void
  836. handle_cadet_join_request (void *cls,
  837. const struct MulticastJoinRequestMessage *req)
  838. {
  839. struct Channel *chn = cls;
  840. GNUNET_CADET_receive_done (chn->channel);
  841. struct GNUNET_HashCode group_pub_hash;
  842. GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
  843. chn->group_pub_key = req->group_pub_key;
  844. chn->group_pub_hash = group_pub_hash;
  845. chn->member_pub_key = req->member_pub_key;
  846. chn->peer = req->peer;
  847. chn->join_status = JOIN_WAITING;
  848. client_send_all (&group_pub_hash,
  849. GNUNET_MQ_msg_copy (&req->header));
  850. }
  851. static int
  852. check_cadet_join_decision (void *cls,
  853. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  854. {
  855. uint16_t size = ntohs (hdcsn->header.size);
  856. if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
  857. sizeof (struct MulticastJoinDecisionMessage))
  858. {
  859. GNUNET_break_op (0);
  860. return GNUNET_SYSERR;
  861. }
  862. struct Channel *chn = cls;
  863. if (NULL == chn)
  864. {
  865. GNUNET_break (0);
  866. return GNUNET_SYSERR;
  867. }
  868. if (NULL == chn->group || GNUNET_NO != chn->group->is_origin)
  869. {
  870. GNUNET_break (0);
  871. return GNUNET_SYSERR;
  872. }
  873. switch (chn->join_status)
  874. {
  875. case JOIN_REFUSED:
  876. return GNUNET_SYSERR;
  877. case JOIN_ADMITTED:
  878. return GNUNET_OK;
  879. case JOIN_NOT_ASKED:
  880. case JOIN_WAITING:
  881. break;
  882. }
  883. return GNUNET_OK;
  884. }
  885. /**
  886. * Incoming join decision message from CADET.
  887. */
  888. static void
  889. handle_cadet_join_decision (void *cls,
  890. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  891. {
  892. const struct MulticastJoinDecisionMessage *
  893. dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
  894. struct Channel *chn = cls;
  895. GNUNET_CADET_receive_done (chn->channel);
  896. // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
  897. struct Member *mem = (struct Member *) chn->group;
  898. client_send_join_decision (mem, hdcsn);
  899. if (GNUNET_YES == ntohl (dcsn->is_admitted))
  900. {
  901. chn->join_status = JOIN_ADMITTED;
  902. }
  903. else
  904. {
  905. chn->join_status = JOIN_REFUSED;
  906. cadet_channel_destroy (chn);
  907. }
  908. }
  909. static int
  910. check_cadet_message (void *cls,
  911. const struct GNUNET_MULTICAST_MessageHeader *msg)
  912. {
  913. uint16_t size = ntohs (msg->header.size);
  914. if (size < sizeof (*msg))
  915. {
  916. GNUNET_break_op (0);
  917. return GNUNET_SYSERR;
  918. }
  919. struct Channel *chn = cls;
  920. if (NULL == chn)
  921. {
  922. GNUNET_break (0);
  923. return GNUNET_SYSERR;
  924. }
  925. if (ntohl (msg->purpose.size) != (size
  926. - sizeof (msg->header)
  927. - sizeof (msg->hop_counter)
  928. - sizeof (msg->signature)))
  929. {
  930. GNUNET_break_op (0);
  931. return GNUNET_SYSERR;
  932. }
  933. if (GNUNET_OK !=
  934. GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
  935. &msg->purpose, &msg->signature,
  936. &chn->group_pub_key))
  937. {
  938. GNUNET_break_op (0);
  939. return GNUNET_SYSERR;
  940. }
  941. return GNUNET_OK;
  942. }
  943. /**
  944. * Incoming multicast message from CADET.
  945. */
  946. static void
  947. handle_cadet_message (void *cls,
  948. const struct GNUNET_MULTICAST_MessageHeader *msg)
  949. {
  950. struct Channel *chn = cls;
  951. GNUNET_CADET_receive_done (chn->channel);
  952. client_send_all (&chn->group_pub_hash,
  953. GNUNET_MQ_msg_copy (&msg->header));
  954. }
  955. static int
  956. check_cadet_request (void *cls,
  957. const struct GNUNET_MULTICAST_RequestHeader *req)
  958. {
  959. uint16_t size = ntohs (req->header.size);
  960. if (size < sizeof (*req))
  961. {
  962. GNUNET_break_op (0);
  963. return GNUNET_SYSERR;
  964. }
  965. struct Channel *chn = cls;
  966. if (NULL == chn)
  967. {
  968. GNUNET_break (0);
  969. return GNUNET_SYSERR;
  970. }
  971. if (ntohl (req->purpose.size) != (size
  972. - sizeof (req->header)
  973. - sizeof (req->member_pub_key)
  974. - sizeof (req->signature)))
  975. {
  976. GNUNET_break_op (0);
  977. return GNUNET_SYSERR;
  978. }
  979. if (GNUNET_OK !=
  980. GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
  981. &req->purpose, &req->signature,
  982. &req->member_pub_key))
  983. {
  984. GNUNET_break_op (0);
  985. return GNUNET_SYSERR;
  986. }
  987. return GNUNET_OK;
  988. }
  989. /**
  990. * Incoming multicast request message from CADET.
  991. */
  992. static void
  993. handle_cadet_request (void *cls,
  994. const struct GNUNET_MULTICAST_RequestHeader *req)
  995. {
  996. struct Channel *chn = cls;
  997. GNUNET_CADET_receive_done (chn->channel);
  998. client_send_origin (&chn->group_pub_hash,
  999. GNUNET_MQ_msg_copy (&req->header));
  1000. }
  1001. // FIXME: do checks in handle_cadet_replay_request
  1002. //static int
  1003. //check_cadet_replay_request (void *cls,
  1004. // const struct MulticastReplayRequestMessage *req)
  1005. //{
  1006. // uint16_t size = ntohs (req->header.size);
  1007. // if (size < sizeof (*req))
  1008. // {
  1009. // GNUNET_break_op (0);
  1010. // return GNUNET_SYSERR;
  1011. // }
  1012. //
  1013. // struct Channel *chn = cls;
  1014. // if (NULL == chn)
  1015. // {
  1016. // GNUNET_break_op (0);
  1017. // return GNUNET_SYSERR;
  1018. // }
  1019. //
  1020. // return GNUNET_OK;
  1021. //}
  1022. /**
  1023. * Incoming multicast replay request from CADET.
  1024. */
  1025. static void
  1026. handle_cadet_replay_request (void *cls,
  1027. const struct MulticastReplayRequestMessage *req)
  1028. {
  1029. struct Channel *chn = cls;
  1030. GNUNET_CADET_receive_done (chn->channel);
  1031. struct MulticastReplayRequestMessage rep = *req;
  1032. GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
  1033. struct GNUNET_CONTAINER_MultiHashMap *
  1034. grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
  1035. &chn->group->pub_key_hash);
  1036. if (NULL == grp_replay_req)
  1037. {
  1038. grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1039. GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
  1040. &chn->group->pub_key_hash, grp_replay_req,
  1041. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1042. }
  1043. struct GNUNET_HashCode key_hash;
  1044. replay_key_hash (rep.fragment_id,
  1045. rep.message_id,
  1046. rep.fragment_offset,
  1047. rep.flags,
  1048. &key_hash);
  1049. GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
  1050. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1051. client_send_random (&chn->group_pub_hash,
  1052. GNUNET_MQ_msg_copy (&rep.header));
  1053. }
  1054. static int
  1055. check_cadet_replay_response (void *cls,
  1056. const struct MulticastReplayResponseMessage *res)
  1057. {
  1058. struct Channel *chn = cls;
  1059. if (NULL == chn)
  1060. {
  1061. GNUNET_break (0);
  1062. return GNUNET_SYSERR;
  1063. }
  1064. return GNUNET_OK;
  1065. }
  1066. /**
  1067. * Incoming multicast replay response from CADET.
  1068. */
  1069. static void
  1070. handle_cadet_replay_response (void *cls,
  1071. const struct MulticastReplayResponseMessage *res)
  1072. {
  1073. struct Channel *chn = cls;
  1074. GNUNET_CADET_receive_done (chn->channel);
  1075. /* @todo FIXME: got replay error response, send request to other members */
  1076. }
  1077. static void
  1078. group_set_cadet_port_hash (struct Group *grp)
  1079. {
  1080. struct CadetPort {
  1081. struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
  1082. uint32_t app_type;
  1083. } port = {
  1084. grp->pub_key,
  1085. GNUNET_APPLICATION_TYPE_MULTICAST,
  1086. };
  1087. GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
  1088. }
  1089. /**
  1090. * Create new outgoing CADET channel.
  1091. *
  1092. * @param peer
  1093. * Peer to connect to.
  1094. * @param group_pub_key
  1095. * Public key of group the channel belongs to.
  1096. * @param group_pub_hash
  1097. * Hash of @a group_pub_key.
  1098. *
  1099. * @return Channel.
  1100. */
  1101. static struct Channel *
  1102. cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
  1103. {
  1104. struct Channel *chn = GNUNET_malloc (sizeof (*chn));
  1105. chn->group = grp;
  1106. chn->group_pub_key = grp->pub_key;
  1107. chn->group_pub_hash = grp->pub_key_hash;
  1108. chn->peer = *peer;
  1109. chn->direction = DIR_OUTGOING;
  1110. chn->is_connected = GNUNET_NO;
  1111. chn->join_status = JOIN_WAITING;
  1112. struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
  1113. GNUNET_MQ_hd_var_size (cadet_message,
  1114. GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
  1115. struct GNUNET_MULTICAST_MessageHeader,
  1116. chn),
  1117. GNUNET_MQ_hd_var_size (cadet_join_decision,
  1118. GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
  1119. struct MulticastJoinDecisionMessageHeader,
  1120. chn),
  1121. GNUNET_MQ_hd_fixed_size (cadet_replay_request,
  1122. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
  1123. struct MulticastReplayRequestMessage,
  1124. chn),
  1125. GNUNET_MQ_hd_var_size (cadet_replay_response,
  1126. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
  1127. struct MulticastReplayResponseMessage,
  1128. chn),
  1129. GNUNET_MQ_handler_end ()
  1130. };
  1131. chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
  1132. &grp->cadet_port_hash,
  1133. cadet_notify_window_change,
  1134. cadet_notify_disconnect,
  1135. cadet_handlers);
  1136. GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
  1137. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1138. return chn;
  1139. }
  1140. /**
  1141. * Destroy outgoing CADET channel.
  1142. */
  1143. static void
  1144. cadet_channel_destroy (struct Channel *chn)
  1145. {
  1146. GNUNET_CADET_channel_destroy (chn->channel);
  1147. GNUNET_CONTAINER_multihashmap_remove_all (channels_out, &chn->group_pub_hash);
  1148. GNUNET_free (chn);
  1149. }
  1150. /**
  1151. * Handle a connecting client starting an origin.
  1152. */
  1153. static void
  1154. handle_client_origin_start (void *cls,
  1155. const struct MulticastOriginStartMessage *msg)
  1156. {
  1157. struct Client *c = cls;
  1158. struct GNUNET_SERVICE_Client *client = c->client;
  1159. struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
  1160. struct GNUNET_HashCode pub_key_hash;
  1161. GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
  1162. GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
  1163. struct Origin *
  1164. orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
  1165. struct Group *grp;
  1166. if (NULL == orig)
  1167. {
  1168. orig = GNUNET_new (struct Origin);
  1169. orig->priv_key = msg->group_key;
  1170. orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
  1171. grp = c->group = &orig->group;
  1172. grp->origin = orig;
  1173. grp->is_origin = GNUNET_YES;
  1174. grp->pub_key = pub_key;
  1175. grp->pub_key_hash = pub_key_hash;
  1176. grp->is_disconnected = GNUNET_NO;
  1177. GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
  1178. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1179. group_set_cadet_port_hash (grp);
  1180. struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
  1181. GNUNET_MQ_hd_var_size (cadet_message,
  1182. GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
  1183. struct GNUNET_MULTICAST_MessageHeader,
  1184. grp),
  1185. GNUNET_MQ_hd_var_size (cadet_request,
  1186. GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
  1187. struct GNUNET_MULTICAST_RequestHeader,
  1188. grp),
  1189. GNUNET_MQ_hd_var_size (cadet_join_request,
  1190. GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
  1191. struct MulticastJoinRequestMessage,
  1192. grp),
  1193. GNUNET_MQ_hd_fixed_size (cadet_replay_request,
  1194. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
  1195. struct MulticastReplayRequestMessage,
  1196. grp),
  1197. GNUNET_MQ_hd_var_size (cadet_replay_response,
  1198. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
  1199. struct MulticastReplayResponseMessage,
  1200. grp),
  1201. GNUNET_MQ_handler_end ()
  1202. };
  1203. orig->cadet_port = GNUNET_CADET_open_port (cadet,
  1204. &grp->cadet_port_hash,
  1205. cadet_notify_connect,
  1206. grp,
  1207. cadet_notify_window_change,
  1208. cadet_notify_disconnect,
  1209. cadet_handlers);
  1210. }
  1211. else
  1212. {
  1213. grp = &orig->group;
  1214. }
  1215. struct ClientList *cl = GNUNET_new (struct ClientList);
  1216. cl->client = client;
  1217. GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
  1218. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1219. "%p Client connected as origin to group %s.\n",
  1220. orig, GNUNET_h2s (&grp->pub_key_hash));
  1221. GNUNET_SERVICE_client_continue (client);
  1222. }
  1223. static int
  1224. check_client_member_join (void *cls,
  1225. const struct MulticastMemberJoinMessage *msg)
  1226. {
  1227. uint16_t msg_size = ntohs (msg->header.size);
  1228. struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
  1229. uint32_t relay_count = ntohl (msg->relay_count);
  1230. if (0 != relay_count)
  1231. {
  1232. if (UINT32_MAX / relay_count < sizeof (*relays)){
  1233. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1234. "relay_count (%lu) * sizeof (*relays) (%lu) exceeds UINT32_MAX!\n",
  1235. (unsigned long)relay_count,
  1236. sizeof (*relays));
  1237. return GNUNET_SYSERR;
  1238. }
  1239. }
  1240. uint32_t relay_size = relay_count * sizeof (*relays);
  1241. struct GNUNET_MessageHeader *join_msg = NULL;
  1242. uint16_t join_msg_size = 0;
  1243. if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
  1244. <= msg_size)
  1245. {
  1246. join_msg = (struct GNUNET_MessageHeader *)
  1247. (((char *) &msg[1]) + relay_size);
  1248. join_msg_size = ntohs (join_msg->size);
  1249. if (UINT16_MAX - join_msg_size < sizeof (struct MulticastJoinRequestMessage)){
  1250. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1251. "join_msg_size (%u) + sizeof (struct MulticastJoinRequestMessage) (%lu) exceeds UINT16_MAX!\n",
  1252. (unsigned)join_msg_size,
  1253. (unsigned long)sizeof (struct MulticastJoinRequestMessage));
  1254. return GNUNET_SYSERR;
  1255. }
  1256. }
  1257. if (msg_size != (sizeof (*msg) + relay_size + join_msg_size)){
  1258. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1259. "msg_size does not match real size of message!\n");
  1260. return GNUNET_SYSERR;
  1261. }else{
  1262. return GNUNET_OK;
  1263. }
  1264. }
  1265. /**
  1266. * Handle a connecting client joining a group.
  1267. */
  1268. static void
  1269. handle_client_member_join (void *cls,
  1270. const struct MulticastMemberJoinMessage *msg)
  1271. {
  1272. struct Client *c = cls;
  1273. struct GNUNET_SERVICE_Client *client = c->client;
  1274. uint16_t msg_size = ntohs (msg->header.size);
  1275. struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
  1276. struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
  1277. GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
  1278. GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
  1279. GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
  1280. struct GNUNET_CONTAINER_MultiHashMap *
  1281. grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
  1282. struct Member *mem = NULL;
  1283. struct Group *grp;
  1284. if (NULL != grp_mem)
  1285. {
  1286. mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
  1287. }
  1288. if (NULL == mem)
  1289. {
  1290. mem = GNUNET_new (struct Member);
  1291. mem->origin = msg->origin;
  1292. mem->priv_key = msg->member_key;
  1293. mem->pub_key = mem_pub_key;
  1294. mem->pub_key_hash = mem_pub_key_hash;
  1295. mem->max_fragment_id = 0; // FIXME
  1296. grp = c->group = &mem->group;
  1297. grp->member = mem;
  1298. grp->is_origin = GNUNET_NO;
  1299. grp->pub_key = msg->group_pub_key;
  1300. grp->pub_key_hash = pub_key_hash;
  1301. grp->is_disconnected = GNUNET_NO;
  1302. group_set_cadet_port_hash (grp);
  1303. if (NULL == grp_mem)
  1304. {
  1305. grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1306. GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
  1307. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1308. }
  1309. GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
  1310. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1311. // FIXME: should the members hash map have option UNIQUE_FAST?
  1312. GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
  1313. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1314. }
  1315. else
  1316. {
  1317. grp = &mem->group;
  1318. }
  1319. struct ClientList *cl = GNUNET_new (struct ClientList);
  1320. cl->client = client;
  1321. GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
  1322. char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
  1323. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1324. "Client connected to group %s as member %s (%s). size = %d\n",
  1325. GNUNET_h2s (&grp->pub_key_hash),
  1326. GNUNET_h2s2 (&mem->pub_key_hash),
  1327. str,
  1328. GNUNET_CONTAINER_multihashmap_size (members));
  1329. GNUNET_free (str);
  1330. if (NULL != mem->join_dcsn)
  1331. { /* Already got a join decision, send it to client. */
  1332. struct GNUNET_MQ_Envelope *
  1333. env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header);
  1334. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1335. env);
  1336. }
  1337. else
  1338. { /* First client of the group, send join request. */
  1339. struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
  1340. uint32_t relay_count = ntohl (msg->relay_count);
  1341. uint16_t relay_size = relay_count * sizeof (*relays);
  1342. struct GNUNET_MessageHeader *join_msg = NULL;
  1343. uint16_t join_msg_size = 0;
  1344. if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
  1345. <= msg_size)
  1346. {
  1347. join_msg = (struct GNUNET_MessageHeader *)
  1348. (((char *) &msg[1]) + relay_size);
  1349. join_msg_size = ntohs (join_msg->size);
  1350. }
  1351. uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
  1352. struct MulticastJoinRequestMessage *
  1353. req = GNUNET_malloc (req_msg_size);
  1354. req->header.size = htons (req_msg_size);
  1355. req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
  1356. req->group_pub_key = grp->pub_key;
  1357. req->peer = this_peer;
  1358. GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
  1359. if (0 < join_msg_size)
  1360. GNUNET_memcpy (&req[1], join_msg, join_msg_size);
  1361. req->member_pub_key = mem->pub_key;
  1362. req->purpose.size = htonl (req_msg_size
  1363. - sizeof (req->header)
  1364. - sizeof (req->reserved)
  1365. - sizeof (req->signature));
  1366. req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
  1367. if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign_ (&mem->priv_key, &req->purpose,
  1368. &req->signature))
  1369. {
  1370. /* FIXME: handle error */
  1371. GNUNET_assert (0);
  1372. }
  1373. if (NULL != mem->join_req)
  1374. GNUNET_free (mem->join_req);
  1375. mem->join_req = req;
  1376. if (0 ==
  1377. client_send_origin (&grp->pub_key_hash,
  1378. GNUNET_MQ_msg_copy (&mem->join_req->header)))
  1379. { /* No local origins, send to remote origin */
  1380. cadet_send_join_request (mem);
  1381. }
  1382. }
  1383. GNUNET_SERVICE_client_continue (client);
  1384. }
  1385. static void
  1386. client_send_join_decision (struct Member *mem,
  1387. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  1388. {
  1389. client_send_group (&mem->group, GNUNET_MQ_msg_copy (&hdcsn->header));
  1390. const struct MulticastJoinDecisionMessage *
  1391. dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
  1392. if (GNUNET_YES == ntohl (dcsn->is_admitted))
  1393. { /* Member admitted, store join_decision. */
  1394. uint16_t dcsn_size = ntohs (dcsn->header.size);
  1395. mem->join_dcsn = GNUNET_malloc (dcsn_size);
  1396. GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
  1397. }
  1398. else
  1399. { /* Refused entry, but replay would be still possible for past members. */
  1400. }
  1401. }
  1402. static int
  1403. check_client_join_decision (void *cls,
  1404. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  1405. {
  1406. return GNUNET_OK;
  1407. }
  1408. /**
  1409. * Join decision from client.
  1410. */
  1411. static void
  1412. handle_client_join_decision (void *cls,
  1413. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  1414. {
  1415. struct Client *c = cls;
  1416. struct GNUNET_SERVICE_Client *client = c->client;
  1417. struct Group *grp = c->group;
  1418. if (NULL == grp)
  1419. {
  1420. GNUNET_break (0);
  1421. GNUNET_SERVICE_client_drop (client);
  1422. return;
  1423. }
  1424. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1425. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1426. "%p got join decision from client for group %s..\n",
  1427. grp, GNUNET_h2s (&grp->pub_key_hash));
  1428. struct GNUNET_CONTAINER_MultiHashMap *
  1429. grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
  1430. &grp->pub_key_hash);
  1431. struct Member *mem = NULL;
  1432. if (NULL != grp_mem)
  1433. {
  1434. struct GNUNET_HashCode member_key_hash;
  1435. GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
  1436. &member_key_hash);
  1437. mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
  1438. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1439. "%p ..and member %s: %p\n",
  1440. grp, GNUNET_h2s (&member_key_hash), mem);
  1441. }
  1442. if (NULL != mem)
  1443. { /* Found local member */
  1444. client_send_join_decision (mem, hdcsn);
  1445. }
  1446. else
  1447. { /* Look for remote member */
  1448. cadet_send_join_decision (grp, hdcsn);
  1449. }
  1450. GNUNET_SERVICE_client_continue (client);
  1451. }
  1452. static void
  1453. handle_client_part_request (void *cls,
  1454. const struct GNUNET_MessageHeader *msg)
  1455. {
  1456. struct Client *c = cls;
  1457. struct GNUNET_SERVICE_Client *client = c->client;
  1458. struct Group *grp = c->group;
  1459. struct GNUNET_MQ_Envelope *env;
  1460. if (NULL == grp)
  1461. {
  1462. GNUNET_break (0);
  1463. GNUNET_SERVICE_client_drop (client);
  1464. return;
  1465. }
  1466. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1467. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1468. "%p got part request from client for group %s.\n",
  1469. grp, GNUNET_h2s (&grp->pub_key_hash));
  1470. grp->is_disconnected = GNUNET_YES;
  1471. env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK);
  1472. client_send_group (grp, env);
  1473. GNUNET_SERVICE_client_continue (client);
  1474. }
  1475. static int
  1476. check_client_multicast_message (void *cls,
  1477. const struct GNUNET_MULTICAST_MessageHeader *msg)
  1478. {
  1479. return GNUNET_OK;
  1480. }
  1481. /**
  1482. * Incoming message from a client.
  1483. */
  1484. static void
  1485. handle_client_multicast_message (void *cls,
  1486. const struct GNUNET_MULTICAST_MessageHeader *msg)
  1487. {
  1488. // FIXME: what if GNUNET_YES == grp->is_disconnected? Do we allow sending messages?
  1489. struct Client *c = cls;
  1490. struct GNUNET_SERVICE_Client *client = c->client;
  1491. struct Group *grp = c->group;
  1492. if (NULL == grp)
  1493. {
  1494. GNUNET_break (0);
  1495. GNUNET_SERVICE_client_drop (client);
  1496. return;
  1497. }
  1498. GNUNET_assert (GNUNET_YES == grp->is_origin);
  1499. struct Origin *orig = grp->origin;
  1500. // FIXME: use GNUNET_MQ_msg_copy
  1501. /* FIXME: yucky, should use separate message structs for P2P and CS! */
  1502. struct GNUNET_MULTICAST_MessageHeader *
  1503. out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
  1504. out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
  1505. out->purpose.size = htonl (ntohs (out->header.size)
  1506. - sizeof (out->header)
  1507. - sizeof (out->hop_counter)
  1508. - sizeof (out->signature));
  1509. out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
  1510. if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign_ (&orig->priv_key, &out->purpose,
  1511. &out->signature))
  1512. {
  1513. GNUNET_assert (0);
  1514. }
  1515. client_send_all (&grp->pub_key_hash, GNUNET_MQ_msg_copy (&out->header));
  1516. cadet_send_children (&grp->pub_key_hash, &out->header);
  1517. client_send_ack (&grp->pub_key_hash);
  1518. GNUNET_free (out);
  1519. GNUNET_SERVICE_client_continue (client);
  1520. }
  1521. static int
  1522. check_client_multicast_request (void *cls,
  1523. const struct GNUNET_MULTICAST_RequestHeader *req)
  1524. {
  1525. return GNUNET_OK;
  1526. }
  1527. /**
  1528. * Incoming request from a client.
  1529. */
  1530. static void
  1531. handle_client_multicast_request (void *cls,
  1532. const struct GNUNET_MULTICAST_RequestHeader *req)
  1533. {
  1534. struct Client *c = cls;
  1535. struct GNUNET_SERVICE_Client *client = c->client;
  1536. struct Group *grp = c->group;
  1537. if (NULL == grp)
  1538. {
  1539. GNUNET_break (0);
  1540. GNUNET_SERVICE_client_drop (client);
  1541. return;
  1542. }
  1543. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1544. GNUNET_assert (GNUNET_NO == grp->is_origin);
  1545. struct Member *mem = grp->member;
  1546. /* FIXME: yucky, should use separate message structs for P2P and CS! */
  1547. struct GNUNET_MULTICAST_RequestHeader *
  1548. out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header);
  1549. out->member_pub_key = mem->pub_key;
  1550. out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
  1551. out->purpose.size = htonl (ntohs (out->header.size)
  1552. - sizeof (out->header)
  1553. - sizeof (out->member_pub_key)
  1554. - sizeof (out->signature));
  1555. out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
  1556. if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign_ (&mem->priv_key, &out->purpose,
  1557. &out->signature))
  1558. {
  1559. GNUNET_assert (0);
  1560. }
  1561. uint8_t send_ack = GNUNET_YES;
  1562. if (0 ==
  1563. client_send_origin (&grp->pub_key_hash,
  1564. GNUNET_MQ_msg_copy (&out->header)))
  1565. { /* No local origins, send to remote origin */
  1566. if (NULL != mem->origin_channel)
  1567. {
  1568. cadet_send_channel (mem->origin_channel, &out->header);
  1569. send_ack = GNUNET_NO;
  1570. }
  1571. else
  1572. {
  1573. /* FIXME: not yet connected to origin */
  1574. GNUNET_SERVICE_client_drop (client);
  1575. GNUNET_free (out);
  1576. return;
  1577. }
  1578. }
  1579. if (GNUNET_YES == send_ack)
  1580. {
  1581. client_send_ack (&grp->pub_key_hash);
  1582. }
  1583. GNUNET_free (out);
  1584. GNUNET_SERVICE_client_continue (client);
  1585. }
  1586. /**
  1587. * Incoming replay request from a client.
  1588. */
  1589. static void
  1590. handle_client_replay_request (void *cls,
  1591. const struct MulticastReplayRequestMessage *rep)
  1592. {
  1593. struct Client *c = cls;
  1594. struct GNUNET_SERVICE_Client *client = c->client;
  1595. struct Group *grp = c->group;
  1596. if (NULL == grp)
  1597. {
  1598. GNUNET_break (0);
  1599. GNUNET_SERVICE_client_drop (client);
  1600. return;
  1601. }
  1602. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1603. GNUNET_assert (GNUNET_NO == grp->is_origin);
  1604. struct Member *mem = grp->member;
  1605. struct GNUNET_CONTAINER_MultiHashMap *
  1606. grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
  1607. &grp->pub_key_hash);
  1608. if (NULL == grp_replay_req)
  1609. {
  1610. grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1611. GNUNET_CONTAINER_multihashmap_put (replay_req_client,
  1612. &grp->pub_key_hash, grp_replay_req,
  1613. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1614. }
  1615. struct GNUNET_HashCode key_hash;
  1616. replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
  1617. rep->flags, &key_hash);
  1618. GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
  1619. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1620. if (0 ==
  1621. client_send_origin (&grp->pub_key_hash,
  1622. GNUNET_MQ_msg_copy (&rep->header)))
  1623. { /* No local origin, replay from remote members / origin. */
  1624. if (NULL != mem->origin_channel)
  1625. {
  1626. cadet_send_channel (mem->origin_channel, &rep->header);
  1627. }
  1628. else
  1629. {
  1630. /* FIXME: not yet connected to origin */
  1631. GNUNET_assert (0);
  1632. GNUNET_SERVICE_client_drop (client);
  1633. return;
  1634. }
  1635. }
  1636. GNUNET_SERVICE_client_continue (client);
  1637. }
  1638. static int
  1639. cadet_send_replay_response_cb (void *cls,
  1640. const struct GNUNET_HashCode *key_hash,
  1641. void *value)
  1642. {
  1643. struct Channel *chn = value;
  1644. struct GNUNET_MessageHeader *msg = cls;
  1645. cadet_send_channel (chn, msg);
  1646. return GNUNET_OK;
  1647. }
  1648. static int
  1649. client_send_replay_response_cb (void *cls,
  1650. const struct GNUNET_HashCode *key_hash,
  1651. void *value)
  1652. {
  1653. struct GNUNET_SERVICE_Client *client = value;
  1654. struct GNUNET_MessageHeader *msg = cls;
  1655. client_send (client, msg);
  1656. return GNUNET_OK;
  1657. }
  1658. static int
  1659. check_client_replay_response_end (void *cls,
  1660. const struct MulticastReplayResponseMessage *res)
  1661. {
  1662. return GNUNET_OK;
  1663. }
  1664. /**
  1665. * End of replay response from a client.
  1666. */
  1667. static void
  1668. handle_client_replay_response_end (void *cls,
  1669. const struct MulticastReplayResponseMessage *res)
  1670. {
  1671. struct Client *c = cls;
  1672. struct GNUNET_SERVICE_Client *client = c->client;
  1673. struct Group *grp = c->group;
  1674. if (NULL == grp)
  1675. {
  1676. GNUNET_break (0);
  1677. GNUNET_SERVICE_client_drop (client);
  1678. return;
  1679. }
  1680. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1681. struct GNUNET_HashCode key_hash;
  1682. replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
  1683. res->flags, &key_hash);
  1684. struct GNUNET_CONTAINER_MultiHashMap *
  1685. grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
  1686. &grp->pub_key_hash);
  1687. if (NULL != grp_replay_req_cadet)
  1688. {
  1689. GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
  1690. }
  1691. struct GNUNET_CONTAINER_MultiHashMap *
  1692. grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
  1693. &grp->pub_key_hash);
  1694. if (NULL != grp_replay_req_client)
  1695. {
  1696. GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
  1697. }
  1698. GNUNET_SERVICE_client_continue (client);
  1699. }
  1700. static int
  1701. check_client_replay_response (void *cls,
  1702. const struct MulticastReplayResponseMessage *res)
  1703. {
  1704. const struct GNUNET_MessageHeader *msg;
  1705. if (GNUNET_MULTICAST_REC_OK == res->error_code)
  1706. {
  1707. msg = GNUNET_MQ_extract_nested_mh (res);
  1708. if (NULL == msg)
  1709. {
  1710. return GNUNET_SYSERR;
  1711. }
  1712. }
  1713. return GNUNET_OK;
  1714. }
  1715. /**
  1716. * Incoming replay response from a client.
  1717. *
  1718. * Respond with a multicast message on success, or otherwise with an error code.
  1719. */
  1720. static void
  1721. handle_client_replay_response (void *cls,
  1722. const struct MulticastReplayResponseMessage *res)
  1723. {
  1724. struct Client *c = cls;
  1725. struct GNUNET_SERVICE_Client *client = c->client;
  1726. struct Group *grp = c->group;
  1727. if (NULL == grp)
  1728. {
  1729. GNUNET_break (0);
  1730. GNUNET_SERVICE_client_drop (client);
  1731. return;
  1732. }
  1733. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1734. const struct GNUNET_MessageHeader *msg = &res->header;
  1735. if (GNUNET_MULTICAST_REC_OK == res->error_code)
  1736. {
  1737. msg = GNUNET_MQ_extract_nested_mh (res);
  1738. }
  1739. struct GNUNET_HashCode key_hash;
  1740. replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
  1741. res->flags, &key_hash);
  1742. struct GNUNET_CONTAINER_MultiHashMap *
  1743. grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
  1744. &grp->pub_key_hash);
  1745. if (NULL != grp_replay_req_cadet)
  1746. {
  1747. GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
  1748. cadet_send_replay_response_cb,
  1749. (void *) msg);
  1750. }
  1751. if (GNUNET_MULTICAST_REC_OK == res->error_code)
  1752. {
  1753. struct GNUNET_CONTAINER_MultiHashMap *
  1754. grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
  1755. &grp->pub_key_hash);
  1756. if (NULL != grp_replay_req_client)
  1757. {
  1758. GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
  1759. client_send_replay_response_cb,
  1760. (void *) msg);
  1761. }
  1762. }
  1763. else
  1764. {
  1765. handle_client_replay_response_end (c, res);
  1766. return;
  1767. }
  1768. GNUNET_SERVICE_client_continue (client);
  1769. }
  1770. /**
  1771. * A new client connected.
  1772. *
  1773. * @param cls NULL
  1774. * @param client client to add
  1775. * @param mq message queue for @a client
  1776. * @return @a client
  1777. */
  1778. static void *
  1779. client_notify_connect (void *cls,
  1780. struct GNUNET_SERVICE_Client *client,
  1781. struct GNUNET_MQ_Handle *mq)
  1782. {
  1783. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
  1784. /* FIXME: send connect ACK */
  1785. struct Client *c = GNUNET_new (struct Client);
  1786. c->client = client;
  1787. return c;
  1788. }
  1789. /**
  1790. * Called whenever a client is disconnected.
  1791. * Frees our resources associated with that client.
  1792. *
  1793. * @param cls closure
  1794. * @param client identification of the client
  1795. * @param app_ctx must match @a client
  1796. */
  1797. static void
  1798. client_notify_disconnect (void *cls,
  1799. struct GNUNET_SERVICE_Client *client,
  1800. void *app_ctx)
  1801. {
  1802. struct Client *c = app_ctx;
  1803. struct Group *grp = c->group;
  1804. GNUNET_free (c);
  1805. if (NULL == grp)
  1806. {
  1807. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1808. "%p User context is NULL in client_disconnect()\n", grp);
  1809. GNUNET_break (0);
  1810. return;
  1811. }
  1812. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1813. "%p Client (%s) disconnected from group %s\n",
  1814. grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
  1815. GNUNET_h2s (&grp->pub_key_hash));
  1816. // FIXME (due to protocol change): here we must not remove all clients,
  1817. // only the one we were notified about!
  1818. struct ClientList *cl = grp->clients_head;
  1819. while (NULL != cl)
  1820. {
  1821. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1822. "iterating clients for group %p\n",
  1823. grp);
  1824. if (cl->client == client)
  1825. {
  1826. GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
  1827. GNUNET_free (cl);
  1828. break;
  1829. }
  1830. cl = cl->next;
  1831. }
  1832. while (GNUNET_YES == replay_req_remove_client (grp, client));
  1833. if (NULL == grp->clients_head)
  1834. { /* Last client disconnected. */
  1835. cleanup_group (grp);
  1836. }
  1837. }
  1838. /**
  1839. * Service started.
  1840. *
  1841. * @param cls closure
  1842. * @param server the initialized server
  1843. * @param cfg configuration to use
  1844. */
  1845. static void
  1846. run (void *cls,
  1847. const struct GNUNET_CONFIGURATION_Handle *c,
  1848. struct GNUNET_SERVICE_Handle *svc)
  1849. {
  1850. cfg = c;
  1851. service = svc;
  1852. GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
  1853. stats = GNUNET_STATISTICS_create ("multicast", cfg);
  1854. origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1855. members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1856. group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1857. channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1858. channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1859. replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1860. replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1861. cadet = GNUNET_CADET_connect (cfg);
  1862. GNUNET_assert (NULL != cadet);
  1863. GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
  1864. NULL);
  1865. }
  1866. /**
  1867. * Define "main" method using service macro.
  1868. */
  1869. GNUNET_SERVICE_MAIN
  1870. ("multicast",
  1871. GNUNET_SERVICE_OPTION_NONE,
  1872. &run,
  1873. &client_notify_connect,
  1874. &client_notify_disconnect,
  1875. NULL,
  1876. GNUNET_MQ_hd_fixed_size (client_origin_start,
  1877. GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
  1878. struct MulticastOriginStartMessage,
  1879. NULL),
  1880. GNUNET_MQ_hd_var_size (client_member_join,
  1881. GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN,
  1882. struct MulticastMemberJoinMessage,
  1883. NULL),
  1884. GNUNET_MQ_hd_var_size (client_join_decision,
  1885. GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
  1886. struct MulticastJoinDecisionMessageHeader,
  1887. NULL),
  1888. GNUNET_MQ_hd_fixed_size (client_part_request,
  1889. GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST,
  1890. struct GNUNET_MessageHeader,
  1891. NULL),
  1892. GNUNET_MQ_hd_var_size (client_multicast_message,
  1893. GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
  1894. struct GNUNET_MULTICAST_MessageHeader,
  1895. NULL),
  1896. GNUNET_MQ_hd_var_size (client_multicast_request,
  1897. GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
  1898. struct GNUNET_MULTICAST_RequestHeader,
  1899. NULL),
  1900. GNUNET_MQ_hd_fixed_size (client_replay_request,
  1901. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
  1902. struct MulticastReplayRequestMessage,
  1903. NULL),
  1904. GNUNET_MQ_hd_var_size (client_replay_response,
  1905. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
  1906. struct MulticastReplayResponseMessage,
  1907. NULL),
  1908. GNUNET_MQ_hd_var_size (client_replay_response_end,
  1909. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END,
  1910. struct MulticastReplayResponseMessage,
  1911. NULL));
  1912. /* end of gnunet-service-multicast.c */