gnunet-service-social.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538
  1. /*
  2. * This file is part of GNUnet
  3. * (C) 2013 Christian Grothoff (and other contributing authors)
  4. *
  5. * GNUnet is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published
  7. * by the Free Software Foundation; either version 3, or (at your
  8. * option) any later version.
  9. *
  10. * GNUnet is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GNUnet; see the file COPYING. If not, write to the
  17. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  18. * Boston, MA 02111-1307, USA.
  19. */
  20. /**
  21. * @file social/gnunet-service-social.c
  22. * @brief Social service
  23. * @author Gabor X Toth
  24. */
  25. #include <inttypes.h>
  26. #include "platform.h"
  27. #include "gnunet_util_lib.h"
  28. #include "gnunet_constants.h"
  29. #include "gnunet_protocols.h"
  30. #include "gnunet_statistics_service.h"
  31. #include "gnunet_psyc_service.h"
  32. #include "gnunet_psyc_util_lib.h"
  33. #include "gnunet_social_service.h"
  34. #include "social.h"
  35. /**
  36. * Handle to our current configuration.
  37. */
  38. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  39. /**
  40. * Handle to the statistics service.
  41. */
  42. static struct GNUNET_STATISTICS_Handle *stats;
  43. /**
  44. * Notification context, simplifies client broadcasts.
  45. */
  46. static struct GNUNET_SERVER_NotificationContext *nc;
  47. /**
  48. * All connected hosts.
  49. * Place's pub_key_hash -> struct Host
  50. */
  51. static struct GNUNET_CONTAINER_MultiHashMap *hosts;
  52. /**
  53. * All connected guests.
  54. * Place's pub_key_hash -> struct Guest
  55. */
  56. static struct GNUNET_CONTAINER_MultiHashMap *guests;
  57. /**
  58. * Connected guests per place.
  59. * Place's pub_key_hash -> Guest's pub_key -> struct Guest
  60. */
  61. static struct GNUNET_CONTAINER_MultiHashMap *place_guests;
  62. /**
  63. * Message fragment transmission queue.
  64. */
  65. struct FragmentTransmitQueue
  66. {
  67. struct FragmentTransmitQueue *prev;
  68. struct FragmentTransmitQueue *next;
  69. struct GNUNET_SERVER_Client *client;
  70. /**
  71. * Pointer to the next message part inside the data after this struct.
  72. */
  73. struct GNUNET_MessageHeader *next_part;
  74. /**
  75. * Size of message.
  76. */
  77. uint16_t size;
  78. /**
  79. * @see enum GNUNET_PSYC_MessageState
  80. */
  81. uint8_t state;
  82. /* Followed by one or more message parts. */
  83. };
  84. /**
  85. * Message transmission queue.
  86. */
  87. struct MessageTransmitQueue
  88. {
  89. struct MessageTransmitQueue *prev;
  90. struct MessageTransmitQueue *next;
  91. struct FragmentTransmitQueue *frags_head;
  92. struct FragmentTransmitQueue *frags_tail;
  93. struct GNUNET_SERVER_Client *client;
  94. };
  95. /**
  96. * List of connected clients.
  97. */
  98. struct ClientListItem
  99. {
  100. struct ClientListItem *prev;
  101. struct ClientListItem *next;
  102. struct GNUNET_SERVER_Client *client;
  103. };
  104. /**
  105. * Common part of the client context for both a host and guest.
  106. */
  107. struct Place
  108. {
  109. struct ClientListItem *clients_head;
  110. struct ClientListItem *clients_tail;
  111. struct MessageTransmitQueue *tmit_msgs_head;
  112. struct MessageTransmitQueue *tmit_msgs_tail;
  113. /**
  114. * Public key of the channel.
  115. */
  116. struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
  117. /**
  118. * Hash of @a pub_key.
  119. */
  120. struct GNUNET_HashCode pub_key_hash;
  121. /**
  122. * Last message ID received for the place.
  123. * 0 if there is no such message.
  124. */
  125. uint64_t max_message_id;
  126. /**
  127. * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)?
  128. */
  129. uint8_t is_host;
  130. /**
  131. * Is this place ready to receive messages from client?
  132. * #GNUNET_YES or #GNUNET_NO
  133. */
  134. uint8_t is_ready;
  135. /**
  136. * Is the client disconnected?
  137. * #GNUNET_YES or #GNUNET_NO
  138. */
  139. uint8_t is_disconnected;
  140. };
  141. /**
  142. * Client context for a host.
  143. */
  144. struct Host
  145. {
  146. /**
  147. * Place struct common for Host and Guest
  148. */
  149. struct Place plc;
  150. /**
  151. * Private key of the channel.
  152. */
  153. struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
  154. /**
  155. * Handle for the multicast origin.
  156. */
  157. struct GNUNET_PSYC_Master *master;
  158. /**
  159. * Transmit handle for multicast.
  160. */
  161. struct GNUNET_PSYC_MasterTransmitHandle *tmit_handle;
  162. /**
  163. * Incoming join requests.
  164. * guest_key -> struct GNUNET_PSYC_JoinHandle *
  165. */
  166. struct GNUNET_CONTAINER_MultiHashMap *join_reqs;
  167. /**
  168. * @see enum GNUNET_PSYC_Policy
  169. */
  170. enum GNUNET_PSYC_Policy policy;
  171. };
  172. /**
  173. * Client context for a guest.
  174. */
  175. struct Guest
  176. {
  177. /**
  178. * Place struct common for Host and Guest.
  179. */
  180. struct Place plc;
  181. /**
  182. * Private key of the slave.
  183. */
  184. struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
  185. /**
  186. * Public key of the slave.
  187. */
  188. struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
  189. /**
  190. * Hash of @a pub_key.
  191. */
  192. struct GNUNET_HashCode pub_key_hash;
  193. /**
  194. * Handle for the PSYC slave.
  195. */
  196. struct GNUNET_PSYC_Slave *slave;
  197. /**
  198. * Transmit handle for multicast.
  199. */
  200. struct GNUNET_PSYC_SlaveTransmitHandle *tmit_handle;
  201. /**
  202. * Peer identity of the origin.
  203. */
  204. struct GNUNET_PeerIdentity origin;
  205. /**
  206. * Number of items in @a relays.
  207. */
  208. uint32_t relay_count;
  209. /**
  210. * Relays that multicast can use to connect.
  211. */
  212. struct GNUNET_PeerIdentity *relays;
  213. /**
  214. * Join request to be transmitted to the master on join.
  215. */
  216. struct GNUNET_MessageHeader *join_req;
  217. /**
  218. * Join decision received from PSYC.
  219. */
  220. struct GNUNET_PSYC_JoinDecisionMessage *join_dcsn;
  221. };
  222. struct Client
  223. {
  224. /**
  225. * Place where the client entered.
  226. */
  227. struct Place *plc;
  228. /**
  229. * Message queue for the message currently being transmitted
  230. * by this client.
  231. */
  232. struct MessageTransmitQueue *tmit_msg;
  233. };
  234. static int
  235. psyc_transmit_message (struct Place *plc);
  236. /**
  237. * Task run during shutdown.
  238. *
  239. * @param cls unused
  240. * @param tc unused
  241. */
  242. static void
  243. shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  244. {
  245. if (NULL != nc)
  246. {
  247. GNUNET_SERVER_notification_context_destroy (nc);
  248. nc = NULL;
  249. }
  250. if (NULL != stats)
  251. {
  252. GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
  253. stats = NULL;
  254. }
  255. }
  256. /**
  257. * Clean up host data structures after a client disconnected.
  258. */
  259. static void
  260. cleanup_host (struct Host *hst)
  261. {
  262. struct Place *plc = &hst->plc;
  263. if (NULL != hst->master)
  264. GNUNET_PSYC_master_stop (hst->master, GNUNET_NO, NULL, NULL); // FIXME
  265. GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs);
  266. GNUNET_CONTAINER_multihashmap_remove (hosts, &plc->pub_key_hash, plc);
  267. }
  268. /**
  269. * Clean up guest data structures after a client disconnected.
  270. */
  271. static void
  272. cleanup_guest (struct Guest *gst)
  273. {
  274. struct Place *plc = &gst->plc;
  275. struct GNUNET_CONTAINER_MultiHashMap *
  276. plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
  277. &plc->pub_key_hash);
  278. GNUNET_assert (NULL != plc_gst);
  279. GNUNET_CONTAINER_multihashmap_remove (plc_gst, &gst->pub_key_hash, gst);
  280. if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst))
  281. {
  282. GNUNET_CONTAINER_multihashmap_remove (place_guests, &plc->pub_key_hash,
  283. plc_gst);
  284. GNUNET_CONTAINER_multihashmap_destroy (plc_gst);
  285. }
  286. GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, gst);
  287. if (NULL != gst->join_req)
  288. GNUNET_free (gst->join_req);
  289. if (NULL != gst->relays)
  290. GNUNET_free (gst->relays);
  291. if (NULL != gst->slave)
  292. GNUNET_PSYC_slave_part (gst->slave, GNUNET_NO, NULL, NULL); // FIXME
  293. GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, plc);
  294. }
  295. /**
  296. * Clean up place data structures after a client disconnected.
  297. */
  298. static void
  299. cleanup_place (struct Place *plc)
  300. {
  301. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  302. "%p Cleaning up place %s\n",
  303. plc, GNUNET_h2s (&plc->pub_key_hash));
  304. (GNUNET_YES == plc->is_host)
  305. ? cleanup_host ((struct Host *) plc)
  306. : cleanup_guest ((struct Guest *) plc);
  307. GNUNET_free (plc);
  308. }
  309. static void
  310. schedule_cleanup_place (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  311. {
  312. cleanup_place (cls);
  313. }
  314. /**
  315. * Called whenever a client is disconnected.
  316. * Frees our resources associated with that client.
  317. *
  318. * @param cls Closure.
  319. * @param client Identification of the client.
  320. */
  321. static void
  322. client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
  323. {
  324. if (NULL == client)
  325. return;
  326. struct Client *
  327. ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
  328. if (NULL == ctx)
  329. {
  330. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  331. "%p User context is NULL in client_disconnect()\n", ctx);
  332. GNUNET_break (0);
  333. return;
  334. }
  335. struct Place *plc = ctx->plc;
  336. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  337. "%p Client (%s) disconnected from place %s\n",
  338. plc, (GNUNET_YES == plc->is_host) ? "host" : "guest",
  339. GNUNET_h2s (&plc->pub_key_hash));
  340. struct ClientListItem *cli = plc->clients_head;
  341. while (NULL != cli)
  342. {
  343. if (cli->client == client)
  344. {
  345. GNUNET_CONTAINER_DLL_remove (plc->clients_head, plc->clients_tail, cli);
  346. GNUNET_free (cli);
  347. break;
  348. }
  349. cli = cli->next;
  350. }
  351. if (NULL == plc->clients_head)
  352. { /* Last client disconnected. */
  353. if (GNUNET_YES != plc->is_disconnected)
  354. {
  355. plc->is_disconnected = GNUNET_YES;
  356. if (NULL != plc->tmit_msgs_head)
  357. { /* Send pending messages to PSYC before cleanup. */
  358. psyc_transmit_message (plc);
  359. }
  360. else
  361. {
  362. cleanup_place (plc);
  363. }
  364. }
  365. }
  366. }
  367. /**
  368. * Send message to all clients connected to the channel.
  369. */
  370. static void
  371. client_send_msg (const struct Place *plc,
  372. const struct GNUNET_MessageHeader *msg)
  373. {
  374. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  375. "%p Sending message to clients.\n", plc);
  376. struct ClientListItem *cli = plc->clients_head;
  377. while (NULL != cli)
  378. {
  379. GNUNET_SERVER_notification_context_add (nc, cli->client);
  380. GNUNET_SERVER_notification_context_unicast (nc, cli->client, msg, GNUNET_NO);
  381. cli = cli->next;
  382. }
  383. }
  384. /**
  385. * Called after a PSYC master is started.
  386. */
  387. static void
  388. psyc_master_started (void *cls, int result, uint64_t max_message_id)
  389. {
  390. struct Host *hst = cls;
  391. struct Place *plc = &hst->plc;
  392. plc->max_message_id = max_message_id;
  393. plc->is_ready = GNUNET_YES;
  394. struct GNUNET_PSYC_CountersResultMessage res;
  395. res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
  396. res.header.size = htons (sizeof (res));
  397. res.result_code = htonl (result - INT32_MIN);
  398. res.max_message_id = GNUNET_htonll (plc->max_message_id);
  399. client_send_msg (plc, &res.header);
  400. }
  401. /**
  402. * Called when a PSYC master receives a join request.
  403. */
  404. static void
  405. psyc_recv_join_request (void *cls,
  406. const struct GNUNET_PSYC_JoinRequestMessage *req,
  407. const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
  408. const struct GNUNET_PSYC_Message *join_msg,
  409. struct GNUNET_PSYC_JoinHandle *jh)
  410. {
  411. struct Host *hst = cls;
  412. struct GNUNET_HashCode slave_key_hash;
  413. GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
  414. GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh,
  415. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  416. client_send_msg (&hst->plc, &req->header);
  417. }
  418. /**
  419. * Called after a PSYC slave is connected.
  420. */
  421. static void
  422. psyc_slave_connected (void *cls, int result, uint64_t max_message_id)
  423. {
  424. struct Guest *gst = cls;
  425. struct Place *plc = &gst->plc;
  426. plc->max_message_id = max_message_id;
  427. plc->is_ready = GNUNET_YES;
  428. struct GNUNET_PSYC_CountersResultMessage res;
  429. res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
  430. res.header.size = htons (sizeof (res));
  431. res.result_code = htonl (result - INT32_MIN);
  432. res.max_message_id = GNUNET_htonll (plc->max_message_id);
  433. client_send_msg (plc, &res.header);
  434. }
  435. /**
  436. * Called when a PSYC slave receives a join decision.
  437. */
  438. static void
  439. psyc_recv_join_dcsn (void *cls,
  440. const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
  441. int is_admitted,
  442. const struct GNUNET_PSYC_Message *join_msg)
  443. {
  444. struct Guest *gst = cls;
  445. client_send_msg (&gst->plc, &dcsn->header);
  446. }
  447. /**
  448. * Called when a PSYC master or slave receives a message.
  449. */
  450. static void
  451. psyc_recv_message (void *cls,
  452. uint64_t message_id,
  453. uint32_t flags,
  454. const struct GNUNET_PSYC_MessageHeader *msg)
  455. {
  456. struct Place *plc = cls;
  457. client_send_msg (plc, &msg->header);
  458. /* FIXME: further processing */
  459. }
  460. /**
  461. * Initialize place data structure.
  462. */
  463. static void
  464. place_init (struct Place *plc)
  465. {
  466. }
  467. /**
  468. * Handle a connecting client entering a place as host.
  469. */
  470. static void
  471. client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client,
  472. const struct GNUNET_MessageHeader *msg)
  473. {
  474. const struct HostEnterRequest *req
  475. = (const struct HostEnterRequest *) msg;
  476. struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
  477. struct GNUNET_HashCode pub_key_hash;
  478. GNUNET_CRYPTO_eddsa_key_get_public (&req->place_key, &pub_key);
  479. GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
  480. struct Host *
  481. hst = GNUNET_CONTAINER_multihashmap_get (hosts, &pub_key_hash);
  482. struct Place *plc;
  483. if (NULL == hst)
  484. {
  485. hst = GNUNET_new (struct Host);
  486. hst->policy = ntohl (req->policy);
  487. hst->priv_key = req->place_key;
  488. hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  489. plc = &hst->plc;
  490. plc->is_host = GNUNET_YES;
  491. plc->pub_key = pub_key;
  492. plc->pub_key_hash = pub_key_hash;
  493. place_init (plc);
  494. GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc,
  495. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  496. hst->master = GNUNET_PSYC_master_start (cfg, &hst->priv_key, hst->policy,
  497. &psyc_master_started,
  498. &psyc_recv_join_request,
  499. &psyc_recv_message, NULL, hst);
  500. }
  501. else
  502. {
  503. plc = &hst->plc;
  504. struct GNUNET_PSYC_CountersResultMessage res;
  505. res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
  506. res.header.size = htons (sizeof (res));
  507. res.result_code = htonl (GNUNET_OK);
  508. res.max_message_id = GNUNET_htonll (plc->max_message_id);
  509. GNUNET_SERVER_notification_context_add (nc, client);
  510. GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
  511. GNUNET_NO);
  512. }
  513. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  514. "%p Client connected as host to place %s.\n",
  515. hst, GNUNET_h2s (&plc->pub_key_hash));
  516. struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
  517. cli->client = client;
  518. GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
  519. struct Client *ctx = GNUNET_new (struct Client);
  520. ctx->plc = plc;
  521. GNUNET_SERVER_client_set_user_context (client, ctx);
  522. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  523. }
  524. /**
  525. * Handle a connecting client entering a place as guest.
  526. */
  527. static void
  528. client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
  529. const struct GNUNET_MessageHeader *msg)
  530. {
  531. const struct GuestEnterRequest *req
  532. = (const struct GuestEnterRequest *) msg;
  533. uint16_t req_size = ntohs (req->header.size);
  534. struct GNUNET_CRYPTO_EcdsaPublicKey gst_pub_key;
  535. struct GNUNET_HashCode pub_key_hash, gst_pub_key_hash;
  536. GNUNET_CRYPTO_ecdsa_key_get_public (&req->guest_key, &gst_pub_key);
  537. GNUNET_CRYPTO_hash (&gst_pub_key, sizeof (gst_pub_key), &gst_pub_key_hash);
  538. GNUNET_CRYPTO_hash (&req->place_key, sizeof (req->place_key), &pub_key_hash);
  539. struct GNUNET_CONTAINER_MultiHashMap *
  540. plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &pub_key_hash);
  541. struct Guest *gst = NULL;
  542. struct Place *plc;
  543. if (NULL != plc_gst)
  544. {
  545. gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &gst_pub_key_hash);
  546. }
  547. if (NULL == gst || NULL == gst->slave)
  548. {
  549. gst = GNUNET_new (struct Guest);
  550. gst->priv_key = req->guest_key;
  551. gst->pub_key = gst_pub_key;
  552. gst->pub_key_hash = gst_pub_key_hash;
  553. gst->origin = req->origin;
  554. gst->relay_count = ntohl (req->relay_count);
  555. const struct GNUNET_PeerIdentity *
  556. relays = (const struct GNUNET_PeerIdentity *) &req[1];
  557. uint16_t relay_size = gst->relay_count * sizeof (*relays);
  558. struct GNUNET_PSYC_Message *join_msg = NULL;
  559. uint16_t join_msg_size = 0;
  560. if (sizeof (*req) + relay_size + sizeof (struct GNUNET_MessageHeader)
  561. <= req_size)
  562. {
  563. join_msg = (struct GNUNET_PSYC_Message *)
  564. (((char *) &req[1]) + relay_size);
  565. join_msg_size = ntohs (join_msg->header.size);
  566. }
  567. if (sizeof (*req) + relay_size + join_msg_size != req_size)
  568. {
  569. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  570. "%u + %u + %u != %u\n",
  571. sizeof (*req), relay_size, join_msg_size, req_size);
  572. GNUNET_break (0);
  573. GNUNET_SERVER_client_disconnect (client);
  574. return;
  575. }
  576. if (0 < gst->relay_count)
  577. {
  578. gst->relays = GNUNET_malloc (relay_size);
  579. memcpy (gst->relays, &req[1], relay_size);
  580. }
  581. plc = &gst->plc;
  582. plc->is_host = GNUNET_NO;
  583. plc->pub_key = req->place_key;
  584. plc->pub_key_hash = pub_key_hash;
  585. place_init (plc);
  586. if (NULL == plc_gst)
  587. {
  588. plc_gst = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  589. GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst,
  590. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  591. }
  592. GNUNET_CONTAINER_multihashmap_put (plc_gst, &gst->pub_key_hash, plc,
  593. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  594. GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, plc,
  595. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  596. gst->slave
  597. = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &gst->priv_key,
  598. &gst->origin, gst->relay_count, gst->relays,
  599. &psyc_recv_message, NULL, &psyc_slave_connected,
  600. &psyc_recv_join_dcsn, gst, join_msg);
  601. }
  602. else
  603. {
  604. plc = &gst->plc;
  605. struct GNUNET_PSYC_CountersResultMessage res;
  606. res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
  607. res.header.size = htons (sizeof (res));
  608. res.result_code = htonl (GNUNET_OK);
  609. res.max_message_id = GNUNET_htonll (plc->max_message_id);
  610. GNUNET_SERVER_notification_context_add (nc, client);
  611. GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
  612. GNUNET_NO);
  613. if (NULL != gst->join_dcsn)
  614. {
  615. GNUNET_SERVER_notification_context_add (nc, client);
  616. GNUNET_SERVER_notification_context_unicast (nc, client,
  617. &gst->join_dcsn->header,
  618. GNUNET_NO);
  619. }
  620. }
  621. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  622. "%p Client connected as guest to place %s.\n",
  623. gst, GNUNET_h2s (&plc->pub_key_hash));
  624. struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
  625. cli->client = client;
  626. GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
  627. struct Client *ctx = GNUNET_new (struct Client);
  628. ctx->plc = plc;
  629. GNUNET_SERVER_client_set_user_context (client, ctx);
  630. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  631. }
  632. struct JoinDecisionClosure
  633. {
  634. int32_t is_admitted;
  635. struct GNUNET_PSYC_Message *msg;
  636. };
  637. /**
  638. * Iterator callback for responding to join requests.
  639. */
  640. static int
  641. psyc_send_join_decision (void *cls, const struct GNUNET_HashCode *pub_key_hash,
  642. void *value)
  643. {
  644. struct JoinDecisionClosure *jcls = cls;
  645. struct GNUNET_PSYC_JoinHandle *jh = value;
  646. // FIXME: add relays
  647. GNUNET_PSYC_join_decision (jh, jcls->is_admitted, 0, NULL, jcls->msg);
  648. return GNUNET_YES;
  649. }
  650. /**
  651. * Handle an entry decision from a host client.
  652. */
  653. static void
  654. client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
  655. const struct GNUNET_MessageHeader *msg)
  656. {
  657. struct Client *
  658. ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
  659. GNUNET_assert (NULL != ctx);
  660. struct Place *plc = ctx->plc;
  661. GNUNET_assert (GNUNET_YES == plc->is_host);
  662. struct Host *hst = (struct Host *) plc;
  663. struct GNUNET_PSYC_JoinDecisionMessage *
  664. dcsn = (struct GNUNET_PSYC_JoinDecisionMessage *) msg;
  665. struct JoinDecisionClosure jcls;
  666. jcls.is_admitted = ntohl (dcsn->is_admitted);
  667. jcls.msg
  668. = (sizeof (*dcsn) + sizeof (*jcls.msg) <= ntohs (msg->size))
  669. ? (struct GNUNET_PSYC_Message *) &dcsn[1]
  670. : NULL;
  671. struct GNUNET_HashCode slave_key_hash;
  672. GNUNET_CRYPTO_hash (&dcsn->slave_key, sizeof (dcsn->slave_key),
  673. &slave_key_hash);
  674. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  675. "%p Got join decision (%d) from client for place %s..\n",
  676. hst, jcls.is_admitted, GNUNET_h2s (&plc->pub_key_hash));
  677. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  678. "%p ..and slave %s.\n",
  679. hst, GNUNET_h2s (&slave_key_hash));
  680. GNUNET_CONTAINER_multihashmap_get_multiple (hst->join_reqs, &slave_key_hash,
  681. &psyc_send_join_decision, &jcls);
  682. GNUNET_CONTAINER_multihashmap_remove_all (hst->join_reqs, &slave_key_hash);
  683. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  684. }
  685. /**
  686. * Send acknowledgement to a client.
  687. *
  688. * Sent after a message fragment has been passed on to multicast.
  689. *
  690. * @param plc The place struct for the client.
  691. */
  692. static void
  693. send_message_ack (struct Place *plc, struct GNUNET_SERVER_Client *client)
  694. {
  695. struct GNUNET_MessageHeader res;
  696. res.size = htons (sizeof (res));
  697. res.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK);
  698. GNUNET_SERVER_notification_context_add (nc, client);
  699. GNUNET_SERVER_notification_context_unicast (nc, client, &res, GNUNET_NO);
  700. }
  701. /**
  702. * Proceed to the next message part in the transmission queue.
  703. *
  704. * @param plc
  705. * Place where the transmission is going on.
  706. * @param tmit_msg
  707. * Currently transmitted message.
  708. * @param tmit_frag
  709. * Currently transmitted message fragment.
  710. *
  711. * @return @a tmit_frag, or NULL if reached the end of fragment.
  712. */
  713. static struct FragmentTransmitQueue *
  714. psyc_transmit_queue_next_part (struct Place *plc,
  715. struct MessageTransmitQueue *tmit_msg,
  716. struct FragmentTransmitQueue *tmit_frag)
  717. {
  718. uint16_t psize = ntohs (tmit_frag->next_part->size);
  719. if ((char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1])
  720. < tmit_frag->size)
  721. {
  722. tmit_frag->next_part
  723. = (struct GNUNET_MessageHeader *) ((char *) tmit_frag->next_part + psize);
  724. }
  725. else /* Reached end of current fragment. */
  726. {
  727. if (NULL != tmit_frag->client)
  728. send_message_ack (plc, tmit_frag->client);
  729. GNUNET_CONTAINER_DLL_remove (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag);
  730. GNUNET_free (tmit_frag);
  731. tmit_frag = NULL;
  732. }
  733. return tmit_frag;
  734. }
  735. /**
  736. * Proceed to next message in transmission queue.
  737. *
  738. * @param plc
  739. * Place where the transmission is going on.
  740. * @param tmit_msg
  741. * Currently transmitted message.
  742. *
  743. * @return The next message in queue, or NULL if queue is empty.
  744. */
  745. static struct MessageTransmitQueue *
  746. psyc_transmit_queue_next_msg (struct Place *plc,
  747. struct MessageTransmitQueue *tmit_msg)
  748. {
  749. GNUNET_CONTAINER_DLL_remove (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg);
  750. GNUNET_free (tmit_msg);
  751. return plc->tmit_msgs_head;
  752. }
  753. /**
  754. * Callback for data transmission to PSYC.
  755. */
  756. static int
  757. psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  758. {
  759. struct Place *plc = cls;
  760. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  761. GNUNET_assert (NULL != tmit_msg);
  762. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  763. if (NULL == tmit_frag)
  764. { /* Rest of the message have not arrived yet, pause transmission */
  765. *data_size = 0;
  766. return GNUNET_NO;
  767. }
  768. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  769. if (NULL == pmsg)
  770. {
  771. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  772. "%p psyc_transmit_notify_data: nothing to send.\n", plc);
  773. *data_size = 0;
  774. return GNUNET_NO;
  775. }
  776. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  777. "%p psyc_transmit_notify_data()\n", plc);
  778. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
  779. uint16_t ptype = ntohs (pmsg->type);
  780. uint16_t pdata_size = ntohs (pmsg->size) - sizeof (*pmsg);
  781. int ret;
  782. switch (ptype)
  783. {
  784. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
  785. if (*data_size < pdata_size)
  786. {
  787. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  788. "%p psyc_transmit_notify_data: buffer size too small for data.\n", plc);
  789. *data_size = 0;
  790. return GNUNET_NO;
  791. }
  792. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  793. "%p psyc_transmit_notify_data: sending %u bytes.\n",
  794. plc, pdata_size);
  795. *data_size = pdata_size;
  796. memcpy (data, &pmsg[1], *data_size);
  797. ret = GNUNET_NO;
  798. break;
  799. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  800. *data_size = 0;
  801. ret = GNUNET_YES;
  802. break;
  803. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  804. *data_size = 0;
  805. ret = GNUNET_SYSERR;
  806. break;
  807. default:
  808. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  809. "%p psyc_transmit_notify_data: unexpected message part of type %u.\n",
  810. plc, ptype);
  811. ret = GNUNET_SYSERR;
  812. }
  813. if (GNUNET_SYSERR == ret && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL != ptype)
  814. {
  815. *data_size = 0;
  816. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  817. plc->is_disconnected = GNUNET_YES;
  818. GNUNET_SERVER_client_disconnect (tmit_frag->client);
  819. GNUNET_SCHEDULER_add_now (&schedule_cleanup_place, plc);
  820. return ret;
  821. }
  822. else
  823. {
  824. tmit_frag = psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  825. if (NULL != tmit_frag)
  826. {
  827. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  828. ptype = ntohs (pmsg->type);
  829. switch (ptype)
  830. {
  831. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  832. ret = GNUNET_YES;
  833. break;
  834. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  835. ret = GNUNET_SYSERR;
  836. break;
  837. }
  838. switch (ptype)
  839. {
  840. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  841. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  842. tmit_frag = psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  843. }
  844. }
  845. if (NULL == tmit_msg->frags_head
  846. && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
  847. { /* Reached end of current message. */
  848. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  849. }
  850. }
  851. if (ret != GNUNET_NO)
  852. {
  853. if (NULL != tmit_msg)
  854. {
  855. psyc_transmit_message (plc);
  856. }
  857. else if (GNUNET_YES == plc->is_disconnected)
  858. {
  859. /* FIXME: handle partial message (when still in_transmit) */
  860. cleanup_place (plc);
  861. }
  862. }
  863. return ret;
  864. }
  865. /**
  866. * Callback for modifier transmission to PSYC.
  867. */
  868. static int
  869. psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  870. uint8_t *oper, uint32_t *full_value_size)
  871. {
  872. struct Place *plc = cls;
  873. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  874. GNUNET_assert (NULL != tmit_msg);
  875. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  876. if (NULL == tmit_frag)
  877. { /* Rest of the message have not arrived yet, pause transmission */
  878. *data_size = 0;
  879. return GNUNET_NO;
  880. }
  881. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  882. if (NULL == pmsg)
  883. {
  884. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  885. "%p psyc_transmit_notify_mod: nothing to send.\n", plc);
  886. *data_size = 0;
  887. return GNUNET_NO;
  888. }
  889. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  890. "%p psyc_transmit_notify_mod()\n", plc);
  891. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
  892. uint16_t ptype = ntohs (pmsg->type);
  893. int ret;
  894. switch (ptype)
  895. {
  896. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
  897. {
  898. if (NULL == oper)
  899. {
  900. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  901. "%p psyc_transmit_notify_mod: oper is NULL.\n", plc);
  902. ret = GNUNET_SYSERR;
  903. break;
  904. }
  905. struct GNUNET_PSYC_MessageModifier *
  906. pmod = (struct GNUNET_PSYC_MessageModifier *) tmit_frag->next_part;
  907. uint16_t mod_size = ntohs (pmod->header.size) - sizeof (*pmod);
  908. if (*data_size < mod_size)
  909. {
  910. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  911. "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc);
  912. *data_size = 0;
  913. return GNUNET_NO;
  914. }
  915. *full_value_size = ntohl (pmod->value_size);
  916. *oper = pmod->oper;
  917. *data_size = mod_size;
  918. memcpy (data, &pmod[1], mod_size);
  919. ret = GNUNET_NO;
  920. break;
  921. }
  922. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
  923. {
  924. if (NULL != oper)
  925. {
  926. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  927. "%p psyc_transmit_notify_mod: oper is not NULL.\n", plc);
  928. ret = GNUNET_SYSERR;
  929. break;
  930. }
  931. uint16_t mod_size = ntohs (pmsg->size) - sizeof (*pmsg);
  932. if (*data_size < mod_size)
  933. {
  934. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  935. "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc);
  936. *data_size = 0;
  937. return GNUNET_NO;
  938. }
  939. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  940. "%p psyc_transmit_notify_mod: sending %u bytes.\n", plc, mod_size);
  941. *data_size = mod_size;
  942. memcpy (data, &pmsg[1], *data_size);
  943. ret = GNUNET_NO;
  944. break;
  945. }
  946. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
  947. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  948. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  949. *data_size = 0;
  950. ret = GNUNET_YES;
  951. break;
  952. default:
  953. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  954. "%p psyc_transmit_notify_mod: unexpected message part of type %u.\n",
  955. plc, ptype);
  956. ret = GNUNET_SYSERR;
  957. }
  958. if (GNUNET_SYSERR == ret)
  959. {
  960. *data_size = 0;
  961. ret = GNUNET_SYSERR;
  962. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  963. plc->is_disconnected = GNUNET_YES;
  964. GNUNET_SERVER_client_disconnect (tmit_frag->client);
  965. GNUNET_SCHEDULER_add_now (&schedule_cleanup_place, plc);
  966. }
  967. else
  968. {
  969. if (GNUNET_YES != ret)
  970. psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  971. if (NULL == tmit_msg->frags_head
  972. && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
  973. { /* Reached end of current message. */
  974. tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
  975. }
  976. }
  977. return ret;
  978. }
  979. /**
  980. * Callback for data transmission from a host to PSYC.
  981. */
  982. static int
  983. host_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  984. {
  985. int ret = psyc_transmit_notify_data (cls, data_size, data);
  986. if (GNUNET_NO != ret)
  987. {
  988. struct Host *hst = cls;
  989. hst->tmit_handle = NULL;
  990. }
  991. return ret;
  992. }
  993. /**
  994. * Callback for the transmit functions of multicast.
  995. */
  996. static int
  997. guest_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
  998. {
  999. int ret = psyc_transmit_notify_data (cls, data_size, data);
  1000. if (GNUNET_NO != ret)
  1001. {
  1002. struct Guest *gst = cls;
  1003. gst->tmit_handle = NULL;
  1004. }
  1005. return ret;
  1006. }
  1007. /**
  1008. * Callback for modifier transmission from a host to PSYC.
  1009. */
  1010. static int
  1011. host_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  1012. uint8_t *oper, uint32_t *full_value_size)
  1013. {
  1014. int ret = psyc_transmit_notify_mod (cls, data_size, data,
  1015. oper, full_value_size);
  1016. if (GNUNET_SYSERR == ret)
  1017. {
  1018. struct Host *hst = cls;
  1019. hst->tmit_handle = NULL;
  1020. }
  1021. return ret;
  1022. }
  1023. /**
  1024. * Callback for modifier transmission from a guest to PSYC.
  1025. */
  1026. static int
  1027. guest_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
  1028. uint8_t *oper, uint32_t *full_value_size)
  1029. {
  1030. int ret = psyc_transmit_notify_mod (cls, data_size, data,
  1031. oper, full_value_size);
  1032. if (GNUNET_SYSERR == ret)
  1033. {
  1034. struct Guest *gst = cls;
  1035. gst->tmit_handle = NULL;
  1036. }
  1037. return ret;
  1038. }
  1039. /**
  1040. * Get method part of next message from transmission queue.
  1041. *
  1042. * @param tmit_msg
  1043. * Next item in message transmission queue.
  1044. * @param[out] pmeth
  1045. * The message method is returned here.
  1046. *
  1047. * @return #GNUNET_OK on success
  1048. * #GNUNET_NO if there are no more messages in queue.
  1049. * #GNUNET_SYSERR if the next message is malformed.
  1050. */
  1051. static int
  1052. psyc_transmit_queue_next_method (struct Place *plc,
  1053. struct GNUNET_PSYC_MessageMethod **pmeth)
  1054. {
  1055. struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
  1056. if (NULL == tmit_msg)
  1057. return GNUNET_NO;
  1058. struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
  1059. if (NULL == tmit_frag)
  1060. {
  1061. GNUNET_break (0);
  1062. return GNUNET_NO;
  1063. }
  1064. struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
  1065. if (NULL == pmsg
  1066. || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD != ntohs (pmsg->type))
  1067. {
  1068. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1069. "%p psyc_transmit_queue_next_method: unexpected message part of type %u.\n",
  1070. plc, ntohs (pmsg->type));
  1071. GNUNET_break (0);
  1072. return GNUNET_SYSERR;
  1073. }
  1074. uint16_t psize = ntohs (pmsg->size);
  1075. *pmeth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
  1076. if (psize < sizeof (**pmeth) + 1 || '\0' != *((char *) *pmeth + psize - 1))
  1077. {
  1078. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1079. "%p psyc_transmit_queue_next_method: invalid method name.\n",
  1080. plc, ntohs (pmsg->type));
  1081. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1082. "%u <= %u || NUL != %u\n",
  1083. sizeof (**pmeth), psize, *((char *) *pmeth + psize - 1));
  1084. GNUNET_break (0);
  1085. return GNUNET_SYSERR;
  1086. }
  1087. psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
  1088. return GNUNET_OK;
  1089. }
  1090. /**
  1091. * Transmit the next message in queue from the host to the PSYC channel.
  1092. */
  1093. static int
  1094. psyc_master_transmit_message (struct Host *hst)
  1095. {
  1096. if (NULL == hst->tmit_handle)
  1097. {
  1098. struct GNUNET_PSYC_MessageMethod *pmeth = NULL;
  1099. int ret = psyc_transmit_queue_next_method (&hst->plc, &pmeth);
  1100. if (GNUNET_OK != ret)
  1101. return ret;
  1102. hst->tmit_handle
  1103. = GNUNET_PSYC_master_transmit (hst->master, (const char *) &pmeth[1],
  1104. &host_transmit_notify_mod,
  1105. &host_transmit_notify_data, hst,
  1106. pmeth->flags);
  1107. }
  1108. else
  1109. {
  1110. GNUNET_PSYC_master_transmit_resume (hst->tmit_handle);
  1111. }
  1112. return GNUNET_OK;
  1113. }
  1114. /**
  1115. * Transmit the next message in queue from a guest to the PSYC channel.
  1116. */
  1117. static int
  1118. psyc_slave_transmit_message (struct Guest *gst)
  1119. {
  1120. if (NULL == gst->tmit_handle)
  1121. {
  1122. struct GNUNET_PSYC_MessageMethod *pmeth = NULL;
  1123. int ret = psyc_transmit_queue_next_method (&gst->plc, &pmeth);
  1124. if (GNUNET_OK != ret)
  1125. return ret;
  1126. gst->tmit_handle
  1127. = GNUNET_PSYC_slave_transmit (gst->slave, (const char *) &pmeth[1],
  1128. &guest_transmit_notify_mod,
  1129. &guest_transmit_notify_data, gst,
  1130. pmeth->flags);
  1131. }
  1132. else
  1133. {
  1134. GNUNET_PSYC_slave_transmit_resume (gst->tmit_handle);
  1135. }
  1136. return GNUNET_OK;
  1137. }
  1138. /**
  1139. * Transmit a message to PSYC.
  1140. */
  1141. static int
  1142. psyc_transmit_message (struct Place *plc)
  1143. {
  1144. return
  1145. (plc->is_host)
  1146. ? psyc_master_transmit_message ((struct Host *) plc)
  1147. : psyc_slave_transmit_message ((struct Guest *) plc);
  1148. }
  1149. /**
  1150. * Queue message parts for sending to PSYC.
  1151. *
  1152. * @param plc Place to send to.
  1153. * @param client Client the message originates from.
  1154. * @param data_size Size of @a data.
  1155. * @param data Concatenated message parts.
  1156. * @param first_ptype First message part type in @a data.
  1157. * @param last_ptype Last message part type in @a data.
  1158. */
  1159. static struct MessageTransmitQueue *
  1160. psyc_transmit_queue_message (struct Place *plc,
  1161. struct GNUNET_SERVER_Client *client,
  1162. size_t data_size,
  1163. const void *data,
  1164. uint16_t first_ptype, uint16_t last_ptype,
  1165. struct MessageTransmitQueue *tmit_msg)
  1166. {
  1167. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == first_ptype)
  1168. {
  1169. tmit_msg = GNUNET_malloc (sizeof (*tmit_msg));
  1170. GNUNET_CONTAINER_DLL_insert_tail (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg);
  1171. }
  1172. else if (NULL == tmit_msg)
  1173. {
  1174. return NULL;
  1175. }
  1176. struct FragmentTransmitQueue *
  1177. tmit_frag = GNUNET_malloc (sizeof (*tmit_frag) + data_size);
  1178. memcpy (&tmit_frag[1], data, data_size);
  1179. tmit_frag->next_part = (struct GNUNET_MessageHeader *) &tmit_frag[1];
  1180. tmit_frag->client = client;
  1181. tmit_frag->size = data_size;
  1182. GNUNET_CONTAINER_DLL_insert_tail (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag);
  1183. tmit_msg->client = client;
  1184. return tmit_msg;
  1185. }
  1186. /**
  1187. * Cancel transmission of current message to PSYC.
  1188. *
  1189. * @param plc Place to send to.
  1190. * @param client Client the message originates from.
  1191. */
  1192. static void
  1193. psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVER_Client *client)
  1194. {
  1195. uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL;
  1196. struct GNUNET_MessageHeader msg;
  1197. msg.size = htons (sizeof (msg));
  1198. msg.type = htons (type);
  1199. psyc_transmit_queue_message (plc, client, sizeof (msg), &msg, type, type, NULL);
  1200. psyc_transmit_message (plc);
  1201. /* FIXME: cleanup */
  1202. }
  1203. /**
  1204. * Handle an incoming message from a client, to be transmitted to the place.
  1205. */
  1206. static void
  1207. client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client,
  1208. const struct GNUNET_MessageHeader *msg)
  1209. {
  1210. struct Client *
  1211. ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
  1212. GNUNET_assert (NULL != ctx);
  1213. struct Place *plc = ctx->plc;
  1214. int ret = GNUNET_SYSERR;
  1215. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1216. "%p Received message from client.\n", plc);
  1217. GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg);
  1218. if (GNUNET_YES != plc->is_ready)
  1219. {
  1220. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1221. "%p Place is not ready yet, disconnecting client.\n", plc);
  1222. GNUNET_break (0);
  1223. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  1224. return;
  1225. }
  1226. uint16_t size = ntohs (msg->size);
  1227. uint16_t psize = size - sizeof (*msg);
  1228. if (psize < sizeof (struct GNUNET_MessageHeader)
  1229. || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < psize)
  1230. {
  1231. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1232. "%p Received message with invalid payload size (%u) from client.\n",
  1233. plc, psize);
  1234. GNUNET_break (0);
  1235. psyc_transmit_cancel (plc, client);
  1236. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  1237. return;
  1238. }
  1239. uint16_t first_ptype = 0, last_ptype = 0;
  1240. if (GNUNET_SYSERR
  1241. == GNUNET_PSYC_receive_check_parts (psize, (const char *) &msg[1],
  1242. &first_ptype, &last_ptype))
  1243. {
  1244. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1245. "%p Received invalid message part from client.\n", plc);
  1246. GNUNET_break (0);
  1247. psyc_transmit_cancel (plc, client);
  1248. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  1249. return;
  1250. }
  1251. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1252. "%p Received message with first part type %u and last part type %u.\n",
  1253. plc, first_ptype, last_ptype);
  1254. ctx->tmit_msg
  1255. = psyc_transmit_queue_message (plc, client, psize, &msg[1],
  1256. first_ptype, last_ptype, ctx->tmit_msg);
  1257. if (NULL != ctx->tmit_msg)
  1258. {
  1259. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= last_ptype)
  1260. ctx->tmit_msg = NULL;
  1261. ret = psyc_transmit_message (plc);
  1262. }
  1263. if (GNUNET_OK != ret)
  1264. {
  1265. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1266. "%p Received invalid message part from client.\n", plc);
  1267. GNUNET_break (0);
  1268. psyc_transmit_cancel (plc, client);
  1269. ret = GNUNET_SYSERR;
  1270. }
  1271. GNUNET_SERVER_receive_done (client, ret);
  1272. }
  1273. /**
  1274. * Initialize the PSYC service.
  1275. *
  1276. * @param cls Closure.
  1277. * @param server The initialized server.
  1278. * @param c Configuration to use.
  1279. */
  1280. static void
  1281. run (void *cls, struct GNUNET_SERVER_Handle *server,
  1282. const struct GNUNET_CONFIGURATION_Handle *c)
  1283. {
  1284. static const struct GNUNET_SERVER_MessageHandler handlers[] = {
  1285. { &client_recv_host_enter, NULL,
  1286. GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, 0 },
  1287. { &client_recv_guest_enter, NULL,
  1288. GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, 0 },
  1289. { &client_recv_join_decision, NULL,
  1290. GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 0 },
  1291. { &client_recv_psyc_message, NULL,
  1292. GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 }
  1293. };
  1294. cfg = c;
  1295. stats = GNUNET_STATISTICS_create ("social", cfg);
  1296. hosts = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1297. guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
  1298. place_guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  1299. nc = GNUNET_SERVER_notification_context_create (server, 1);
  1300. GNUNET_SERVER_add_handlers (server, handlers);
  1301. GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
  1302. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
  1303. &shutdown_task, NULL);
  1304. }
  1305. /**
  1306. * The main function for the service.
  1307. *
  1308. * @param argc number of arguments from the command line
  1309. * @param argv command line arguments
  1310. * @return 0 ok, 1 on error
  1311. */
  1312. int
  1313. main (int argc, char *const *argv)
  1314. {
  1315. return (GNUNET_OK ==
  1316. GNUNET_SERVICE_run (argc, argv, "social",
  1317. GNUNET_SERVICE_OPTION_NONE,
  1318. &run, NULL)) ? 0 : 1;
  1319. }
  1320. /* end of gnunet-service-social.c */