gnunet-service-messenger_handle.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  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/gnunet-service-messenger_handle.c
  19. * @brief GNUnet MESSENGER service
  20. */
  21. #include "gnunet-service-messenger_handle.h"
  22. #include "gnunet-service-messenger.h"
  23. #include "gnunet-service-messenger_message_kind.h"
  24. #include "messenger_api_util.h"
  25. struct GNUNET_MESSENGER_SrvHandle*
  26. create_handle (struct GNUNET_MESSENGER_Service *service,
  27. struct GNUNET_MQ_Handle *mq)
  28. {
  29. GNUNET_assert((service) && (mq));
  30. struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle);
  31. handle->service = service;
  32. handle->mq = mq;
  33. handle->name = NULL;
  34. handle->ego = NULL;
  35. handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
  36. return handle;
  37. }
  38. int
  39. iterate_free_member_ids (void *cls,
  40. const struct GNUNET_HashCode *key,
  41. void *value)
  42. {
  43. GNUNET_free(value);
  44. return GNUNET_YES;
  45. }
  46. void
  47. destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
  48. {
  49. GNUNET_assert(handle);
  50. if (handle->service->dir)
  51. save_handle_configuration (handle);
  52. if (handle->name)
  53. GNUNET_free(handle->name);
  54. GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_free_member_ids, NULL);
  55. GNUNET_CONTAINER_multihashmap_destroy (handle->member_ids);
  56. GNUNET_free(handle);
  57. }
  58. void
  59. get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle,
  60. const char *name,
  61. char **dir)
  62. {
  63. GNUNET_assert((handle) && (dir));
  64. if (name)
  65. GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities",
  66. DIR_SEPARATOR, name, DIR_SEPARATOR);
  67. else
  68. GNUNET_asprintf (dir, "%s%s%c", handle->service->dir, "anonymous",
  69. DIR_SEPARATOR);
  70. }
  71. static int
  72. create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
  73. const struct GNUNET_HashCode *key)
  74. {
  75. GNUNET_assert((handle) && (key));
  76. struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
  77. if (!random_id)
  78. return GNUNET_NO;
  79. generate_free_member_id (random_id, NULL);
  80. if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id,
  81. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
  82. {
  83. GNUNET_free(random_id);
  84. return GNUNET_NO;
  85. }
  86. GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", GNUNET_sh2s (random_id),
  87. GNUNET_h2s (key));
  88. return GNUNET_YES;
  89. }
  90. const struct GNUNET_ShortHashCode*
  91. get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
  92. const struct GNUNET_HashCode *key)
  93. {
  94. GNUNET_assert((handle) && (key));
  95. return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
  96. }
  97. int
  98. change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle,
  99. const struct GNUNET_HashCode *key,
  100. const struct GNUNET_ShortHashCode *unique_id)
  101. {
  102. GNUNET_assert((handle) && (key) && (unique_id));
  103. struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
  104. if (!member_id)
  105. {
  106. member_id = GNUNET_new(struct GNUNET_ShortHashCode);
  107. GNUNET_memcpy(member_id, unique_id, sizeof(*member_id));
  108. if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id,
  109. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
  110. {
  111. GNUNET_free(member_id);
  112. return GNUNET_SYSERR;
  113. }
  114. }
  115. if (0 == GNUNET_memcmp(unique_id, member_id))
  116. goto send_message_to_client;
  117. GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Change a member id (%s) for room (%s).\n", GNUNET_sh2s (member_id),
  118. GNUNET_h2s (key));
  119. GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
  120. GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member id changed to (%s).\n", GNUNET_sh2s (unique_id));
  121. struct GNUNET_MESSENGER_MemberMessage *msg;
  122. struct GNUNET_MQ_Envelope *env;
  123. send_message_to_client:
  124. env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
  125. GNUNET_memcpy(&(msg->key), key, sizeof(*key));
  126. GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
  127. GNUNET_MQ_send (handle->mq, env);
  128. return GNUNET_OK;
  129. }
  130. static void
  131. change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
  132. const char *name)
  133. {
  134. GNUNET_assert(handle);
  135. if (handle->name)
  136. GNUNET_free(handle->name);
  137. handle->name = name ? GNUNET_strdup(name) : NULL;
  138. const uint16_t name_len = handle->name ? strlen (handle->name) : 0;
  139. struct GNUNET_MESSENGER_NameMessage *msg;
  140. struct GNUNET_MQ_Envelope *env;
  141. env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME);
  142. char *extra = ((char*) msg) + sizeof(*msg);
  143. if (name_len)
  144. GNUNET_memcpy(extra, handle->name, name_len);
  145. extra[name_len] = '\0';
  146. GNUNET_MQ_send (handle->mq, env);
  147. }
  148. static void
  149. change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
  150. const struct GNUNET_MESSENGER_Ego *ego)
  151. {
  152. GNUNET_assert(handle);
  153. handle->ego = ego;
  154. ego = get_handle_ego (handle);
  155. const uint16_t length = GNUNET_IDENTITY_key_get_length(&(ego->pub));
  156. struct GNUNET_MESSENGER_KeyMessage *msg;
  157. struct GNUNET_MQ_Envelope *env;
  158. env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY);
  159. char *extra = ((char*) msg) + sizeof(*msg);
  160. if (GNUNET_IDENTITY_write_key_to_buffer(&(ego->pub), extra, length) < 0)
  161. GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Could not write key to buffer.\n");
  162. GNUNET_MQ_send (handle->mq, env);
  163. }
  164. struct GNUNET_MESSENGER_MessageHandle
  165. {
  166. struct GNUNET_MESSENGER_SrvHandle *handle;
  167. struct GNUNET_MESSENGER_Message *message;
  168. };
  169. static int
  170. iterate_send_message (void *cls,
  171. const struct GNUNET_HashCode *key,
  172. void *value)
  173. {
  174. struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls;
  175. send_handle_message (msg_handle->handle, key, msg_handle->message);
  176. return GNUNET_YES;
  177. }
  178. void
  179. set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
  180. const struct GNUNET_MESSENGER_Ego *ego)
  181. {
  182. GNUNET_assert((handle) && (ego));
  183. struct GNUNET_MESSENGER_MessageHandle msg_handle;
  184. msg_handle.handle = handle;
  185. msg_handle.message = create_message_key (&(ego->priv));
  186. GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
  187. destroy_message (msg_handle.message);
  188. change_handle_ego (handle, ego);
  189. }
  190. const struct GNUNET_MESSENGER_Ego*
  191. get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle)
  192. {
  193. GNUNET_assert(handle);
  194. static struct GNUNET_MESSENGER_Ego anonymous;
  195. static int read_keys = 0;
  196. if (handle->ego)
  197. return handle->ego;
  198. if (!read_keys)
  199. {
  200. struct GNUNET_IDENTITY_Ego *ego = GNUNET_IDENTITY_ego_get_anonymous ();
  201. GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key (ego), sizeof(anonymous.priv));
  202. GNUNET_IDENTITY_ego_get_public_key (ego, &(anonymous.pub));
  203. read_keys = 1;
  204. }
  205. return &anonymous;
  206. }
  207. static void
  208. callback_setup_handle_name (void *cls,
  209. const char *name,
  210. const struct GNUNET_MESSENGER_Ego *ego)
  211. {
  212. struct GNUNET_MESSENGER_SrvHandle *handle = cls;
  213. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting up handle...\n");
  214. change_handle_name (handle, name);
  215. change_handle_ego (handle, ego);
  216. if (handle->service->dir)
  217. load_handle_configuration (handle);
  218. }
  219. void
  220. setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
  221. const char *name)
  222. {
  223. GNUNET_assert(handle);
  224. struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
  225. lookup_store_ego (store, name, callback_setup_handle_name, handle);
  226. }
  227. static void
  228. callback_update_handle (void *cls,
  229. const char *name,
  230. const struct GNUNET_MESSENGER_Ego *ego)
  231. {
  232. struct GNUNET_MESSENGER_SrvHandle *handle = cls;
  233. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating handle...\n");
  234. struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
  235. if (!ego)
  236. create_store_ego(store, handle->name, handle);
  237. else
  238. change_handle_ego (handle, ego);
  239. }
  240. void
  241. update_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
  242. {
  243. GNUNET_assert(handle);
  244. if (!handle->name)
  245. {
  246. GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating handle failed: Name is required!\n");
  247. return;
  248. }
  249. struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
  250. lookup_store_ego (store, handle->name, callback_update_handle, handle);
  251. }
  252. static void
  253. callback_set_handle_name (void *cls,
  254. const char *name,
  255. const struct GNUNET_MESSENGER_Ego *ego)
  256. {
  257. struct GNUNET_MESSENGER_SrvHandle *handle = cls;
  258. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Renaming handle...\n");
  259. if (ego)
  260. {
  261. GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is occupied! (%s)\n", name);
  262. return;
  263. }
  264. struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
  265. int rename_ego_in_store = handle->ego? GNUNET_YES : GNUNET_NO;
  266. char *old_dir;
  267. get_handle_data_subdir (handle, handle->name, &old_dir);
  268. char *new_dir;
  269. get_handle_data_subdir (handle, name, &new_dir);
  270. int result = 0;
  271. if (GNUNET_YES == GNUNET_DISK_directory_test (old_dir, GNUNET_YES))
  272. {
  273. GNUNET_DISK_directory_create_for_file (new_dir);
  274. result = rename (old_dir, new_dir);
  275. }
  276. else if (GNUNET_YES == GNUNET_DISK_directory_test (new_dir, GNUNET_NO))
  277. result = -1;
  278. if (0 == result)
  279. {
  280. struct GNUNET_MESSENGER_MessageHandle msg_handle;
  281. msg_handle.handle = handle;
  282. msg_handle.message = create_message_name (name);
  283. GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
  284. destroy_message (msg_handle.message);
  285. change_handle_name (handle, name);
  286. }
  287. else
  288. rename_ego_in_store = GNUNET_NO;
  289. GNUNET_free(old_dir);
  290. GNUNET_free(new_dir);
  291. if (GNUNET_YES == rename_ego_in_store)
  292. rename_store_ego(store, handle->name, name);
  293. }
  294. void
  295. set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
  296. const char *name)
  297. {
  298. GNUNET_assert(handle);
  299. if (!name)
  300. {
  301. if (handle->ego)
  302. GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is required!\n");
  303. else
  304. change_handle_name (handle, name);
  305. return;
  306. }
  307. struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
  308. lookup_store_ego (store, name, callback_set_handle_name, handle);
  309. }
  310. int
  311. open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
  312. const struct GNUNET_HashCode *key)
  313. {
  314. GNUNET_assert((handle) && (key));
  315. if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
  316. return GNUNET_NO;
  317. return open_service_room (handle->service, handle, key);
  318. }
  319. int
  320. entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
  321. const struct GNUNET_PeerIdentity *door,
  322. const struct GNUNET_HashCode *key)
  323. {
  324. GNUNET_assert((handle) && (door) && (key));
  325. if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
  326. return GNUNET_NO;
  327. return entry_service_room (handle->service, handle, door, key);
  328. }
  329. int
  330. close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
  331. const struct GNUNET_HashCode *key)
  332. {
  333. GNUNET_assert((handle) && (key));
  334. if (!get_handle_member_id (handle, key))
  335. return GNUNET_NO;
  336. return close_service_room (handle->service, handle, key);
  337. }
  338. int
  339. send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
  340. const struct GNUNET_HashCode *key,
  341. const struct GNUNET_MESSENGER_Message *message)
  342. {
  343. GNUNET_assert((handle) && (key) && (message));
  344. const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
  345. if (!id)
  346. {
  347. GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "It is required to be a member of a room to send messages!\n");
  348. return GNUNET_NO;
  349. }
  350. struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (handle->service, key);
  351. if (!room)
  352. {
  353. GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "The room (%s) is unknown!\n", GNUNET_h2s (key));
  354. return GNUNET_NO;
  355. }
  356. struct GNUNET_MESSENGER_Message *msg = copy_message(message);
  357. GNUNET_memcpy(&(msg->header.sender_id), id, sizeof(*id));
  358. return send_room_message (room, handle, msg);
  359. }
  360. static const struct GNUNET_HashCode*
  361. get_next_member_session_contect(const struct GNUNET_MESSENGER_MemberSession *session)
  362. {
  363. if (session->next)
  364. return get_next_member_session_contect (session->next);
  365. else
  366. return get_member_session_context(session);
  367. }
  368. static const struct GNUNET_MESSENGER_MemberSession*
  369. get_handle_member_session (struct GNUNET_MESSENGER_SrvHandle *handle,
  370. const struct GNUNET_HashCode *key)
  371. {
  372. GNUNET_assert((handle) && (key) && (handle->service));
  373. const struct GNUNET_ShortHashCode *id = get_handle_member_id(handle, key);
  374. struct GNUNET_MESSENGER_SrvRoom *room = get_service_room(handle->service, key);
  375. if ((!id) || (!room))
  376. return NULL;
  377. struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
  378. struct GNUNET_MESSENGER_Member *member = get_store_member(store, id);
  379. const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
  380. if (!ego)
  381. return NULL;
  382. return get_member_session(member, &(ego->pub));
  383. }
  384. void
  385. notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
  386. const struct GNUNET_HashCode *key,
  387. const struct GNUNET_MESSENGER_MemberSession *session,
  388. const struct GNUNET_MESSENGER_Message *message,
  389. const struct GNUNET_HashCode *hash)
  390. {
  391. GNUNET_assert((handle) && (key) && (session) && (message) && (hash));
  392. if ((!handle->mq) || (!get_handle_member_id (handle, key)))
  393. {
  394. GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notifying client about message requires membership!\n");
  395. return;
  396. }
  397. const struct GNUNET_IDENTITY_PublicKey *pubkey = get_contact_key(session->contact);
  398. struct GNUNET_HashCode sender;
  399. GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
  400. const struct GNUNET_HashCode *context = get_next_member_session_contect (session);
  401. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying client about message: %s\n", GNUNET_h2s (hash));
  402. struct GNUNET_MESSENGER_Message *private_message = NULL;
  403. if (GNUNET_MESSENGER_KIND_PRIVATE == message->header.kind)
  404. {
  405. private_message = copy_message(message);
  406. if (GNUNET_YES != decrypt_message(private_message, &(get_handle_ego(handle)->priv)))
  407. {
  408. destroy_message(private_message);
  409. private_message = NULL;
  410. }
  411. else
  412. message = private_message;
  413. }
  414. struct GNUNET_MESSENGER_RecvMessage *msg;
  415. struct GNUNET_MQ_Envelope *env;
  416. uint16_t length = get_message_size (message, GNUNET_YES);
  417. env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
  418. GNUNET_memcpy(&(msg->key), key, sizeof(msg->key));
  419. GNUNET_memcpy(&(msg->sender), &sender, sizeof(msg->sender));
  420. GNUNET_memcpy(&(msg->context), context, sizeof(msg->context));
  421. GNUNET_memcpy(&(msg->hash), hash, sizeof(msg->hash));
  422. msg->flags = (uint32_t) GNUNET_MESSENGER_FLAG_NONE;
  423. if (get_handle_member_session(handle, key) == session)
  424. msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_SENT;
  425. if (private_message)
  426. msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_PRIVATE;
  427. char *buffer = ((char*) msg) + sizeof(*msg);
  428. encode_message (message, length, buffer, GNUNET_YES);
  429. if (private_message)
  430. destroy_message(private_message);
  431. GNUNET_MQ_send (handle->mq, env);
  432. }
  433. static int
  434. callback_scan_for_rooms (void *cls,
  435. const char *filename)
  436. {
  437. struct GNUNET_MESSENGER_SrvHandle *handle = cls;
  438. struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
  439. if ((GNUNET_YES == GNUNET_DISK_file_test (filename)) && (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename)))
  440. {
  441. struct GNUNET_HashCode key;
  442. struct GNUNET_ShortHashCode member_id;
  443. if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "key", &key, sizeof(key))) &&
  444. (GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "member_id", &member_id, sizeof(member_id))))
  445. change_handle_member_id (handle, &key, &member_id);
  446. }
  447. GNUNET_CONFIGURATION_destroy (cfg);
  448. return GNUNET_OK;
  449. }
  450. void
  451. load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
  452. {
  453. GNUNET_assert(handle);
  454. char *id_dir;
  455. get_handle_data_subdir (handle, handle->name, &id_dir);
  456. if (GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_YES))
  457. {
  458. char *scan_dir;
  459. GNUNET_asprintf (&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
  460. if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
  461. GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_rooms, handle);
  462. GNUNET_free(scan_dir);
  463. }
  464. GNUNET_free(id_dir);
  465. }
  466. static int
  467. iterate_save_rooms (void *cls,
  468. const struct GNUNET_HashCode *key,
  469. void *value)
  470. {
  471. struct GNUNET_MESSENGER_SrvHandle *handle = cls;
  472. struct GNUNET_ShortHashCode *member_id = value;
  473. char *id_dir;
  474. get_handle_data_subdir (handle, handle->name, &id_dir);
  475. char *filename;
  476. GNUNET_asprintf (&filename, "%s%s%c%s.cfg", id_dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (key));
  477. GNUNET_free(id_dir);
  478. struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
  479. char *key_data = GNUNET_STRINGS_data_to_string_alloc (key, sizeof(*key));
  480. if (key_data)
  481. {
  482. GNUNET_CONFIGURATION_set_value_string (cfg, "room", "key", key_data);
  483. GNUNET_free(key_data);
  484. }
  485. char *member_id_data = GNUNET_STRINGS_data_to_string_alloc (member_id, sizeof(*member_id));
  486. if (member_id_data)
  487. {
  488. GNUNET_CONFIGURATION_set_value_string (cfg, "room", "member_id", member_id_data);
  489. GNUNET_free(member_id_data);
  490. }
  491. GNUNET_CONFIGURATION_write (cfg, filename);
  492. GNUNET_CONFIGURATION_destroy (cfg);
  493. GNUNET_free(filename);
  494. return GNUNET_YES;
  495. }
  496. void
  497. save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
  498. {
  499. GNUNET_assert(handle);
  500. char *id_dir;
  501. get_handle_data_subdir (handle, handle->name, &id_dir);
  502. if ((GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_NO)) || (GNUNET_OK
  503. == GNUNET_DISK_directory_create (id_dir)))
  504. {
  505. char *save_dir;
  506. GNUNET_asprintf (&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
  507. if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
  508. (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
  509. GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_save_rooms, handle);
  510. GNUNET_free(save_dir);
  511. }
  512. GNUNET_free(id_dir);
  513. }