multicast_api.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2012, 2013 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. 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. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file multicast/multicast_api.c
  19. * @brief Multicast service; implements multicast groups using CADET connections.
  20. * @author Christian Grothoff
  21. * @author Gabor X Toth
  22. */
  23. #include "platform.h"
  24. #include "gnunet_util_lib.h"
  25. #include "gnunet_multicast_service.h"
  26. #include "multicast.h"
  27. #define LOG(kind,...) GNUNET_log_from (kind, "multicast-api",__VA_ARGS__)
  28. /**
  29. * Handle for a request to send a message to all multicast group members
  30. * (from the origin).
  31. */
  32. struct GNUNET_MULTICAST_OriginTransmitHandle
  33. {
  34. GNUNET_MULTICAST_OriginTransmitNotify notify;
  35. void *notify_cls;
  36. struct GNUNET_MULTICAST_Origin *origin;
  37. uint64_t message_id;
  38. uint64_t group_generation;
  39. uint64_t fragment_offset;
  40. };
  41. /**
  42. * Handle for a message to be delivered from a member to the origin.
  43. */
  44. struct GNUNET_MULTICAST_MemberTransmitHandle
  45. {
  46. GNUNET_MULTICAST_MemberTransmitNotify notify;
  47. void *notify_cls;
  48. struct GNUNET_MULTICAST_Member *member;
  49. uint64_t request_id;
  50. uint64_t fragment_offset;
  51. };
  52. struct GNUNET_MULTICAST_Group
  53. {
  54. /**
  55. * Configuration to use.
  56. */
  57. const struct GNUNET_CONFIGURATION_Handle *cfg;
  58. /**
  59. * Client connection to the service.
  60. */
  61. struct GNUNET_CLIENT_MANAGER_Connection *client;
  62. /**
  63. * Message to send on reconnect.
  64. */
  65. struct GNUNET_MessageHeader *connect_msg;
  66. GNUNET_MULTICAST_JoinRequestCallback join_req_cb;
  67. GNUNET_MULTICAST_MembershipTestCallback member_test_cb;
  68. GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb;
  69. GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb;
  70. GNUNET_MULTICAST_MessageCallback message_cb;
  71. void *cb_cls;
  72. /**
  73. * Function called after disconnected from the service.
  74. */
  75. GNUNET_ContinuationCallback disconnect_cb;
  76. /**
  77. * Closure for @a disconnect_cb.
  78. */
  79. void *disconnect_cls;
  80. /**
  81. * Are we currently transmitting a message?
  82. */
  83. uint8_t in_transmit;
  84. /**
  85. * Is this the origin or a member?
  86. */
  87. uint8_t is_origin;
  88. /**
  89. * Is this channel in the process of disconnecting from the service?
  90. * #GNUNET_YES or #GNUNET_NO
  91. */
  92. uint8_t is_disconnecting;
  93. };
  94. /**
  95. * Handle for the origin of a multicast group.
  96. */
  97. struct GNUNET_MULTICAST_Origin
  98. {
  99. struct GNUNET_MULTICAST_Group grp;
  100. struct GNUNET_MULTICAST_OriginTransmitHandle tmit;
  101. GNUNET_MULTICAST_RequestCallback request_cb;
  102. };
  103. /**
  104. * Handle for a multicast group member.
  105. */
  106. struct GNUNET_MULTICAST_Member
  107. {
  108. struct GNUNET_MULTICAST_Group grp;
  109. struct GNUNET_MULTICAST_MemberTransmitHandle tmit;
  110. GNUNET_MULTICAST_JoinDecisionCallback join_dcsn_cb;
  111. uint64_t next_fragment_id;
  112. };
  113. /**
  114. * Handle that identifies a join request.
  115. *
  116. * Used to match calls to #GNUNET_MULTICAST_JoinCallback to the
  117. * corresponding calls to #GNUNET_MULTICAST_join_decision().
  118. */
  119. struct GNUNET_MULTICAST_JoinHandle
  120. {
  121. struct GNUNET_MULTICAST_Group *group;
  122. /**
  123. * Public key of the member requesting join.
  124. */
  125. struct GNUNET_CRYPTO_EcdsaPublicKey member_key;
  126. /**
  127. * Peer identity of the member requesting join.
  128. */
  129. struct GNUNET_PeerIdentity peer;
  130. };
  131. /**
  132. * Handle to pass back for the answer of a membership test.
  133. */
  134. struct GNUNET_MULTICAST_MembershipTestHandle
  135. {
  136. };
  137. /**
  138. * Opaque handle to a replay request from the multicast service.
  139. */
  140. struct GNUNET_MULTICAST_ReplayHandle
  141. {
  142. };
  143. /**
  144. * Handle for a replay request.
  145. */
  146. struct GNUNET_MULTICAST_MemberReplayHandle
  147. {
  148. };
  149. /**
  150. * Send first message to the service after connecting.
  151. */
  152. static void
  153. group_send_connect_msg (struct GNUNET_MULTICAST_Group *grp)
  154. {
  155. uint16_t cmsg_size = ntohs (grp->connect_msg->size);
  156. struct GNUNET_MessageHeader * cmsg = GNUNET_malloc (cmsg_size);
  157. memcpy (cmsg, grp->connect_msg, cmsg_size);
  158. GNUNET_CLIENT_MANAGER_transmit_now (grp->client, cmsg);
  159. }
  160. /**
  161. * Got disconnected from service. Reconnect.
  162. */
  163. static void
  164. group_recv_disconnect (void *cls,
  165. struct GNUNET_CLIENT_MANAGER_Connection *client,
  166. const struct GNUNET_MessageHeader *msg)
  167. {
  168. struct GNUNET_MULTICAST_Group *
  169. grp = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*grp));
  170. GNUNET_CLIENT_MANAGER_reconnect (client);
  171. group_send_connect_msg (grp);
  172. }
  173. /**
  174. * Receive join request from service.
  175. */
  176. static void
  177. group_recv_join_request (void *cls,
  178. struct GNUNET_CLIENT_MANAGER_Connection *client,
  179. const struct GNUNET_MessageHeader *msg)
  180. {
  181. struct GNUNET_MULTICAST_Group *
  182. grp = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*grp));
  183. const struct MulticastJoinRequestMessage *
  184. jreq = (const struct MulticastJoinRequestMessage *) msg;
  185. struct GNUNET_MULTICAST_JoinHandle *jh = GNUNET_malloc (sizeof (*jh));
  186. jh->group = grp;
  187. jh->member_key = jreq->member_key;
  188. jh->peer = jreq->peer;
  189. const struct GNUNET_MessageHeader *jmsg = NULL;
  190. if (sizeof (*jreq) + sizeof (*jmsg) <= ntohs (jreq->header.size))
  191. jmsg = (const struct GNUNET_MessageHeader *) &jreq[1];
  192. if (NULL != grp->join_req_cb)
  193. grp->join_req_cb (grp->cb_cls, &jreq->member_key, jmsg, jh);
  194. }
  195. /**
  196. * Receive multicast message from service.
  197. */
  198. static void
  199. group_recv_message (void *cls,
  200. struct GNUNET_CLIENT_MANAGER_Connection *client,
  201. const struct GNUNET_MessageHeader *msg)
  202. {
  203. struct GNUNET_MULTICAST_Group *
  204. grp = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*grp));
  205. struct GNUNET_MULTICAST_MessageHeader *
  206. mmsg = (struct GNUNET_MULTICAST_MessageHeader *) msg;
  207. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  208. "Calling message callback with a message of size %u.\n",
  209. ntohs (mmsg->header.size));
  210. if (NULL != grp->message_cb)
  211. grp->message_cb (grp->cb_cls, mmsg);
  212. }
  213. /**
  214. * Origin receives uniquest request from a member.
  215. */
  216. static void
  217. origin_recv_request (void *cls,
  218. struct GNUNET_CLIENT_MANAGER_Connection *client,
  219. const struct GNUNET_MessageHeader *msg)
  220. {
  221. struct GNUNET_MULTICAST_Group *grp;
  222. struct GNUNET_MULTICAST_Origin *
  223. orig = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*grp));
  224. grp = &orig->grp;
  225. struct GNUNET_MULTICAST_RequestHeader *
  226. req = (struct GNUNET_MULTICAST_RequestHeader *) msg;
  227. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  228. "Calling request callback with a request of size %u.\n",
  229. ntohs (req->header.size));
  230. if (NULL != orig->request_cb)
  231. orig->request_cb (grp->cb_cls, req);
  232. }
  233. /**
  234. * Member receives join decision.
  235. */
  236. static void
  237. member_recv_join_decision (void *cls,
  238. struct GNUNET_CLIENT_MANAGER_Connection *client,
  239. const struct GNUNET_MessageHeader *msg)
  240. {
  241. struct GNUNET_MULTICAST_Group *grp;
  242. struct GNUNET_MULTICAST_Member *
  243. mem = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*grp));
  244. grp = &mem->grp;
  245. const struct MulticastJoinDecisionMessageHeader *
  246. hdcsn = (const struct MulticastJoinDecisionMessageHeader *) msg;
  247. const struct MulticastJoinDecisionMessage *
  248. dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
  249. uint16_t dcsn_size = ntohs (dcsn->header.size);
  250. int is_admitted = ntohl (dcsn->is_admitted);
  251. LOG (GNUNET_ERROR_TYPE_DEBUG,
  252. "%p Member got join decision from multicast: %d\n",
  253. mem, is_admitted);
  254. const struct GNUNET_MessageHeader *join_resp = NULL;
  255. uint16_t join_resp_size = 0;
  256. uint16_t relay_count = ntohl (dcsn->relay_count);
  257. const struct GNUNET_PeerIdentity *relays = NULL;
  258. uint16_t relay_size = relay_count * sizeof (*relays);
  259. if (0 < relay_count && dcsn_size < sizeof (*dcsn) + relay_size)
  260. relays = (struct GNUNET_PeerIdentity *) &dcsn[1];
  261. if (sizeof (*dcsn) + relay_size + sizeof (*join_resp) <= dcsn_size)
  262. {
  263. join_resp = (const struct GNUNET_MessageHeader *) &dcsn[1];
  264. join_resp_size = ntohs (join_resp->size);
  265. }
  266. if (dcsn_size < sizeof (*dcsn) + relay_size + join_resp_size)
  267. {
  268. LOG (GNUNET_ERROR_TYPE_DEBUG,
  269. "Received invalid join decision message from multicast.\n");
  270. GNUNET_break_op (0);
  271. is_admitted = GNUNET_SYSERR;
  272. }
  273. if (NULL != mem->join_dcsn_cb)
  274. mem->join_dcsn_cb (grp->cb_cls, is_admitted, &hdcsn->peer,
  275. relay_count, relays, join_resp);
  276. // FIXME:
  277. //if (GNUNET_YES != is_admitted)
  278. // GNUNET_MULTICAST_member_part (mem);
  279. }
  280. /**
  281. * Message handlers for an origin.
  282. */
  283. static struct GNUNET_CLIENT_MANAGER_MessageHandler origin_handlers[] =
  284. {
  285. { &group_recv_disconnect, NULL, 0, 0, GNUNET_NO },
  286. { &group_recv_message, NULL,
  287. GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
  288. sizeof (struct GNUNET_MULTICAST_MessageHeader), GNUNET_YES },
  289. { &origin_recv_request, NULL,
  290. GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
  291. sizeof (struct GNUNET_MULTICAST_RequestHeader), GNUNET_YES },
  292. { &group_recv_join_request, NULL,
  293. GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
  294. sizeof (struct MulticastJoinRequestMessage), GNUNET_YES },
  295. { NULL, NULL, 0, 0, GNUNET_NO }
  296. };
  297. /**
  298. * Message handlers for a member.
  299. */
  300. static struct GNUNET_CLIENT_MANAGER_MessageHandler member_handlers[] =
  301. {
  302. { &group_recv_disconnect, NULL, 0, 0, GNUNET_NO },
  303. { &group_recv_message, NULL,
  304. GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
  305. sizeof (struct GNUNET_MULTICAST_MessageHeader), GNUNET_YES },
  306. { &group_recv_join_request, NULL,
  307. GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
  308. sizeof (struct MulticastJoinRequestMessage), GNUNET_YES },
  309. { &member_recv_join_decision, NULL,
  310. GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
  311. sizeof (struct MulticastJoinDecisionMessage), GNUNET_YES },
  312. { NULL, NULL, 0, 0, GNUNET_NO }
  313. };
  314. static void
  315. group_cleanup (struct GNUNET_MULTICAST_Group *grp)
  316. {
  317. GNUNET_free (grp->connect_msg);
  318. if (NULL != grp->disconnect_cb)
  319. grp->disconnect_cb (grp->disconnect_cls);
  320. }
  321. static void
  322. origin_cleanup (void *cls)
  323. {
  324. struct GNUNET_MULTICAST_Origin *orig = cls;
  325. group_cleanup (&orig->grp);
  326. GNUNET_free (orig);
  327. }
  328. static void
  329. member_cleanup (void *cls)
  330. {
  331. struct GNUNET_MULTICAST_Member *mem = cls;
  332. group_cleanup (&mem->grp);
  333. GNUNET_free (mem);
  334. }
  335. /**
  336. * Function to call with the decision made for a join request.
  337. *
  338. * Must be called once and only once in response to an invocation of the
  339. * #GNUNET_MULTICAST_JoinRequestCallback.
  340. *
  341. * @param join Join request handle.
  342. * @param is_admitted #GNUNET_YES if the join is approved,
  343. * #GNUNET_NO if it is disapproved,
  344. * #GNUNET_SYSERR if we cannot answer the request.
  345. * @param relay_count Number of relays given.
  346. * @param relays Array of suggested peers that might be useful relays to use
  347. * when joining the multicast group (essentially a list of peers that
  348. * are already part of the multicast group and might thus be willing
  349. * to help with routing). If empty, only this local peer (which must
  350. * be the multicast origin) is a good candidate for building the
  351. * multicast tree. Note that it is unnecessary to specify our own
  352. * peer identity in this array.
  353. * @param join_resp Message to send in response to the joining peer;
  354. * can also be used to redirect the peer to a different group at the
  355. * application layer; this response is to be transmitted to the
  356. * peer that issued the request even if admission is denied.
  357. */
  358. struct GNUNET_MULTICAST_ReplayHandle *
  359. GNUNET_MULTICAST_join_decision (struct GNUNET_MULTICAST_JoinHandle *join,
  360. int is_admitted,
  361. uint16_t relay_count,
  362. const struct GNUNET_PeerIdentity *relays,
  363. const struct GNUNET_MessageHeader *join_resp)
  364. {
  365. struct GNUNET_MULTICAST_Group *grp = join->group;
  366. uint16_t join_resp_size = (NULL != join_resp) ? ntohs (join_resp->size) : 0;
  367. uint16_t relay_size = relay_count * sizeof (*relays);
  368. struct MulticastJoinDecisionMessageHeader * hdcsn;
  369. struct MulticastJoinDecisionMessage *dcsn;
  370. hdcsn = GNUNET_malloc (sizeof (*hdcsn) + sizeof (*dcsn)
  371. + relay_size + join_resp_size);
  372. hdcsn->header.size = htons (sizeof (*hdcsn) + sizeof (*dcsn)
  373. + relay_size + join_resp_size);
  374. hdcsn->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION);
  375. hdcsn->member_key = join->member_key;
  376. hdcsn->peer = join->peer;
  377. dcsn = (struct MulticastJoinDecisionMessage *) &hdcsn[1];
  378. dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION);
  379. dcsn->header.size = htons (sizeof (*dcsn) + relay_size + join_resp_size);
  380. dcsn->is_admitted = htonl (is_admitted);
  381. dcsn->relay_count = htonl (relay_count);
  382. if (0 < relay_size)
  383. memcpy (&dcsn[1], relays, relay_size);
  384. if (0 < join_resp_size)
  385. memcpy (((char *) &dcsn[1]) + relay_size, join_resp, join_resp_size);
  386. GNUNET_CLIENT_MANAGER_transmit (grp->client, &hdcsn->header);
  387. GNUNET_free (join);
  388. return NULL;
  389. }
  390. /**
  391. * Call informing multicast about the decision taken for a membership test.
  392. *
  393. * @param mth Handle that was given for the query.
  394. * @param result #GNUNET_YES if peer was a member, #GNUNET_NO if peer was not a member,
  395. * #GNUNET_SYSERR if we cannot answer the membership test.
  396. */
  397. void
  398. GNUNET_MULTICAST_membership_test_result (struct GNUNET_MULTICAST_MembershipTestHandle *mth,
  399. int result)
  400. {
  401. }
  402. /**
  403. * Replay a message fragment for the multicast group.
  404. *
  405. * @param rh Replay handle identifying which replay operation was requested.
  406. * @param msg Replayed message fragment, NULL if unknown/error.
  407. * @param ec Error code.
  408. */
  409. void
  410. GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh,
  411. const struct GNUNET_MessageHeader *msg,
  412. enum GNUNET_MULTICAST_ReplayErrorCode ec)
  413. {
  414. }
  415. /**
  416. * Indicate the end of the replay session.
  417. *
  418. * Invalidates the replay handle.
  419. *
  420. * @param rh Replay session to end.
  421. */
  422. void
  423. GNUNET_MULTICAST_replay_response_end (struct GNUNET_MULTICAST_ReplayHandle *rh)
  424. {
  425. }
  426. /**
  427. * Replay a message for the multicast group.
  428. *
  429. * @param rh Replay handle identifying which replay operation was requested.
  430. * @param notify Function to call to get the message.
  431. * @param notify_cls Closure for @a notify.
  432. */
  433. void
  434. GNUNET_MULTICAST_replay_response2 (struct GNUNET_MULTICAST_ReplayHandle *rh,
  435. GNUNET_MULTICAST_ReplayTransmitNotify notify,
  436. void *notify_cls)
  437. {
  438. }
  439. /**
  440. * Start a multicast group.
  441. *
  442. * Will advertise the origin in the P2P overlay network under the respective
  443. * public key so that other peer can find this peer to join it. Peers that
  444. * issue GNUNET_MULTICAST_member_join() can then transmit a join request to
  445. * either an existing group member or to the origin. If the joining is
  446. * approved, the member is cleared for @e replay and will begin to receive
  447. * messages transmitted to the group. If joining is disapproved, the failed
  448. * candidate will be given a response. Members in the group can send messages
  449. * to the origin (one at a time).
  450. *
  451. * @param cfg Configuration to use.
  452. * @param priv_key ECC key that will be used to sign messages for this
  453. * multicast session; public key is used to identify the multicast group;
  454. * @param max_fragment_id Maximum fragment ID already sent to the group.
  455. * 0 for a new group.
  456. * @param join_request_cb Function called to approve / disapprove joining of a peer.
  457. * @param member_test_cb Function multicast can use to test group membership.
  458. * @param replay_frag_cb Function that can be called to replay a message fragment.
  459. * @param replay_msg_cb Function that can be called to replay a message.
  460. * @param request_cb Function called with message fragments from group members.
  461. * @param message_cb Function called with the message fragments sent to the
  462. * network by GNUNET_MULTICAST_origin_to_all(). These message fragments
  463. * should be stored for answering replay requests later.
  464. * @param cls Closure for the various callbacks that follow.
  465. *
  466. * @return Handle for the origin, NULL on error.
  467. */
  468. struct GNUNET_MULTICAST_Origin *
  469. GNUNET_MULTICAST_origin_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
  470. const struct GNUNET_CRYPTO_EddsaPrivateKey *priv_key,
  471. uint64_t max_fragment_id,
  472. GNUNET_MULTICAST_JoinRequestCallback join_request_cb,
  473. GNUNET_MULTICAST_MembershipTestCallback member_test_cb,
  474. GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb,
  475. GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb,
  476. GNUNET_MULTICAST_RequestCallback request_cb,
  477. GNUNET_MULTICAST_MessageCallback message_cb,
  478. void *cls)
  479. {
  480. struct GNUNET_MULTICAST_Origin *orig = GNUNET_malloc (sizeof (*orig));
  481. struct GNUNET_MULTICAST_Group *grp = &orig->grp;
  482. struct MulticastOriginStartMessage *start = GNUNET_malloc (sizeof (*start));
  483. start->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START);
  484. start->header.size = htons (sizeof (*start));
  485. start->max_fragment_id = max_fragment_id;
  486. memcpy (&start->group_key, priv_key, sizeof (*priv_key));
  487. grp->connect_msg = (struct GNUNET_MessageHeader *) start;
  488. grp->is_origin = GNUNET_YES;
  489. grp->cfg = cfg;
  490. grp->cb_cls = cls;
  491. grp->join_req_cb = join_request_cb;
  492. grp->member_test_cb = member_test_cb;
  493. grp->replay_frag_cb = replay_frag_cb;
  494. grp->replay_msg_cb = replay_msg_cb;
  495. grp->message_cb = message_cb;
  496. orig->request_cb = request_cb;
  497. grp->client = GNUNET_CLIENT_MANAGER_connect (cfg, "multicast", origin_handlers);
  498. GNUNET_CLIENT_MANAGER_set_user_context_ (grp->client, orig, sizeof (*grp));
  499. group_send_connect_msg (grp);
  500. return orig;
  501. }
  502. /**
  503. * Stop a multicast group.
  504. *
  505. * @param origin Multicast group to stop.
  506. */
  507. void
  508. GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *orig,
  509. GNUNET_ContinuationCallback stop_cb,
  510. void *stop_cls)
  511. {
  512. struct GNUNET_MULTICAST_Group *grp = &orig->grp;
  513. grp->is_disconnecting = GNUNET_YES;
  514. grp->disconnect_cb = stop_cb;
  515. grp->disconnect_cls = stop_cls;
  516. GNUNET_CLIENT_MANAGER_disconnect (orig->grp.client, GNUNET_YES,
  517. &origin_cleanup, orig);
  518. }
  519. static void
  520. origin_to_all (struct GNUNET_MULTICAST_Origin *orig)
  521. {
  522. LOG (GNUNET_ERROR_TYPE_DEBUG, "origin_to_all()\n");
  523. struct GNUNET_MULTICAST_Group *grp = &orig->grp;
  524. struct GNUNET_MULTICAST_OriginTransmitHandle *tmit = &orig->tmit;
  525. size_t buf_size = GNUNET_MULTICAST_FRAGMENT_MAX_SIZE;
  526. struct GNUNET_MULTICAST_MessageHeader *msg = GNUNET_malloc (buf_size);
  527. int ret = tmit->notify (tmit->notify_cls, &buf_size, &msg[1]);
  528. if (! (GNUNET_YES == ret || GNUNET_NO == ret)
  529. || GNUNET_MULTICAST_FRAGMENT_MAX_SIZE < buf_size)
  530. {
  531. LOG (GNUNET_ERROR_TYPE_ERROR,
  532. "OriginTransmitNotify() returned error or invalid message size.\n");
  533. /* FIXME: handle error */
  534. GNUNET_free (msg);
  535. return;
  536. }
  537. if (GNUNET_NO == ret && 0 == buf_size)
  538. {
  539. GNUNET_free (msg);
  540. return; /* Transmission paused. */
  541. }
  542. msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
  543. msg->header.size = htons (sizeof (*msg) + buf_size);
  544. msg->message_id = GNUNET_htonll (tmit->message_id);
  545. msg->group_generation = tmit->group_generation;
  546. msg->fragment_offset = GNUNET_htonll (tmit->fragment_offset);
  547. tmit->fragment_offset += sizeof (*msg) + buf_size;
  548. GNUNET_CLIENT_MANAGER_transmit (grp->client, &msg->header);
  549. }
  550. /**
  551. * Send a message to the multicast group.
  552. *
  553. * @param orig Handle to the multicast group.
  554. * @param message_id Application layer ID for the message. Opaque to multicast.
  555. * @param group_generation Group generation of the message.
  556. * Documented in struct GNUNET_MULTICAST_MessageHeader.
  557. * @param notify Function to call to get the message.
  558. * @param notify_cls Closure for @a notify.
  559. *
  560. * @return Message handle on success,
  561. * NULL on error (i.e. another request is already pending).
  562. */
  563. struct GNUNET_MULTICAST_OriginTransmitHandle *
  564. GNUNET_MULTICAST_origin_to_all (struct GNUNET_MULTICAST_Origin *orig,
  565. uint64_t message_id,
  566. uint64_t group_generation,
  567. GNUNET_MULTICAST_OriginTransmitNotify notify,
  568. void *notify_cls)
  569. {
  570. /* FIXME
  571. if (GNUNET_YES == orig->grp.in_transmit)
  572. return NULL;
  573. orig->grp.in_transmit = GNUNET_YES;
  574. */
  575. struct GNUNET_MULTICAST_OriginTransmitHandle *tmit = &orig->tmit;
  576. tmit->origin = orig;
  577. tmit->message_id = message_id;
  578. tmit->group_generation = group_generation;
  579. tmit->notify = notify;
  580. tmit->notify_cls = notify_cls;
  581. origin_to_all (orig);
  582. return tmit;
  583. }
  584. /**
  585. * Resume message transmission to multicast group.
  586. *
  587. * @param th Transmission to cancel.
  588. */
  589. void
  590. GNUNET_MULTICAST_origin_to_all_resume (struct GNUNET_MULTICAST_OriginTransmitHandle *th)
  591. {
  592. origin_to_all (th->origin);
  593. }
  594. /**
  595. * Cancel request for message transmission to multicast group.
  596. *
  597. * @param th Transmission to cancel.
  598. */
  599. void
  600. GNUNET_MULTICAST_origin_to_all_cancel (struct GNUNET_MULTICAST_OriginTransmitHandle *th)
  601. {
  602. }
  603. /**
  604. * Join a multicast group.
  605. *
  606. * The entity joining is always the local peer. Further information about the
  607. * candidate can be provided in the @a join_request message. If the join fails, the
  608. * @a message_cb is invoked with a (failure) response and then with NULL. If
  609. * the join succeeds, outstanding (state) messages and ongoing multicast
  610. * messages will be given to the @a message_cb until the member decides to part
  611. * the group. The @a test_cb and @a replay_cb functions may be called at
  612. * anytime by the multicast service to support relaying messages to other
  613. * members of the group.
  614. *
  615. * @param cfg Configuration to use.
  616. * @param group_key ECC public key that identifies the group to join.
  617. * @param member_key ECC key that identifies the member and used to sign
  618. * requests sent to the origin.
  619. * @param origin Peer ID of the origin to send unicast requsets to. If NULL,
  620. * unicast requests are sent back via multiple hops on the reverse path
  621. * of multicast messages.
  622. * @param relay_count Number of peers in the @a relays array.
  623. * @param relays Peer identities of members of the group, which serve as relays
  624. * and can be used to join the group at. and send the @a join_request to.
  625. * If empty, the @a join_request is sent directly to the @a origin.
  626. * @param join_msg Application-dependent join message to be passed to the peer
  627. * @a origin.
  628. * @param join_request_cb Function called to approve / disapprove joining of a peer.
  629. * @param join_decision_cb Function called to inform about the join decision.
  630. * @param member_test_cb Function multicast can use to test group membership.
  631. * @param replay_frag_cb Function that can be called to replay message fragments
  632. * this peer already knows from this group. NULL if this
  633. * client is unable to support replay.
  634. * @param replay_msg_cb Function that can be called to replay message fragments
  635. * this peer already knows from this group. NULL if this
  636. * client is unable to support replay.
  637. * @param message_cb Function to be called for all message fragments we
  638. * receive from the group, excluding those our @a replay_cb
  639. * already has.
  640. * @param cls Closure for callbacks.
  641. * @return Handle for the member, NULL on error.
  642. */
  643. struct GNUNET_MULTICAST_Member *
  644. GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg,
  645. const struct GNUNET_CRYPTO_EddsaPublicKey *group_key,
  646. const struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key,
  647. const struct GNUNET_PeerIdentity *origin,
  648. uint16_t relay_count,
  649. const struct GNUNET_PeerIdentity *relays,
  650. const struct GNUNET_MessageHeader *join_msg,
  651. GNUNET_MULTICAST_JoinRequestCallback join_request_cb,
  652. GNUNET_MULTICAST_JoinDecisionCallback join_decision_cb,
  653. GNUNET_MULTICAST_MembershipTestCallback member_test_cb,
  654. GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb,
  655. GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb,
  656. GNUNET_MULTICAST_MessageCallback message_cb,
  657. void *cls)
  658. {
  659. struct GNUNET_MULTICAST_Member *mem = GNUNET_malloc (sizeof (*mem));
  660. struct GNUNET_MULTICAST_Group *grp = &mem->grp;
  661. uint16_t relay_size = relay_count * sizeof (*relays);
  662. uint16_t join_msg_size = (NULL != join_msg) ? ntohs (join_msg->size) : 0;
  663. struct MulticastMemberJoinMessage *
  664. join = GNUNET_malloc (sizeof (*join) + relay_size + join_msg_size);
  665. join->header.size = htons (sizeof (*join) + relay_size + join_msg_size);
  666. join->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN);
  667. join->group_key = *group_key;
  668. join->member_key = *member_key;
  669. join->origin = *origin;
  670. if (0 < relay_size)
  671. memcpy (&join[1], relays, relay_size);
  672. if (0 < join_msg_size)
  673. memcpy (((char *) &join[1]) + relay_size, join_msg, join_msg_size);
  674. grp->connect_msg = (struct GNUNET_MessageHeader *) join;
  675. grp->is_origin = GNUNET_NO;
  676. grp->cfg = cfg;
  677. mem->join_dcsn_cb = join_decision_cb;
  678. grp->join_req_cb = join_request_cb;
  679. grp->member_test_cb = member_test_cb;
  680. grp->replay_frag_cb = replay_frag_cb;
  681. grp->message_cb = message_cb;
  682. grp->cb_cls = cls;
  683. grp->client = GNUNET_CLIENT_MANAGER_connect (cfg, "multicast", member_handlers);
  684. GNUNET_CLIENT_MANAGER_set_user_context_ (grp->client, mem, sizeof (*grp));
  685. group_send_connect_msg (grp);
  686. return mem;
  687. }
  688. /**
  689. * Part a multicast group.
  690. *
  691. * Disconnects from all group members and invalidates the @a member handle.
  692. *
  693. * An application-dependent part message can be transmitted beforehand using
  694. * #GNUNET_MULTICAST_member_to_origin())
  695. *
  696. * @param member Membership handle.
  697. */
  698. void
  699. GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *mem,
  700. GNUNET_ContinuationCallback part_cb,
  701. void *part_cls)
  702. {
  703. struct GNUNET_MULTICAST_Group *grp = &mem->grp;
  704. grp->is_disconnecting = GNUNET_YES;
  705. grp->disconnect_cb = part_cb;
  706. grp->disconnect_cls = part_cls;
  707. GNUNET_CLIENT_MANAGER_disconnect (mem->grp.client, GNUNET_YES,
  708. &member_cleanup, mem);
  709. }
  710. /**
  711. * Request a fragment to be replayed by fragment ID.
  712. *
  713. * Useful if messages below the @e max_known_fragment_id given when joining are
  714. * needed and not known to the client.
  715. *
  716. * @param member Membership handle.
  717. * @param fragment_id ID of a message fragment that this client would like to
  718. see replayed.
  719. * @param flags Additional flags for the replay request. It is used and defined
  720. * by the replay callback. FIXME: which replay callback? FIXME: use enum?
  721. * FIXME: why not pass reply cb here?
  722. * @return Replay request handle, NULL on error.
  723. */
  724. struct GNUNET_MULTICAST_MemberReplayHandle *
  725. GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *member,
  726. uint64_t fragment_id,
  727. uint64_t flags)
  728. {
  729. return NULL;
  730. }
  731. /**
  732. * Request a message fragment to be replayed.
  733. *
  734. * Useful if messages below the @e max_known_fragment_id given when joining are
  735. * needed and not known to the client.
  736. *
  737. * @param member Membership handle.
  738. * @param message_id ID of the message this client would like to see replayed.
  739. * @param fragment_offset Offset of the fragment within the message to replay.
  740. * @param flags Additional flags for the replay request. It is used & defined
  741. * by the replay callback.
  742. * @param result_cb Function to be called for the replayed message.
  743. * @param result_cb_cls Closure for @a result_cb.
  744. * @return Replay request handle, NULL on error.
  745. */
  746. struct GNUNET_MULTICAST_MemberReplayHandle *
  747. GNUNET_MULTICAST_member_replay_message (struct GNUNET_MULTICAST_Member *member,
  748. uint64_t message_id,
  749. uint64_t fragment_offset,
  750. uint64_t flags,
  751. GNUNET_MULTICAST_ResultCallback result_cb,
  752. void *result_cb_cls)
  753. {
  754. return NULL;
  755. }
  756. /**
  757. * Cancel a replay request.
  758. *
  759. * @param rh Request to cancel.
  760. */
  761. void
  762. GNUNET_MULTICAST_member_replay_cancel (struct GNUNET_MULTICAST_MemberReplayHandle *rh)
  763. {
  764. }
  765. static void
  766. member_to_origin (struct GNUNET_MULTICAST_Member *mem)
  767. {
  768. LOG (GNUNET_ERROR_TYPE_DEBUG, "member_to_origin()\n");
  769. struct GNUNET_MULTICAST_Group *grp = &mem->grp;
  770. struct GNUNET_MULTICAST_MemberTransmitHandle *tmit = &mem->tmit;
  771. size_t buf_size = GNUNET_MULTICAST_FRAGMENT_MAX_SIZE;
  772. struct GNUNET_MULTICAST_RequestHeader *req = GNUNET_malloc (buf_size);
  773. int ret = tmit->notify (tmit->notify_cls, &buf_size, &req[1]);
  774. if (! (GNUNET_YES == ret || GNUNET_NO == ret)
  775. || GNUNET_MULTICAST_FRAGMENT_MAX_SIZE < buf_size)
  776. {
  777. LOG (GNUNET_ERROR_TYPE_ERROR,
  778. "MemberTransmitNotify() returned error or invalid message size.\n");
  779. /* FIXME: handle error */
  780. GNUNET_free (req);
  781. return;
  782. }
  783. if (GNUNET_NO == ret && 0 == buf_size)
  784. {
  785. /* Transmission paused. */
  786. GNUNET_free (req);
  787. return;
  788. }
  789. req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST);
  790. req->header.size = htons (sizeof (*req) + buf_size);
  791. req->request_id = GNUNET_htonll (tmit->request_id);
  792. req->fragment_offset = GNUNET_ntohll (tmit->fragment_offset);
  793. tmit->fragment_offset += sizeof (*req) + buf_size;
  794. GNUNET_CLIENT_MANAGER_transmit (grp->client, &req->header);
  795. }
  796. /**
  797. * Send a message to the origin of the multicast group.
  798. *
  799. * @param mem Membership handle.
  800. * @param request_id Application layer ID for the request. Opaque to multicast.
  801. * @param notify Callback to call to get the message.
  802. * @param notify_cls Closure for @a notify.
  803. * @return Handle to cancel request, NULL on error (i.e. request already pending).
  804. */
  805. struct GNUNET_MULTICAST_MemberTransmitHandle *
  806. GNUNET_MULTICAST_member_to_origin (struct GNUNET_MULTICAST_Member *mem,
  807. uint64_t request_id,
  808. GNUNET_MULTICAST_MemberTransmitNotify notify,
  809. void *notify_cls)
  810. {
  811. /* FIXME
  812. if (GNUNET_YES == mem->grp.in_transmit)
  813. return NULL;
  814. mem->grp.in_transmit = GNUNET_YES;
  815. */
  816. struct GNUNET_MULTICAST_MemberTransmitHandle *tmit = &mem->tmit;
  817. tmit->member = mem;
  818. tmit->request_id = request_id;
  819. tmit->notify = notify;
  820. tmit->notify_cls = notify_cls;
  821. member_to_origin (mem);
  822. return tmit;
  823. }
  824. /**
  825. * Resume message transmission to origin.
  826. *
  827. * @param th Transmission to cancel.
  828. */
  829. void
  830. GNUNET_MULTICAST_member_to_origin_resume (struct GNUNET_MULTICAST_MemberTransmitHandle *th)
  831. {
  832. member_to_origin (th->member);
  833. }
  834. /**
  835. * Cancel request for message transmission to origin.
  836. *
  837. * @param th Transmission to cancel.
  838. */
  839. void
  840. GNUNET_MULTICAST_member_to_origin_cancel (struct GNUNET_MULTICAST_MemberTransmitHandle *th)
  841. {
  842. }
  843. /* end of multicast_api.c */