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.
 
 
 
 

2235 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 "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_signatures.h"
  24. #include "gnunet_applications.h"
  25. #include "gnunet_statistics_service.h"
  26. #include "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. GNUNET_CADET_OPTION_RELIABLE,
  1134. cadet_notify_window_change,
  1135. cadet_notify_disconnect,
  1136. cadet_handlers);
  1137. GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
  1138. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1139. return chn;
  1140. }
  1141. /**
  1142. * Destroy outgoing CADET channel.
  1143. */
  1144. static void
  1145. cadet_channel_destroy (struct Channel *chn)
  1146. {
  1147. GNUNET_CADET_channel_destroy (chn->channel);
  1148. GNUNET_CONTAINER_multihashmap_remove_all (channels_out, &chn->group_pub_hash);
  1149. GNUNET_free (chn);
  1150. }
  1151. /**
  1152. * Handle a connecting client starting an origin.
  1153. */
  1154. static void
  1155. handle_client_origin_start (void *cls,
  1156. const struct MulticastOriginStartMessage *msg)
  1157. {
  1158. struct Client *c = cls;
  1159. struct GNUNET_SERVICE_Client *client = c->client;
  1160. struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
  1161. struct GNUNET_HashCode pub_key_hash;
  1162. GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
  1163. GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
  1164. struct Origin *
  1165. orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
  1166. struct Group *grp;
  1167. if (NULL == orig)
  1168. {
  1169. orig = GNUNET_new (struct Origin);
  1170. orig->priv_key = msg->group_key;
  1171. orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
  1172. grp = c->group = &orig->group;
  1173. grp->origin = orig;
  1174. grp->is_origin = GNUNET_YES;
  1175. grp->pub_key = pub_key;
  1176. grp->pub_key_hash = pub_key_hash;
  1177. grp->is_disconnected = GNUNET_NO;
  1178. GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
  1179. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1180. group_set_cadet_port_hash (grp);
  1181. struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
  1182. GNUNET_MQ_hd_var_size (cadet_message,
  1183. GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
  1184. struct GNUNET_MULTICAST_MessageHeader,
  1185. grp),
  1186. GNUNET_MQ_hd_var_size (cadet_request,
  1187. GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
  1188. struct GNUNET_MULTICAST_RequestHeader,
  1189. grp),
  1190. GNUNET_MQ_hd_var_size (cadet_join_request,
  1191. GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
  1192. struct MulticastJoinRequestMessage,
  1193. grp),
  1194. GNUNET_MQ_hd_fixed_size (cadet_replay_request,
  1195. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
  1196. struct MulticastReplayRequestMessage,
  1197. grp),
  1198. GNUNET_MQ_hd_var_size (cadet_replay_response,
  1199. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
  1200. struct MulticastReplayResponseMessage,
  1201. grp),
  1202. GNUNET_MQ_handler_end ()
  1203. };
  1204. orig->cadet_port = GNUNET_CADET_open_port (cadet,
  1205. &grp->cadet_port_hash,
  1206. cadet_notify_connect,
  1207. grp,
  1208. cadet_notify_window_change,
  1209. cadet_notify_disconnect,
  1210. cadet_handlers);
  1211. }
  1212. else
  1213. {
  1214. grp = &orig->group;
  1215. }
  1216. struct ClientList *cl = GNUNET_new (struct ClientList);
  1217. cl->client = client;
  1218. GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
  1219. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1220. "%p Client connected as origin to group %s.\n",
  1221. orig, GNUNET_h2s (&grp->pub_key_hash));
  1222. GNUNET_SERVICE_client_continue (client);
  1223. }
  1224. static int
  1225. check_client_member_join (void *cls,
  1226. const struct MulticastMemberJoinMessage *msg)
  1227. {
  1228. uint16_t msg_size = ntohs (msg->header.size);
  1229. struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
  1230. uint32_t relay_count = ntohl (msg->relay_count);
  1231. if (0 != relay_count)
  1232. {
  1233. if (UINT32_MAX / relay_count < sizeof (*relays)){
  1234. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1235. "relay_count (%lu) * sizeof (*relays) (%lu) exceeds UINT32_MAX!\n",
  1236. (unsigned long)relay_count,
  1237. sizeof (*relays));
  1238. return GNUNET_SYSERR;
  1239. }
  1240. }
  1241. uint32_t relay_size = relay_count * sizeof (*relays);
  1242. struct GNUNET_MessageHeader *join_msg = NULL;
  1243. uint16_t join_msg_size = 0;
  1244. if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
  1245. <= msg_size)
  1246. {
  1247. join_msg = (struct GNUNET_MessageHeader *)
  1248. (((char *) &msg[1]) + relay_size);
  1249. join_msg_size = ntohs (join_msg->size);
  1250. if (UINT16_MAX - join_msg_size < sizeof (struct MulticastJoinRequestMessage)){
  1251. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1252. "join_msg_size (%u) + sizeof (struct MulticastJoinRequestMessage) (%lu) exceeds UINT16_MAX!\n",
  1253. (unsigned)join_msg_size,
  1254. (unsigned long)sizeof (struct MulticastJoinRequestMessage));
  1255. return GNUNET_SYSERR;
  1256. }
  1257. }
  1258. if (msg_size != (sizeof (*msg) + relay_size + join_msg_size)){
  1259. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1260. "msg_size does not match real size of message!\n");
  1261. return GNUNET_SYSERR;
  1262. }else{
  1263. return GNUNET_OK;
  1264. }
  1265. }
  1266. /**
  1267. * Handle a connecting client joining a group.
  1268. */
  1269. static void
  1270. handle_client_member_join (void *cls,
  1271. const struct MulticastMemberJoinMessage *msg)
  1272. {
  1273. struct Client *c = cls;
  1274. struct GNUNET_SERVICE_Client *client = c->client;
  1275. uint16_t msg_size = ntohs (msg->header.size);
  1276. struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
  1277. struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
  1278. GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
  1279. GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
  1280. GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
  1281. struct GNUNET_CONTAINER_MultiHashMap *
  1282. grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
  1283. struct Member *mem = NULL;
  1284. struct Group *grp;
  1285. if (NULL != grp_mem)
  1286. {
  1287. mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
  1288. }
  1289. if (NULL == mem)
  1290. {
  1291. mem = GNUNET_new (struct Member);
  1292. mem->origin = msg->origin;
  1293. mem->priv_key = msg->member_key;
  1294. mem->pub_key = mem_pub_key;
  1295. mem->pub_key_hash = mem_pub_key_hash;
  1296. mem->max_fragment_id = 0; // FIXME
  1297. grp = c->group = &mem->group;
  1298. grp->member = mem;
  1299. grp->is_origin = GNUNET_NO;
  1300. grp->pub_key = msg->group_pub_key;
  1301. grp->pub_key_hash = pub_key_hash;
  1302. grp->is_disconnected = GNUNET_NO;
  1303. group_set_cadet_port_hash (grp);
  1304. if (NULL == grp_mem)
  1305. {
  1306. grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1307. GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
  1308. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1309. }
  1310. GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
  1311. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1312. // FIXME: should the members hash map have option UNIQUE_FAST?
  1313. GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
  1314. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1315. }
  1316. else
  1317. {
  1318. grp = &mem->group;
  1319. }
  1320. struct ClientList *cl = GNUNET_new (struct ClientList);
  1321. cl->client = client;
  1322. GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
  1323. char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
  1324. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1325. "Client connected to group %s as member %s (%s). size = %d\n",
  1326. GNUNET_h2s (&grp->pub_key_hash),
  1327. GNUNET_h2s2 (&mem->pub_key_hash),
  1328. str,
  1329. GNUNET_CONTAINER_multihashmap_size (members));
  1330. GNUNET_free (str);
  1331. if (NULL != mem->join_dcsn)
  1332. { /* Already got a join decision, send it to client. */
  1333. struct GNUNET_MQ_Envelope *
  1334. env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header);
  1335. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1336. env);
  1337. }
  1338. else
  1339. { /* First client of the group, send join request. */
  1340. struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
  1341. uint32_t relay_count = ntohl (msg->relay_count);
  1342. uint16_t relay_size = relay_count * sizeof (*relays);
  1343. struct GNUNET_MessageHeader *join_msg = NULL;
  1344. uint16_t join_msg_size = 0;
  1345. if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
  1346. <= msg_size)
  1347. {
  1348. join_msg = (struct GNUNET_MessageHeader *)
  1349. (((char *) &msg[1]) + relay_size);
  1350. join_msg_size = ntohs (join_msg->size);
  1351. }
  1352. uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
  1353. struct MulticastJoinRequestMessage *
  1354. req = GNUNET_malloc (req_msg_size);
  1355. req->header.size = htons (req_msg_size);
  1356. req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
  1357. req->group_pub_key = grp->pub_key;
  1358. req->peer = this_peer;
  1359. GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
  1360. if (0 < join_msg_size)
  1361. GNUNET_memcpy (&req[1], join_msg, join_msg_size);
  1362. req->member_pub_key = mem->pub_key;
  1363. req->purpose.size = htonl (req_msg_size
  1364. - sizeof (req->header)
  1365. - sizeof (req->reserved)
  1366. - sizeof (req->signature));
  1367. req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
  1368. if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
  1369. &req->signature))
  1370. {
  1371. /* FIXME: handle error */
  1372. GNUNET_assert (0);
  1373. }
  1374. if (NULL != mem->join_req)
  1375. GNUNET_free (mem->join_req);
  1376. mem->join_req = req;
  1377. if (0 ==
  1378. client_send_origin (&grp->pub_key_hash,
  1379. GNUNET_MQ_msg_copy (&mem->join_req->header)))
  1380. { /* No local origins, send to remote origin */
  1381. cadet_send_join_request (mem);
  1382. }
  1383. }
  1384. GNUNET_SERVICE_client_continue (client);
  1385. }
  1386. static void
  1387. client_send_join_decision (struct Member *mem,
  1388. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  1389. {
  1390. client_send_group (&mem->group, GNUNET_MQ_msg_copy (&hdcsn->header));
  1391. const struct MulticastJoinDecisionMessage *
  1392. dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
  1393. if (GNUNET_YES == ntohl (dcsn->is_admitted))
  1394. { /* Member admitted, store join_decision. */
  1395. uint16_t dcsn_size = ntohs (dcsn->header.size);
  1396. mem->join_dcsn = GNUNET_malloc (dcsn_size);
  1397. GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
  1398. }
  1399. else
  1400. { /* Refused entry, but replay would be still possible for past members. */
  1401. }
  1402. }
  1403. static int
  1404. check_client_join_decision (void *cls,
  1405. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  1406. {
  1407. return GNUNET_OK;
  1408. }
  1409. /**
  1410. * Join decision from client.
  1411. */
  1412. static void
  1413. handle_client_join_decision (void *cls,
  1414. const struct MulticastJoinDecisionMessageHeader *hdcsn)
  1415. {
  1416. struct Client *c = cls;
  1417. struct GNUNET_SERVICE_Client *client = c->client;
  1418. struct Group *grp = c->group;
  1419. if (NULL == grp)
  1420. {
  1421. GNUNET_break (0);
  1422. GNUNET_SERVICE_client_drop (client);
  1423. return;
  1424. }
  1425. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1426. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1427. "%p got join decision from client for group %s..\n",
  1428. grp, GNUNET_h2s (&grp->pub_key_hash));
  1429. struct GNUNET_CONTAINER_MultiHashMap *
  1430. grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
  1431. &grp->pub_key_hash);
  1432. struct Member *mem = NULL;
  1433. if (NULL != grp_mem)
  1434. {
  1435. struct GNUNET_HashCode member_key_hash;
  1436. GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
  1437. &member_key_hash);
  1438. mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
  1439. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1440. "%p ..and member %s: %p\n",
  1441. grp, GNUNET_h2s (&member_key_hash), mem);
  1442. }
  1443. if (NULL != mem)
  1444. { /* Found local member */
  1445. client_send_join_decision (mem, hdcsn);
  1446. }
  1447. else
  1448. { /* Look for remote member */
  1449. cadet_send_join_decision (grp, hdcsn);
  1450. }
  1451. GNUNET_SERVICE_client_continue (client);
  1452. }
  1453. static void
  1454. handle_client_part_request (void *cls,
  1455. const struct GNUNET_MessageHeader *msg)
  1456. {
  1457. struct Client *c = cls;
  1458. struct GNUNET_SERVICE_Client *client = c->client;
  1459. struct Group *grp = c->group;
  1460. struct GNUNET_MQ_Envelope *env;
  1461. if (NULL == grp)
  1462. {
  1463. GNUNET_break (0);
  1464. GNUNET_SERVICE_client_drop (client);
  1465. return;
  1466. }
  1467. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1468. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1469. "%p got part request from client for group %s.\n",
  1470. grp, GNUNET_h2s (&grp->pub_key_hash));
  1471. grp->is_disconnected = GNUNET_YES;
  1472. env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK);
  1473. client_send_group (grp, env);
  1474. GNUNET_SERVICE_client_continue (client);
  1475. }
  1476. static int
  1477. check_client_multicast_message (void *cls,
  1478. const struct GNUNET_MULTICAST_MessageHeader *msg)
  1479. {
  1480. return GNUNET_OK;
  1481. }
  1482. /**
  1483. * Incoming message from a client.
  1484. */
  1485. static void
  1486. handle_client_multicast_message (void *cls,
  1487. const struct GNUNET_MULTICAST_MessageHeader *msg)
  1488. {
  1489. // FIXME: what if GNUNET_YES == grp->is_disconnected? Do we allow sending messages?
  1490. struct Client *c = cls;
  1491. struct GNUNET_SERVICE_Client *client = c->client;
  1492. struct Group *grp = c->group;
  1493. if (NULL == grp)
  1494. {
  1495. GNUNET_break (0);
  1496. GNUNET_SERVICE_client_drop (client);
  1497. return;
  1498. }
  1499. GNUNET_assert (GNUNET_YES == grp->is_origin);
  1500. struct Origin *orig = grp->origin;
  1501. // FIXME: use GNUNET_MQ_msg_copy
  1502. /* FIXME: yucky, should use separate message structs for P2P and CS! */
  1503. struct GNUNET_MULTICAST_MessageHeader *
  1504. out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
  1505. out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
  1506. out->purpose.size = htonl (ntohs (out->header.size)
  1507. - sizeof (out->header)
  1508. - sizeof (out->hop_counter)
  1509. - sizeof (out->signature));
  1510. out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
  1511. if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
  1512. &out->signature))
  1513. {
  1514. GNUNET_assert (0);
  1515. }
  1516. client_send_all (&grp->pub_key_hash, GNUNET_MQ_msg_copy (&out->header));
  1517. cadet_send_children (&grp->pub_key_hash, &out->header);
  1518. client_send_ack (&grp->pub_key_hash);
  1519. GNUNET_free (out);
  1520. GNUNET_SERVICE_client_continue (client);
  1521. }
  1522. static int
  1523. check_client_multicast_request (void *cls,
  1524. const struct GNUNET_MULTICAST_RequestHeader *req)
  1525. {
  1526. return GNUNET_OK;
  1527. }
  1528. /**
  1529. * Incoming request from a client.
  1530. */
  1531. static void
  1532. handle_client_multicast_request (void *cls,
  1533. const struct GNUNET_MULTICAST_RequestHeader *req)
  1534. {
  1535. struct Client *c = cls;
  1536. struct GNUNET_SERVICE_Client *client = c->client;
  1537. struct Group *grp = c->group;
  1538. if (NULL == grp)
  1539. {
  1540. GNUNET_break (0);
  1541. GNUNET_SERVICE_client_drop (client);
  1542. return;
  1543. }
  1544. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1545. GNUNET_assert (GNUNET_NO == grp->is_origin);
  1546. struct Member *mem = grp->member;
  1547. /* FIXME: yucky, should use separate message structs for P2P and CS! */
  1548. struct GNUNET_MULTICAST_RequestHeader *
  1549. out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header);
  1550. out->member_pub_key = mem->pub_key;
  1551. out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
  1552. out->purpose.size = htonl (ntohs (out->header.size)
  1553. - sizeof (out->header)
  1554. - sizeof (out->member_pub_key)
  1555. - sizeof (out->signature));
  1556. out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
  1557. if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
  1558. &out->signature))
  1559. {
  1560. GNUNET_assert (0);
  1561. }
  1562. uint8_t send_ack = GNUNET_YES;
  1563. if (0 ==
  1564. client_send_origin (&grp->pub_key_hash,
  1565. GNUNET_MQ_msg_copy (&out->header)))
  1566. { /* No local origins, send to remote origin */
  1567. if (NULL != mem->origin_channel)
  1568. {
  1569. cadet_send_channel (mem->origin_channel, &out->header);
  1570. send_ack = GNUNET_NO;
  1571. }
  1572. else
  1573. {
  1574. /* FIXME: not yet connected to origin */
  1575. GNUNET_SERVICE_client_drop (client);
  1576. GNUNET_free (out);
  1577. return;
  1578. }
  1579. }
  1580. if (GNUNET_YES == send_ack)
  1581. {
  1582. client_send_ack (&grp->pub_key_hash);
  1583. }
  1584. GNUNET_free (out);
  1585. GNUNET_SERVICE_client_continue (client);
  1586. }
  1587. /**
  1588. * Incoming replay request from a client.
  1589. */
  1590. static void
  1591. handle_client_replay_request (void *cls,
  1592. const struct MulticastReplayRequestMessage *rep)
  1593. {
  1594. struct Client *c = cls;
  1595. struct GNUNET_SERVICE_Client *client = c->client;
  1596. struct Group *grp = c->group;
  1597. if (NULL == grp)
  1598. {
  1599. GNUNET_break (0);
  1600. GNUNET_SERVICE_client_drop (client);
  1601. return;
  1602. }
  1603. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1604. GNUNET_assert (GNUNET_NO == grp->is_origin);
  1605. struct Member *mem = grp->member;
  1606. struct GNUNET_CONTAINER_MultiHashMap *
  1607. grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
  1608. &grp->pub_key_hash);
  1609. if (NULL == grp_replay_req)
  1610. {
  1611. grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1612. GNUNET_CONTAINER_multihashmap_put (replay_req_client,
  1613. &grp->pub_key_hash, grp_replay_req,
  1614. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  1615. }
  1616. struct GNUNET_HashCode key_hash;
  1617. replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
  1618. rep->flags, &key_hash);
  1619. GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
  1620. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1621. if (0 ==
  1622. client_send_origin (&grp->pub_key_hash,
  1623. GNUNET_MQ_msg_copy (&rep->header)))
  1624. { /* No local origin, replay from remote members / origin. */
  1625. if (NULL != mem->origin_channel)
  1626. {
  1627. cadet_send_channel (mem->origin_channel, &rep->header);
  1628. }
  1629. else
  1630. {
  1631. /* FIXME: not yet connected to origin */
  1632. GNUNET_assert (0);
  1633. GNUNET_SERVICE_client_drop (client);
  1634. return;
  1635. }
  1636. }
  1637. GNUNET_SERVICE_client_continue (client);
  1638. }
  1639. static int
  1640. cadet_send_replay_response_cb (void *cls,
  1641. const struct GNUNET_HashCode *key_hash,
  1642. void *value)
  1643. {
  1644. struct Channel *chn = value;
  1645. struct GNUNET_MessageHeader *msg = cls;
  1646. cadet_send_channel (chn, msg);
  1647. return GNUNET_OK;
  1648. }
  1649. static int
  1650. client_send_replay_response_cb (void *cls,
  1651. const struct GNUNET_HashCode *key_hash,
  1652. void *value)
  1653. {
  1654. struct GNUNET_SERVICE_Client *client = value;
  1655. struct GNUNET_MessageHeader *msg = cls;
  1656. client_send (client, msg);
  1657. return GNUNET_OK;
  1658. }
  1659. static int
  1660. check_client_replay_response_end (void *cls,
  1661. const struct MulticastReplayResponseMessage *res)
  1662. {
  1663. return GNUNET_OK;
  1664. }
  1665. /**
  1666. * End of replay response from a client.
  1667. */
  1668. static void
  1669. handle_client_replay_response_end (void *cls,
  1670. const struct MulticastReplayResponseMessage *res)
  1671. {
  1672. struct Client *c = cls;
  1673. struct GNUNET_SERVICE_Client *client = c->client;
  1674. struct Group *grp = c->group;
  1675. if (NULL == grp)
  1676. {
  1677. GNUNET_break (0);
  1678. GNUNET_SERVICE_client_drop (client);
  1679. return;
  1680. }
  1681. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1682. struct GNUNET_HashCode key_hash;
  1683. replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
  1684. res->flags, &key_hash);
  1685. struct GNUNET_CONTAINER_MultiHashMap *
  1686. grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
  1687. &grp->pub_key_hash);
  1688. if (NULL != grp_replay_req_cadet)
  1689. {
  1690. GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
  1691. }
  1692. struct GNUNET_CONTAINER_MultiHashMap *
  1693. grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
  1694. &grp->pub_key_hash);
  1695. if (NULL != grp_replay_req_client)
  1696. {
  1697. GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
  1698. }
  1699. GNUNET_SERVICE_client_continue (client);
  1700. }
  1701. static int
  1702. check_client_replay_response (void *cls,
  1703. const struct MulticastReplayResponseMessage *res)
  1704. {
  1705. const struct GNUNET_MessageHeader *msg;
  1706. if (GNUNET_MULTICAST_REC_OK == res->error_code)
  1707. {
  1708. msg = GNUNET_MQ_extract_nested_mh (res);
  1709. if (NULL == msg)
  1710. {
  1711. return GNUNET_SYSERR;
  1712. }
  1713. }
  1714. return GNUNET_OK;
  1715. }
  1716. /**
  1717. * Incoming replay response from a client.
  1718. *
  1719. * Respond with a multicast message on success, or otherwise with an error code.
  1720. */
  1721. static void
  1722. handle_client_replay_response (void *cls,
  1723. const struct MulticastReplayResponseMessage *res)
  1724. {
  1725. struct Client *c = cls;
  1726. struct GNUNET_SERVICE_Client *client = c->client;
  1727. struct Group *grp = c->group;
  1728. if (NULL == grp)
  1729. {
  1730. GNUNET_break (0);
  1731. GNUNET_SERVICE_client_drop (client);
  1732. return;
  1733. }
  1734. GNUNET_assert (GNUNET_NO == grp->is_disconnected);
  1735. const struct GNUNET_MessageHeader *msg = &res->header;
  1736. if (GNUNET_MULTICAST_REC_OK == res->error_code)
  1737. {
  1738. msg = GNUNET_MQ_extract_nested_mh (res);
  1739. }
  1740. struct GNUNET_HashCode key_hash;
  1741. replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
  1742. res->flags, &key_hash);
  1743. struct GNUNET_CONTAINER_MultiHashMap *
  1744. grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
  1745. &grp->pub_key_hash);
  1746. if (NULL != grp_replay_req_cadet)
  1747. {
  1748. GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
  1749. cadet_send_replay_response_cb,
  1750. (void *) msg);
  1751. }
  1752. if (GNUNET_MULTICAST_REC_OK == res->error_code)
  1753. {
  1754. struct GNUNET_CONTAINER_MultiHashMap *
  1755. grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
  1756. &grp->pub_key_hash);
  1757. if (NULL != grp_replay_req_client)
  1758. {
  1759. GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
  1760. client_send_replay_response_cb,
  1761. (void *) msg);
  1762. }
  1763. }
  1764. else
  1765. {
  1766. handle_client_replay_response_end (c, res);
  1767. return;
  1768. }
  1769. GNUNET_SERVICE_client_continue (client);
  1770. }
  1771. /**
  1772. * A new client connected.
  1773. *
  1774. * @param cls NULL
  1775. * @param client client to add
  1776. * @param mq message queue for @a client
  1777. * @return @a client
  1778. */
  1779. static void *
  1780. client_notify_connect (void *cls,
  1781. struct GNUNET_SERVICE_Client *client,
  1782. struct GNUNET_MQ_Handle *mq)
  1783. {
  1784. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
  1785. /* FIXME: send connect ACK */
  1786. struct Client *c = GNUNET_new (struct Client);
  1787. c->client = client;
  1788. return c;
  1789. }
  1790. /**
  1791. * Called whenever a client is disconnected.
  1792. * Frees our resources associated with that client.
  1793. *
  1794. * @param cls closure
  1795. * @param client identification of the client
  1796. * @param app_ctx must match @a client
  1797. */
  1798. static void
  1799. client_notify_disconnect (void *cls,
  1800. struct GNUNET_SERVICE_Client *client,
  1801. void *app_ctx)
  1802. {
  1803. struct Client *c = app_ctx;
  1804. struct Group *grp = c->group;
  1805. GNUNET_free (c);
  1806. if (NULL == grp)
  1807. {
  1808. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1809. "%p User context is NULL in client_disconnect()\n", grp);
  1810. GNUNET_break (0);
  1811. return;
  1812. }
  1813. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1814. "%p Client (%s) disconnected from group %s\n",
  1815. grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
  1816. GNUNET_h2s (&grp->pub_key_hash));
  1817. // FIXME (due to protocol change): here we must not remove all clients,
  1818. // only the one we were notified about!
  1819. struct ClientList *cl = grp->clients_head;
  1820. while (NULL != cl)
  1821. {
  1822. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1823. "iterating clients for group %p\n",
  1824. grp);
  1825. if (cl->client == client)
  1826. {
  1827. GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
  1828. GNUNET_free (cl);
  1829. break;
  1830. }
  1831. cl = cl->next;
  1832. }
  1833. while (GNUNET_YES == replay_req_remove_client (grp, client));
  1834. if (NULL == grp->clients_head)
  1835. { /* Last client disconnected. */
  1836. cleanup_group (grp);
  1837. }
  1838. }
  1839. /**
  1840. * Service started.
  1841. *
  1842. * @param cls closure
  1843. * @param server the initialized server
  1844. * @param cfg configuration to use
  1845. */
  1846. static void
  1847. run (void *cls,
  1848. const struct GNUNET_CONFIGURATION_Handle *c,
  1849. struct GNUNET_SERVICE_Handle *svc)
  1850. {
  1851. cfg = c;
  1852. service = svc;
  1853. GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
  1854. stats = GNUNET_STATISTICS_create ("multicast", cfg);
  1855. origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1856. members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1857. group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1858. channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1859. channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1860. replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1861. replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1862. cadet = GNUNET_CADET_connect (cfg);
  1863. GNUNET_assert (NULL != cadet);
  1864. GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
  1865. NULL);
  1866. }
  1867. /**
  1868. * Define "main" method using service macro.
  1869. */
  1870. GNUNET_SERVICE_MAIN
  1871. ("multicast",
  1872. GNUNET_SERVICE_OPTION_NONE,
  1873. &run,
  1874. &client_notify_connect,
  1875. &client_notify_disconnect,
  1876. NULL,
  1877. GNUNET_MQ_hd_fixed_size (client_origin_start,
  1878. GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
  1879. struct MulticastOriginStartMessage,
  1880. NULL),
  1881. GNUNET_MQ_hd_var_size (client_member_join,
  1882. GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN,
  1883. struct MulticastMemberJoinMessage,
  1884. NULL),
  1885. GNUNET_MQ_hd_var_size (client_join_decision,
  1886. GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
  1887. struct MulticastJoinDecisionMessageHeader,
  1888. NULL),
  1889. GNUNET_MQ_hd_fixed_size (client_part_request,
  1890. GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST,
  1891. struct GNUNET_MessageHeader,
  1892. NULL),
  1893. GNUNET_MQ_hd_var_size (client_multicast_message,
  1894. GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
  1895. struct GNUNET_MULTICAST_MessageHeader,
  1896. NULL),
  1897. GNUNET_MQ_hd_var_size (client_multicast_request,
  1898. GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
  1899. struct GNUNET_MULTICAST_RequestHeader,
  1900. NULL),
  1901. GNUNET_MQ_hd_fixed_size (client_replay_request,
  1902. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
  1903. struct MulticastReplayRequestMessage,
  1904. NULL),
  1905. GNUNET_MQ_hd_var_size (client_replay_response,
  1906. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
  1907. struct MulticastReplayResponseMessage,
  1908. NULL),
  1909. GNUNET_MQ_hd_var_size (client_replay_response_end,
  1910. GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END,
  1911. struct MulticastReplayResponseMessage,
  1912. NULL));
  1913. /* end of gnunet-service-multicast.c */