messenger_api.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2020--2021 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. * @author Tobias Frisch
  18. * @file src/messenger/messenger_api.c
  19. * @brief messenger api: client implementation of GNUnet MESSENGER service
  20. */
  21. #include "gnunet_messenger_service.h"
  22. #include "gnunet-service-messenger.h"
  23. #include "messenger_api_handle.h"
  24. #include "messenger_api_message.h"
  25. #include "messenger_api_util.h"
  26. const char*
  27. GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
  28. {
  29. switch (kind)
  30. {
  31. case GNUNET_MESSENGER_KIND_INFO:
  32. return "INFO";
  33. case GNUNET_MESSENGER_KIND_JOIN:
  34. return "JOIN";
  35. case GNUNET_MESSENGER_KIND_LEAVE:
  36. return "LEAVE";
  37. case GNUNET_MESSENGER_KIND_NAME:
  38. return "NAME";
  39. case GNUNET_MESSENGER_KIND_KEY:
  40. return "KEY";
  41. case GNUNET_MESSENGER_KIND_PEER:
  42. return "PEER";
  43. case GNUNET_MESSENGER_KIND_ID:
  44. return "ID";
  45. case GNUNET_MESSENGER_KIND_MISS:
  46. return "MISS";
  47. case GNUNET_MESSENGER_KIND_MERGE:
  48. return "MERGE";
  49. case GNUNET_MESSENGER_KIND_REQUEST:
  50. return "REQUEST";
  51. case GNUNET_MESSENGER_KIND_INVITE:
  52. return "INVITE";
  53. case GNUNET_MESSENGER_KIND_TEXT:
  54. return "TEXT";
  55. case GNUNET_MESSENGER_KIND_FILE:
  56. return "FILE";
  57. case GNUNET_MESSENGER_KIND_PRIVATE:
  58. return "PRIVATE";
  59. default:
  60. return "UNKNOWN";
  61. }
  62. }
  63. static int
  64. check_get_name (void *cls,
  65. const struct GNUNET_MESSENGER_NameMessage *msg)
  66. {
  67. GNUNET_MQ_check_zero_termination(msg);
  68. return GNUNET_OK;
  69. }
  70. static void
  71. handle_get_name (void *cls,
  72. const struct GNUNET_MESSENGER_NameMessage *msg)
  73. {
  74. struct GNUNET_MESSENGER_Handle *handle = cls;
  75. const char *name = ((const char*) msg) + sizeof(*msg);
  76. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name);
  77. set_handle_name (handle, strlen (name) > 0 ? name : NULL);
  78. }
  79. static int
  80. check_get_key (void *cls,
  81. const struct GNUNET_MESSENGER_KeyMessage *msg)
  82. {
  83. const uint16_t full_length = ntohs (msg->header.size);
  84. if (full_length < sizeof(*msg))
  85. return GNUNET_NO;
  86. const uint16_t length = full_length - sizeof(*msg);
  87. const char *buffer = ((const char*) msg) + sizeof(*msg);
  88. struct GNUNET_IDENTITY_PublicKey pubkey;
  89. if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
  90. return GNUNET_NO;
  91. return GNUNET_OK;
  92. }
  93. static void
  94. handle_get_key (void *cls,
  95. const struct GNUNET_MESSENGER_KeyMessage *msg)
  96. {
  97. struct GNUNET_MESSENGER_Handle *handle = cls;
  98. const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
  99. const char *buffer = ((const char*) msg) + sizeof(*msg);
  100. struct GNUNET_IDENTITY_PublicKey pubkey;
  101. if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
  102. return;
  103. char* str = GNUNET_IDENTITY_public_key_to_string (&pubkey);
  104. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", str);
  105. GNUNET_free(str);
  106. set_handle_key (handle, &pubkey);
  107. if (handle->identity_callback)
  108. handle->identity_callback (handle->identity_cls, handle);
  109. }
  110. static void
  111. handle_member_id (void *cls,
  112. const struct GNUNET_MESSENGER_MemberMessage *msg)
  113. {
  114. struct GNUNET_MESSENGER_Handle *handle = cls;
  115. const struct GNUNET_HashCode *key = &(msg->key);
  116. const struct GNUNET_ShortHashCode *id = &(msg->id);
  117. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set id of handle in room: %s\n", GNUNET_h2s (key));
  118. struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
  119. if (room)
  120. {
  121. if (!room->contact_id)
  122. room->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
  123. GNUNET_memcpy(room->contact_id, id, sizeof(*id));
  124. }
  125. }
  126. static void
  127. handle_room_open (void *cls,
  128. const struct GNUNET_MESSENGER_RoomMessage *msg)
  129. {
  130. struct GNUNET_MESSENGER_Handle *handle = cls;
  131. const struct GNUNET_HashCode *key = &(msg->key);
  132. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key));
  133. open_handle_room (handle, key);
  134. }
  135. static void
  136. handle_room_entry (void *cls,
  137. const struct GNUNET_MESSENGER_RoomMessage *msg)
  138. {
  139. struct GNUNET_MESSENGER_Handle *handle = cls;
  140. const struct GNUNET_PeerIdentity *door = &(msg->door);
  141. const struct GNUNET_HashCode *key = &(msg->key);
  142. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key));
  143. entry_handle_room_at (handle, door, key);
  144. }
  145. static void
  146. handle_room_close (void *cls,
  147. const struct GNUNET_MESSENGER_RoomMessage *msg)
  148. {
  149. struct GNUNET_MESSENGER_Handle *handle = cls;
  150. const struct GNUNET_HashCode *key = &(msg->key);
  151. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
  152. close_handle_room (handle, key);
  153. }
  154. static int
  155. check_recv_message (void *cls,
  156. const struct GNUNET_MESSENGER_RecvMessage *msg)
  157. {
  158. const uint16_t full_length = ntohs (msg->header.size);
  159. if (full_length < sizeof(*msg))
  160. return GNUNET_NO;
  161. const uint16_t length = full_length - sizeof(*msg);
  162. const char *buffer = ((const char*) msg) + sizeof(*msg);
  163. struct GNUNET_MESSENGER_Message message;
  164. if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
  165. return GNUNET_NO;
  166. if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
  167. return GNUNET_NO;
  168. return GNUNET_OK;
  169. }
  170. static void
  171. handle_recv_message (void *cls,
  172. const struct GNUNET_MESSENGER_RecvMessage *msg)
  173. {
  174. struct GNUNET_MESSENGER_Handle *handle = cls;
  175. const struct GNUNET_HashCode *key = &(msg->key);
  176. const struct GNUNET_HashCode *sender = &(msg->sender);
  177. const struct GNUNET_HashCode *context = &(msg->context);
  178. const struct GNUNET_HashCode *hash = &(msg->hash);
  179. const enum GNUNET_MESSENGER_MessageFlags flags = (
  180. (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
  181. );
  182. const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
  183. const char *buffer = ((const char*) msg) + sizeof(*msg);
  184. struct GNUNET_MESSENGER_Message message;
  185. decode_message (&message, length, buffer, GNUNET_YES, NULL);
  186. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind));
  187. struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
  188. if (room)
  189. {
  190. struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(handle);
  191. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: (%s : %s)\n",
  192. GNUNET_h2s(sender), GNUNET_h2s_full(context));
  193. struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw(
  194. store, context, sender
  195. );
  196. handle_room_message (room, contact, &message, hash);
  197. if (handle->msg_callback)
  198. handle->msg_callback (handle->msg_cls, room, contact, &message, hash, flags);
  199. }
  200. else
  201. GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found\n");
  202. }
  203. static void
  204. reconnect (struct GNUNET_MESSENGER_Handle *handle);
  205. static void
  206. send_open_room (struct GNUNET_MESSENGER_Handle *handle,
  207. struct GNUNET_MESSENGER_Room *room)
  208. {
  209. struct GNUNET_MESSENGER_RoomMessage *msg;
  210. struct GNUNET_MQ_Envelope *env;
  211. env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
  212. GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
  213. GNUNET_MQ_send (handle->mq, env);
  214. }
  215. static void
  216. send_enter_room (struct GNUNET_MESSENGER_Handle *handle,
  217. struct GNUNET_MESSENGER_Room *room,
  218. const struct GNUNET_PeerIdentity *door)
  219. {
  220. struct GNUNET_MESSENGER_RoomMessage *msg;
  221. struct GNUNET_MQ_Envelope *env;
  222. env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
  223. GNUNET_memcpy(&(msg->door), door, sizeof(*door));
  224. GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
  225. GNUNET_MQ_send (handle->mq, env);
  226. }
  227. static void
  228. send_close_room (struct GNUNET_MESSENGER_Handle *handle,
  229. struct GNUNET_MESSENGER_Room *room)
  230. {
  231. struct GNUNET_MESSENGER_RoomMessage *msg;
  232. struct GNUNET_MQ_Envelope *env;
  233. env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
  234. GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
  235. GNUNET_MQ_send (handle->mq, env);
  236. }
  237. static int
  238. iterate_reset_room (void *cls,
  239. const struct GNUNET_HashCode *key,
  240. void *value)
  241. {
  242. struct GNUNET_MESSENGER_Handle *handle = cls;
  243. struct GNUNET_MESSENGER_Room *room = value;
  244. if (GNUNET_YES == room->opened)
  245. send_open_room (handle, room);
  246. struct GNUNET_MESSENGER_ListTunnel *entry = room->entries.head;
  247. struct GNUNET_PeerIdentity door;
  248. while (entry)
  249. {
  250. GNUNET_PEER_resolve (entry->peer, &door);
  251. send_enter_room (handle, room, &door);
  252. entry = entry->next;
  253. }
  254. return GNUNET_YES;
  255. }
  256. static void
  257. callback_reconnect (void *cls)
  258. {
  259. struct GNUNET_MESSENGER_Handle *handle = cls;
  260. handle->reconnect_task = NULL;
  261. handle->reconnect_time = GNUNET_TIME_STD_BACKOFF(handle->reconnect_time)
  262. ;
  263. reconnect (handle);
  264. GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_reset_room, handle);
  265. }
  266. static int
  267. iterate_close_room (void *cls,
  268. const struct GNUNET_HashCode *key,
  269. void *value)
  270. {
  271. struct GNUNET_MESSENGER_Handle *handle = cls;
  272. struct GNUNET_MESSENGER_Room *room = value;
  273. send_close_room (handle, room);
  274. return GNUNET_YES;
  275. }
  276. static void
  277. callback_mq_error (void *cls,
  278. enum GNUNET_MQ_Error error)
  279. {
  280. struct GNUNET_MESSENGER_Handle *handle = cls;
  281. GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error);
  282. GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle);
  283. if (handle->mq)
  284. {
  285. GNUNET_MQ_destroy (handle->mq);
  286. handle->mq = NULL;
  287. }
  288. handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_time, &callback_reconnect, handle);
  289. }
  290. static void
  291. reconnect (struct GNUNET_MESSENGER_Handle *handle)
  292. {
  293. const struct GNUNET_MQ_MessageHandler handlers[] =
  294. {
  295. GNUNET_MQ_hd_var_size(
  296. get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME,
  297. struct GNUNET_MESSENGER_NameMessage, handle
  298. ),
  299. GNUNET_MQ_hd_var_size(
  300. get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY,
  301. struct GNUNET_MESSENGER_KeyMessage, handle
  302. ),
  303. GNUNET_MQ_hd_fixed_size(
  304. member_id,
  305. GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
  306. struct GNUNET_MESSENGER_MemberMessage, handle
  307. ),
  308. GNUNET_MQ_hd_fixed_size(
  309. room_open,
  310. GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
  311. struct GNUNET_MESSENGER_RoomMessage, handle
  312. ),
  313. GNUNET_MQ_hd_fixed_size(
  314. room_entry,
  315. GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
  316. struct GNUNET_MESSENGER_RoomMessage, handle
  317. ),
  318. GNUNET_MQ_hd_fixed_size(
  319. room_close,
  320. GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
  321. struct GNUNET_MESSENGER_RoomMessage, handle
  322. ),
  323. GNUNET_MQ_hd_var_size(
  324. recv_message,
  325. GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
  326. struct GNUNET_MESSENGER_RecvMessage, handle
  327. ),
  328. GNUNET_MQ_handler_end()
  329. };
  330. handle->mq = GNUNET_CLIENT_connect (handle->cfg, GNUNET_MESSENGER_SERVICE_NAME, handlers, &callback_mq_error, handle);
  331. }
  332. struct GNUNET_MESSENGER_Handle*
  333. GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
  334. const char *name,
  335. GNUNET_MESSENGER_IdentityCallback identity_callback,
  336. void *identity_cls,
  337. GNUNET_MESSENGER_MessageCallback msg_callback,
  338. void *msg_cls)
  339. {
  340. struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, identity_callback, identity_cls, msg_callback, msg_cls);
  341. reconnect (handle);
  342. if (handle->mq)
  343. {
  344. const uint16_t name_len = name ? strlen (name) : 0;
  345. struct GNUNET_MESSENGER_CreateMessage *msg;
  346. struct GNUNET_MQ_Envelope *env;
  347. env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE);
  348. char *extra = ((char*) msg) + sizeof(*msg);
  349. if (name_len)
  350. GNUNET_memcpy(extra, name, name_len);
  351. extra[name_len] = '\0';
  352. GNUNET_MQ_send (handle->mq, env);
  353. return handle;
  354. }
  355. else
  356. {
  357. destroy_handle (handle);
  358. return NULL;
  359. }
  360. }
  361. int
  362. GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle)
  363. {
  364. if ((!handle) || (!get_handle_name (handle)))
  365. return GNUNET_SYSERR;
  366. struct GNUNET_MESSENGER_UpdateMessage *msg;
  367. struct GNUNET_MQ_Envelope *env;
  368. env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE);
  369. GNUNET_MQ_send (handle->mq, env);
  370. return GNUNET_OK;
  371. }
  372. void
  373. GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle)
  374. {
  375. if (!handle)
  376. return;
  377. struct GNUNET_MESSENGER_DestroyMessage *msg;
  378. struct GNUNET_MQ_Envelope *env;
  379. env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY);
  380. GNUNET_MQ_send (handle->mq, env);
  381. destroy_handle (handle);
  382. }
  383. const char*
  384. GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle)
  385. {
  386. if (!handle)
  387. return NULL;
  388. return get_handle_name (handle);
  389. }
  390. int
  391. GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle,
  392. const char *name)
  393. {
  394. if (!handle)
  395. return GNUNET_SYSERR;
  396. const uint16_t name_len = name ? strlen (name) : 0;
  397. struct GNUNET_MESSENGER_NameMessage *msg;
  398. struct GNUNET_MQ_Envelope *env;
  399. env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME);
  400. char *extra = ((char*) msg) + sizeof(*msg);
  401. if (name_len)
  402. GNUNET_memcpy(extra, name, name_len);
  403. extra[name_len] = '\0';
  404. GNUNET_MQ_send (handle->mq, env);
  405. return GNUNET_YES;
  406. }
  407. static const struct GNUNET_IDENTITY_PublicKey*
  408. get_non_anonymous_key (const struct GNUNET_IDENTITY_PublicKey* public_key)
  409. {
  410. if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key()))
  411. return NULL;
  412. return public_key;
  413. }
  414. const struct GNUNET_IDENTITY_PublicKey*
  415. GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle)
  416. {
  417. if (!handle)
  418. return NULL;
  419. return get_non_anonymous_key (get_handle_key (handle));
  420. }
  421. struct GNUNET_MESSENGER_Room*
  422. GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle,
  423. const struct GNUNET_HashCode *key)
  424. {
  425. if ((!handle) || (!key))
  426. return NULL;
  427. struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
  428. if (!room)
  429. {
  430. room = create_room (handle, key);
  431. if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
  432. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
  433. {
  434. destroy_room (room);
  435. return NULL;
  436. }
  437. }
  438. send_open_room (handle, room);
  439. return room;
  440. }
  441. struct GNUNET_MESSENGER_Room*
  442. GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle,
  443. const struct GNUNET_PeerIdentity *door,
  444. const struct GNUNET_HashCode *key)
  445. {
  446. if ((!handle) || (!door) || (!key))
  447. return NULL;
  448. struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
  449. if (!room)
  450. {
  451. room = create_room (handle, key);
  452. if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
  453. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
  454. {
  455. destroy_room (room);
  456. return NULL;
  457. }
  458. }
  459. send_enter_room (handle, room, door);
  460. return room;
  461. }
  462. void
  463. GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room)
  464. {
  465. if (!room)
  466. return;
  467. send_close_room (room->handle, room);
  468. }
  469. struct GNUNET_MESSENGER_RoomFind
  470. {
  471. const struct GNUNET_MESSENGER_Contact *contact;
  472. GNUNET_MESSENGER_MemberCallback callback;
  473. size_t counter;
  474. void *cls;
  475. };
  476. static int
  477. iterate_find_room (void* cls,
  478. const struct GNUNET_HashCode *key,
  479. void *value)
  480. {
  481. struct GNUNET_MESSENGER_RoomFind *find = cls;
  482. struct GNUNET_MESSENGER_Room *room = value;
  483. if ((find->counter > 0) && ((!find->contact) || (GNUNET_YES == find_room_member(room, find->contact))))
  484. {
  485. find->counter--;
  486. if (!find->callback)
  487. return GNUNET_YES;
  488. return find->callback(find->cls, room, find->contact);
  489. }
  490. else
  491. return GNUNET_NO;
  492. }
  493. int
  494. GNUNET_MESSENGER_find_rooms (const struct GNUNET_MESSENGER_Handle *handle,
  495. const struct GNUNET_MESSENGER_Contact *contact,
  496. GNUNET_MESSENGER_MemberCallback callback,
  497. void *cls)
  498. {
  499. if (!handle)
  500. return GNUNET_SYSERR;
  501. struct GNUNET_MESSENGER_RoomFind find;
  502. find.contact = contact;
  503. find.callback = callback;
  504. find.counter = (contact? contact->rc : SIZE_MAX);
  505. find.cls = cls;
  506. return GNUNET_CONTAINER_multihashmap_iterate(handle->rooms, iterate_find_room, &find);
  507. }
  508. const struct GNUNET_HashCode*
  509. GNUNET_MESSENGER_room_get_key (const struct GNUNET_MESSENGER_Room *room)
  510. {
  511. if (!room)
  512. return NULL;
  513. return &(room->key);
  514. }
  515. const struct GNUNET_MESSENGER_Contact*
  516. GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room,
  517. const struct GNUNET_HashCode *hash)
  518. {
  519. if ((!room) || (!hash))
  520. return NULL;
  521. return get_room_sender(room, hash);
  522. }
  523. const char*
  524. GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact)
  525. {
  526. if (!contact)
  527. return NULL;
  528. return get_contact_name (contact);
  529. }
  530. const struct GNUNET_IDENTITY_PublicKey*
  531. GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact)
  532. {
  533. if (!contact)
  534. return NULL;
  535. return get_non_anonymous_key (get_contact_key (contact));
  536. }
  537. void
  538. GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room,
  539. const struct GNUNET_MESSENGER_Message *message,
  540. const struct GNUNET_MESSENGER_Contact *contact)
  541. {
  542. if ((!room) || (!message))
  543. return;
  544. switch (filter_message_sending (message))
  545. {
  546. case GNUNET_SYSERR:
  547. GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message aborted: This kind of message is reserved for the service!\n");
  548. return;
  549. case GNUNET_NO:
  550. GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: This kind of message could cause issues!\n");
  551. return;
  552. default:
  553. break;
  554. }
  555. ssize_t key_length = 0;
  556. if (contact)
  557. {
  558. const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key (
  559. get_contact_key(contact)
  560. );
  561. if (public_key)
  562. key_length = GNUNET_IDENTITY_key_get_length(public_key);
  563. else
  564. key_length = -1;
  565. }
  566. if (key_length < 0)
  567. {
  568. GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid key!\n");
  569. return;
  570. }
  571. const uint16_t msg_length = get_message_size (message, GNUNET_NO);
  572. struct GNUNET_MESSENGER_SendMessage *msg;
  573. struct GNUNET_MQ_Envelope *env;
  574. const uint16_t length = (uint16_t) key_length + msg_length;
  575. env = GNUNET_MQ_msg_extra(
  576. msg, length,
  577. GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
  578. );
  579. GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
  580. msg->flags = (uint32_t) (
  581. contact? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
  582. );
  583. char *buffer = ((char*) msg) + sizeof(*msg);
  584. char *msg_buffer = buffer + key_length;
  585. if (key_length > 0)
  586. GNUNET_IDENTITY_write_key_to_buffer(get_contact_key(contact), buffer, key_length);
  587. encode_message (message, msg_length, msg_buffer, GNUNET_NO);
  588. GNUNET_MQ_send (room->handle->mq, env);
  589. }
  590. const struct GNUNET_MESSENGER_Message*
  591. GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room,
  592. const struct GNUNET_HashCode *hash)
  593. {
  594. if ((!room) || (!hash))
  595. return NULL;
  596. const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash);
  597. if (!message)
  598. {
  599. struct GNUNET_MESSENGER_GetMessage *msg;
  600. struct GNUNET_MQ_Envelope *env;
  601. env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
  602. GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
  603. GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
  604. GNUNET_MQ_send (room->handle->mq, env);
  605. }
  606. return message;
  607. }
  608. int
  609. GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room,
  610. GNUNET_MESSENGER_MemberCallback callback,
  611. void *cls)
  612. {
  613. if (!room)
  614. return GNUNET_SYSERR;
  615. return iterate_room_members(room, callback, cls);
  616. }